开发者

How to toggle attribute in jQuery

I'm trying to use images as checkboxes. The following would work fine if it were radios instead of checkboxes that I was targeting but with checkboxes the problem is I can't select an element by clicking on it again after selecting it.

// image checkbox
$('#imageCheckBoxes img').click(function() {
    $(this).parent('span').find('input:checkbox').attr('checked', 'checked');
});
<div id="imageCheckBoxes">
    <ul>
        <li><a href="">Africa</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" />开发者_开发问答</span>
        </li>
        <li><a href="">Asia/Pacific Islands</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
        <li><a href="">Australia</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
        <li><a href="">Central/South America</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
        <li><a href="">Europe/Russia</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
        <li><a href="">North America</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
        <li><a href="">United Kingdom</a>  <span><img src="images/checkbox-inactive.png" /><input type="checkbox" name="" value="" /></span>
        </li>
    </ul>
</div>

I need to basically toggle the check attr() part.

How to do that?


I'd do this by passing a function to prop (since jQuery 1.6, attr before). The return value of this is set as the new property value.

$(this)
    .closest('li')
        .find('input:checkbox').prop('checked', function(idx, oldProp) {
            return !oldProp;
        });

The key fact here is that you can pass true or false to prop to set the checked property. oldProp is the existing value of the property (which will be either true or false), so !oldProp is the inversion: checked elements are unchecked and vice versa.

Note that I have also changed your code to look for the closest ancestor li element with closest, which should be more reliable and effective.


You could add a rather basic jQuery extension, that works in the same way as "toggle()" and "toggle(showOrHide)" but for attributes - "toggleAttr(attribute)" and "toggleAttr(attribute, addOrRemove)"

$.fn.toggleAttr = function(a, b) {
    var c = (b === undefined);
    return this.each(function() {
        if((c && !$(this).is("["+a+"]")) || (!c && b)) $(this).attr(a,a);
        else $(this).removeAttr(a);
    });
};

Note, this is xhtml compatible, and is designed for attributes such as "disabled", "enabled", "checked", "selected" and so on.

Example of use (for your scenario):

$('#imageCheckBoxes img').click(function() {
    $(this).parent('span').find('input:checkbox').toggleAttr('checked');
}

EDIT - though as pointed out by artlung - a label is probably best for your scenario


Another possible approach:

$('#imageCheckBoxes').delegate('img', 'click', function(){
    var $associatedCheckbox = $(this).siblings('input:checkbox');
    if ($associatedCheckbox.is(':checked')){
        $(this).removeClass('checked');
        $associatedCheckbox.removeAttr('checked');
    } else {
        $(this).addClass('checked');
        $associatedCheckbox.attr('checked', 'checked');
    }
});

I'm using delegate(), though you could just as easily use your standard click() or a bind() call to add the listening function.

I also have added some code to add a class to the image. If you, say, wanted to give visual feedback to the user, you could implement that with your .checked class on those images.

#imageCheckboxes img {
  border: 2px solid #fff;
}
/* feedback for your users! */
#imageCheckboxes img.checked {
  border: 2px solid #6f6;
}

Now, it strikes me that you could also avoid JavaScript for this, and simple put <label> tags around your images, and then associate them with your checkboxes to get the same effect. Just replace your <span>s in your html with <label>.


Try this.

$('#imageCheckBoxes img').click(function() {
    var el = $(this).parent('span').find('input:checkbox');
    if(el.is(':checked'))
        el.attr('checked', '');
    else
        el.attr('checked', 'checked');
});


My solution was a little more clever:

var $formContainer = $(".form-container"),
    $myCheckbox = $formContainer.find(".my-checkbox"),
    $requiredFields = $formContainer.find("input[required], textarea[required], select[required]").removeAttr("required"); // remove the required attribute on all required form inputs
$myCheckbox.change(function () {
    $formContainer.toggle("fast", function() {
        if ($(this).is(":visible")) {
            $requiredFields.attr("required", true);
        }
        else {
            $requiredFields.removeAttr("required");
        }
    });
});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜