【问题标题】:How to prevent clicking an underlying checkbox如何防止单击底层复选框
【发布时间】:2014-09-13 01:23:19
【问题描述】:

我有 2 个复选框和第三个用作“全部切换”的复选框。我有以下标准:

  • 当其他 2 个复选框均未选中时,“toggle all”也应取消选中。
  • 当另外两个复选框都被选中时,“toggle all”也应该被选中。
  • 当仅选中一个其他复选框时,应选中“全部切换”并禁用以显示“半选中”状态。

另外,应该可以点击“toggle all”来选中或取消选中另外2个(如果“toggle all”是半选中的,两个都应该选中)。

我创建了以下 JS/jQuery 函数:

function setPdfDialogPriceCheckboxes(pElement)
{
    var tSuperCheckbox = jQuery("#superCheckbox").next();
    var tCheckbox1 = jQuery("#checkbox1");
    var tCheckbox2 = jQuery("#checkbox2");

    console.log(pElement.id);

    if(pElement.id == "superCheckbox")
    {
        tSuperCheckbox.click();
        var tCheckAll = tSuperCheckbox.is(':checked');
        if(tCheckbox1.is(':checked') != tCheckAll)
        {
            tCheckbox1.click();
        }
        if(tCheckbox2.is(':checked') != tCheckAll)
        {
            tCheckbox2.click();
        }
    }
    else
    {
        if(tCheckbox1.is(':checked') && tCheckbox2.is(':checked'))
        {
            tSuperCheckbox.prop('checked', true);
            tSuperCheckbox.prop('disabled', false);
        }
        else if(tCheckbox1.is(':checked') || tCheckbox2.is(':checked'))
        {
            tSuperCheckbox.prop('checked', true);
            tSuperCheckbox.prop('disabled', true);
        }
        else
        {
            tSuperCheckbox.prop('checked', false);
            tSuperCheckbox.prop('disabled', false);
        }
    }
}

另外,“toggle all”复选框有一个覆盖的 div,防止直接点击它,所以即使复选框被禁用,我也可以处理 onclick()-Events:

<div style="position: relative; ">
    <div id="superCheckbox" onclick="setPdfDialogPriceCheckboxes(this)" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 9999; "></div>
    <input type="checkbox" />
</div>

我在这里为此创建了一个小提琴:http://jsfiddle.net/9mhag8b6/

它适用于 Firefox 和 Chrome,但 Internet Explorer 似乎只是忽略了覆盖的 div,让我直接单击复选框。

我知道我可能会使用“不确定”来显示复选框上的半选中状态,但我宁愿这样。我目前的解决方法是改用图像,但在所有浏览器上看起来都一样,而复选框不同。

任何帮助将不胜感激。

【问题讨论】:

  • “另外,“toggle all”复选框有一个重叠的 div,防止直接点击它” 你为什么要这样做?只是阻止点击。
  • 为什么不使用&lt;label&gt; 而不是div 并利用复选框的默认标签单击行为?您正在做的事情过于复杂,并试图重新发明轮子
  • 由于仅选中一个其他复选框时,toggle-all 复选框可以(并且将会)被禁用,因此它将无法触发 onclick() 事件。因此,div 处理事件。标签也一样,因为复选框被禁用,它可能不会做任何事情。
  • 为什么不将处理程序绑定到复选框?方法没有意义
  • 我试过这个很好,但处理程序不会在禁用的复选框上触发。至少不在 Firefox 上,所以我没有费心测试其他浏览器。

标签: javascript jquery internet-explorer checkbox


【解决方案1】:

演示http://jsfiddle.net/9mhag8b6/6/

为避免无法单击禁用复选框的问题,我们只需将其设为半透明即可。

你说你使用了 Jquery,你部分地这样做了。在这里,它充分利用了 jQuery。

我使用了这个 HTML,带有类、标签并且没有 onlick 事件。不需要在每个复选框上都有 ID,您只需从所有复选框中明确识别“超级复选框”即可。 当它们的功能是同义词时,您确实应该避免为所有内容分配 id 并在您的 javascript 中单独引用它们,例如if (checkbox1.is(':checked') &amp;&amp; checkbox2.is(':checked')) - 它使您的代码更加凌乱,并且不必要地大于它需要的大小。

<label><input type="checkbox" class="setPdfDialogPriceCheckboxes" id="superCheckbox" /> Preisanzeige</label>
<div class="indent">
    <label><input class="setPdfDialogPriceCheckboxes" type="checkbox" /> Preis</label>

    <label><input class="setPdfDialogPriceCheckboxes" type="checkbox" /> Ø-Preis</label>

</div>

JQuery。通过使用.prop() 而不是.attr(),我们不必使用.trigger('change'),这会导致递归问题。您还将看到您可以链接事件,而不是编写像 tSuperCheckbox.prop('checked', true); tSuperCheckbox.prop('disabled', false); 这样的代码。变量赋值中的$ 表示它是一个jQuery 对象,它不是必需的,它是一个偏好。

$(function(){
    $('.setPdfDialogPriceCheckboxes').on('change', function(){
        // assign these to make it easier to read and not look up > once
        var $superCheckbox = $('#superCheckbox');
        var $checkboxes = $('.setPdfDialogPriceCheckboxes').not($superCheckbox);
        // create a reduced list of the ones that are checked
        var $checkboxes_checked = $checkboxes.map(function(){ 
            if ($(this).is(':checked')) return true;
        });

        // supercheckbox does something different to the rest
        if ($(this).is($superCheckbox)){
            var check;
            // ignore current status of this checkbox, check all if < all are checked
            if ($checkboxes_checked.length == $checkboxes.length){
                // they are all checked
                check = false;
            }else{
                check = true;
            }

            $checkboxes.add($superCheckbox).prop({checked: check});
            $superCheckbox.css({opacity: 1});
        }else{
            // are they all checked?
            if ($checkboxes_checked.length == $checkboxes.length){
                // all checked
                $superCheckbox.prop({checked: true}).css({opacity: 1});
            }else if (!$checkboxes_checked.length){
                // none checked
                $superCheckbox.prop({checked: false}).css({opacity: 1});
            }else{
                // some checked
                 $superCheckbox.prop({checked: true}).css({opacity: 0.5});

            }
        }
    });
});

【讨论】:

  • 我一般喜欢这个解决方案,但有两个小错误:当超级复选框被点击时不透明度不会重置,当只选中一些复选框时,点击超级复选框将取消选中它们它应该检查它们的所有地方。我可能会接受这个并从这里开始工作。
  • 我明白了,它取消选中,因为它在被点击之前被选中。您可以使用那些被检查的计数来告诉它“取消检查是否全部检查,否则检查”
  • 不透明度的东西,只要在$checkboxes.prop({checked: $(this).is(':checked')});后面加一行$superCheckbox.css({opacity: 1});
  • 此外,如果您想将其应用于页面上的几组不同的复选框,只需进行一些小的更改(而不是重复代码)。
【解决方案2】:

怎么样,而不是让“检查所有”变灰,你只是淡出一点,这样你仍然有一个可点击的复选框。 下面是一个简单的例子:

/* CSS */ 
#toggle-all{
  position: absolute; 
  top: 0; 
  left: 0; 
  width: 100%; 
  height: 100%; 
  z-index: 9999;
} 
.some-toggle { /* you can add more styles if necessary */
  filter: alpha(opacity=50); /*IE*/ 
  opacity: 0.5;
}

/* HTML */
<label id="toggle-all">
  <input type="checkbox" id="toggle-all-checkbox"> Toggle All 
</label>
<div> 
  <label><input type="checkbox" id="checkbox1"> Checkbox 1 </label>
  <label><input type="checkbox" id="checkbox2"> Checkbox 2 </label>
</div>

/* JS */
$("#toggle-all-checkbox, #checkbox1, #checkbox2").on('click', function(){
  if (this.id == 'toggle-all-checkbox') {
    $('#checkbox1, #checkbox2').prop('checked', this.checked);
  } else {
    var checked1 = $('#checkbox1').prop('checked'),
        checked2 = $('#checkbox2').prop('checked');
    if (checked1 && checked2) {
      $('#toggle-all-checkbox').removeClass('some-toggle').prop('checked', true);
    } else {
      if (!checked1 && !checked2)
        $('#toggle-all-checkbox').removeClass('some-toggle').prop('checked', false);
      else
        $('#toggle-all-checkbox').addClass('some-toggle').prop('checked', true);
    }
  }
});

我还没有测试过这段代码,但我希望它能给你另一个关于如何处理这个问题的想法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-01
    • 2013-03-26
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多