Understanding jQuery 1.6’s DOM Attribute and Properties

jQuery 1.6 released a significant change to the way it handles DOM attributes and properties.

Take for example in version 1.5.2, the following code would return isCheckedAttr as “true”.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
</script>

In version 1.6 the addition of .prop() and .removeProp() changes what the .attr() method will return when referencing DOM properties. The following example will return isCheckedAttr as “” and isCheckedProp as “true”. Notice 1.5.2 returned “true” instead of “” for isCheckedAttr.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

Now… check this out. In HTML and XHTML you can set the checked property as an attribute. This example in jQuery 1.6 will return “checked” for isCheckedAttr (remember 1.5.2 returned “true”). The isCheckedProp will still return “true”.

<input type="checkbox" checked="checked" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

Try this case on for size… If I don’t set the checked attribute or property isCheckedAttr will always return “undefined” (not an empty string) and isCheckedProp will return false (until I click the checkbox which will make it true).

<input type="checkbox" />

<script type="text/javascript">
var isCheckedAttr = $('input').attr("checked");
var isCheckedProp = $('input').prop("checked");
</script>

This all makes sense, though a bit confusing since the attribute is basically converted into a property at DOM load making upgrading to version 1.6 much more difficult than most recent version upgrades, so be sure to do some extra testing.

Okay, ready for this, one more item to throw at you… if I’m reading the bug ticket right, if an attribute does not exist but the property does, the .attr() will bring back the property boolean value as the attribute in the next release (probably 1.6.1). This appears to be a backwards compatibility fix for reading properties, but not setting them.

UPDATE 5/9/2011: appendTo, a jQuery company I highly respect, released an executive brief on jQuery 1.6 stating that it recommends not upgrading to jQuery 1.6 until 1.6.1 is released. This version will return either the name of the attribute (if true) or undefined (if false) for .attr(BooleanAttribute) and could be released as early as Tuesday, May 10, 2011. It also has a good read on the rest of the features new to this version.

John Resig also released an example:

“Let’s pretend we’re working with a checkbox that isn’t checked at all:

<input type="checkbox" id="c"/>

$("#c").attr("checked") => false // 1.5.2
$("#c").attr("checked") => undefined // 1.6
$("#c").attr("checked") => undefined // 1.6.1

The user then checks the checkbox OR we set the check by doing .prop(“checked”, true) OR we set the check by doing [0].checked = true, the result would be:

$("#c").attr("checked") => true // 1.5.2
$("#c").attr("checked") => undefined // 1.6
$("#c").attr("checked") => "checked" // 1.6.1

Note that if we had done .attr(“checked”, “checked”) OR .attr(“checked”, true) to set the checked property then .attr(“checked”) would’ve returned “checked” in both 1.6 and 1.6.1.

In short: In jQuery 1.6.1 .attr(BooleanAttribute) now returns either the name of the attribute (if true) or undefined (if false). Which is consistent with the rest of the API and with the DOM itself.

I should note that all of this is a moot point if you’re using .prop(“checked”) – that will just return true/false consistently based upon the current checked state of the checkbox.”