
/* 
## HEADER
##
##########################################################################
## Class cMouseEvent #####################################################
##########################################################################
## 
## File       : cMouseEvent.js
## Author     : Stefan Wilhelm
## Homepage   : www.AtWillys.de
## Created at : Sept-08-2004
## Copyright  : Stefan Wilhelm, 2004
## Licence    : Freeware for noncommercial usage (GPL)
##              You are free to use and change this file if you do not
##              change this header.
##
## Description:
## ######################################################################
## 
## This javascript-"class" enables the programmer to catch mouse events
## in the same way using different browsers. Therefore he includes this
## file and creates a new cMouseObject using the constructor 
##
##   function cMouseEvent(referedObject, userEventHandler, catchedEvents)
##
##   for a HTML-Object referedObject, e.g. document.getElementById(...), 
##     document.body, document.layers, document.all.tags[..], .... 
##
##   for a self made function userEventHandler, which implements actions
##     for the registered events. e.g If You write a function MyHandler(e) {...}
##     then use MyHandler as parameter. The Parameter e points/referes to
##     your cMouseEvent-object and gives infomation about the occoured 
##     event.
##
##   for one or more events that you want to catch. Use the Flags below 
##     (cME_) for the event. For more than one event use the or- operator |
##     or simply the plus-operator +.
##
##
##  Example: myMouseEvent = new cMouseEvent(
##                                            MyDIVLayer,
##                                            MyDIVLayerEventHandler,
##                                            cME_MOUSEDOWN + cME_MOUSEMOVE + cME_MOUSEUP
##                                         );
##                  
##    
##  You can always block, unblock, debug and delete/kill an event using this class.
##  For the given example, write a function
##
##  //////////////////////////////////////////////////////////////////  
##
##  function MyDIVLayerEventHandler(e) {
##
##		switch(e.type) {
##         case cME_MOUSEDOWN:
##            // Actions //
##            break;
##         case cME_MOUSEMOVE:
##            // Actions //
##            break;
##         case cME_MOUSEUP:
##            // Actions //
##            break;
##         default:
##            // Actions if other event (error) //
##      }
##      
##      // Actions for all events.
##
##
##  //////////////////////////////////////////////////////////////////
##
##  The cMouseEvent-object e gives to You:
##    e.type   : Which type the event is. Good for switch{case}
##    e.button : Which button was pressed. 
##                  	   cME_BUTTONNONE    : no button
##                         cME_BUTTONLEFT    : left button
##                         cME_BUTTONRIGHT   : right button
##                         cME_BUTTONMIDDLE  : middle button
##             
##    e.absCrds.x : Absolute page coordinate X.
##    e.absCrds.y : Absolute page coordinate y.
##    
##    Both coordinates are refered to the top of site, not top of window.
##    That means if the user scrolls down by 500 pixels and moves the 
##    mouse to the top of the window, the absCrds.y will be 500, not 0.
##    The same for x and scroll left.
##
#########################################################################
## GIMMIC FUNCTIONS
#########################################################################
##
##  If you have created : MyEvent = new cMouseEvent( ... ),
##    then you can block the event at any time in any function using
##    
##       MyEvent.block();
##
##    and continue catching events with
##
##       MyEvent.unblock();
##
##    If you want to see what happens there, use
##
##       MyEvent.debug();
##
##    and take a look to the status-bar.
##
##    The Method
##    
##      MyEvent.Kill();
##
##    deletes and unregisteres the event and cleans up the memory.
##
##
##    e.relCrds.x : Object-relative coordinate x
##    e.relCrds.y : Object-relative coordinate y
##
##    Both are refered to the top of the object that throws the event, 
##    e.g. an IMG, DIV, SPAN and so on. That means if you have created
##    a new cMouseEvent(..) for a refered HTML-IMG-Object and move the
##    mouse to the left border of this IMG, the relCrds.x will be 0 and
##    not the distance of the IMG to the left border of the whole page.
##    The same for e.relCrds.y. Top Left of an object is (0/0).
##
#########################################################################
## DO NOT USE THE PROPERTIES BELOW, I DID NOT FIX THAT YET.
#########################################################################
##
##    e.shift, e.alt, e.ctrl (has been deleted, 'cause NS6, FireF and 
##               Mozilla have Problems with event.modifiers. Opera does 
##               not support the ALT-Key.
##
##
#########################################################################
#########################################################################
##
## END HEADER
*/


/* 
##########################################################################
## Object Constructor ####################################################
##########################################################################
## Call this function to create a new capture.
##
## Input parameters
##   referedObject    : A document object, e.g. 
##                      document.GetElementById("myDIVBlock")
##   userEvent handler: Reference (name) to a function that should be 
##                      executed if an listened event occours. Standard
##                      function is cMouseEventPhantom(), which does
##                      nothing.
##   catchedEvents    : One or more event-types that you want to capture.
##                      Use the flags below to select the events.
*/
                        var cME_CLICK         = 0x01;
                        var cME_DBLCLICK      = 0x02;
                        var cME_MOUSEDOWN     = 0x04;
                        var cME_MOUSEUP       = 0x08;
                        var cME_MOUSEOVER     = 0x10;
                        var cME_MOUSEMOVE     = 0x20;
                        var cME_MOUSEOUT      = 0x40;
/*
##                      If You want to use more than one event, use
##                      OR-Operator or the Plus-Operator to concatenate.
##                      e.g. cME_CLICK | cME_MOUSEOVER
##                      e.g. cME_CLICK + cME_MOUSEOVER
##                      Standart is MouseMove and Click
##########################################################################
*/
						var cME_BUTTONNONE   = 0x00;
                        var cME_BUTTONLEFT   = 0x01;
                        var cME_BUTTONRIGHT  = 0x02;
                        var cME_BUTTONMIDDLE = 0x04;


function cMouseEvent(referedObject, userEventHandler, catchedEvents) {
	
	/* Init and error prevention */
	
	if(!catchedEvents) { 
		/* Standart event settings: MouseMove and Click */
		catchedEvents = cME_CLICK | cME_MOUSEMOVE;
	} else {
		/* No catched events --> Error*/
		if(catchedEvents==0x00) {
			alert("If you don't intend to use MouseEvents, then " + 
			      "do not load this object !?\n (That means parameter" + 
				  " catchedEvents=0)");
			return 0;
		}
	}

	if (!userEventHandler) 			{ userEventHandler = cMouseEventPhantom;}
	if (!referedObject) 			{ alert("No object to catch events!"); return 0;}
	if (cMouseEvent_IsInit!=true)	{ cMouseEventInit();}

	/* Init Event-Handlers */
    if((catchedEvents & cME_CLICK)!=0)		{referedObject.onclick 		= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_DBLCLICK)!=0)	{referedObject.ondblclick	= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_MOUSEDOWN)!=0)	{referedObject.onmousedown	= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_MOUSEUP)!=0)	{referedObject.onmouseup	= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_MOUSEOVER)!=0)	{referedObject.onmouseover	= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_MOUSEMOVE)!=0)	{referedObject.onmousemove	= eval(cMouseEvent_GESR);}
	if((catchedEvents & cME_MOUSEOUT)!=0)	{referedObject.onmouseout	= eval(cMouseEvent_GESR);}
	
	/* Register this event object*/
	cMouseEvent_AllCapturedEvents.push(this);
	
	/* Init Methods */
	this.handler = userEventHandler;

	/* Init Properties */
	this.blocked   = null;
	this.debugging = null;
	this.events    = catchedEvents;
	this.refObj    = referedObject;
	
	/* Init user Methods*/
	this.debug   = cMouseEventDebug;
	this.block   = cMouseEventBlock;
	this.unblock = cMouseEventUnBlock;
	this.kill    = cMouseEventKill;
	
	/* Init user Properties */
	this.absCrds = new cMouseEventCoords();
	this.relCrds = new cMouseEventCoords();
	this.button  = 0;
	this.type    = 0;
	
	/* Return success */
	return 1; 
}

/* 
##########################################################################
## Sub Objects ###########################################################
##########################################################################
*/

function cMouseEventCoords()	{ this.x = 0; this.y	= 0; 	}
function cMouseEventDebug()	{ this.debugging 		= true;	}
function cMouseEventBlock()	{ this.blocked 		= true;	}	
function cMouseEventUnBlock()	{ this.blocked			= null;	}
function cMouseEventKill(p)	{ 
	this.block();	
	for (var key in cMouseEvent_AllCapturedEvents) {
		if(cMouseEvent_AllCapturedEvents[key]==this) {
			cMouseEvent_AllCapturedEvents[key] = null;
			break;
		}
	}	
	if((this.events & cME_CLICK)!=0)		{this.refObj.onclick 		= null;}
	if((this.events & cME_DBLCLICK)!=0)	{this.refObj.ondblclick	= null;}
	if((this.events & cME_MOUSEDOWN)!=0)	{this.refObj.onmousedown	= null;}
	if((this.events & cME_MOUSEUP)!=0)	{this.refObj.onmouseup		= null;}
	if((this.events & cME_MOUSEOVER)!=0)	{this.refObj.onmouseover	= null;}
	if((this.events & cME_MOUSEMOVE)!=0)	{this.refObj.onmousemove	= null;}
	if((this.events & cME_MOUSEOUT)!=0)	{this.refObj.onmouseout	= null;}
	cMouseEventKillMe(this);
}

function cMouseEventKillMe(obj) {
	/* Obj cannot delete itself, that's because that fn()*/
	delete(obj.absCrds); obj.absCrds = null;
	delete(obj.relCrds); obj.relCrds = null;
	delete(obj); obj=null;
}


function cMouseEventFindRef(refObj) {
	if(!refObj) return null;
	for(var i=0; i<cMouseEvent_AllCapturedEvents.length; i++) {
	//	alert(	refObj.getAttribute("id") +	"/"	+ cMouseEvent_AllCapturedEvents[i].refObj.getAttribute("id") + 	" -- "	+ (cMouseEvent_AllCapturedEvents[i].refObj==refObj));
		if(cMouseEvent_AllCapturedEvents[i].refObj==refObj) 
			return cMouseEvent_AllCapturedEvents[i];
	}
	return null;
}

/* 
##########################################################################
## Global Event Routines (Browser dependened) ############################
##########################################################################
*/

function cMouseEventGESRWinIE() { 
	/* Find registered source */
	var e  = window.event
	var se = e.srcElement; 
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.absCrds.x = (e.clientX + document.body.scrollLeft);
	o.absCrds.y = (e.clientY + document.body.scrollTop);
	if(se==e.srcElement) {
		o.relCrds.x = (e.offsetX);
		o.relCrds.y = (e.offsetY);
	} else {
		o.relCrds.x = (o.absCrds.x-se.offsetLeft);
		o.relCrds.y = (o.absCrds.y-se.offsetTop);
	}
	o.button    = (cMouseEvent_ButtonPattern[e.button] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type]);
	/* Call user handler and/or debug handler */
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRMacIE() { 
	/* Find registered source */
	var e = window.event;
	var se = e.srcElement; 
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.relCrds.x = (e.offsetX);
	o.relCrds.y = (e.offsetY);
	o.absCrds.x = (e.clientX + ((document.body.scrollLeft) ? (document.body.scrollLeft) : (0)));
	o.absCrds.y = (e.clientY + ((document.body.scrollTop) ? (document.body.scrollTop) : (0)));
	o.button    = (cMouseEvent_ButtonPattern[e.button] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type]);
	/* Call user handler and/or debug handler */
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRAllOP(e) { 
	/* Find registered source */
	var se = e.srcElement; 
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.relCrds.x = (e.clientX-se.offsetLeft);
	o.relCrds.y = (e.clientY-se.offsetTop);
	o.absCrds.x = (e.clientX + ((document.body.scrollLeft) ? (document.body.scrollLeft) : (0)));
	o.absCrds.y = (e.clientY + ((document.body.scrollTop) ? (document.body.scrollTop) : (0)));
	o.button    = (cMouseEvent_ButtonPattern[e.button] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type]);
	/* Call user handler and/or debug handler */
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRAllFF(e) {
	/* Find registered source */
	var se = e.target;
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.relCrds.x = (e.pageX-se.offsetLeft);
	o.relCrds.y = (e.pageY-se.offsetTop);
	o.absCrds.x = (e.pageX);
	o.absCrds.y = (e.pageY);
	o.button    = (cMouseEvent_ButtonPattern[e.which] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type] || 0);
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRAllMZ(e) { 
	/* Find registered source */
	var se = e.target;
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.relCrds.x = (e.pageX-se.offsetLeft);
	o.relCrds.y = (e.pageY-se.offsetTop);
	o.absCrds.x = (e.pageX);
	o.absCrds.y = (e.pageY);
	o.button    = (cMouseEvent_ButtonPattern[e.which] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type] || 0);
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRAllNS6(e) { 
	/* Find registered source */
	var se = e.target;
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.relCrds.x = (e.pageX-se.offsetLeft);
	o.relCrds.y = (e.pageY-se.offsetTop);
	o.absCrds.x = (e.pageX);
	o.absCrds.y = (e.pageY);
	o.button    = (cMouseEvent_ButtonPattern[e.which] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type] || 0);
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}

function cMouseEventGESRW3C() { 
	/* Find registered source */
	var e  = window.event
	var se = e.srcElement; 
	var o  = cMouseEventFindRef(se);
	for(var i=64; !o && se && se.parentNode && i>0;i--)
		o = cMouseEventFindRef(se = se.parentNode);
	if(!o) return;
	/* Update properties */
	o.absCrds.x = (e.clientX + document.body.scrollLeft);
	o.absCrds.y = (e.clientY + document.body.scrollTop);
	if(se==e.srcElement) {
		o.relCrds.x = (e.offsetX);
		o.relCrds.y = (e.offsetY);
	} else {
		o.relCrds.x = (o.absCrds.x-se.offsetLeft);
		o.relCrds.y = (o.absCrds.y-se.offsetTop);
	}
	o.button    = (cMouseEvent_ButtonPattern[e.button] || 0);
	o.type      = (cMouseEvent_AllEventFlags[e.type]);
	/* Call user handler and/or debug handler */
	if(!o.blocked) o.handler(o);
	if(o.debugging) cMouseEventDebugEvent(se,o);
}


/* 
##########################################################################
## Phantom Handler #######################################################
##########################################################################
*/

function cMouseEventPhantom(e) {if(debugging) window.status = "PhantomEvent(null)";}

function cMouseEventDebugEvent(obj,e) {
	if(!(e && e.relCrds && e.relCrds.x)) return;
	if(obj && obj.getAttribute && obj.getAttribute("id")) {
		window.status = "Event for: "+obj.getAttribute("id") +
									"( rel[" + e.relCrds.x	+ "/" 
											 + e.relCrds.y	+ "], abs[" 
											 + e.absCrds.x 	+ "/"
											 + e.absCrds.y 	+ "], button:" + 
											 + e.button	+ ", type:" +
											 + e.type		+
									");";
	} 
}

/* 
##########################################################################
## Browser Identification ################################################
##########################################################################
*/

function cMouseEventInit() {
	/* Setup General Interrupt Service Routine */
	cMouseEvent_GESR 	= "cMouseEventGESR" + cMouseEventBrowserId();
	/* Setup common event flags*/
	cMouseEvent_AllEventFlags["click"] = 0x01;
	cMouseEvent_AllEventFlags["dblclick"] = 0x02;
	cMouseEvent_AllEventFlags["mousedown"] = 0x04;
	cMouseEvent_AllEventFlags["mouseup"] = 0x08;
	cMouseEvent_AllEventFlags["mouseover"] = 0x10;
	cMouseEvent_AllEventFlags["mousemove"] = 0x20;
	cMouseEvent_AllEventFlags["mouseout"] = 0x40;
	/* Setup browser dependened button mask*/
	switch(cMouseEvent_GESR) {
		case "cMouseEventGESRWinIE":	
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x02,0x00,0x04); break;
		case "cMouseEventGESRWinIE4": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x02,0x00,0x04); break;
		case "cMouseEventGESRAllOP": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x02,0x00,0x04); break;
		case "cMouseEventGESRMacIE": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x02,0x00,0x04); break;
		case "cMouseEventGESRMacIE4": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x02,0x00,0x04); break;
		case "cMouseEventGESRAllFF": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x04,0x02,0x00); break;
		case "cMouseEventGESRAllMZ": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x04,0x02,0x00); break;
		case "cMouseEventGESRAllNS6": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x04,0x02,0x00); break;
		case "cMouseEventGESRAllNS4": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x04,0x02,0x00); break;
		case "cMouseEventGESRW3C": 
			cMouseEvent_ButtonPattern = new Array(0x00,0x01,0x04,0x02,0x00); break;
	}
	
	/* Prove that is init */
	cMouseEvent_IsInit 	= true;
}

function cMouseEventBrowserId() {

	/* Identification Flags */
	var AGT	= 	(navigator && navigator.userAgent && navigator.userAgent) ?
				(navigator.userAgent.toLowerCase()) : ("");
	var MAC	= 	(AGT.indexOf("mac") > -1) ? (1) : (0);
	var WIN	= 	(AGT.indexOf("windows") > -1) ? (1) : (0);
	var DOM	= 	(document && document.getElementById) ? (1) : (0);
	var IE	= 	(AGT.indexOf("msie") > -1 && document && document.all &&
				document.body && document.body.innerHTML) ? (1) : (0);
	var OP 	= 	(AGT.indexOf("opera") > -1 && window && window.opera) ? (1) : (0); 
	var NS	= 	(AGT.indexOf("netscape") > -1) ? (1) : (0);
	var MZ	= 	(AGT.indexOf("gecko") > -1) ? (1) : (0);
	var FF	= 	(AGT.indexOf("firefox") > -1) ? (1) : (0);

	/* Combination and result */
	if ( DOM && IE	&& WIN)	{cMouseEvent_BrowserId = "WinIE"; return cMouseEvent_BrowserId;} 	// OK
	if (!DOM && IE	&& WIN)	{cMouseEvent_BrowserId = "WinIE4"; return cMouseEvent_BrowserId;} 
	if ( DOM && FF) 		{cMouseEvent_BrowserId = "AllFF"; return cMouseEvent_BrowserId;}  	// OK
	if ( DOM && OP) 		{cMouseEvent_BrowserId = "AllOP"; return cMouseEvent_BrowserId;}	// OK
	if ( DOM && NS) 		{cMouseEvent_BrowserId = "AllNS6"; return cMouseEvent_BrowserId;}	// OK
	if (!DOM && NS) 		{cMouseEvent_BrowserId = "AllNS4"; return cMouseEvent_BrowserId;}
	if ( DOM && MZ) 		{cMouseEvent_BrowserId = "AllMZ"; return cMouseEvent_BrowserId;}	// OK
	if ( DOM && IE && MAC)	{cMouseEvent_BrowserId = "MacIE"; return cMouseEvent_BrowserId;}	// OK
	if (!DOM && IE && MAC)	{cMouseEvent_BrowserId = "MacIE4"; return cMouseEvent_BrowserId;}	// OK
	if (DOM)				{cMouseEvent_BrowserId = "W3C"; return cMouseEvent_BrowserId;}
	/* If it goes to here, I've something forgotten --> Error*/
	alert("swErr:No such Browser signature. Cannot init cMouseEvent-object.");
	return 0; 
}

/* 
##########################################################################
## Global Variables ######################################################
##########################################################################
*/

	var cMouseEvent_AllCapturedEvents = new Array();
	var cMouseEvent_AllEventFlags = new Array();
	var cMouseEvent_IsInit 	= false;
	var cMouseEvent_ButtonPattern;
	var cMouseEvent_GESR 	= "";
	cMouseEventInit();










