user1241091
user1241091

Reputation: 1391

Events-- 'mouseup' not firing after mousemove

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

Answers (10)

Red Forest
Red Forest

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

pmad
pmad

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

Vo Hieu Nghia Phan
Vo Hieu Nghia Phan

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

Rishabh Titvilasi
Rishabh Titvilasi

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

LitileXueZha
LitileXueZha

Reputation: 620

For above two methods:

  • add e.preventDefault() in mouseup event
  • add user-select: none CSS rule

Tried on Chrome 87 but both useless. Finally I add a additional mouseout event listener and it fired when drag out of element.

Upvotes: 1

Alexandru
Alexandru

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

egekhter
egekhter

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

TimDog
TimDog

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

marcy23
marcy23

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

user1241091
user1241091

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

Related Questions