A New jQuery.attr and the New jQuery.prop Method
4/18/2011
The rewrite of the internal method jQuery.attr and the addition of jQuery.prop will be released in the upcoming release of jQuery 1.6 (May 1). This comes with a solid performance improvement, a modularized implementation, and a cleaner way of dealing with attributes. However, this rewrite will confuse some people who have been using jQuery.fn.attr for cases for which it was not intended, but have always worked. It used to be a jumbled juxtaposition of concepts attempting to deal with two things in one method, which caused many bugs.
First, we'll start with the difference between content attributes and IDL(Interface Definition Language) attributes. Once this distinction is understood, you will understand when to use attr and when to use prop.
Let's take a look at some common use cases for jQuery.fn.attr
$("div").attr("id", "timmy"); // OK
$("video").attr("autofocus", true); // OK
$(window).attr... // NO
$(document).attr... // NO
$("input").attr("value"); // DEPENDS
$("input:checkbox").attr("checked"); // DEPENDS
The reason it makes no sense to call attr on the document or the window is due to the fact that they cannot have content attributes.
They are objects that contain IDL attributes( let's call them properties ), so getting or setting a content attribute with attr on these objects will not work anymore. Here are some examples of content attributes:
<input id="timmy1" class="timmy" name="timmy1"
onclick="javascript:void()" type="radio" value="one" selected="selected">
All of these content attributes have properties that they map to. For instance, if elem is the node above, setting id="timmy1" on that <input> will also set it's property: elem.id. Setting class="timmy" will set elem.className. However, not all attributes work this way and the annoying inconsistencies between browsers are mainly caused by the differences in the way they are mapped onto node objects. For instance, when retrieving any content attribute from a form in IE6 or IE7, multiple node objects are returned instead of a string or some commonly returned value and therefore require a special call. This is because form.action can not only map to the action attribute of that form, but it can also map to some input within the form that has a name="action" if it exists (even though you should NEVER do that). The main job attr performs is get and set the correct attributes consistently across browsers.
Now, one issue that will come up and will have to be answered often in the bug tracker is how come .attr("value") or .attr("checked") or .attr("selected")don't work anymore? Well, actually they now work how they always should have worked. You see, in the official specification for these attributes, these attributes do not map to the properties that have the same name. The value attribute does not map to the value property and the checked attribute does not map to the checked property, even though that's what attr gave you in the past. These attributes should only be used to set their initial values, or default versions of these properties such as .defaultValue. So, in the above code where I said "depends", I say this to make it clear that retrieving these attributes will not give you the element's current value. That is why it has always been recommended to use .is(":checked") when checking the checked property or .val() when retrieving values.
jQuery.fn.prop
If you find that attr is broken in your app, try switching it to this method. This can be used to set properties on the window, document, plain objects, arrays, and all sorts of things. It's really just a method for dot notation that has some fixes for cross-browser consistency. Normally, attr will still be the method of choice and you should keep in mind that attr is the preferred method for getting and setting content attributes.
Boolean Attributes
Finally, allow me to say a word about boolean attributes such as checked, selected, disabled, readOnly, and many html5 attributes that go on video or audio tags. Anyone who wants to set these attributes with javascript should know that the mere presence of these attributes on the DOM will be treated as if set to true. This means that even when you see checked="false" or autofocus="false", these attributes can still be true in certain browsers. We account for some of the most common boolean attributes being set to false in jQuery, but to safely ensure you are setting all of your boolean attributes to false, remove them.