当您单击它时,IE 不会在不确定的复选框上触发“更改”事件
Posted
技术标签:
【中文标题】当您单击它时,IE 不会在不确定的复选框上触发“更改”事件【英文标题】:IE does not fire 'Change' event on indeterminate checkbox when you click on it 【发布时间】:2016-02-05 00:32:51 【问题描述】:我有一个三态复选框,我需要在用户单击它时触发 change 事件,但是当复选框的状态为“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/1698 和 How to deal with browser differences with indeterminate checkbox,但我可以找到适合我的情况的具体解决方案。
任何想法如何解决这个问题?
提前谢谢你。
【问题讨论】:
github.com/jquery/jquery/issues/1698 我已经阅读了该内容,不适用于我的情况 是的,刚刚测试过,不行 看起来它可以工作,但这是一个丑陋的修复(它也处理空格键):jsfiddle.net/5ro92490 不确定您的预期行为是什么,但您可以发送事件:jsfiddle.net/5ro92490/2 看看是否符合您的需求 【参考方案1】:复选框输入只能有两种状态:选中或未选中。不确定状态只是可视的,它掩盖了复选框的真实状态。
第一次单击不确定设置为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>
【讨论】:
为了清楚正确的行为,规范说html.spec.whatwg.org/multipage/…,它说点击一个不确定的复选框应该切换值。然而,IE 只是删除了不确定的状态。 @ClarkPan 是的,该文档中的规范令人困惑。它清楚地表明不确定属性除了改变复选框控件的外观外没有任何作用。这意味着IE行为是正确的。但随后它说 点击前激活步骤包括将元素的选中状态设置为相反的值,这与假设点击前激活意味着点击其不确定设置为 false 的复选框的第一条语句相矛盾. 这是解释它的一种方式,它似乎是 IE 团队的方式。我解释它的方式是,不管不确定属性如何,单击复选框将切换选中状态。在这种情况下,单击不确定复选框的正确行为是删除不确定标志,然后将选中的更改与其当前值相反。这是其他浏览器所做的。 IE,仅将不确定状态设置为 false,但不会切换底层检查状态。这就是它不触发更改事件的原因。 @ClarkPan 是的,这正是我在回答中想要表达的。拥有如此模糊的规范,对不同的解释持开放态度,这真的很烦人。制定标准的唯一原因是每个人都以完全相同的方式实施规范。含糊不清的标准/规范使我们陷入了以不同方式实施的问题,使标准/规范变得毫无意义。 请注意,实际情况可能涉及修复与复选框、keydown 和 touchstart 事件相关联的标签的此问题。以上是关于当您单击它时,IE 不会在不确定的复选框上触发“更改”事件的主要内容,如果未能解决你的问题,请参考以下文章
React 基于原生的 DatePicker 出现在 iOS 上最小化
在 IE11 中,当单击其子元素之一时,焦点事件未在具有显示 flex 的可聚焦父 HTML 元素上触发