Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery Checkbox toggle with button not working after few times

Can anyone explain why the code fragment does not work after pressing toggle 3 times?

The attribute checked is still set to "checked" but the browser doesn't check the checkbox anymore.

$(document).ready(function() {

  $("#btn").click(function() {

    if($("#chk").is(":checked"))  
       $("#chk").removeAttr("checked");  
    else
       $("#chk").attr("checked","checked");

    $("#lbldebug").text($("#chk").clone().wrap('<p>').parent().html());
  });
});

See http://jsbin.com/ewawih/2/edit

I've tested it both on Opera and Chrome, with the same problem in both.

What am I missing here?

like image 454
Drakarah Avatar asked Feb 10 '13 18:02

Drakarah


2 Answers

for jQuery 1.9+, attr for properties will not work, you can simplify a toggle of a checkbox like:

  $("#btn").click(function() {
      $("#chk").prop("checked",!$("#chk").prop("checked"));
      $("#lbldebug").text($("#chk").clone().wrap('<p>').parent().html());
  });

EDIT: see that:!$("#chk").prop("checked") notice that first character which makes the boolean value the opposite of what it currently is, thus the toggle works by setting it to the opposite of what it currently is, no matter what that value is.

Just for an explanation, accessing the attr('checked') in jQuery 1.9+ gets the original attribute - which is a part of the markup, while the .prop("checked") accesses the current property value for that. Some things are still attributes, however this is one that is a property and access to properties through/as an attribute was deprecated and then removed in jQuery 1.9/2.0. In jQuery 1.6 they made changes and in 1.6.1 they reverted some of those changes and deprecated the attr() even though it still worked due to those 1.6.1 change. 1.9+ then removed those usages. Think of an attribute as some string, and a property as a current value. Your use of the the attribute was accessing that string which did not change whereas the property did change and hence why .prop() works.

Also note that your use of the text/wrap for the element (for debug I assume) does not show the property but only the "string" of the element which does not include the property - hence it appears not to change/be there in your "debug" this way and your would need to add access to the property (a true/false value) and append that also to get a visible representation of that value.

  • The attribute value reflects the default (what it was in markup at the beginning/when the page first rendered) rather than the current visible state and actual value (some older versions of IE differ). Thus you see attributes tell you nothing about the whether the checkbox is checked.

For 1.9.1 on chrome:

$("#chk").checked //returns undefined

(used to work prior to change, feels like a bug)

EDIT2:wrong:incorrect form

$("#chk")[0].checked // proper form works
$("#chk").get(0).checked  // same as above, works
document.getElementById("chk").getAttribute("checked") // returns "checked" or null or "true" or "fun" or empty "" if it was set thay way, attribute present checks box
$("#chk").is(":checked") // returns true/false current value
$("#chk").attr("checked") // returns "checked" or undefined does not change
document.getElementById("chk").defaultChecked // returns true/false of original, does not change
$("#chk").prop("checked") // returns current value true/false
document.getElementById("chk").checked //returns current value true/false
$("#chk").is("[checked]") // attribute selector returns original value, does not change
like image 188
Mark Schultheiss Avatar answered Nov 03 '22 00:11

Mark Schultheiss


if($("#chk").is(":checked"))  
    $("#chk").prop("checked", false);  
else
    $("#chk").prop("checked", true);

You should use .prop() and also checked can also be specified with BOOLEAN.

like image 20
Muhammad Talha Akbar Avatar answered Nov 03 '22 00:11

Muhammad Talha Akbar