Javascript Drag-And-Drops Made Easy: SimpleDrag

I've seen a lot of Javascript Drag-and-Drop (or "drag-n-drop") examples out there. Many of them are excellent. But most are fairly large and use global variables, trample on existing event handlers, etc.

I like things that are compact, simple, and unobtrusive. So I set out to make my own drag-and-drop feature.

Javascript brings a really wonderful feature from the world of functional programming called 'closures'. Closures allowed me to get rid of all of the usual global variables and really make a tight, clean drag-and-drop. See it in action.

SimpleDrag

Of course, this code is free, so get your own copy of the source .js file here. Remember, you can see a very simple working example here.

Go ahead, grab the script at the link above and then take a look at it. Notice the two functions dragMakeMoveFunc() and dragMakeStopFunc().

function dragMakeMoveFunc(elem, y, x){
  return function(e){
    e = (e ? e : event);
		elem.style.top  = (e.clientY - y) + 'px';
		elem.style.left = (e.clientX - x) + 'px';
  }
}

function dragMakeStopFunc(elem, oldMousemove, oldMouseup, oldCursor){
  return function(){
    document.onmousemove  = oldMousemove;
    document.onmouseup    = oldMouseup;
    elem.style.cursor     = oldCursor;
  }
}

These both return functions. In functional programming, these are known as higher-order functions. Anyway, what makes them cool is that any variables we "give" to the returned functions get copied behind the scenes and become local to the returned functions.

What makes this extremely useful for us in this case is that we can store multiple copies of what would have been global data (oldMousemove for the old onmousemove event handler function) inside the new event handler for onmouseup.

In the end, we have just a single function which needs to be assigned to make an object draggable, dragDown(). Here's how:

  <script type="text/javascript">
    // assuming "moveme" is the ID of a tag on the page
    var moveme = document.getElementById("moveme");
    moveme.onmousedown = dragDown;
  </script>

After assigning dragDown() to the onmousedown event of moveme, everything else is automatic. When the user presses the mouse over the moveme object, the dragDown function is called, the other event handlers are created by the higher-order functions dragMakeMoveFunc() and dragMakeStopFunc() on the fly. We don't even need a global variable to keep track of whether or not there is an object being dragged because when the user releases the mouse, we simply un-assign our onmousemove event handler and the object stops moving.