jQuery Attr() Function Doesn't Work With IMAGE.complete

Posted October 23, 2007 at 2:03 PM

Tags: Javascript / DHTML

I ran into what I think is a jQuery bug this morning when testing to see if an image had finished loading. As you may or may not know, the image object has a boolean attribute, "complete", which determines whether or not the image has finished loading (either to success or failure/error). It seems, however, that this attribute can only be accessed via the image node property and not through .attr() function.

Take a look at this test code:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>jQuery Bug</title>
  •  
  • <script type="text/javascript" src="jquery-latest.pack.js"></script>
  • <script type="text/javascript">
  •  
  • // Once the document is loaded, check to see if the
  • // image has loaded.
  • $(
  • function(){
  • var jImg = $( "img:first" );
  •  
  • // Alert the image "complete" flag using the
  • // attr() method as well as the DOM property.
  • alert(
  • "attr(): " +
  • jImg.attr( "complete" ) + "\n\n" +
  •  
  • ".complete: " +
  • jImg[ 0 ].complete + "\n\n" +
  •  
  • "getAttribute(): " +
  • jImg[ 0 ].getAttribute( "complete" )
  • );
  • }
  • );
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <p>
  • <img src="about:blank" alt="Empty Image" />
  • </p>
  •  
  • </body>
  • </html>

Notice that we are alerting the "complete" value via the .attr() method as well as the DOM node propertyy and the DOM getAttribute() method. This is what we get:


 
 
 

 
jQuery .attr() Method Calls  
 
 
 

The .attr() method fails to return a valid value. The .complete attribute works fine. Behind the scene, the jQuery .attr() method works in conjunction with the .getAttribute() method, which looks like it fails to get the "complete" attribute as well. So, maybe this is a bug with the browser?

Of course, that above output was run in FireFox. This is what we get when we run it in Internet Explorer:


 
 
 

 
jQuery .attr() Function Calls  
 
 
 

Notice here that .getAttribute() does return a valid value (false), and still, .attr() fails to return a boolean value. This seems very odd. Anyone have any thoughts?

Download Code Snippet ZIP File

Comments (7)  |  Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Reader Comments

@Ben:

You're using $(document).ready() when really you should be using $(window).load().

The ready() fires when the DOM is ready--which is generally before images have loaded. Often you don't need to wait for images to load, but there are occasions when you want to make sure everything on the page has finished loading.

I'm also not so sure that the img.complete property is all that reliable.

Perhaps you'd be better off doing something like:

$(function (){
$("img:first").load(function (){
alert("Image loaded!");
});
});

Posted by Dan G. Switzer, II on Oct 23, 2007 at 3:02 PM


An educated guess... getAttribute probably only works for attributes of the tag. complete isn't an attribute - it's a property of the DOM element, set by the browser itself. It's a fine line, and like I said it's a stab in the dimly lit, but thought I'd throw it in. Just ignore IE... stupid browser :p

As already mentioned, the onload callback is more handy as it saved polling the complete flag. onerror is another useful one as well.

Posted by George Bridgeman on Oct 23, 2007 at 3:41 PM


@Dan,

You can't rely on the onLoad method of the image since that will only fire if the image has not already finished loading at the time of the event binding.

I suppose that I could wait till the window loaded. That's not a bad option, however, then I have to wait for ALL images to load, not just the one I want to target... seems weak. But, maybe that is the best option.

However, looking at the W3C website, it looks like it is NOT part of the standard:

http://www.w3schools.com/htmldom/dom_obj_image.asp

However, it is supported in FireFox, IE, and Opera. I guess, since it's not a W3C standard, you could argue that is is *not* a bug.

Posted by Ben Nadel on Oct 23, 2007 at 3:41 PM


But, then again, innerHTML is also not a W3C standard, and it is what all of the html() methods rely on in jQuery... so, not a good argument perhaps.

Posted by Ben Nadel on Oct 23, 2007 at 3:46 PM


Unfortunately, this is how getAttribute and setAttribute are supposed to work.

For example:

document.body.onload = function() {}
assert( typeof(document.body.onload) == "function" )
assert( document.body.getAttribute("onload") == null )
assert( typeof(document.body["onload"]) == "function" )

Specifically, get/setAttribute are intended to change the attributes of the element, but not the properties of the node.

As a rule of thumb, I'd only ever use getAttribute() to access things I also set with setAttribute(), but not for anything else. I pretty much never use get/setAttribute for this very reason.

What they should really be using in jQuery is the [] notation since it's equivalent to dot notation in ECMAScript.

Also, note that the "complete" property is non-standard
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-17701901 , though it does seem to work in most modern browsers.

Posted by Elliott Sprehn on Oct 24, 2007 at 10:26 AM


Woops, you already mentioned the fact that it's not standard in a comment! :P

Posted by Elliott Sprehn on Oct 24, 2007 at 10:29 AM


@Elliott,

So, for things like ID and HREF, do you go down into the DOM element via the jQuery stack? Example:

$( "a:first" )[ 0 ].href

Or do you find a balance in between somewhere?

Posted by Ben Nadel on Oct 24, 2007 at 7:38 PM


Post Comment  |  Ask Ben


Home   |   Web Log   |   ColdFusion   |   Projects   |   Resume   |   Job Form   |   Search   |   Contact
Epicenter Consulting - Custom Software Solutions for Business Evolution HostMySite.com - The Leader In ColdFusion Hosting