Drag and Drop Concepts

Drag and drop scripts are entirely based around the mouse events. This lesson will show step by step how to make one layer draggable. The next lesson will show how to make any number of layers draggable with a generic Drag Object.

A drag and drop sequence is handled like so:

Setting up the Layer:

I will be using one layer named "square" and defining a DynLayer to it named "dragObject"

<script language="JavaScript">
<!--

function init() {
	dragObject = new DynLayer("square")
	dragObject.dragActive = false
}

//-->
</script>
<style type="text/css">
<!--
#square {position:absolute; left:100px; top:120px; width:50px; height:50px; clip:rect(0px 50px 50px 0px); background-color:blue; layer-background-color:blue;}
-->
</style>
</head>

<body bgcolor="#FFFFFF" onload="init()">

<div id="square"></div>

Notice I have tacked on a dragActive property to the DynLayer. This boolean property will represent whether the layer is currently being dragged.

The MouseDown Handler

The first stage in the drag sequence is to check if you have clicked on the layer or not. To do this you simply compare the x-y coordinate of the mouse to the edges of the layer:

if (x>=dragObject.x && x<=dragObject.x+dragObject.w && y>=dragObject.y && y<=dragObject.y+dragObject.h)

If we have indeed clicked on a layer we will begin the actual dragging of the layer. All that's needed in the mouseDown is to set the dragActive flag to true:

if (x>=dragObject.x && x<=dragObject.x+dragObject.w && y>=dragObject.y && y<=dragObject.y+dragObject.h) {
	dragObject.dragActive = true
	return false
}

Notice that I have placed a return false in the block if we have clicked on a layer. This stops Netscape from using the mouseDown event for anything else (including a MacIntosh mouse-hold).

The full mouseDown handler looks like this:

function mouseDown(e) {
	if ((is.ns && e.which!=1) || (is.ie && event.button!=1)) return true
	var x = (is.ns)? e.pageX : event.x+document.body.scrollLeft
	var y = (is.ns)? e.pageY : event.y+document.body.scrollTop
	if (x>=dragObject.x && x<=dragObject.x+dragObject.w && y>=dragObject.y && y<=dragObject.y+dragObject.h) {
		dragObject.dragActive = true
		return false
	}
	else return true
}

The MouseMove Handler

The mouseDown handler on it's own won't do anything to the layer, but by setting the dragActive flag to true we have a way of "activating" the mouseMove event. The mouseMove event simply checks if the dragActive flag is true, and if so moves the layer to the coordinates of the mouse:

function mouseMove(e) {
	var x = (is.ns)? e.pageX : event.x+document.body.scrollLeft
	var y = (is.ns)? e.pageY : event.y+document.body.scrollTop
	if (dragObject.dragActive) {
		dragObject.moveTo(x,y)
		return false
	}
	else return true
}

As soon as dragActive is set to true the mouseMove function will begin moving the layer. Again note the placement of the return false, it is important. While we are dragging the layer around we do not want Netscape to use the mouseMove event for anything else (such as selecting text).

The MouseUp Handler

To end the drag sequence all you need to do is set the dragActive flag back to false. This stops the mouseMove function from moving the layer:

function mouseUp(e) {
	var x = (is.ns)? e.pageX : event.x+document.body.scrollLeft
	var y = (is.ns)? e.pageY : event.y+document.body.scrollTop
	dragObject.dragActive = false
	return true
}

In this case no return false is necessary. It doesn't matter if Netscape handles the mouseUp event anymore because we have already stopped the drag sequence.

View dragconcepts.html to see this example

Accounting for the Offset Values

You'll notice in that example that if the layer is moved directly to the location of the layer it doesn't look right. The layer pops to the corner regardless of where it was click on. We can account for this situation and correct it by capturing the difference between the location of the layer, and the coordinate of the mouse (the offset values). This is done in the mouseDown function:

if (x>=dragObject.x && x<=dragObject.x+dragObject.w && y>=dragObject.y && y<=dragObject.y+dragObject.h) {
	dragObject.dragOffsetX = x-dragObject.x
	dragObject.dragOffsetY = y-dragObject.y
	dragObject.dragActive = true
	return false
}

By tacking on the dragOffsetX and dragOffsetY properties we have captured the offset values and can utilize them in the mouseMove handler to move the layer accordingly:

if (dragObject.dragActive) {
	dragObject.moveTo(x-dragObject.dragOffsetX,y-dragObject.dragOffsetY)
	return false
}

View dragconcepts2.html to see the complete drag and drop example

Home Next Lesson: Drag Object
copyright 1998 Dan Steinman


Casa de Bender