Bookmark and Share

Generic Drag

See the demo page for the finished version of the code.

This coding example demonstrates using a combination of mouse events to make any positioned element on a page draggable by the user.

First we'll look at how to define elements on a page so they can be dragged, then we'll see how the code works.

Setting Up Elements for Dragging

The user drags an element by placing the mouse pointer over it, pressing down on the mouse button and moving the pointer while holding the button down. Releasing the button ends the drag.

Obviously, the mousedown, mousemove and mouseup events will be used. And, in order for an element to be moved, it must be a positioned element. That is, it must have a position style of absolute, fixed or relative.

Browser Compatibility

Internet Explorer does not currently support fixed positioning for elements. Netscape 6.1 does but not version 6.0.

Since the browser gives the mouse position in pixel coordinates, the element's left and top style properties should be defined in px units. Note that the position must be set in an inline style (or omitted so that they will default to zero) and not in a style rule.

To initiate a drag, an onmousedown event handler needs to be assigned in the element's tag to call a function named dragStart(). Following the DOM event standard, the event object is passed as an argument.

<div style="position:absolute;left:200px;top:100px;"
     onmousedown="dragStart(event)">Drag Me</div>

Below is a DIV set up similar to the sample code above. Try dragging it around the page.

Drag Me

To make the script more useful, the dragStart() function allows an optional argument to specify the ID of a positioned element. In other words, you can move one element by dragging the mouse on some other element, even a non-positioned one. For example,

<div id="outerDiv" style="position:relative;left:0px;top:0px;">
  <span onmousedown="dragStart(event, 'outerDiv')">Drag Me</span>
  <p>Some text.</p>
</div>

Here, the SPAN containing the text "Drag Me" has the event handler set to drag its parent element, the DIV named "outerDiv." Below is a sample to illustrate how this works. Try dragging the DIV with the mouse over different areas.

Drag Me

Some text.

You'll find that you can move the DIV only if you mouse down on the text "Drag Me" and that the contents of the DIV, including the SPAN, move with it. The demo shows some more possibilities.

Also note that if you overlap the above samples, the element being dragged always appears above the other. That's because the script updates the target element's zIndex style at the start of the drag.

Code Details

See the DOM Event Model for details on events and browser compatibility.

The code itself is fairly simple in concept. But, as usual, certain browser incompatibilities necessitates different code for different browsers to accomplish the same task.

So first off, the script defines a global object called browser which contains information on the particular browser and version. This is used throughout the script to deal with any browser incompatibilities.

// Determine browser and version.

function Browser() {

  var ua, s, i;

  this.isIE    = false;
  this.isNS    = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}

var browser = new Browser();

The script could be extended to detect and work with other browsers as well, provided they support CSS positioning and custom event handling for the necessary mouse events.

Next the script defines a global named dragObj. It's simply a generic JavaScript Object that will be used to store information during any particular drag operation.

// Global object to hold drag information.

var dragObj = new Object();
dragObj.zIndex = 0;

One initial property is set, zIndex which will be used to set the stacking order on that element. Here it's initialized to zero but if any positioned elements on the page have a zIndex set, it can be changed to match the highest value used. This will ensure that the element being dragged will appear on top of any others.

The rest of the script consists of the functions used to handle the three mouse events used in dragging.