Is it possible with jQuery to prevent a click event on the same element from being executed, after a mousedown & mouseup event has just been fired.
Any help/examples would be appreciated.
Is it possible with jQuery to prevent a click event on the same element from being executed, after a mousedown & mouseup event has just been fired.
Any help/examples would be appreciated.
No one seems to have answered this one yet, at least not in an elegant way, so I figure I'll share the solution I found by NewbeDev (source: https://newbedev.com/cancel-click-event-in-the-mouseup-event-handler )
The answer is to use the capture phase, so before the event gets triggered on your element, all of its parents receive it during what's called the "capture phase". Then after that the event is delivered to your element followed by its parents in what's called the "bubbling phase".
The solution here is to just cancel the event at the top during the capture phase so it never reaches your element for the bubbling phase.
My use case was for a slider, so the code I used worked out to something like this:
slider.addEventListener('mousedown', ev => {
// we start sliding (details omitted)
function captureClick(e) {
// we cancel the event and stop it from going further.
// preventDefault() on its own should be enough for most cases
// Your handler can also check e.defaultPrevented to know if preventDefault() was called
e.preventDefault();
// e.stopPropagation();
}
window.addEventListener('click', captureClick, true);
document.addEventListener('mouseup', e => {
// cleanup - we wait an extra frame to remove our capture
// in case the click event is delayed
requestAnimationFrame(() => {
window.removeEventListener('click', captureClick, true);
});
});
});
There's an awkward approach that is to disable the button when mousedown, and enable it after a short period, like 100ms. If the mouseup happens in this period, click won't be fired.
$('#btn').on('click', function() {
alert('clicked')
});
$('#btn').on('mousedown', function() {
var btn = $(this);
btn.attr('disabled', 'disabled');
setTimeout(function() { btn.removeAttr('disabled'); }, 100);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<button id='btn'>Click me</button>
</body>
In Chrome and Internet Explorer, not Firefox though, detaching and reattaching the element at mousedown or mouseup will prevent the click event to be triggered. In Internet Explorer, this trick does not catch double-clicks though (in Chrome it does).
But I wouldn't rely on this strange behavior, who knows if it won't change at some point. Also, beware that detaching and reattaching can also have side-effects ont the children of the detached element (iframes reloading, file fields reset, ...).
There is a solution:
const COORDS = {
xDown: null,
xUp: null
}
const handleOnMouseDown = e => {
e.preventDefault()
COORDS.xUp = null
COORDS.xDown = e.clientX
}
const handleMouseUp = e => {
e.preventDefault()
COORDS.xUp = e.clientX
}
const handleOnClick = e => {
if (COORDS.xDown !== COORDS.xUp) {
e.preventDefault()
console.log('drag')
} else {
console.log('click')
}
}
const el = document.getElementById('test')
el.addEventListener('mousedown', handleOnMouseDown)
el.addEventListener('mouseup', handleMouseUp)
el.addEventListener('click', handleOnClick)
#test {
padding: 20px;
display: block;
background: #ccc
}
<a href="#" id="test">Link</a>
Yes, it should be possible if you return false;
in the mouseup handler, because the onclick is fired after a mousedown and a mouseup have occurred. This is possible in regular javascript, so it should work with jquery event handlers as well.
EDIT:
Returning a boolean value from an event handler should actually be enough for event consumption. However, as this is very flaky across browsers you should use the function for manually canceling event bubbling:
event.stopPropagation();
where event is the parameter your event handler receives.
event.stopPropagation()
? Also: returning false
from an event handler is the method defined in the javascript standard, even if not all browser vendors hold to that standard. Don't downvote an answer because one of the proposed solutions didn't work for you. –
Mandorla © 2022 - 2024 — McMap. All rights reserved.
mousedown
followed by amouseup
would be a click, and to just have a click work once, there's theone()
method ? – Luckey