Reputation: 698
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
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