16

If you spacebar on a checkbox, it checks the box. Everything was fine until I decide to disable the click event on the parent div, which I realized, disabled the spacebar on the checkbox as well!

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/

How can I prevent that? It seems like a very odd behaviour to me. Click events are click events, not keyboard events...

Note: tested with chrome and FF

Edit: worst: outputing the event in the console gives a ... MouseEvent!

Sebas
  • 21,192
  • 9
  • 55
  • 109
  • 1
    what is the behavior you are looking for? – jmore009 Jan 10 '15 at 17:21
  • 3
    I'm with you here, I wouldn't have expected that. Maybe browser vendors thought this was a good idea? Like when they changed the keycode of the `[enter]` key on the far right of the keyboard to be the same as the one near the center. – Halcyon Jan 10 '15 at 17:21
  • @jmore009, keyboard events should not be disabled, only click events – Sebas Jan 10 '15 at 17:21
  • 1
    Why is spacebar allowed, but not click? – Halcyon Jan 10 '15 at 17:22
  • So, a way to filter is to check the event's x/clientX and y/clientY coordinates. On a "spacebar click", the x and y are set to 0. But that's a dirty trick and not garanteed to work tomorrow morning when you wake up... – Sebas Jan 10 '15 at 17:34
  • 1
    filed a bug, I really want to hear what the devs say about it. https://bugzilla.mozilla.org/show_bug.cgi?id=1120106 – Sebas Jan 10 '15 at 17:45

2 Answers2

14

Quirksmode - click, mousedown, mouseup, dblclick

The click event fires when the user clicks on an element OR activates an element by other means (i.e. the keyboard) ... “click” event is really a misnomer: it should be called the “activate” event.

To work around this, you can attach a click and keyup event to the checkbox.

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

Listen to both events, and always disable the default behavior. From there, you can determine if the spacebar fired a keyup event if the key 32 is pressed (e.keyCode === 32).

If so, manually check the checkbox if it is not checked, and uncheck it if it is checked.

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

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

Updated Example - tested in the latest versions of 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" />
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • Ok, so you're manually overriding the built-in behavior. To some extent, this is an acceptable workaround I believe... – Sebas Jan 11 '15 at 22:40
3

Kaiido seems to have a good solution. As for the behavior this is apparently expected. According to:

W3C - SCR35: Making actions keyboard accessible by using the onclick event of anchors and buttons

the onclick event is triggered by the keyboard for accessibility purposes. Browsers use the click event even if its triggered from the keyboard in the event that a mouse isnt present:

While "onclick" sounds like it is tied to the mouse, the onclick event is actually mapped to the default action of a link or button. The default action occurs when the user clicks the element with a mouse, but it also occurs when the user focuses the element and hits enter or space, and when the element is triggered via the accessibility API.

Sebas
  • 21,192
  • 9
  • 55
  • 109
jmore009
  • 12,863
  • 1
  • 19
  • 34
  • Wait, no, I don't buy it! What about accessibility for developers? No, more seriously, they must do it differently. At the very least, do not give me a `MouseEvent`. – Sebas Jan 10 '15 at 17:53
  • yeah i agree, they could at least register the event as a keyboard event and then you could easily disable the click – jmore009 Jan 10 '15 at 17:55
  • If you think the solution is good enough, you can include it, I'll delete my own answer, yours is better – Kaiido Jan 10 '15 at 18:01
  • @Kaiido The problem is that your proposition works that's right, but is a trick. I found it out too, but I don't think it is safe to use, since this is not in the specification and looks sort of "dirty dodgy" – Sebas Jan 10 '15 at 18:05
  • @jmore009 Figured out a way to do this :) http://stackoverflow.com/a/27891665/2680216 – Josh Crozier Jan 11 '15 at 20:24