如何检测单选按钮取消选择事件?

时间:2012-06-23 23:03:21

标签: javascript jquery

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

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

10 个答案:

答案 0 :(得分:27)

为什么不简单地创建一个自定义事件,例如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 :(得分:20)

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

如果您希望能够说出类似的内容:

$("#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

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

答案 2 :(得分:4)

我发现在没有设置新框架来创建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.
    }
});​

答案 3 :(得分:1)

这是怎么回事?

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

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

答案 4 :(得分:0)

我认为这可能会发生,因为focus事件在change事件之前触发,因此您点击的下一个电台将在上一个检查的无线电触发更改事件之前被聚焦。不要引用我的话......

你可以这样做:

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

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

答案 5 :(得分:0)

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

试试这个:

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

答案 6 :(得分:0)

您可以触发&#39;更改&#39;事件你自己。避免无线电按钮无限触发“改变”有点棘手。相互之间的事件,但可以这样做:

$('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 正在运作。

答案 7 :(得分:0)

我找到了可能有帮助的我的具体案例的解决方法。当&#34;取消选择&#34;事件可以应用于所有未被选中的单选按钮。

我想:

  1. 在选择单选按钮时向该元素添加,并
  2. 当按钮&#34;取消选择&#34; 时,
  3. 删除该类
  4. 我碰巧找到了这个问题,因为我遇到了同样的问题:

    $('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')
        }
    });​
    

    通过这个简单的调整,我不需要找到一种方法来触发&#34;取消选择&#34;事件

    因此,如果在您的情况下,您可以将该事件应用于所有未被选中的单选按钮,而不仅仅是那个刚刚被选中的按钮&#34 ;取消选择&#34;,你可以使用这个措施!

答案 8 :(得分:0)

注意:我使用的是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>

答案 9 :(得分:0)

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

<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