0

I'm developing a web application where users can learn Spanish by putting words together like pieces of a puzzle. I've created some JavaScript to make the puzzle pieces "draggable" (I know there is a new D&D API with HTML5, but the way I did it even works on browsers that don't support that).

Anyway, everything works perfectly in IE (even my old IE7) and Firefox, but I ran into an interesting snag with Google Chrome: each piece could only be dragged once; then they became "locked" (unable to move).

So my question is, is there something that needs to be done differently for this to be compatible with Chrome? I was thinking of maybe having the "drop" script refresh the browser every time the user drops a piece, but that would probably be a pain for users with slow connections... anyway I'm sure there's something I'm overlooking, but I'm not sure what it could be. Here's my code:

<html>
<head>
<title> Making Sense out o Spanish </title>
<style>

#div1, #div2{
 position: absolute;
 left: 100px; top: 100px;
 width: 80px; height: 60px;
 background-color: yellow;
}

#div3, #div4{
 position: absolute;
 left: 200px; top: 200px;
 width: 80px; height: 60px;
 background-color: green;
}

</style>
<script>

var activePiece = "nothing";

function move(id,x,y){
 if (activePiece == id){
  var element = document.getElementById(id);
  element.style.left = x-40 + "px";
  element.style.top = y-30 + "px";
 }
}

function go(id){
 activePiece = id;
 var element = document.getElementById(id);
 element.style.zIndex = "1";
}

function stop(id){
 activePiece = "nothing";
 var element = document.getElementById(id);
 element.style.zIndex = "-1";
}
</script>
</head>
<body bgcolor="blue" onmousemove="update(event.clientX,event.clientY);">

<div id="div1" onmousedown="go('div1');" onmouseup="stop('div1');" onmousemove="move('div1',event.clientX,event.clientY);">Quiero</div>
<div id="div2" onmousedown="go('div2');" onmouseup="stop('div2');" onmousemove="move('div2',event.clientX,event.clientY);">Necesito</div>
<div id="div3" onmousedown="go('div3');" onmouseup="stop('div3');" onmousemove="move('div3',event.clientX,event.clientY);">bailar</div>
<div id="div4" onmousedown="go('div4');" onmouseup="stop('div4');" onmousemove="move('div4',event.clientX,event.clientY);">trabajar</div>

</body>
</html> 
user2403876
  • 239
  • 2
  • 4
  • 16
  • See http://stackoverflow.com/questions/16404327/how-to-pass-event-as-argument-to-an-inline-event-handler-in-javascript for passing the event object to inline event handlers. Personally, I'd prefer to use `.addEventListner()` and let the system pass it to me automatically. – jfriend00 Apr 12 '14 at 04:11
  • I looked up addEventListener after you mentioned it, and I'll give it a try tonight. Thanks for the quick response! :) – user2403876 Apr 12 '14 at 04:17
  • I tried this ("start" called on load): function start(){ document.getElementById('div1').addEventListener("click",test,false); } function test(){ alert("Cool!"); } This had the same result: it worked, but only once. – user2403876 Apr 12 '14 at 04:41
  • You can't really put an `alert()` in the middle of your drag and expect things to work because that interrupts all your timing and event sequencing (use a `console.log()` if you just want to see what happened). If you really want to implement your own drag/drop, you need to use capturing so you capture all mouse movements (not just the ones over your object) until you're done with the drag. Otherwise a quick mouse motion with the button down will get off your element and the drag/drop will break. I'm not sure why you're trying to reinvent the wheel vs. use built-in drag/drop functionality. – jfriend00 Apr 12 '14 at 04:53
  • Relevant link: [Implement Drag drop from scratch](http://stackoverflow.com/questions/1039986/how-to-implement-a-drag-and-drop-div-from-scratch). – jfriend00 Apr 12 '14 at 04:59
  • Well for a few reasons: (1) this way seems to work on every other browser, including older ones, and (2) I spent some time studying the docs on the "built-in" HTML5 way, and to someone who doesn't yet understand all every last detail of event handling, it seemed much closer to "reinventing the wheel" than this. :) Do you happen to know anywhere where I can see a clear explanation, in layman's terms, of how event handlers actually work? Unfortunately, things like event "capturing" and "bubbling" are still all Greek to me. – user2403876 Apr 12 '14 at 05:04
  • Show me a demo or jsFiddle of what you have already and I can probably show you all sorts of issues with it. It's not as simple as you think to do this properly. You can start [here](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener) for info about `addEventListener()` and the capture argument to that. The idea with capture is that once you start dragging an object, you want ALL mouse events to go to your object UNTIL the mouseup happens and you stop the drag, regardless of whether the mouse is still over your object so you never lose the drag. – jfriend00 Apr 12 '14 at 05:09
  • btw, the page tracks the mouse coordinates regardless of which element is being dragged; the "clientX" and "clientY" are relative to the whole page, and the onmousedown event moves the selected object's z-index to the top, so the only way I've seen it stop dragging (and mess things up) is if I move the mouse as fast as possible. I've seen that same problem with simple mouseover events, but I don't think there's anything that'll fix that... or is there? – user2403876 Apr 12 '14 at 05:11
  • Yes, mouse capture fixes that. That's exactly what it's for. – jfriend00 Apr 12 '14 at 05:16

1 Answers1

0

I spent some time looking into this, and it seems the "short answer is, the event listener is the solution. I found this site:

JavaScript mouse events tutorial

And they have a demo that works exactly like mine, EXCEPT that they added the event functions in the script instead of the individual div elements. I haven't had the chance to do try it in my code yet, but their demo works fine in Chrome as well as Firefox and IE.

user2403876
  • 239
  • 2
  • 4
  • 16