为什么浏览器停止显示复选框更新?

Why does the browser stop displaying checkbox updates?

我正在使用 jQuery 来帮助 select 表单中的一些匹配复选框元素。表单是动态创建的,但这里是它的精简版本,说明了我的观点:

http://jsfiddle.net/phinor/qj7uj3rc/

这是相关的 JavaScript:

$(document).ready (function () {
    $('.lessoncount').on ('click', tickAlike);
});

function tickAlike ()
{
    var classes = $(this).attr('data-classes');

    if ($(this).siblings ('.tick_' + classes).attr ('checked'))
    {
        console.log ('ticking');
        $('.tick_' + classes).removeAttr ('checked');
    }
    else
    {
        console.log ('unticking');
        $('.tick_' + classes).attr ('checked', true);
    }
}

想法是复选框可以单独select编辑,或者,如果单击 "label",所有复选框相同的 class 将被 selected 或 deselected 以匹配它旁边的框。因为我想要两种可能的行为取决于他们是点击框还是点击标签,所以我不能使用 <label> 标签。作为后续,由于独立的 selection,"toggling" 不可行。

这似乎适用于 "ticks" 和 "unticks" 的一个周期,然后停止。如果我检查 Chrome 中的复选框元素,我可以看到正在适当地添加和删除 "checked" 属性,但是浏览器视图不再更新并且勾号不显示。

这在 Chrome、Firefox 和 IE 的最新版本中是一致的,所以我猜我做错了什么!

如果您的表单是动态创建的,那么它的行为可能与静态的不同。对动态创建的元素使用 bind 或 live 而不是 click:

 $(".lessoncount" ).live( "click", function() {
  tickAlike();
});

你应该使用 .prop() instead of .attr() when modifying boolean attributes, e.g. checked, disabled, readonly, selected and etc. Using .removeAttr() or .removeProp() will cause the attribute to be removed forever, and cannot be further manipulated. To understand the difference between .prop() and .attr(), there is actually a very good question (with a well-structured answer) asked on SO before.

要以编程方式选中复选框,只需使用 $selector.prop('checked',true)。要取消选中,请使用 $selector.prop('checked',false).

此外,要检查复选框是否被选中(没有双关语意),您可以使用 .is() 方法来执行此操作,即 $selector.is(':checked').


$(document).ready(function () {
    $('.lessoncount').on('click', tickAlike);
});

function tickAlike ()
{
    var classes = $(this).attr('data-classes');
    if ($(this).siblings('.tick_' + classes).is(':checked'))
    {
        console.log('ticking');
        $('.tick_' + classes).prop('checked', false);
    }
    else
    {
        console.log('unticking');
        $('.tick_' + classes).prop('checked', true);
    }
}

一个工作演示:http://jsfiddle.net/teddyrised/qj7uj3rc/5/


更好:我可以看到包含每个复选框描述的 <span> 元素在语义上 unhinged随附的复选框,即无法为每个复选框提供上下文。 <label> 元素就是为此目的而创建的。

您可能仍想独立设置描述符的样式,因此我们可以将它们包裹在 <span> 中,但我们可以使用 <label> 元素包裹每个 <td> 中的所有内容,因此单击文本 复选框将触发相同的响应。

table 正文中行的修订标记如下所示:

<tr>
    <td>1-Mo</td>
    <td><label for="lesson_1_1"><input type="checkbox" name="lesson[1][1]" value="1" id="lesson_1_1" class="tick_1645_1646_1647_1648_1649_1650_2024"/> <span data-classes="1645_1646_1647_1648_1649_1650_2024" class="lessoncount">(7)</span></label></td>
    <td><label for="lesson_1_2"><input type="checkbox" name="lesson[1][2]" value="1" id="lesson_1_2" class="tick_1582_1583_1584_1585_1586_1587"/> <span data-classes="1582_1583_1584_1585_1586_1587" class="lessoncount">(6)</span></label></td>
    <td><label for="lesson_1_3"><input type="checkbox" name="lesson[1][3]" value="1" id="lesson_1_3" class="tick_1658_1673_1684_1700_1706_1736_1737_1769"/> <span data-classes="1658_1673_1684_1700_1706_1736_1737_1769" class="lessoncount">(8)</span></label></td>
    <td><label for="lesson_1_4"><input type="checkbox" name="lesson[1][4]" value="1" id="lesson_1_4" class="tick_1602_1603_1604_1605_1618_1628"/> <span data-classes="1602_1603_1604_1605_1618_1628" class="lessoncount">(6)</span></label></td>
    <td><label for="lesson_1_5"><input type="checkbox" name="lesson[1][5]" value="1" id="lesson_1_5" class="tick_"/> <span>(0)</span></label></td>
    <td><label for="lesson_1_6"><input type="checkbox" name="lesson[1][6]" value="1" id="lesson_1_6" class="tick_1659_1674_1701_1738_1755_1756"/> <span data-classes="1659_1674_1701_1738_1755_1756" class="lessoncount">(6)</span></label></td>
    <td><label for="lesson_1_7"><input type="checkbox" name="lesson[1][7]" value="1" id="lesson_1_7" class="tick_1719_1720_1721_1722_1723_2003"/> <span data-classes="1719_1720_1721_1722_1723_2003" class="lessoncount">(6)</span></label></td>
    <td>detail | clear</td>
  </tr>

使用稍微修改过的脚本来收听甚至在环绕 <label> 元素而不是文本范围上的点击:

$(document).ready(function () {
    $('table tbody label').on('click', tickAlike);
});

function tickAlike ()
{
    var classes = $(this).find('span.lessoncount').attr('data-classes');
    if ($(this).find('input[type="checkbox"]').is(':checked'))
    {
        console.log('ticking');
        $('.tick_' + classes).prop('checked', false);
    }
    else
    {
        console.log('unticking');
        $('.tick_' + classes).prop('checked', true);
    }
}

查看替代工作演示:http://jsfiddle.net/teddyrised/pb68gk2n/

问题是当您想要切换属性时,您不应该使用属性进行操作 checked

这里是更新和简化的代码:

$(document).ready(function () {
    $('.lessoncount').on('click', tickAlike);
});

function tickAlike() {
    var classes = $(this).data('classes');
    var $checkbox = $(this).siblings('.tick_' + classes).click();
    $('.tick_' + classes).prop('checked', $checkbox.is(':checked'));
}

演示: http://jsfiddle.net/qj7uj3rc/6/

然而这仍然不理想:注意点击复选框本身是如何不起作用的。所以可以改进。您需要使用 label 而不是 span 并将复选框包装到这些标签中。所以 HTML 应该是这样的:

<label data-classes="1645_1646_1647_1648_1649_1650_2024" class="lessoncount">
    <input type="checkbox" name="lesson[1][1]" value="1" id="lesson_1_1" class="tick_1645_1646_1647_1648_1649_1650_2024" /> (7)
</label>

然后在复选框而不是 span 上绑定 onchange 事件:

$(document).ready(function () {
    $('.lessoncount :checkbox').on('change', tickAlike);
});

function tickAlike() {
    var classes = $(this).parent().data('classes');
    $('.tick_' + classes).not(this).prop('checked', this.checked);
}

对条件使用 "is(':checked')",并使用“.prop ('checked', false)”和“.prop ('checked', true)”来更改检查输入。

这里是linkhttps://jsfiddle.net/qj7uj3rc/7/

if ($(this).siblings ('.tick_' + classes).is(':checked'))
{
    console.log ('ticking');
    $('.tick_' + classes).prop ('checked', false);
}
else
{
    console.log ('unticking');
    $('.tick_' + classes).prop ('checked', true);
}