当您单击它时,IE不会在不确定复选框上触发“更改”事件

时间:2015-11-04 13:26:35

标签: jquery html internet-explorer checkbox

我有一个三态复选框,我需要在用户点击它时触发更改事件,但当复选框的状态为“INDETERMINATE”时,IE将不会触发它(浏览器错误可能?)。登记/> 作为IE的解决方法,我可以通过编程方式触发更改事件,但这对我的情况不起作用,因为我需要知道事件是否因为用户实际点击它而被触发。

Fiddle here / Test on IE and Chrome

<label for="cb">
  <input id="cb" type="checkbox" />
   click me
</label>

var checkbox = document.getElementById("cb");
checkbox.indeterminate = true;
$('#cb').change(function(){alert('Change Event')});

我已阅读这篇文章https://github.com/jquery/jquery/issues/1698How to deal with browser differences with indeterminate checkbox,但我可以为我的案例找到具体的解决方案。

任何想法如何解决这个问题?

提前谢谢。

1 个答案:

答案 0 :(得分:6)

复选框输入只能有两种状态:已选中或未选中。不确定状态仅是可视状态,它掩盖了复选框的实际状态。

首次点击其不确定设置为true的复选框时,只需将其更改为false,复选框即会显示其真实状态。因此,从“不确定”到“已检查”或“未选中”的更改不是实际状态的更改,也不会触发onchange事件。

有趣的是,唯一正确实现此行为的浏览器是IE。您可以在IE和其他浏览器中测试它:

document.getElementById("cb1").indeterminate = true;
document.getElementById("cb2").indeterminate = true;
<label for="cb1"><input id="cb1" type="checkbox" checked="checked" />I'm actually checked</label>
<label for="cb2"><input id="cb2" type="checkbox" />I'm actually unchecked</label>

在IE中,第一次点击将显示复选框的实际状态。在Chrome中,它会将真实状态更改为其他实际状态。

虽然IE技术上的实现是正确的,但其他浏览器的实现更为实用。对于大多数应用程序,视觉“不确定”状态需要被视为真实状态,就像“已检查”和“未检查”一样,这意味着从这3个状态中的任何状态到另一个状态的更改都应触发onchange事件

如何解决这个问题?嗯,最明显的答案可能是仅为IE注册一次点击事件,就像https://github.com/jquery/jquery/issues/1698建议的那样。

// As other browsers already fire the change event,
// only bind the listener for IE.
if ( window.navigator.userAgent.indexOf('Trident') >= 0 ) {
    $(function(){
        // Pointer events in IE10, IE11 can be handled as mousedown.
        $(document).on('mousedown', 'input', function(){
            // Only fire the change event if the input is indeterminate.
            if ( this.indeterminate ) {
                $(this).trigger('change');
            }
        });
    });
}

但是,A. Wolff给出的更通用的方法可能是更好的方法,因为尽可能避免使用特定于浏览器的代码总是更好:

var checkbox = document.getElementById("cb");
checkbox.indeterminate = true;
$('#cb').one('click', function () {
    if (!this.checked) {
        this.checked = true;
        var evt = document.createEvent("HTMLEvents");
    evt.initEvent("change", false, true);
    this.dispatchEvent(evt);
    }
}).change(function (e) {
    console.log(e);
    alert(e.originalEvent)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cb">
    <input id="cb" type="checkbox" />click me
</label>