0

So I'm trying to use jquery to detect when a checkbox has been checked and unchecked (by clicking the label I should add) to change a css attribute.

Here's an example of the code for the checkbox:

<div class="block" id="block_1">
   <input type="checkbox" name="images" id="image_1" class="block_input" />
   <label for="image_1" class="block_button" style="background-image:url(img/bnw/block_1bnw.png);">
   <span>Label text</span></label>
</div>

and here is the jQuery I have so far that only half works:

$('.block_button').click(function(){
    var imgId = $(this).parent().attr('id');

    if ($(this).siblings('.block_input').checked == true) {
        $(this).css("background-image", "url(img/color/" + imgId + ".png)");
    } else {
        $(this).css("background-image", "url(img/bnw/" + imgId + "bnw.png)");
    }
});

The css changes correctly when you check the box initially, but once it's unchecked nothing changes. I've tried logging the result of the .checked method on click and it seems to stay true even when you uncheck. So how do I get the else statement to work once the user decides to uncheck the box?

Thanks!!

daviddcarr
  • 15
  • 5

2 Answers2

1

I believe your mistake is here:

if ($(this).siblings('.block_input').checked = true) {

It should be == instead of =. In fact, you could just write it as:

if ($(this).siblings('.block_input').checked) {

What is happening: when that line runs, you set the value of checked to true. This overrides the previous value of checked.

Edit: A few changes were necessary to get a rudimentary working example (JSFiddle).

  1. Changing the event to be triggered when the checkbox changes, rather than from the perspective of the label. This is also going to catch users clicking on the checkbox itself, or changing the state of the checkbox via other means (e.g., via the keyboard).

    $('.block_input').change(function(){

  2. Checking the property .checked (see this SO answer for more details), like this:

    if ($(this).prop('checked')) {

  3. Now that the event is being triggered on the checkbox, you need to amend your reference to the label:

    $(this).siblings('.block_button').css( ...

Community
  • 1
  • 1
wonglkd
  • 96
  • 2
  • 7
  • Unfortunately that doesn't seem to be the problem, That would indeed be an issue though, thanks for pointing that out and explaining it! – daviddcarr Dec 09 '13 at 20:39
1

A JQuery object has no property "checked" so it will never evaluate to true.

To access the property of an HTML element through its corresponding JQuery object, you have to use the .prop() method. Or, in other words...

$('.block_button').click(function(){
    var imgId = $(this).parent().attr('id');

    if (! $(this).siblings('.block_input').prop('checked')) {
        $(this).css("background-image", "url(img/color/" + imgId + ".png)");
    } else {
        $(this).css("background-image", "url(img/bnw/" + imgId + "bnw.png)");
    }
});

Note, I also added in a "!" in the if statement, because this function triggers before the checkbox's state is changed. So the state here is the opposite of what it will be once the click event finishes propagating.

There is another way of doing it that makes a little more sense, too:

$('.block_input').change(function(){
    var imgId = $(this).parent().attr('id');

    if ($(this).prop('checked')) {
        $(this).siblings('.block_button').css("background-image", "url(img/color/" + imgId + ".png)");
    } else {
        $(this).siblings('.block_button').css("background-image", "url(img/bnw/" + imgId + "bnw.png)");
    }
});

This way, the function you're defining gets called after the input changes, not before. It also gets triggered if the user clicks on the checkbox itself, not just the image it's next to. (Which is useful if your users are tabbing around the page)

Hope this helps!

wampastompa
  • 130
  • 7
  • @daviddcarr It is also worth noting that you can convert a jQuery object to a DOM object by passing the index of the array. Remembering JavaScript is a zero indexed language this would be $(this)[0] in this case. That then exposes all the native JavaScript properties of the object, at the expense of the jQuery objects. I have created a JS fiddle to demonstrate this at http://jsfiddle.net/pwdst/6Cyvf/1/. See https://www.inkling.com/read/jquery-cookbook-cody-lindley-1st/chapter-3/recipe-3-3 for more. – pwdst Dec 17 '13 at 23:59