DynAPI Mouse Events

Just as you can capture keyboard events, you can capture mouse events like onMouseDown, onMouseUp, and onMouseMove - there are other if you want to read up on them but these are the most important ones. For each of these events, you can obtain the location of the mouse and use those coordinates to move a layer.

The first part will explain the basics of mouse events in a cross-browser setting, the second part will explain the mouse event functions used for elements in the DynAPI.

Overview of Document Mouse Events:

Each of onMouseDown, onMouseUp, and onMouseMove are initialized the same way. Here's the set up I like to use:

function init() {
	document.onmousedown = mouseDown
	document.onmousemove = mouseMove
	document.onmouseup = mouseUp
	if (is.ns) document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP)
}

function mouseDown(e) {
}
function mouseMove(e) {
}
function mouseUp(e) {
}

The function names can be whatever you want, but to keep it consitant I will always use mouseDown(e), mouseMove(e), and mouseUp(e). Netscape 4 has a different event model than IE which requires you to "capture" events before they can be used. In IE they are always captured.

Getting the Mouse Coordinates

The "e's" in each function represent the built-in Event object for Netscape. It is how Netscape obtainss the location of the mouse:

function mouseDown(e) {
	if (is.ns) {
		var x = e.pageX
		var y = e.pageY
	}
}

IE will ignore the e's because it uses a slightly different system for capturing mouse events. IE has an "window.event" object which handles all events. The window.event object contains the properties x and y which represent the location of where the mouse event occured:

function mouseDown(e) {
	if (is.ns) {
		var x = e.pageX
		var y = e.pageY
	}
	if (is.ie) {
		var x = event.x
		var y = event.y
	}
}

Those values reflect where in IE's browser window the mouse event occured - it does not necessarily reflect exactly where on the document has been clicked. If you scroll down the window.event.y value isn't in synch with the document, so we have to account for that discrepency ourselves. You add the amount that the document has been scrolled by using document.body.scrollTop.

var x = event.x+document.body.scrollLeft
var y = event.y+document.body.scrollTop

What I usually like to do is compact the x-y capturing with these 2 lines:

var x = (is.ns)? e.pageX : event.x+document.body.scrollLeft
var y = (is.ns)? e.pageY : event.y+document.body.scrollTop

Now when any of the events occur we can work with the x and y variables (the current location of the mouse) and do some neat things with them.

An improvemet I like to do is only allow left mouse button clicks. In Netscape you check for e.which, and IE you check for event.button:

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
}

I like to do this because the default action when right clicking your mouse is to pop open the command menu (Back, Forward etc). This interfers when coding mouse events, so I don't do anything when you right click.

Return Values:

The return values in the mouse events are very important for Netscape. When you click the mouse somewhere on a page, the document recieves the event first (and thus the mouseDown event is triggered). Even if you are clicking on a hyperlink the mouseDown event will be called. By returning true in the event handler you allow other elements on the page use that event. If you return false you stop the page from doing anything else with that event. So for example if you were to always return false in your mouseDown handler:

function mouseDown(e) {
	return false
}

Than you would never be able to click on a hyperlink - which is obviously not desired. Always returning true isn't the answer either because sometimes elements on the page will interfere with what you want to do with the mouse. Also, on MacIntosh's there is no left mouse button. So to open the command menu you must hold down the mouse for about a second before it pops up. This causes major problems. But by returning false in the mouseDown handler it will stop this from occuring.

The mouseMove event is a bit of a pain as well. On the document, the mouseMove event is what allows you to select/highlight text on the page (for copy/paste reasons). By returning false in the mouseMove event you disable Netscape from being able to highlight the text.

So you must carefully place a return false only when you are specifically making use of the event, all other times you return true. Notice I return true when checking if the left mouse button was not clicked (I let the document use the mouseDown event).

In the end, these are the mouse functions that work pretty good

function init() {
	document.onmousedown = mouseDown
	document.onmousemove = mouseMove
	document.onmouseup = mouseUp
	if (is.ns4) document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP)
}

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
	// your code goes here
	return true
}
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
	// your code goes here
	return true
}
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
	// your code goes here
	return true
}

Example: mouseevents1.html [source] - a quick mouse event example.

DynAPI Mouse Events

To replace the need to manually insert the above functions, I've created a default JavaScript file that I'll be using in demos that require document mouse events. The particular sections are the Drag object and the Scroll2 object.

To use the DynAPI mouse events include the mouseevents.js file after the dynlayer.js and BEFORE the drag.js and scroll2.js if you will be using them:

<script language="JavaScript" src="../dynlayer.js"></script>
<script language="JavaScript" src="../mouseevents.js"></script>
<script language="JavaScript" src="../drag.js"></script>  // if needed
<script language="JavaScript" src="../scroll2.js"></script>  // if needed

These files will take care of retrieving the co-ordinates of the mouse, and the handling required to operate the Scroll2 and the Drag object. To initialize these you'll call the initMouseEvents() function in the init():

function init() {
	initMouseEvents()
}

Instead of having your own mouseDown, mouseMove, and mouseUp functions, you can now have simpler means of obtaining mouse coordinates by incorporating the DynMouseDown, DynMouseMove, and DynMouseUp functions:

function DynMouseDown(x,y) {
	// your code for mousedown
	return true
}

function DynMouseMove(x,y) {
	// your code for mousemove
	return true
}

function DynMouseUp(x,y) {
	// your code for mouseup
	return true
}

These functions are optional. If the mouse events are only to be used by a Scroll2 or the Drag, then they don't even have to be included in your source code because the above empty default functions are already in the MouseEvents code.

Example: mouseevents1.html [source] - for a DynAPI Mouse Event example.

Source Code

mouseevents.js

Layer-based Mouse Events

In the DynLayer Mouse Events lesson I explain how to use layer-based events which are essentially the same as I've outlined here except all the events occur directly on the layer.

Home Next Lesson: Drag and Drop Concepts
copyright 1998 Dan Steinman