如何在选中“全部”复选框时取消选中相关复选框,并在选中任何相关复选框时取消选中“全部”复选框?

时间:2013-04-10 16:32:23

标签: javascript jquery checkbox

我有一个包含多个复选框组的表单,每个复选框组都有一个相关的“全部”选项,单击该选项后,取消选中所有相关的复选框。当选中任何相关复选框时,表单还需要取消选中“全部”选项。基本上,表单可以提交“全部”选项,任何相关选项,或者没有选项。

选中任何复选框后,相关标签将变为粗体,包括“全部”选项。

我已经在jQuery中编写了这个逻辑,但是,我似乎无法正常工作 - 在选中其中一个相关选项时取消选择“全部”选项。它在用户单击其中一个相关选项时起作用,但在刚刚检查完它后,它也会检查“全部”选项。

我想我的问题是,我如何确定“源”事件是什么,所以我可以确定是否运行那段代码?

使用“取消选择'全部'”进行演示,注释掉:http://jsfiddle.net/8Ctvd/

JS:

$(function () {
    $(".all").change(function () {
        if ($(this).is(":checked")) $("input[rel='" + $(this).attr("rel") + "']:checked").not(".all").removeAttr("checked").change();
    });

    $("input[type='checkbox']").change(function (e) {
        if ($(this).is(":checked")) $("label[for='" + $(this).attr("id") + "']").css("font-weight", "bold");
        else {
            $("label[for='" + $(this).attr("id") + "']").css("font-weight", "normal");
            /* THIS UNCHECKS THE ALL EVERYTIME
            if  ($(this).not(".all"))
                $("input.all[rel='" + $(this).attr("rel") + "']").removeAttr('checked').change();
            */
        }
    });
});

HTML:

<INPUT id=items_All class="checkbox all" name=items value=ALL type=checkbox rel="items">
<LABEL class="items checkbox-label" for=items_All>All</LABEL>
<INPUT id=items_1 class=checkbox name=items value=1 type=checkbox rel="items">
<LABEL class="items checkbox-label" for=items_1>Item 1</LABEL>
<INPUT id=items_2 class=checkbox name=items value=2 type=checkbox rel="items">
<LABEL class="items checkbox-label" for=items_2>Item 2</LABEL>
<INPUT id=items_3 class=checkbox name=items value=3 type=checkbox rel="items">
<LABEL class="items checkbox-label" for=items_3>Item 3</LABEL>
<br />
<INPUT id=widgets_All class="checkbox all" name=widgets value=ALL type=checkbox rel="widgets">
<LABEL class="widgets checkbox-label" for=widgets_All>All</LABEL>
<INPUT id=widgets_1 class=checkbox name=widgets value=1 type=checkbox rel="widgets">
<LABEL class="widgets checkbox-label" for=widgets_1>Widget 1</LABEL>
<INPUT id=widgets_2 class=checkbox name=widgets value=2 type=checkbox rel="widgets">
<LABEL class="widgets checkbox-label" for=widgets_2>Widget 2</LABEL>
<INPUT id=widgets_3 class=checkbox name=widgets value=3 type=checkbox rel="widgets">
<LABEL class="widgets checkbox-label" for=widgets_3>Widget 3</LABEL>

2 个答案:

答案 0 :(得分:0)

修改

我已经调整了JS以符合我误解的要求。部分问题在于您的逻辑有点偏差,并且可能会大大简化。将格式化逻辑分离到单独的函数可以让您与检查分开查看格式。

$("input[type='checkbox']").change(function (e) {
    var $o = $(this);
    if ($o.hasClass("all")) {
        //all box was checked, uncheck others
        if ($o.prop("checked"))
            $("input[rel='" + $o.attr("rel") + "']").not(this).prop("checked", false);
    } else {
        // other box was checked, uncheck all
        if ($o.prop("checked")) {
            $("input.all[rel='" + $o.attr("rel") + "']").prop("checked", false);
        }
    }
    fixMarkup();
});

请参阅此处以获取完整示例:http://jsfiddle.net/8Ctvd/3/

原始答案

您正在使用attr,这会在您的情况下为您提供不可预测的结果。此外,使用.is.prop慢。您应该在jQuery中使用.prop,它将被转换为布尔值并反映标记的当前状态而不是其初始标记。见this SO answer for reference

此外,您在最终.change()上致电not('.all'),这会导致在“全部”复选框中触发更改事件。检查这个更新的小提琴。

http://jsfiddle.net/8Ctvd/1/

答案 1 :(得分:0)

我通过对相关复选框使用“click”事件来解决这个问题。这样,更改事件不会触发它。

JS:

$('.all').change(function(){
    if ($(this).is(':checked'))
        $('input[rel="' + $(this).prop('rel') + '"]:checked').not('.all').removeProp('checked').change();
});

$('input[type="checkbox"]').change(function(e){
    var $label = $('label[for="' + $(this).prop('id') + '"]');

    if ($(this).is(':checked'))
        $label.css('font-weight', 'bold');
    else
        $label.css('font-weight', 'normal');
});

$('input[type="checkbox"]').not('.all').click(function(e){
    var $allCheckbox =
        $('input.all[rel="' + $(this).prop('rel') + '"]');

    if ($allCheckbox.is(':checked'))
        $allCheckbox.removeProp('checked').change();
});