Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture mouseup event outside of mousedown element? (i.e. for proper Drag-n-Drop?)

The Javascript onmouseup event is not triggered if the mouse button is released outside the element on which onmousedown has been triggered.

This causes a drag&drop bug in JQuery UI: A JQuery draggable element does not stop dragging when mouse button is released outside of its container (because the element will stop moving when reaching it's parent boundaries). Steps to reproduce:

  • Go to http://jqueryui.com/draggable/.
  • Drag the draggable downward until the mouse has left the surrounding container
  • Release mouse button (no mouse button is pressed at this point)
  • Move mouse back into container
  • And the draggable is still being dragged. I would expect the dragging to have stopped as soon as I released the mouse button - no matter where it is released.

I see that behavior in latest Chrome and IE.

Is there any work-around?

I know that we could stop dragging the container on mouseout or mouseleave, but I would like to keep dragging, even if I am outside the parent container, much like in google maps (no matter, where you release the mouse, it always stops dragging the map).

like image 843
Domi Avatar asked Jan 12 '14 11:01

Domi


People also ask

Which of the following event triggers after Mousedown and then mouseup over the same element if the left mouse button was used?

click. Triggers after mousedown and then mouseup over the same element if the left mouse button was used. dblclick. Triggers after two clicks on the same element within a short timeframe.

What is mouseup and Mousedown?

MouseDown occurs when the user presses the mouse button; MouseUp occurs when the user releases the mouse button.

How do I trigger a mouseup event?

The mouseup event occurs when the left mouse button is released over the selected element. The mouseup() method triggers the mouseup event, or attaches a function to run when a mouseup event occurs. Tip: This method is often used together with the mousedown() method.

Do the mouse events click and Mousedown have the same functionality?

Note: This differs from the click event in that click is fired after a full click action occurs; that is, the mouse button is pressed and released while the pointer remains inside the same element. mousedown is fired the moment the button is initially pressed.


1 Answers

I found this to be the best solution: Attach the mouseup event handler to document instead. Then it will always cancel, even if you release the mouse button outside the browser. Of course, this is not a pretty solution, but apparently, this is the only way to get dragging to work correctly.

Try the solution below:

  • You will see that "Drag END" will always happen, no matter where you release the cursor.
  • Also, in order to prevent text selection while dragging, I added an unselectable class.

let dragging = false;
const dragEl = document.querySelector('div');
const logEl = document.querySelector('pre');

dragEl.addEventListener('mousedown touchstart', (evt) => {
  dragging = true;
  dragEl.classList.add('unselectable');
  logEl.textContent += 'drag START\n';
});
document.addEventListener('mouseup touchend', (evt) => {
  if (dragging) {
    event.preventDefault();
    dragEl.classList.remove('unselectable');
    dragging = false;
    logEl.textContent += 'drag END\n';
  }
});
div {
  background: red;
}

.unselectable {
  -webkit-user-select: none; /* Safari */        
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* IE10+/Edge */
  user-select: none; /* Standard */
}
<div>drag me</div>
<hr>
LOG:
<p><pre></pre></p>

Update

These days, the setPointerCapture API provides a cleaner solution, as explained in this answer.

like image 170
Domi Avatar answered Sep 28 '22 09:09

Domi