【问题标题】:How to check/uncheck radio button on click?如何在点击时选中/取消选中单选按钮?
【发布时间】:2011-06-24 20:09:24
【问题描述】:

我希望能够通过单击取消选中单选按钮。

所以,如果单选按钮未选中,我想选中它,如果选中,我想取消选中它。

这不起作用:

$('input[type=radio]:checked').click(function(){
    $(this).attr('checked', false);
});

我现在无法选中单选按钮。

【问题讨论】:

  • 您的意思是选择/取消选择而不是选中/取消选中?

标签: javascript jquery


【解决方案1】:

不是替换一个复选框,它是允许一个单选组回到未选中状态。这很棘手,因为收音机选择不像正常事件。

浏览器处理正常事件链之外的单选按钮。因此,带有 event.preventDefault() 或 event.stopPropagation() 的单选按钮上的单击处理程序不会阻止检查单选按钮。 .removeAttr('checked') 必须在 setTimeout 中完成以允许事件完成,并且浏览器检查单选按钮(再次),然后 setTimeout 将触发。

这也正确处理了用户开始 mousedown 但在 mouseup 之前离开单选按钮的情况。

//$ = jQuery;
$(':radio').mousedown(function(e){
  var $self = $(this);
  if( $self.is(':checked') ){
    var uncheck = function(){
      setTimeout(function(){$self.removeAttr('checked');},0);
    };
    var unbind = function(){
      $self.unbind('mouseup',up);
    };
    var up = function(){
      uncheck();
      unbind();
    };
    $self.bind('mouseup',up);
    $self.one('mouseout', unbind);
  }
});

希望对你有帮助

【讨论】:

  • 这快把我逼疯了!非常感谢!
  • 你,先生,是个天才。
  • 它确实可以在 Firefox 18 上运行,伙计! (同意天才的说法!)
  • 只是指出今天这仍然是一个很好的解决方案。另外,$self.bind('mouseup', up) 可以替换为 $self.mouseup(up)$self.unbind('mouseup',up)$self.off('mouseup') 以摆脱不推荐使用的方法。最后,我使用标签方法实现了这一点,以防有人想知道在这种情况下这是否也有帮助:)
  • 未来的读者,在盲目复制此解决方案之前,请阅读此答案 (stackoverflow.com/a/27476660/8430155)。
【解决方案2】:

试试这个:

$('input[type=radio]').click(function(){
    if (this.previous) {
        this.checked = false;
    }
    this.previous = this.checked;
});

【讨论】:

  • 由于@HexInteractive 回答中所述的原因,您的解决方案效果不佳。我在 Webkit 中,它的行为非常不稳定......是的,它允许取消选择单选按钮,但大多数时候您必须单击单选按钮两次才能选择它们。 jsfiddle.net/sparky672/KdZG7
  • 在 chrome 中,现在它可以工作了。有没有其他人可以证实或反驳这一点。
  • 在 Chrome 版本 68(截至 2018 年 8 月)中运行顺利。
  • 不能远程工作。使用单选按钮的唯一原因是允许互斥选择。因此,添加两个或更多单选按钮并观察此失败,因为当另一个按钮更改此按钮的选中状态但上一个按钮没有反映这一点时。
  • 在 Firefox v68 中也可以使用
【解决方案3】:

接受的答案不适用于移动设备。它依赖于 setTimeout 和与鼠标事件相关的绑定,这些事件不会在平板电脑/移动设备上触发。
我的解决方案是使用“click”事件处理程序和自定义类状态手动跟踪所选状态。

  1. 处理单选输入元素上的点击事件
  2. 检查被点击的元素上是否存在“selected”类
  3. 如果是,(意味着它之前已经被点击过),删除类并取消选中元素,返回
  4. 如果没有,请从所有同名元素中删除该类,然后仅将其添加到单击的元素中。

无需阻止默认行为。这是Jquery中的代码:

$("input:radio").on("click",function (e) {
    var inp=$(this); //cache the selector
    if (inp.is(".theone")) { //see if it has the selected class
        inp.prop("checked",false).removeClass("theone");
        return;
    }
    $("input:radio[name='"+inp.prop("name")+"'].theone").removeClass("theone");
    inp.addClass("theone");
});

http://jsfiddle.net/bhzako65/

【讨论】:

  • 非常有趣,我正在努力理解为什么添加类会删除选定的状态:o)
  • 自定义类与按钮状态无关。您可以根据需要设置样式,但选中状态与类无关。
【解决方案4】:

我一定是想念它,但经过这么多年 AFAIK,上述解决方案似乎都不起作用,或者我只是愚蠢。

除非同一组中有多个单选按钮,否则绝对没有理由使用单选按钮。如果它是一个单独的单选按钮,那么只需使用一个复选框。使用单选按钮的原因是选择互斥选项之一。这意味着任何只查看单个按钮的解决方案都会失败,因为单击一个按钮会影响其他按钮的状态

换句话说,由于我们使用的是单选框,因此解决方案需要适用于

<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>

这是一个查看所有按钮的按钮。

这似乎有效

document.querySelectorAll(
    'input[type=radio][name=foo]').forEach((elem) => {
  elem.addEventListener('click', allowUncheck);
  // only needed if elem can be pre-checked
  elem.previous = elem.checked;
});

function allowUncheck(e) {
  if (this.previous) {
    this.checked = false;
  }
  // need to update previous on all elements of this group
  // (either that or store the id of the checked element)
  document.querySelectorAll(
      `input[type=radio][name=${this.name}]`).forEach((elem) => {
    elem.previous = elem.checked;
  });
}
body { font-size: xx-large; }
label, input {
  /* added because a second click to unselect radio often
     appears as a double click to select text */
  -webkit-user-select: none;
  user-select: none;
}
<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>

如果elem.previous 担心你可以使用elem.dataset.previous,请注意

另一种解决方案是存储选中的按钮

function makeRadioboxGroupUnCheckable(groupSelector) {

  let currentId;

  document.querySelectorAll(groupSelector).forEach((elem) => {
    elem.addEventListener('click', allowUncheck);
    // only needed if can be pre-checked
    if (elem.checked) {
      currentId = elem.id;
    }
  });

  function allowUncheck(e) {
    if (this.id === currentId) {
      this.checked = false;
      currentId = undefined;
    } else {
      currentId = this.id;
    }
  }
}

makeRadioboxGroupUnCheckable('input[type=radio][name=foo]');
body { font-size: xx-large; }
label, input {
  /* added because a second click to unselect radio often
     appears as a double click to select text */
  -webkit-user-select: none;
  user-select: none;
}
<input type="radio" name="foo" id="foo1"><label for="foo1">foo1</label>
<input type="radio" name="foo" id="foo2"><label for="foo2">foo2</label>
<input type="radio" name="foo" id="foo3"><label for="foo3">foo3</label>

【讨论】:

    【解决方案5】:

    这才是真正的解决方案...

    var check;
    
    $('input[type="radio"]').hover(function() {
        check = $(this).is(':checked');
    });
    
    $('input[type="radio"]').click(function() {
        check = !check;
        $(this).attr("checked", check);
    });
    

    试试吧,它对我有用!

    【讨论】:

    • 在我希望通过单击父级 div 来选择/取消选择单选按钮的情况下,我不得不稍微调整一下。但我所要做的就是将第一个 $('input[type="radio"]') 更改为 $('div.parentClass') 并将 check = $(this).is(':checked'); 更改为 check = $(this).find('input[type="radio"]').is(':checked');
    【解决方案6】:

    如果只有一个单选按钮,您需要使用复选框。

    将一个单选按钮与组一起使用是没有意义的。

    您可能正在寻找复选框控件。

    【讨论】:

    • 组中有更多单选按钮。不选中它们是有效的,所以我想允许用户取消选中它们。
    【解决方案7】:

    我知道这个问题很老了,但我只是遇到了这个问题并决定自己尝试一下,不想使用像 ctrl 这样的修改按钮。

    见小提琴http://jsfiddle.net/ArktekniK/yhbw469f/ 通过单击单选按钮本身来切换单选按钮

    $('input[type=radio]').on('mousedown', function(e){
      var wasChecked = $(this).prop('checked');
      this.turnOff = wasChecked;
      $(this).prop('checked', !wasChecked);
    });
    
    $('input[type=radio]').on('click', function(e){
      $(this).prop('checked', !this.turnOff);
      this['turning-off'] = !this.turnOff;
    });
    

    通过单击标签或单选按钮本身来切换单选按钮

    $('label:has(input[type=radio])').on('mousedown', function(e){
      var radio = $(this).find('input[type=radio]');
      var wasChecked = radio.prop('checked');
      radio[0].turnOff = wasChecked;
      radio.prop('checked', !wasChecked);
    });
    
    $('label:has(input[type=radio])').on('click', function(e){
      var radio = $(this).find('input[type=radio]');
      radio.prop('checked', !radio[0].turnOff);
      radio[0]['turning-off'] = !radio[0].turnOff;
    });
    

    【讨论】:

    • 这个问题很老,但有新的用途。谢谢。
    • 哦。由于某种原因,这在您使用标签时不起作用:jsfiddle.net/1bfsnzn9/5
    • @Rafael 您的链接对我来说似乎工作正常。我可以切换收音机。我在 Windows 10 上使用 Chrome 53.0.2785.89。我假设您的意思是单击标签本身而不是单选按钮不会触发切换行为?
    • @Rafael 试试这个:jsfiddle.net/ArktekniK/1bfsnzn9/6 我会把它添加到答案中
    【解决方案8】:

    那些正在寻求纯 JavaScript 解决方案的人我修改了 Jase in ATL 的代码。

    我编写此代码是为了建议使用 CSS 样式的 3 位置开关,该开关提供 4 种切换状态(开、关、中性和未激活)。

    function toggle_radio(ev) {
    	var radio = ev.target;
    	var cut_pos = radio.className.indexOf(' switcher-active');
    
    	// the switch itself
    	if (cut_pos !== -1) { // if the button checked it is '.switcher-active'
    		radio.checked = false; // toggle its state
    		radio.className = radio.className.slice(0, cut_pos); // remove '.switcher-active'
    		return true; // work is done. Break the function
    	}
    
    	// the button was inactive before it was clicked. Then it should became '.switcher-active'
    	radio.className = radio.className + ' switcher-active';
    
    	// we need to remove '.switcher-active' if either the left or right radio button was clicked. This part is uggly but I don't bother, because I'm late for barber
    	var radios = document.getElementsByName(radio.name); // get all these radio siblings as a collection of elements
    	for (var i=0; i < radios.length; i++) { // iterate through the collection
    		if (radios[i].className.indexOf('switcher-radio-neutral') !== -1)
    			continue; // skip the '.switcher-neutral' radio input
    
    		radios[i].onclick = function(ev2) {
    			sib_radios = document.getElementsByName(ev2.target.name); // get a group of radio inputs linked by the name
    
    			// get the '.switcher-neutral'
    			for (var k=0, cut_pos = -1, sib; k < sib_radios.length; k++) {
    				sib = sib_radios[k];
    				cut_pos = sib.className.indexOf(' switcher-active');
    				if (cut_pos !== -1)
    					sib.className = sib.className.slice(0, cut_pos);
    			}
    		}
    	}
    }
    
    var switchers = document.getElementsByClassName('switcher-radio-neutral');
    
    for (var i=0; i < switchers.length; i++) { // bind onclick handlers
    	switchers[i].onclick = toggle_radio;
    }
    .switcher {
    	position: relative;
    	display: inline-block;
    	margin: 1px 10px;
    	height: 20px;
    	width: 58px;
    	z-index: 1;
    }
    
    .switcher-off {
    	left: 1px;
    	width: 33%;
    	height: 100%;
    }
    
    .switcher-neutral {
    	left: 33%;
    	width: 33%;
    	height: 100%;
    }
    
    .switcher-on{
    	right: 1px;
    	width: 33%;
    	height: 100%;
    }
    
    .switcher-label {
    	position: absolute;
    	text-indent: -9999px;
    	z-index: 2;
    }
    
    .switcher input {
    	visibility: hidden;
    	position: absolute;
    }
    
    .switcher-slider {
    	height: 100%;
    	width: 100%;
    	border-radius: 10px;
    	box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1) inset, 0 0 4px rgba(0, 0, 0, 0.5) inset, 0 2px 2px 1px rgba(0, 0, 0, 0.3) inset;
    	transition: background-color 0.2s linear 0s;
    }
    
    .switcher-slider:after {
    	transition: left 0.2s linear 0s, right 0.2s linear 0s;
    	background: linear-gradient(#D0D0D0, #FDFDFD) repeat scroll 0 0 rgba(0, 0, 0, 0);
    	content: "";
    	position: absolute;
    	top: 1px;
    	border-radius: 50%;
    	height: calc(100% - 2px);
    	width: calc(100%/3 - 1px);
    	box-shadow: 0 0 1px 1px #f4f4f4 inset, 0 0 3px 1px rgba(0, 0, 0, 0.6);
    	left: 33%;
    }
    
    .switcher-radio-on:checked  ~ .switcher-slider {
    	background-color: #81EA89;
    }
    
    .switcher-radio-neutral:checked  ~ .switcher-slider {
    	background: #ddd;
    }
    
    .switcher-radio-off:checked  ~ .switcher-slider {
    	background-color: #ED8282;
    }
    
    .switcher-radio-on:checked  ~ .switcher-slider:after {
    	left: calc(2*(100%/3));
    }
    
    .switcher-radio-neutral:checked  ~ .switcher-slider:after {
    	left: calc(1px + 100%/3);
    }
    
    .switcher-radio-off:checked  ~ .switcher-slider:after {
    	left: 1px;
    }
    <form action="">
    		<input type="radio" name="radio_input" value="1">
    		<input type="radio" name="radio_input" class="switcher-radio-neutral" value="2">
    		<input type="radio" name="radio_input" value="3">
    </form>
    <br><br>
    <div class="switcher">
    	<label  class='switcher-label switcher-off' for='off'>off</label>
    	<input id='off' class='switcher-radio-off' type='radio' name='value' value='off'>
    	
    	<label class='switcher-label switcher-neutral' for='neutral'>neutral</label>
    	<input id='neutral' class='switcher-radio-neutral' type='radio' name='value' value='neutral' data-neutral="">
    	
    	<label class='switcher-label switcher-on' for='on'>on</label>
    	<input id='on' class='switcher-radio-on' type='radio' name='value' value='on'>
    	<div class='switcher-slider'></div>
    </div>

    【讨论】:

      【解决方案9】:

      在寻找解决方案时在某个地方发现了这个,喜欢它的简单性......

      var checkedradio;
      function docheck(thisradio) {
          if (checkedradio == thisradio) {
              thisradio.checked = false;
              checkedradio = null;
          }
          else {checkedradio = thisradio;}
      }
      

      用于:

      <input type='radio' onclick='docheck(this);'>
      

      当您在一个表单中有多个无线电组时,似乎确实需要双击才能取消选择,但这可以通过为每个组设置一个函数来解决...

      【讨论】:

        【解决方案10】:

        最好有一个默认选择的“选择无”显式选项,而不是让用户取消选中任何单选按钮。

        (在此 nngroup (neilsen) 文章中列出第 9 项:

        http://www.nngroup.com/articles/checkboxes-vs-radio-buttons/

        【讨论】:

        • 这是有争议的,有许多不同的用例,所以尼尔森的概括就是......即概括。
        【解决方案11】:

        正如 HexInteractive 所提到的,单选按钮是在正常事件链之外处理的。 所以,下面的例子是通过类名而不是属性来判断按钮状态的。

        var $self;
        
        $('input[type=radio]').on('click', function() {
          $self = $(this);
          if ( $self.hasClass('is-checked') ) {
            $self.prop('checked', false).removeClass('is-checked');
          } else {
            $self.addClass('is-checked');
          }
        });
        

        【讨论】:

          【解决方案12】:

          是的,您也可以在单击选中时执行此操作,再次单击取消选中。 逻辑如下:

          $('input[name=check1]').prop('checked',!$('input[name=check1]').prop('checked'));
          

          【讨论】:

            【解决方案13】:
             var checked = {};
                $('.desectable-radio').each(function (index) {
                    checked[index] = this.checked;
                    $(this).click(function () {
                        if (checked[index])
                            this.checked = false;
                        for (var i in checked) {
                            checked[i] = false;
                        }
                        checked[index] = this.checked;
                    });
                });
            

            【讨论】:

              【解决方案14】:

              这是一个超轻量级脚本,您可以通过控制台窗口将其添加到页面中,该脚本允许您在用鼠标单击时按住 Ctrl 来取消选择单选按钮。

              document.addEventListener('click', function(e){
                 if (e.ctrlKey == true && 
                     e.target.tagName == 'INPUT' && 
                     e.target.type == "radio" && 
                     e.target.checked == true) {
                     e.target.checked = false;
                 }
              });
              

              由于它不依赖 jQuery,您可以轻松地将其添加到任何页面以暂时允许取消选择。
              如需更多信息,您可以阅读我刚刚在How To Deselect A Radio Button 上写的一篇文章。

              【讨论】:

                【解决方案15】:

                需要解决此问题,我决定用“取消”图标按钮替换当前活动的单选按钮,例如 http://fontawesome.io/icon/ban/

                单击此图标取消选中活动单选按钮,然后重新出现,有效地重置单选按钮组。取消图标也从 DOM 中移除。

                或者,用户可以单击组中的另一个单选按钮,除了取消按钮外,其他单选按钮的行为都正常,然后“移动”以替换新的活动单选按钮。

                这将取消图标保持在一个直观的位置(即用户上次单击的位置),并且比假设用户知道重新单击当前活动的单选按钮来停用组更安全。

                最糟糕的情况是,如果单选按钮列表很长,用户只需单击其中任何一个按钮两次即可清除组。

                【讨论】:

                • 如果您有不同的问题,请单独提出。如果上下文对此有帮助,您可能可以链接这个问题。但这并不试图回答 OP 问题。
                • @ArunVinoth Matt 正在描述他们使用的解决方法,而不是提出新问题。如果他们包含演示所描述行为的代码会更好,但它是“这样做而不是获得你想要的功能”类型的答案。
                • 是的 - 我是根据@Eterm 的建议构建的,从 UI 的角度来看,“取消”按钮比第二次单击选定的单选按钮更直观,并补充说这是最好的地方将代替活动的单选按钮。我会写一些代码并添加进去。
                【解决方案16】:

                根据 Stephen 的回答 - 这涉及多个单选按钮组,而且您大多不需要双击单选按钮。这并不完美,因为如果您在组之间切换检查 id 将需要额外点击,但工作正常。

                $("input[type='radio']").on('click', function (e) {
                            if (this.previous && this.value == previousvalue && this.id == previousid) {
                                this.checked = false;
                            }
                            this.previous = this.checked;
                            previousvalue = this.value;
                            previousid = this.id;
                
                        });
                

                【讨论】:

                  【解决方案17】:

                  我认为这是最短的方法。我在 Chrome 和 MS Edge 上对其进行了测试。

                  $(document).on('click', 'input:radio', function () {
                      var check = $(this).attr('checked')
                      if (check) $(this).removeAttr('checked').prop('checked',false)
                      else $(this).attr('checked', true).prop('checked',true)
                  })
                  

                  这段代码也适用于 AJAX 加载的内容

                  【讨论】:

                    【解决方案18】:

                    使用 prop 函数并以 checked 为键:

                    $("input:radio").prop("checked",false);
                    

                    【讨论】:

                      【解决方案19】:

                      这应该适用于桌面和移动设备。我在 Chrome 和 Firefox 上进行了测试。 基于评分最高的答案,但使用更新的 JQuery 和使用 $.one 的更简单的实现。

                      $(':radio').on("mousedown touchstart", function (e) {
                          var mobile = true;
                          if(e.type.toLowerCase() === 'mousedown'){
                              mobile = false;
                          }
                          
                          var $self = $(this);
                          if($self.prop('checked')){
                              var uncheck = function(){
                                  setTimeout(function(){
                                      $self.prop('checked',false);
                                  },10);
                              };
                              if(!mobile){
                                  $self.one('mouseup', uncheck);
                              } else {
                                  $self.one('touchstart', uncheck);
                              }
                          }
                      });
                      

                      【讨论】:

                        【解决方案20】:
                        <script type="text/javascript">
                            $( document ).ready(function() {
                                $('input[type=radio]').click(function(){
                                    if (this.previous) {
                                        this.checked = false;
                                        document.getElementById("nc").style.display = "block";
                                        this.previous=false;
                                    }
                                    else {
                                        this.previous = this.checked;
                                        document.getElementById("nc").style.display = "none";
                                    }
                                });
                            });
                        </script>
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2019-01-31
                          • 1970-01-01
                          • 1970-01-01
                          • 2014-05-11
                          • 2012-06-08
                          • 1970-01-01
                          • 2014-08-07
                          • 2016-10-18
                          相关资源
                          最近更新 更多