window.onload = function()
{
	var test = document.getElementById("test");
	var timeout;
	
	var red = document.getElementById("red");
	var green = document.getElementById("green");
	var blue = document.getElementById("blue");
	blue.onmouseout = handler;
	blue.onmouseover = handler;
	var gray = document.getElementById("gray");
	gray.onmouseout = handler;
	gray.onmouseover = handler;
	
	function handler(evt)
	{
		if(!timeout) test.innerHTML = "";
		
		evt = evt || event;
		
		test.innerHTML += "<b>"+evt.type+":</b><br>";
		try{
			var mbc = new MouseBoundaryCrossing(evt, red);
		}catch(e){
			test.innerHTML += e.name+": "+e.message;
			return;
		}
		var action = mbc.leftLandmark ? "left" : mbc.enteredLandmark ? "entered" : mbc.inLandmark ? 
			"remained inside of" : "remained outside of";
		test.innerHTML += "Mouse has <span style=\"color:red;\">"+action+"</span> the red box.<br>";
		
		mbc = new MouseBoundaryCrossing(evt, green);
		action = mbc.leftLandmark ? "left" : mbc.enteredLandmark ? "entered" : mbc.inLandmark ? 
			"remained inside of" : "remained outside of";
		test.innerHTML += "Mouse has <span style=\"color:green;\">"+action+"</span> the green box.<br>";
		
		mbc = new MouseBoundaryCrossing(evt, blue);
		action = mbc.leftLandmark ? "left" : mbc.enteredLandmark ? "entered" : mbc.inLandmark ? 
			"remained inside of" : "remained outside of";
		test.innerHTML += "Mouse has <span style=\"color:blue;\">"+action+"</span> the blue box.<br>";
		
		mbc = new MouseBoundaryCrossing(evt, gray);
		action = mbc.leftLandmark ? "left" : mbc.enteredLandmark ? "entered" : mbc.inLandmark ? 
			"remained inside of" : "remained outside of";
		test.innerHTML += "Mouse has <span style=\"color:dimgray;\">"+action+"</span> the gray box.<br><br>";
		
		test.scrollTop = (test.scrollHeight<test.clientHeight ? test.clientHeight : test.scrollHeight) - test.clientHeight;
		
		timeout = setTimeout(function(){ timeout = null; }, 10);
	}
};


//since mouseenter & mouseleave are only supported in IE, this object helps to
// determine if the mouse is entering or leaving an element
//landmark: did the mouse enter or leave this "landmark" element? Was the event fired from within this element?
//usage:   var mbc = new MouseBoundaryCrossing(mouse_event, landmark);
function MouseBoundaryCrossing(evt, landmark)
{
	evt = evt || window.event;
	
	var eventType = evt.type;
	
	this.inLandmark = false;
	this.leftLandmark = false;
	this.enteredLandmark = false;
	
	if(eventType == "mouseout")
	{
		this.toElement = evt.relatedTarget || evt.toElement;
		this.fromElement = evt.target || evt.srcElement;
	}
	else if(eventType == "mouseover")
	{
		this.toElement = evt.target || evt.srcElement;
		this.fromElement = evt.relatedTarget || evt.fromElement;
	}
	else throw (new Error("Event type \""+eventType+"\" is irrelevant"));	//irrelevant event type
	
	//target is unknown
	//this seems to happen on the mouseover event when the mouse is already inside the element when the page loads and
	// the mouse is moved: fromElement is undefined
	if(!this.toElement || !this.fromElement) throw (new Error("Event target(s) undefined"));
	
	//determine whether from-element is inside or outside of landmark (i.e., does tmpFrom == the landmark or the document?)
	var tmpFrom = this.fromElement;
	while(tmpFrom.nodeType == 1)	//while tmpFrom is an element node
	{
		if(tmpFrom == landmark) break;
		tmpFrom = tmpFrom.parentNode;
	}
	
	//determine whether to-element is inside or outside of landmark (i.e., does tmpTo == the landmark or the document?)
	var tmpTo = this.toElement;
	while(tmpTo.nodeType == 1)	//while tmpTo is an element node
	{
		if(tmpTo == landmark) break;
		tmpTo = tmpTo.parentNode;
	}
	
	if(tmpFrom == landmark && tmpTo == landmark) this.inLandmark = true;	//mouse is inside landmark; didn't enter or leave
	else if(tmpFrom == landmark && tmpTo != landmark)	//mouse left landmark
	{
		this.leftLandmark = true;
		this.inLandmark = (eventType == "mouseout");	//mouseout: currently inside landmark, but leaving now
														//mouseover: currently outside of landmark; just left
	}
	else if(tmpFrom != landmark && tmpTo == landmark)	//mouse entered landmark
	{
		this.enteredLandmark = true;
		this.inLandmark = (eventType == "mouseover");	//mouseover: currently inside landmark; just entered
														//mouseout: currently outside of landmark, but entering now
	}
	//else	//mouse is outside of landmark; didn't enter or leave
}

