空格键触发复选框的点击事件?

17

当你在复选框上按空格键时,它会选中复选框。一切都很好,直到我决定禁用父级 div 上的点击事件,我意识到这也禁用了复选框上的空格键!

div1.addEventListener("click",function (e) {
  if (e.preventDefault) e.preventDefault();
  e.cancelBubble = true;
  return false;
}, true);
<div id="div1">
    <input id="chk1" type="checkbox">
</div>

http://jsfiddle.net/0t01252x/1/

我该如何避免这种情况?这对我来说似乎是一种非常奇怪的行为。点击事件是点击事件,而不是键盘事件...

注意:在chrome和FF下测试过

编辑:最糟糕的是:在控制台输出事件却得到了一个... MouseEvent!


1
你想要什么样的行为? - jmore009
3
我在这里和你一样,也没有想到会出现这种情况。也许浏览器供应商认为这是个好主意?就像他们将键盘最右边的[Enter]键的键码改成与靠近中心的那个相同一样。 - Halcyon
@jmore009,键盘事件不应被禁用,只有点击事件。 - Sebas
1
为什么允许使用空格键,但不允许点击? - Halcyon
因此,一种过滤的方法是检查事件的x/clientX和y/clientY坐标。在“空格键单击”上,x和y被设置为0。但那是个糊弄人的把戏,不能保证明天早上醒来后还能用... - Sebas
1
提交了一个 Bug,我真的很想听听开发人员对此的看法。https://bugzilla.mozilla.org/show_bug.cgi?id=1120106 - Sebas
2个回答

15

Quirksmode - click, mousedown, mouseup, dblclick

当用户点击元素或通过其他方式(如键盘)激活元素时,将触发“click”事件...其实,“click”事件的命名不准确,应该称为“activate”事件。

为了解决这个问题,你可以给复选框附加一个clickkeyup事件。

checkbox.addEventListener("click", handleCheckboxEvent, true);
checkbox.addEventListener("keyup", handleCheckboxEvent, true);

同时监听两个事件,并且始终禁用默认行为。从那里开始,您可以确定如果按下键 32e.keyCode === 32),则空格键触发了 keyup 事件。

如果是这样,请手动检查复选框是否被选中,如果已经选中请取消选中。

function handleCheckboxEvent(e) {
    e.preventDefault();

    if (e.keyCode === 32) {  // If spacebar fired the event
        this.checked = !this.checked;
    }
}

更新后的示例 - 在最新版本的Chrome/FF/IE中进行了测试。

(function () {
    var checkbox = document.getElementById('checkbox');

    function handleCheckboxEvent(e) {
        e.preventDefault();

        if (e.keyCode === 32) {  // If spacebar fired the event
            this.checked = !this.checked;
        }
    }

    checkbox.addEventListener("click", handleCheckboxEvent, true);
    checkbox.addEventListener("keyup", handleCheckboxEvent, true);
})();
<input id="checkbox" type="checkbox" />


好的,所以你正在手动覆盖内置行为。在某种程度上,我认为这是一个可以接受的解决方法... - Sebas

4
Kaiido似乎有一个很好的解决方案。至于行为,这显然是预期的。根据W3C - SCR35: Making actions keyboard accessible by using the onclick event of anchors and buttonsonclick事件通过键盘触发以实现辅助功能。浏览器即使在没有鼠标的情况下也会使用单击事件:

虽然 "onclick" 听起来像是与鼠标相关联的,但 onclick 事件实际上映射到链接或按钮的默认操作。默认操作发生在用户点击元素时,但当用户聚焦元素并按下 enter 或 space 键时,以及通过可访问性API触发元素时也会发生。


等等,不,我不相信!开发者的可访问性怎么办?不,更严肃地说,他们必须以不同的方式做。至少,不要给我一个 MouseEvent - Sebas
是的,我同意,他们至少可以将事件注册为键盘事件,然后您可以轻松禁用点击。 - jmore009
如果您认为这个解决方案足够好,您可以将其包含在内,我会删除自己的答案,您的更好。 - Kaiido
@Kaiido,问题在于你的建议确实有效,但有些欺骗成分。我也发现了这一点,但我认为使用它并不安全,因为这不在规范中,并且看起来有点“不太靠谱”。 - Sebas
@jmore009 找到了一种方法来实现这个 :) https://dev59.com/pF4c5IYBdhLWcg3weaT8#27891665 - Josh Crozier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接