jQuery 1.6 release and checkboxes

jQuery have now released version 1.6 in to the wild, but if you use it, you need to be aware of some compatibility issues.

The above-linked page goes through all of the issues, but I think that the one that will affect the most people is when getting the checked attribute from a checkbox.


<input type="checkbox" checked>

Previously, the attr() method was used to get true or false for the checkbox. In version 1.6 though it just returns an empty string.


var isChecked = $('input:checkbox').attr('checked');
// prior to jQuery 1.6 you would get the boolean value true
// from version 1.6 onwards you instead get ""

With version 1.6 onwards the attribute called checked is empty, as it has no string value, so the attribute string will always be “”

You now need to use the prop() method instead when using jQuery 1.6.


var isChecked = $('input:checkbox').prop('checked'); // true or false

The checkbox thing has the potential to affect a lot of code…that’s unfortunate. I would’ve liked to have seen an alias of some sort put in place for radio/checkbox detection to prevent things from breaking.

What a stupid change. Seems like they are running out of useful things to do. If it isn’t broken – fix it, wait that isn’t not right.

Edit: actually it kinda makes sense, after actually reading the logic. Still its something that is going to break many things.

Before with attr attempting to do everything, it was wrong according to the W3C specs, and it was disguising the differences between properties and attributes.

They have now fixed the problem, but as a result we face a few growing pains when we transition to 1.6 as we learn that attributes are quite different from properties.

This probably would have no relevance on those coding XHTML wouldn’t it? Given that in XHTML all attributes must have values?

<input type=“checkbox” checked=“checked” />

Avoids the issue, right?

Not happy about this :frowning: Ive been using Prototype and although its a bit more code to type it feels like it makes sense better because its an actual extension of JavaScript, rather than just 1 object to handle everything. But I still like using both at this time.

That’s a good point, because the attr() value then becomes even more inconsistent.

Before jQuery 1.6, attr(‘checked’) value for both of the following would be the boolean value true.


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

With jQuery 1.6 onwards, attr(‘checked’) provide the value undefined and ‘checked’ respectively for the above, whereas prop(‘checked’) on each of the above HTML lines will be consistantly the boolean value of true.

Here’s a summary of the values for checked=“checked”, from the prop() documentation page:

elem.checked	                 true (Boolean)
$(elem).prop("checked")	         true (Boolean)
elem.getAttribute("checked")     "checked" (String)
$(elem).attr("checked")(1.6+)    "checked" (String)
$(elem).attr("checked")(pre-1.6) true (Boolean)

Am I missing something here? What’s the point of using jQuery’s attr(‘checked’) or prop(‘checked’) while javascript natively provides the checked property on input fields? Then you just use:

var isChecked = $('input:checkbox').checked;

Cleaner, less typing and you always get true/false as a result. Sorry for the little off topic, I haven’t used jquery much and am wondering why would anyone use something like attr(‘checked’).

I find that $(‘input:checkbox’).checked always gives me undefined as a result. I don’t know how you are getting anything else, but perhaps it’s from some other unmentioned variation of your above code.

The use of attr() method exists for several reasons. It gives the attribute only fir the first matched element in a group, it fixes some cross-browser incompatibilities so that you don’t have to deal with them, and you can chain on other jquery commands after it.

The existence of prop() is partially to achieve the same ability to chain on other commands, to retrieve the property for only the first element in a collection, and to correct compatibility issues where the attr() method was providing incorrect information for good reasons, but which in hind-sight have been found to be wanting.

As a result, attr() is updated to provide the correct information, so that the checked attribute doesn’t report the wrong information. The side-effect of this is that a similar method called prop() is created to access element properties but with the same flexibilities and usefulness that currently exists with the attr() method.

If you personally find that they are of no use to you though, then there is no need for you to use them. We all have our own differences in our coding styles.

Thanks for the explanation, I may not be too knowledgeable about jquery and thought that $(‘input:checkbox’) returns the same type of element object as getElementById() on the input field. What I use is this:


var isChecked = document.getElementById('my_checkbox').checked;

or:


var isChecked = myForm.mycheckbox.checked;

And it works provided the element is a checkbox or radio field.

And if attr() and prop() have some other purposes like object chaining, etc. then I see they can be useful sometimes. I have always used the ‘checked’ property on element objects and it has failed me.

That’s not the case. What is returned instead is a jQuery object, which is what encapsulates a collection of results, and allows the chaining.

I say that about every ‘shortcut’ method in jquery…

[ot]Well, it’s a trade-off.

Using traditional Javascript makes it tricker to do some things, but since you are dealing with DOM elements directly, you can just get properties and attributes directly.

With jQuery and chaining, you need it to be wrapped so you can do the chaining, but then you have to use the wrapper to get at things the DOM has.

I personally prefer jQuery (in large part because it handles most of the cross-browser inconsistencies for me), but it is a trade-off… and not something I deploy in every project.[/ot]

Thanks for the heads up, Paul. I do a ton of work with check boxes and this one would have thrown me for a loop. I’m currently working on a Wordpress-based project, which ships with jQuery (so it’s still 1.5). Did the prop() function exist prior to 1.6? (I’m guessing yet, but couldn’t find anything in the documentation to explicitly confirm this). If so, I can use prop() and future proof my stuff for when Wordpress starts shipping with 1.6. =)

The prop() page says the following which provides a strong hint:

Before jQuery 1.6, the .attr() method sometimes took property values into account when retrieving some attributes, which could cause inconsistent behavior. As of jQuery 1.6, the .prop() method provides a way to explicitly retrieve property values, while .attr() only retrieves attributes.

But the full confirmation is on the release notes for jQuery 1.6, linked to from the [URL=“http://www.sitepoint.com/forums/javascript-15/jquery-1-6-release-checkboxes-755949.html#post4872719”]first post, which among other things says:

In the 1.6 release we’ve split apart the handling of DOM attributes and DOM properties into separate methods. The new .prop() method sets or gets properties on DOM elements, and .removeProp() removes properties.

That would be interesting, but no it’s not possible. As soon as the move is made to 1.6, is when those things will break and you need to fix them right away.

I’d start making a list, checking it twice, etc…

You can augment JQuery with your own prop implementation or perhaps grab the one from 1.6 so long as there aren’t to may dependencies than remove it when you update.

Thanks paul,

I saw the first thing you linked, but didn’t know if it explicitly meant prop() didn’t exist or not.

Could I do something like this to future proof as well?


if(typeof $('.something').prop == 'function')
  $('.something').prop('checked');
else
  $('.something').attr('checked');

Or possibly adding my own version of prop() which is basically just a wrapper for attr():


if(typeof $('.something).prop != 'function')
  $.fn.prop = function(attr, value) {
    // May not be the exact code needed for proper implementation, but you get the idea.
    return $(this).attr(attr, value);
  }

This way, in theory, if you don’t have prop() available, it acts just like attr(). If you do have prop() available, it works properly. If used only in certain cases (like check boxes), nothing should break when the version changes, right?

That seems like the cleanest approach I can think of (taking into account it’s 1am here =p).

Yes, you could do something like that, but don’t return the jQuery attr value. That’s guaranteed to break in V1.6 which is what this is all about.

Instead, get the first element that’s passed in, as with jQuery it can easily be multiple elements that it’s used on, and return el[attr]

Something like this might be closer to a somewhat compatible workaround:


jQuery.fn.prop = jQuery.fn.prop || function (name, value) {
    return jQuery.access(this, name, value, true, function (elem, name, value) {
        var set = value !== undefined;
        if (set) {
            elem[name] = value;
        }
        return elem[name];
    });
};

Here’s a quick and dirty test that shows the attr and prop values of the checkboxes.

When you change the jquery library from 1.5.2 to 1.6.0, you should see the attr results change, but the prop results remain the same.


<p>
    <input type="checkbox" name="unchecked"> unchecked
    <input type="checkbox" name="checked" checked> checked
    <input type="checkbox" name="fullchecked" checked="checked"> checked="checked"
</p>
<p>
    <input type="button" name="attr" value="Checked attrs">
    <input type="button" name="prop" value="Checked props">
</p>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.js"></script>
<script>
$(function () {
    jQuery.fn.prop = jQuery.fn.prop || function (name, value) {
        return jQuery.access( this, name, value, true, function (elem, name, value) {
            var set = value !== undefined;
            if (set) {
                elem[name] = value;
            }
            return elem[name];
        });
    };
    
    $('input[name="attr"]').click(function () {
        var unchecked = $('input[name="unchecked"]').attr('checked');
        var checked = $('input[name="checked"]').attr('checked');
        var fullchecked = $('input[name="fullchecked"]').attr('checked');
        alert('unchecked:'+unchecked+', checked:'+checked+', fullchecked:'+fullchecked);
    });
    $('input[name="prop"]').click(function () {
        var unchecked = $('input[name="unchecked"]').prop('checked');
        var checked = $('input[name="checked"]').prop('checked');
        var fullchecked = $('input[name="fullchecked"]').prop('checked');
        alert('unchecked:'+unchecked+', checked:'+checked+', fullchecked:'+fullchecked);
    });
    
});
</script>

Great news - it looks like the jQuery team have been paying attention to the attr compatibility trouble, and have come out with jQuery 1.6.1 which means that you shouldn’t have to change how you use the attr function. It is still advised though that you use prop and val where appropriate for them.

Read more about it - jQuery 1.6.1 release notes

And for the sake of completion, here’s the blog post form John Resig about jQuery 1.6 and attr()