【问题标题】:How to detect radio button deselect event?如何检测单选按钮取消选择事件?
【发布时间】:2012-06-25 18:50:01
【问题描述】:

有没有一种简单的方法可以在单选按钮上附加“取消选择”事件?似乎只有在选择按钮时才会触发更改事件。

HTML

<input type="radio" id="one" name="a" />
<input type="radio" id="two" name="a" />

JavaScript

$('#one').change(function() {
    if(this.checked) {
        // do something when selected
    } else { // THIS WILL NEVER HAPPEN
        // do something when deselected
    }
});​

jsFiddle

【问题讨论】:

  • 用户无法取消选择收音机...您要做什么?
  • 用户可以取消选择一个单选但选择另一个单选按钮。
  • 听起来收音机控制错误……或者只是不了解您的期望。所有的答案基本上都是你写的东西的衍生品,因为没有事件可以利用
  • @未定义 - 希望在选择变化时,先得知道先前选择了该组中的哪个单选按钮并不合理。当只有两个收音机时有点微不足道,因为显然它总是不只是被点击,但是在一个组中拥有两个以上的收音机是很常见的......
  • 一个收音机可以被取消选择。收音机onchange 的奇怪之处在于它不是“onChange”——它是“onChangeToTrue”。除了装饰/表示之外,它们当前的实现与&lt;select /&gt; + &lt;option /&gt; 没有什么不同。从逻辑上讲,当另一个按钮被选中时,它会改变!!!为什么不调用onchange?相反,应该使用target.checked === false 调用组中每个无线电的每个处理程序,但刚刚选择的除外。

标签: javascript jquery


【解决方案1】:

这对你来说怎么样?

http://jsfiddle.net/WZND9/6/

 $('input').change(function() {
    if ($('#one').is(':checked')) {
        alert('checked');
    } else { 
        alert('not checked');
    }
 }); 

【讨论】:

  • 赞成清除反对票:不知道为什么它被反对,因为它显然有效。显然需要限制到有问题的输入组而不是所有 。我知道它在这里复制了其他答案,但它没有错。那些投反对票的人请评论为什么。
  • 这不会做任何事情,除了告诉你是否检查了 ID“一”。它不会告诉你之前检查了哪个按钮,只是你只有两个按钮,所以简单的推论告诉你。
  • 更改为选中的单选按钮触发。这并不能解决问题。
【解决方案2】:

您为什么不简单地创建一个自定义事件,比如deselect,并让它在被点击的单选组的所有成员上触发,除了被点击的元素本身?它更容易使用 jQuery 提供的事件处理 API。

HTML

<!-- First group of radio buttons -->
<label for="btn_red">Red:</label><input id="btn_red" type="radio" name="radio_btn" />
<label for="btn_blue">Blue:</label><input id="btn_blue"  type="radio" name="radio_btn" />
<label for="btn_yellow">Yellow:</label><input id="btn_yellow" type="radio" name="radio_btn" />
<label for="btn_pink">Pink:</label><input id="btn_pink"  type="radio" name="radio_btn" />
<hr />
<!-- Second group of radio buttons -->
<label for="btn_red_group2">Red 2:</label><input id="btn_red_group2" type="radio" name="radio_btn_group2" />
<label for="btn_blue_group2">Blue 2:</label><input id="btn_blue_group2"  type="radio" name="radio_btn_group2" />
<label for="btn_yellow_group2">Yellow 2:</label><input id="btn_yellow_group2" type="radio" name="radio_btn_group2" />
<label for="btn_pink_group2">Pink 2:</label><input id="btn_pink_group2"  type="radio" name="radio_btn_group2" />

jQuery

// Attaching click event handlers to all radio buttons...
$('input[type="radio"]').bind('click', function(){
    // Processing only those that match the name attribute of the currently clicked button...
    $('input[name="' + $(this).attr('name') + '"]').not($(this)).trigger('deselect'); // Every member of the current radio group except the clicked one...
});

$('input[type="radio"]').bind('deselect', function(){
    console.log($(this));
})

​取消选择事件只会在同一个单选组的成员(具有相同name 属性的元素)中触发。

jsFiddle solution

编辑:为了考虑附加标签标签的所有可能位置(包装单选元素或通过 id 选择器附加),最好使用onchange 事件触发处理程序。感谢Faust 指出这一点。

$('input[type="radio"]').on('change', function(){
    // ...
}

【讨论】:

  • +1。不错的解决方案,只是它没有指明之前选择了哪个收音机。
  • 我在这里关注的主要问题是为自定义取消选择事件提供解决方案,但当然 OP 可以根据他/她的喜好对其进行修改。
  • 最好是绑定更改事件而不是点击。
  • 如果收音机发生变化,因为它的(非环绕)标签被点击了,这将不起作用。
  • @Faust 您可以使用onchange 事件,无论标签是否换行都会触发。
【解决方案3】:

我认为这可能会发生,因为focus 事件在change 事件之前触发,因此您单击的下一个收音机将在前一个选中的收音机触发更改事件之前获得焦点。不过不要引用我的话……

你可以这样做:

var isChecked = function(id) { alert(id + ': ' + $('#' + id).is(':checked')) }
$('input[name="a"]').change(function(){ isChecked('one') })

演示: http://jsfiddle.net/elclanrs/cD5ww/

【讨论】:

    【解决方案4】:

    您可以相对轻松地创建自定义“取消选择”事件,但您已经发现标准更改事件仅在新选中的单选按钮上触发,而不是在之前选中的刚刚取消选中的单选按钮上触发。

    如果你想要这样说:

    $("#one").on("deselect", function() {
        alert("Radio button one was just deselected");
    });
    

    然后从您的文档就绪处理程序中运行类似以下函数(或将代码直接放入您的文档就绪处理程序中):

    function setupDeselectEvent() {
        var selected = {};
        $('input[type="radio"]').on('click', function() {
            if (this.name in selected && this != selected[this.name])
                $(selected[this.name]).trigger("deselect");
            selected[this.name] = this;
        }).filter(':checked').each(function() {
            selected[this.name] = this;
        });
    }
    

    工作演示: http://jsfiddle.net/s7f9s/2

    这样做是在页面上的所有收音机上放置一个点击处理程序(这不会阻止您将自己的点击事件处理程序添加到相同的收音机),这将检查同一组中是否有先前选择的收音机(即,具有相同的名称),如果是,则触发 that 收音机上的“取消选择”事件。然后它将刚刚单击的一个保存为当前的。如果单击已选中的单选或之前没有选中单选,则不会触发“取消选择”事件。最后的.filter().each() 位用于记录已经选择了哪些无线电。 (如果您需要在同一页面上处理多个具有相同名称的独立无线电组的表单,请相应地更新上述功能。)

    【讨论】:

    • +1 谢谢!!!这对我来说是完美的解决方案!我只需要将“on”函数调用更改为“bind”,因为我使用的是旧版本的 jQuery。
    • 最好是绑定更改事件而不是点击。
    • @KamilSzot - 不,不会。 Click 适用于所有浏览器,但在某些浏览器中,如果您通过键盘进行更改,则在您关闭控件之前不会发生更改事件。
    • 干得好,但不幸的是,这在 Mobile Safari 中不起作用。
    【解决方案5】:

    我认为您需要在输入级别添加更改功能,而不是在每个单选按钮上。

    试试这个:

    $("input[name='a']").change(function() {
      $("input[name='a']").each(function(){
        if(this.checked) {
            // do something when selected
        } else {
            // do something when deselected
        }
      });   
    });​
    

    【讨论】:

      【解决方案6】:

      我发现在不使用新框架来创建deselected 事件的情况下,最简单的方法是让更改任何 单选按钮在 上触发update 事件 其组中的所有单选按钮,然后在更新事件中定义您想要的行为。

      缺点是即使之前没有选择单选按钮,取消选择分支中的代码也会运行。如果您所做的只是简单地显示、隐藏或禁用 UI 元素,那应该没什么大不了的。

      使用您的示例:

      buttons = $('input[name="a"]');
      buttons.change(function() {
          buttons.trigger('update:groupA');
      
      }).bind('update:groupA', function(){
          if(this.checked) {
              //Do your checked things
          } else {
              //Do your unchecked things. Gets called whenever any other button is selected, so don't toggle or do heavy computation in here.
          }
      });​
      

      【讨论】:

        【解决方案7】:

        您可以自己触发“更改”事件。避免单选按钮无限触发彼此的“更改”事件有点棘手,但可以这样做:

        $('input[type="radio"]').each(function() {
            var name = $(this).attr('name');
            var that = this;
            $('input[name="'+name+'"][type="radio"]').not(that)
                .on('change', function(e, alreadyTriggered) {
                    if(!alreadyTriggered || alreadyTriggered.indexOf(this) == -1) {
                        if(!alreadyTriggered) {
                            alreadyTriggered = [that];
                        }
                        alreadyTriggered.push(this);
                        $(that).trigger('change', [alreadyTriggered]);
                    }
            });
        });
        

        这是上述代码的demo

        【讨论】:

          【解决方案8】:

          我为我的具体案例找到了可能有帮助的解决方法。当“取消选择”事件可以应用于所有未选中的单选按钮时,此方法有效。

          我想:

          1. 单选按钮被选中时添加一个类到元素,并且
          2. 当按钮“取消选择”删除该类

          我偶然发现了这个问题,因为我遇到了同样的问题:

          $('input:radio').on('change', function() {
              if( $(this).is(':checked') ) {
                  $(this).addClass('my-class-for-selected-buttons')
              } else { // THIS WILL NEVER HAPPEN
                  $(this).removeClass('my-class-for-selected-buttons')
              }
          });​
          

          但是,就我而言,解决方案要简单得多,因为我可以尝试使用 jQuery 非常简单地从所有单选按钮中删除该类,然后将该类添加到选定的单选按钮中:

          $('input:radio').on('change', function() {
              $('input:radio').removeClass('my-class-for-selected-buttons') // Here!
          
              if( $(this).is(':checked') ) {
                  $(this).addClass('my-class-for-selected-buttons')
              }
          });​
          

          通过这个简单的调整,我不需要找到触发“取消选择”事件的方法。

          因此,如果在您的情况下您可以将事件应用于所有未选择的单选按钮,而不仅仅是刚刚“取消选择”的单选按钮,您可以使用此措施!

          【讨论】:

            【解决方案9】:

            注意:我使用的是最新版本的 jquery:版本 3.4.1。但这也适用于旧版本。

            这里的主要挑战是为选中的单选按钮触发更改事件。下面的代码证实了这一点。

            $("input[name^='account']").change(function() {
                console.log($(this).prop('id') + " was checked");
            });
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
            
            <form action='#'>
                <input id='john' type='radio' name='account[]' value=''><label for='john'>John</label><br>
                <input id='jane' type='radio' name='account[]' value=''><label for='jane'>Jane</label><br>
                <input id='jeff' type='radio' name='account[]' value=''><label for='jeff'>Jeff</label><br>
                <input id='jude' type='radio' name='account[]' value=''><label for='jude'>Jude</label><br>
                <input type='text' name='amount' value=''><br>
                <input type='submit' value='submit'>
            </form>

            我的解决方案:通过 3 个简单的步骤处理更改事件处理程序中的所有内容:

            1. 处理当前选中的单选按钮的更改。
            2. 将自定义事件和处理程序附加到同一组中的所有其他单选按钮。
            3. 立即触发此自定义事件。

            这里不需要玩点击事件。简单!

            var radioBtns = $("input[name^='account']");
            radioBtns.change(function() {
                // 1. handle changes for the currently checked radio button.
                console.log($(this).prop('id') + " was checked");
                // 2. attach custom event and handler to all other radio buttons in the same group.
                radioBtns.not(':checked').off('deselect').on('deselect', function() {
                    $(this).each(function(i, e) {
                        console.log($(e).prop('id') + " was not checked");
                    });
                }).trigger('deselect'); // 3. immediately trigger this custom event.
                 
            });
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
            
            <form action='#'>
                <input id='john' type='radio' name='account[]' value=''><label for='john'>John</label><br>
                <input id='jane' type='radio' name='account[]' value=''><label for='jane'>Jane</label><br>
                <input id='jeff' type='radio' name='account[]' value=''><label for='jeff'>Jeff</label><br>
                <input id='jude' type='radio' name='account[]' value=''><label for='jude'>Jude</label><br>
                <input type='text' name='amount' value=''><br>
                <input type='submit' value='submit'>
            </form>

            【讨论】:

              【解决方案10】:

              我玩了一下 ids。 公平地说,这可能是一个低效的解决方案。

              <input type="radio" id="radio-1" name="a" value="initial 1"/>
              <input type="radio" id="radio-2" name="a" value="initial 2"/>
              
              let id;
              $('input[id*="radio-"]').on('click', (function() {
                    if (this.id != id && this.checked) {
                      id = this.id;
                      this.checked = true;
                      console.log('selected');
                    } else if (this.id == id && this.checked) {
                      id = undefined;
                      this.checked = false;
                      console.log('deselected');
                    }
              }));
              
              

              JSFiddle

              【讨论】:

                猜你喜欢
                • 2019-09-11
                • 2011-03-21
                • 2012-12-27
                • 2012-02-21
                • 2011-07-17
                • 1970-01-01
                • 2015-07-01
                • 2012-05-19
                相关资源
                最近更新 更多