Erlik
Erlik

Reputation: 698

Mousedown event handler interferes with key handlers

My application kept misbehaving. After removing more and more code I managed to find the core of the problem which however makes no sense to me.

Bit of a background. My web editor application reacts to key strokes, e.g. when Alt is pressed, handlers for resizing are hidden. It also reacts to mouse operations for dragging, resizing, deleting, drawing a selection box, etc. When experimenting with event handlers and preventing default behavior (I didn't want Alt to change focus to browser menu, neither mouse to select text), I found a weird thing.

When I create event handlers for keyup and keydown (and these contain preventDefault()), it works fine. However when I add handler for mousedown, it works as well, but the previous handlers stop working. If I remove preventDefault() from the mousedown handler, all works fine.

Here's my JS code stripped to minimum (or rather created for purposes of verifying the problem is not somewhere else):

// it works fine with these events
var events = ['keyup', 'keydown'];

// but when mousedown is added, its preventDefault() method somehow breaks keydown and keyup
//var events = ['keyup', 'keydown', 'mousedown'];

var log = document.getElementById('log');

var handler = function(e) {
  log.innerHTML = e.type + '<br>' + log.innerHTML;
  e.preventDefault();
}

for (var i = 0; i < events.length; i++) {
  window.addEventListener(events[i], handler);
}

See jsfiddle here.

Why on earth would preventDefault() method in mousedown handler interfere with key events?

Tested in Chrome and Firefox.

Upvotes: 1

Views: 1084

Answers (1)

Enethion
Enethion

Reputation: 1257

New:

I just had to test it further and further. It seems that this.focus() works as well as documen.getElementById().focus() and window.focus() from my last update. Best practice (IMO) will be using this because it's universal reference to clicked object.

Latest old: New Demo

Finaly! What I did wrong was using document object while I should use window. This time there's no errors in console in any tested browser (even IE11). So the code should look like this:

var handler = function(e) {
    log.innerHTML = e.type + '<br>' + log.innerHTML;
    document.focus();
    e.preventDefault();
}

Old 2: I just tested this further this time. It seems that e.preventDefault() on mousedown doesn't break other events and is working just as it should: prevents default action which is (among the others) setting focus on the DOM element. I tried same code on local html file and it works perfectly. What you need to do is to set focus by yourself on object that has to read those events.

EDIT: DEMO and code of handler function:

var handler = function(e) {
    log.innerHTML = e.type + '<br>' + log.innerHTML;
    document.focus();
    e.preventDefault();
}

Old 1: That's because mousedown event lasts until you 'let it go' (try same code but use mouseup instead of mousedown). It just doesn't work like keydown where event is being sent, ends and then this event is repeated until you stop pressing the key.

Upvotes: 1

Related Questions