【问题标题】:Prevent checkbox from ticking/checking COMPLETELY完全防止复选框打勾/选中
【发布时间】:2012-05-23 12:37:58
【问题描述】:

我被要求禁用复选框的“勾选”。我没有被要求禁用复选框,而是简单地禁用“滴答”。

换句话说,用户会认为复选框是可勾选的,但事实并非如此。相反,单击复选框将导致出现模式对话框,为用户提供更多选项来打开或关闭复选框所代表的功能。如果在对话框中选择的选项导致该功能被打开,那么复选框将被勾选。

现在,真正的问题是,对于 一秒,您仍然可以看到复选框被选中。

我试过这样的方法:

<input type='checkbox' onclick='return false' onkeydown='return false' />

$('input[type="checkbox"]').click(function(event) {
    event.preventDefault();
    alert('Break');
});

如果您运行此程序,则会出现警报,显示刻度是可见的(警报只是在那里证明它仍然会被打勾,在生产中,警报不存在)。在一些机器速度较慢的用户和/或渲染器/javascript 速度较慢的浏览器中,用户可以看到非常微弱的闪烁(闪烁有时会持续半秒,这很明显)。

我团队中的一名测试人员将此标记为缺陷,我应该修复它。我不确定还有什么方法可以防止复选框中的勾闪烁!

【问题讨论】:

    标签: javascript checkbox


    【解决方案1】:

    试试

    event.stopPropagation();
    

    http://jsfiddle.net/DrKfE/3/

    【讨论】:

    • 不幸的是,这似乎并没有完全阻止复选框打勾。使用我上面的示例代码,您将看到当警报出现时,该复选框仍处于选中状态。至少,它在 Chrome 中。
    • 其实,ISWYDT,“return false”是在alert之前。不幸的是,我不能使用这种方法,因为我需要在勾选复选框后弹出一个模式对话框。我认为 stopPropagation() 正在阻止执行此操作的处理程序(单击复选框时)触发。
    • 实际上,阻止模态对话框处理程序触发的是“return false”,而不是 stopPropagation()。我尝试了您的代码的这个版本,并且复选框仍然打勾:jsfiddle.net/737hX/1
    【解决方案2】:

    我想出的最佳解决方案:

    $('input[type="checkbox"]').click(function(event) {
        var $checkbox = $(this);
    
        // Ensures this code runs AFTER the browser handles click however it wants.
        setTimeout(function() {
          $checkbox.removeAttr('checked');
        }, 0);
    
        event.preventDefault();
        event.stopPropagation();
    });
    

    【讨论】:

    • 这不是第一次使用 setTimeout() 函数来实现此功能!
    • 为我工作,我必须处理 onclick 事件并发送一个 ajax 请求,因此只有在成功的 ajax 回调时更改 checked 状态。
    【解决方案3】:

    在我看来,这很简单:

    $(this).prop('checked', !$(this).prop('checked'));
    

    适用于选中和未选中的框

    【讨论】:

      【解决方案4】:

      这个效果恐怕无法抑制。一旦你点击复选框,状态(和渲染)就会改变。然后将调用事件处理程序。如果您执行event.preventDefault(),复选框将在所有处理程序执行后重置。如果您的处理程序执行时间较长(可以使用模态 alert() 轻松测试)和/或渲染引擎在重置之前重新绘制,则该框将闪烁。

      $('input[type="checkbox"]').click(function(event) {
          this.checked = false; // reset first
          event.preventDefault();
          // event.stopPropagation() like in Zoltan's answer would also spare some
          // handler execution time, but is no more needed here
      
          // then do the heavy processing:
          alert('Break');
      });
      

      此解决方案将闪烁减少到最低限度,但不能真正阻碍它。有关如何模拟复选框,请参阅 Thr4wn 和 RobG 的答案。我更喜欢以下内容:

      <button id="settings" title="open extended settings">
          <img src="default_checkbox.png" />
      </button>
      
      document.getElementById("settings").addEventListener("click", function(e) {
          var img = this.getElementsByTagName("img")[0]);
          openExtendedSettingsDialog(function callbackTick() {
              img.src = "checked_checkbox.png";
          }, function callbackUntick() {
              img.src = "unchecked_checkbox.png";
          });
      }, false);
      

      【讨论】:

        【解决方案5】:

        不是更简单吗? :

        <input type="checkbox" onchange="this.checked = !this.checked">
        

        【讨论】:

        • 即使这没有回答问题,它也是一个紧凑的解决方案,用于防止单击时复选框更改。谢谢。
        • 做得很好。谢谢!
        【解决方案6】:

        TL:DR;

        HTML api 在 JavaScript 之前执行。因此,您必须使用 JavaScript 来撤消 HTML 的更改。

        event.target.checked = false
        

        有什么问题?

        严格来说:我们不能“阻止”复选框被选中。为什么不?因为“被打勾”正好意味着 DOM 的,HTML &lt;input&gt; 元素的 checked 属性值为 truefalse,由 HTML api

        立即分配>
        console.log(event.target.checked) // will be opposite of the previous value
        

        所以值得一提的是这个 HTML api 在脚本之前被调用。这很直观并且应该有意义,因为所有 JavaScript 文件本身都是 &lt;script&gt; 元素的属性 src 的分配,以及 DOM 树中的祖先关系,在你的 &lt;input&gt;&lt;script&gt; 元素之间运行 JavaScript,非常重要需要考虑。

        如何获得我们的解决方案

        在我们有机会拦截控制流(通过 JS 文件,如 jQuery)之前,尚未绘制 HTML 分配的值,因此我们只需将 checked 属性重新分配给我们想要的布尔值:@987654332 @(在你的情况下)。

        因此,总而言之,我们实际上可以“阻止”复选框被选中,只需确保在下一次渲染时checked 属性为false,因此不会看到任何更改。

        【讨论】:

        • 表单提交是 HTML API 的一部分吗?如果是,为什么我们可以通过 JS 来阻止它?
        【解决方案7】:

        最后使用return false很重要。

        类似这样的:

        $("#checkbox").click((e) => {
          e.stopPropagation();
          return false;
        });
        

        【讨论】:

        • 被低估的答案,对我来说效果很好。谢谢你
        【解决方案8】:

        使用 CSS,您可以更改复选框的图像。请参阅http://ryanfait.com/resources/custom-checkboxes-and-radio-buttons/CSS Styling Checkboxes

        我会禁用该复选框,但将其替换为工作复选框的图像。这样复选框看起来不会被禁用,但不会被点击。

        【讨论】:

          【解决方案9】:

          用另一个以某种方式阻止指针事件(可能通过 CSS)的元素包裹复选框。然后,直接处理 wrapper 的点击事件而不是复选框。这可以通过多种方式完成,但这里有一个相对简单的示例实现:

          $('input[type="checkbox"').parent('.disabled').click( function() {
              
              // Add in whatever functionality you need here
              
              alert('Break');
              
          });
          /* Insert an invisible element that covers the checkbox */
          .disabled {
              position: relative;
          }
          .disabled::after {
              content: "";
              position: absolute;
              top: 0px;
              left: 0px;
              right: 0px;
              bottom: 0px;
          }
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
          
          <!-- Only wrapped checkboxes are "disabled" -->
          <input type="checkbox" />
          <span class="disabled"><input type="checkbox" /></span>
          <input type="checkbox" />
          <span class="disabled"><input type="checkbox" /></span>
          <span class="disabled"><input type="checkbox" /></span>
          <input type="checkbox" />

          注意:如果您愿意,也可以通过编程方式添加包装器元素。

          【讨论】:

            【解决方案10】:

            为什么不简单地在 CSS 中添加一个设置 pointer-events: none; 的类?

            类似:

            <style>
                input.lockedCbx { pointer-events: none; }
            </style>
            ...
            <input type="checkbox" class="lockedCbx" tabindex=-1 />
            ...
            

            您需要tabindex=-1 来防止用户在复选框中切换并按空格键进行切换。

            现在理论上你可以避开这个类并使用tabindex=-1 来控制禁用,如下所示:

            <script>
                input[type="checkbox"][tabindex="-1"] { pointer-events: none; }
            </script>
            

            【讨论】:

              【解决方案11】:

              在我看来,您使用了错误的界面元素,更合适的应该是默认禁用的按钮,但在该选项可用时启用。显示的图像可以是任何你想要的。

              <button disabled onclick="doSomething();">Some option</button>
              

              当用户选择了该功能后,启用该按钮。按钮上的图片可以通过 CSS 来修改,取决于它是否启用,或者通过启用/禁用功能。

              例如

              <script type="text/javascript">
              
              function setOption(el) {
                var idMap = {option1:'b0', option2: 'b1'};
                document.getElementById(idMap[el.value]).disabled = !el.checked; 
              }
              
              </script>
              
              <div><p>Select options</p>
                <input type="checkbox" onclick="setOption(this);" value="option1"> Option 1
                <br>
                <input type="checkbox" onclick="setOption(this);" value="option2"> Option 2
                <br>
              </div>
              <div>
                <button id="b0" onclick="alert('Select…');" disabled>Option 1 settings</button>
                <button id="b1" onclick="alert('Select…');" disabled>Option 2 settings</button>
              </div>
              

              【讨论】:

              • 好主意。然而,我不会说打开对话框的按钮应该被禁用 - 它只是应该替换复选框。状态应该由按钮的标签来表示。
              • 使用 disabled 最接近 OP 想要的。它还避免了隐藏和显示不同大小的元素(复选框与按钮),这会导致布局复杂化。我几乎总是赞成使用最简单的解决方案来完成这项工作。
              【解决方案12】:

              只需将值还原

              $('input[type="checkbox"]').on('change', function(e) {
                  if (new Date().getDate() === 13) {
                      $(this).prop('checked', !$(this).prop('checked'));
                      e.preventDefault();
                      return false;
                   }
                   // some code here
              });
              

              【讨论】:

                【解决方案13】:

                Event.preventDefault 方法应该适用于 changekeydownmousedown 事件,但不适用于我的测试。

                我在 Mozilla Firefox 53.0 扩展中解决此问题的方法是切换一个 HTML 类,该类启用/禁用 CSS 声明 pointer-events: none 应用于复选框。这解决了基于光标的情况,而不是基于键的情况。见https://www.w3.org/TR/SVG2/interact.html#PointerEventsProp

                我通过添加/删除 HTML tabindex="-1" 属性来解决基于键的情况。见https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex

                请注意,禁用 pointer-events 将禁用您在悬停时触发 CSS 光标的能力(例如,cursor: not-allowed)。我的复选框已经包含在 span 元素中,因此我向该 span 元素添加了一个 HTML 类,然后我将我的 CSS cursor 声明重新定位到该元素上。

                另请注意,添加tabindex="-1" 属性不会从复选框中移除焦点,因此需要使用HTMLElement.blur() 方法或通过聚焦另一个元素来显式散焦它以防止关键- 如果复选框在添加属性时是活动元素,则基于输入。复选框是否为焦点元素可以用my_checkbox.isEqualNode(document.activeElement)测试。

                【讨论】:

                  【解决方案14】:

                  将此添加到js文件中的点击事件

                  event.stopPropagation();                  
                  

                  【讨论】:

                    猜你喜欢
                    • 2010-12-15
                    • 2023-02-09
                    • 1970-01-01
                    • 2013-09-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-02-26
                    • 1970-01-01
                    • 2015-06-26
                    相关资源
                    最近更新 更多