Reputation: 1391
I am trying to drag an image with Javascript (no libraries). I am able to listen to mousedown
and mousemove
events. For some reason, I am not able to capture the mouseup
event after mousemove
. (I can capture mouseup
if it is a click but not if it is a drag).
I have tried to listen to the event on document, window, and the image.
Here's the url to my test page:
https://dl-web.dropbox.com/get/Public/move.html?w=74a0d498
Any help on this would be greatly appreciated!
Upvotes: 45
Views: 39078
Reputation: 46
I encountered this problem when using React and the following things helped me:
1: Change the purpose of the event from
document.addEventListener
to
window.addEventListener
As suggested by user Vo Hieu Nghia Phan. As a result, the useEffect
hook looks like this:
React.useEffect(
() => {
window.addEventListener('mousedown', mouseDown);
window.addEventListener('mouseup', mouseUp);
return () => {
window.removeEventListener('mousedown', mouseDown);
window.removeEventListener('mouseup', mouseUp);
};
},
[mouseDown, mouseUp]
);
I don't know why, but when using document.addEventListener
, if the change of mouseUp
is frequent, then the 'mouseup'
event doesn't work. If the change of mouseUp
is not frequent (it won't occur after the mouse down and before the mouse up), this problem doesn't occur.
2: I think it can help also those who do not use React. In the "mouseDown"
event handler I call:
e.preventDefault();
It is not necessary to call e.stopPropagation();
.
However, you should be careful when using this method because e.preventDefault();
may change the expected behavior of your application after a mouse down. As a way to mitigate the effects, you can call e.preventDefault();
not always, but by condition, for example, when clicking on a certain element or an element with a certain selector.
Upvotes: 0
Reputation: 182
The problem is in selection. Some elements are draggable, when user - having unknowingly uncollapsed selection (likely across many non-text elements), starts moving his mouse with mouse button pushed down he drags these elements alongside the movement of his mouse.
Try setting draggable="false"
on html elements where mousedown
event starts or if it doesn't work try clearing or collapsing selection on mousedown
.
Clear:
getSelection().setPosition(null);
A bit cleaner, collapse:
const selection = getSelection();
selection.setPosition(selection.anchorNode, selection.anchorOffset)
Setting draggable="false"
worked for me when working with mousedown
event starting with an <img>
element and clearing selection worked when I had selections spanning over multiple elements on a control panel an this made some input[type="range"]
elements unusable (click event worked but not thumbnail dragging).
Upvotes: 1
Reputation: 1
It is going to be of help to anyone:
I recommended you use window
instead of document
when adding Event mouseup
Upvotes: 0
Reputation: 33
The event which you want to fire in mouseup , You can fire in mousedown and inside the function write event.stopPropagation()
.
It will stop the drag event.
Upvotes: 0
Reputation: 620
For above two methods:
e.preventDefault()
in mouseup
eventuser-select: none
CSS ruleTried on Chrome 87 but both useless. Finally I add a additional mouseout
event listener and it fired when drag out of element.
Upvotes: 1
Reputation: 12872
I have seen the mouseup
event not fire on my target div
because its parent div
began consuming drag events. I clicked my target div
and this caused my mousedown
and mousemove
handlers to run. I was expecting to see a mouseup
but I did not.
In my case, I had a parent div
living beneath my target div
in the same location where I launched my mouse button click, and instead of bubbling up the mouseup
event on my document once I let go of the left mouse button, I instead got a dragend
event fire on its parent div
.
The solution for me was simply to set user-select: none;
CSS property on the parent div
which houses my target div
and to make sure I set user-select: text
on my target div
. This property seems to disable dragging for my parent div
and because it has stopped consuming drag events, my mouseup
event now properly bubbles its way up.
I presume the reason why this might happen is because the browser starts thinking your mouse move is actually part of a drag event on another element, at which point it seems to stop reporting the standard mouse events and switches to drag events instead.
Upvotes: 5
Reputation: 2225
Neither of the above answers reliably worked to ensure a mouseup event.
Here's what I discovered works consistently:
document.querySelector('html').addEventListener('mouseup', function (e) {
console.log("html mouseup");
var evt = document.createEvent("MouseEvents");
evt.initEvent("mouseup", true, true);
document.getElementById('drag-me').dispatchEvent(evt);
});
If mouseup fires on target element, it does not fire on html, and if it did not fire on target, it will fire on html.
Upvotes: 2
Reputation: 8918
Strangely, I've found that when I set my text as unselectable using the below CSS, that inhibits the mouseup
event from firing as well -- perhaps this will help someone else.
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
Upvotes: 16
Reputation: 123
I was running into this exact same issue! Adding event.preventDefault();
worked for me but I was forced to add it to both the mousedown and mousemove functions.
Upvotes: 2
Reputation: 1391
Found the issue, if it is going to be of help to anyone:
I added event.preventDefault();
in the mousedown
event and now I am getting mouseup
notifications.
Upvotes: 93