I can't get the pointerup
event to fire on a link (an A
tag with a href
attribtue set) for event.pointerType == 'mouse'
if the mouse was moved between pointerdown
and pointerup
.
I have the following scenario:
var lastEvent = false;
var handler = function (e) {
if (lastEvent != e.type) {
e.target.innerHTML += e.type + ' with ' + e.pointerType + '<br/>';
e.target.scrollTo(0, e.target.scrollHeight);
}
lastEvent = e.type;
}
document.querySelector('a').addEventListener('pointerdown', handler);
document.querySelector('a').addEventListener('pointermove', handler);
document.querySelector('a').addEventListener('pointerup', handler);
div {
height: 100vh;
display: flex;
}
a {
height: 60vh;
width: 75vw;
margin: auto;
background-color: red;
display: inline-block;
user-select: none;
touch-action: none;
overflow-y: scroll;
}
<div>
<a href="#"></a>
</div>
If I press a mouse button, keeps it pressed for a while and then releases it, I get this sequence:
However if I press my mouse button, keeps it pressed and moves the mouse pointer around, and then releases it, I get this sequence:
Problem: pointerup never fires.
I guess it is the built-in click-or-drag features in the browser (I have tested in Chrome) which blocks the pointerup
event from firing, because If do this on a span
or removes the href
from the anchor link it works with this sequence:
Also, it works flawlessly for touch-driven PointerEvents
:
I guess there is a clever css property to set on the element to disable this pointerup
prevention. Something like a { pointer-actions: click; }
, but I haven't been able to find what.
D'oh! I stated the answer in the question, basically. It was the drag action which prevented the pointerup
event from firing. Simply adding the draggable="false"
attribute on the link element fixed this issue.
<a href="#" draggable="false"></a>
Proof of concept:
var lastEvent = false;
var handler = function (e) {
if (lastEvent != e.type) {
e.target.innerHTML += e.type + ' with ' + e.pointerType + '<br/>';
e.target.scrollTo(0, e.target.scrollHeight);
}
lastEvent = e.type;
}
document.querySelector('a').addEventListener('pointerdown', handler);
document.querySelector('a').addEventListener('pointermove', handler);
document.querySelector('a').addEventListener('pointerup', handler);
div {
height: 100vh;
display: flex;
}
a {
height: 60vh;
width: 75vw;
margin: auto;
background-color: red;
display: inline-block;
user-select: none;
touch-action: none;
overflow-y: scroll;
}
<div>
<a href="#" draggable="false"></a>
</div>
The only downside is that with draggable
set to false
, all mousedown
-mousemove
-mouseup
will trigger a click
event. But this can be prevented by checking if the difference for clientX
/clientY
between pointerdown
and pointerup
event is greater than a certain amount of pixels, store that in a variable and add an click
event handler which runs e.preventDefault(); e.stopPropagation();
in this case.