Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is event.clientX incorrectly showing as 0 in firefox for dragend event?

The alert from dragend is showing mouseX as zero no matter where it is currently. This works fine in Chrome so not sure what I'm doing wrong.

function move(e,obj,but){     if(typeof(obj) === 'string'){         obj = document.getElementById(obj) ;     }          if(typeof(but) === 'string'){         but = document.getElementById(but) ;     }      //elementCoord(but) ;//get the current coords of the button &     elementCoord(obj) ;//the container          e = e || window.event ;     var mouseX = e.clientX ;     var mouseY = e.clientY ;                  //alert('mouseX='+mouseX+', but.XCoord '+but.XCoord) ;     var diffX = Math.abs(obj.XCoord - mouseX) ;     var diffY = Math.abs(obj.YCoord - mouseY) ;          but.addEventListener("dragend",function(evt){         evt = evt || window.event ;         mouseX = evt.clientX ;         mouseY = evt.clientY ;         obj.style.left = mouseX - diffX + 'px';         obj.style.top = mouseY - diffY + 'px';         alert('mouseX='+mouseX+' diffX='+diffX) ;         }     ,false) ;      } 

Forgot to mention, elementCoord just gets the offset of an object adding it as a property. It works fine in all browsers.

like image 755
Magic Lasso Avatar asked Jul 25 '12 18:07

Magic Lasso


1 Answers

This is officially an issue with Firefox -- Bugzilla: Bug #505521, Set screen coordinates during HTML5 drag event. I'll quote jbmj to summarize, and I will bold the original developer they are quoting...

I can't believe that this comment
"Note though that it doesn't specify what the properties should be set to, just that they should be set and we currently set them to 0."
from 11years ago is still state of the art.

I was inspired by Jay's comment, to use the "drop" event. But that was only a comment, so let me thresh it out into an answer.

Our problem: dragend event has e.clientY and e.clientX set to 0.

How we will solve it: document's drop event also fires at the same exact time as the element we are dragging's dragend event. And: drop will have the correct values for e.clientY and e.clientX.

Two working demos, 100% JavaScript-Only Solution: SO Code Snippet and JSBin. The SO Code Snippet console sometimes gobbles up the dragged element in the console, and JSBin gave me more consistent results.

var startx = 0; var starty = 0; dragStartHandler = function(e) {   startx = e.clientX;   starty = e.clientY; }  dragOverHandler = function(e) {   e.preventDefault();   return false; }  dragEndHandler = function(e) {   if(!startx || !starty) {     return false;   }      var diffx = e.clientX - startx;   var diffy = e.clientY - starty;      var rect = e.target.getBoundingClientRect();  var offset = {                  top: rect.top + window.scrollY,                  left: rect.left + window.scrollX,              };      var newleft = offset.left + diffx;   var newtop = offset.top + diffy;      e.target.style.position = 'absolute';   e.target.style.left = newleft + 'px';   e.target.style.top = newtop + 'px';      startx = 0;   starty = 0; }  document.getElementsByClassName("draggable")[0].addEventListener('dragstart', dragStartHandler);  document.addEventListener('dragover', dragOverHandler); document.addEventListener('drop', dragEndHandler);
.draggable {   border: 1px solid black;   cursor: move;   width:250px; };
<!DOCTYPE html> <html> <head>   <meta charset="utf-8">   <meta name="viewport" content="width=device-width">   <title>JS Bin</title> </head> <body>      <BR><BR><BR>    <div id="draggable1" class="draggable" draggable="true">     Hey, try to drag this element!   </div>    </body> </html>

Explanation:

  • dragStartHandler() : This is bound to the draggable element. Here, all we do is record the current x/y coordinates at start.
  • dragOverHandler() : This is bound to the document, so that we can override the default dragover behavior. This is needed to do any type of drag & dropping.
  • dragEndHandler() : This is bound to the document's drop. Normally, we would want this to bind to the element's dragend, but since clientY and clientX are missing, we bind it to the document. This just does exactly what you'd want to happen when dragend is called, except you have x/y coordinates.
like image 62
HoldOffHunger Avatar answered Sep 20 '22 22:09

HoldOffHunger