Click Events From Hell
Click events are a godsend from hell. Here's how you can avoid at least one of the many problems they bring to the table: the end of a drag is not a click.
Back in the days I learned most of my current knowledge of event handling by reading @ppk's quirksmode. If you don't know how mouse events behave (across browsers) read up on the topic.
Mouse events have been driving me crazy the last couple of days. especially the fact that a click
-event is triggered for every mousedown
and mouseup
on the same element. This is even true if the mouse has been moved as you can see in this simple draggable demo:
A click? really? Sadly yes, that is how those darn mouse events are defined. But fear not, we can throw some javascript at the problem. In mousedown
and mouseup
we can capture the pointer's position. In mouseup
we compare the current pointer position to where it was when mousedown
was triggered. If the positions are within a certain threshold, the mousedown/up combination's intention was indeed a click. But if the positions are too far off, we've most likely dragged something around and in turn do not expect the click event to be triggered. In our little event hell, there's no way to prevent a click
event from being triggered, so we need to augment the click
event handler a bit. Wrapping things up in a bit of delegated events, we get to the following snippet. (see the jsfiddle)
(function($){
var $doc = $(document),
moved = false,
pos = {x: null, y: null},
abs = Math.abs,
mclick = {
'mousedown.mclick': function(e) {
pos.x = e.pageX;
pos.y = e.pageY;
moved = false;
},
'mouseup.mclick': function(e) {
moved = abs(pos.x - e.pageX) > $.clickMouseMoved.threshold
|| abs(pos.y - e.pageY) > $.clickMouseMoved.threshold;
}
};
$doc.on(mclick);
// globally valid test if the current click was indeed a click
$.clickMouseMoved = function () {
return moved;
};
// expose threshold configuration
$.clickMouseMoved.threshold = 3;
})(jQuery);
Now we can add a test to our click handlers and ignore those pesky non-click clicks:
if ($.clickMouseMoved()) {
// oh no, the mouse moved!
return;
}
// do something clicky
});
The author does not allow comments to this entry
Comments
Display comments as Linear | Threaded