/////////////////////////////////////////////////////////////////////////////////////////////////////
// Developer	: Chris Hack
// Date			: 2006/11/12
// Description	: This module provides a code base for dealing with the Mouse and the document 
//				  Window.
// Dependencies : 
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Capture the mouse x,y position in a browser independent object that can be used globally
/////////////////////////////////////////////////////////////////////////////////////////////////////
var g_mouseDownListeners = new Array();
var g_mouseUpListeners = new Array();
var g_mouseMoveListeners = new Array();
var g_mouseWheelListeners = new Array();
var g_mouse = new function() {
        this.x = 0;
        this.y = 0;
        this.relativeX = 0;
        this.relativeY = 0;
}
var g_scroll = new function() {
        this.x = 0;
        this.y = 0;
}
var g_scrollListeners = new Array();
				  
function copyMouse() {
    return new function() {
        this.x = g_mouse.x;
        this.y = g_mouse.y;
        this.relativeX = g_mouse.relativeX;
        this.relativeY = g_mouse.relativeY;
    }
}

function copyScroll() {
    return new function() {
        this.x = g_scroll.x;
        this.y = g_scroll.y;
    }
}
				  
function registerMouseDownListener(handler) {
    g_mouseDownListeners[g_mouseDownListeners.length] = handler;
}

function registerMouseUpListener(handler) {
    g_mouseUpListeners[g_mouseUpListeners.length] = handler;
}

function registerMouseMoveListener(handler) {    
    g_mouseMoveListeners[g_mouseMoveListeners.length] = handler;
}

function translateMouseWheel(e) {
    var delta = 0;
    				        
    // IE
    if (!e) e = window.event;
    
    // IE & Opera
    if (e.wheelDelta) {
        delta = e.wheelDelta / 120;
        delta = (window.opera) ? -delta : delta;				            
    }
    // Firefox
    else if (e.detail) {
        delta = -e.detail / 3;
    }
    
    return delta;
} 

function registerMouseWheelListener(handler, element) {
   
    
    this.localwheel = function(e) {
        var delta = translateMouseWheel(e);
        if (this.mousewheelhandler) 
            setEventBubble(e, this.mousewheelhandler(delta));
    }
    
    this.globalwheel = function(e) {
        var delta = translateMouseWheel(e);        
        var bubbleEvent = true;
        
        for (var i = 0; i < g_mouseWheelListeners.length; i++) {
            bubbleEvent = bubbleEvent && g_mouseWheelListeners[i](delta);
        }
        
        setEventBubble(e, bubbleEvent);
    }
    
    if (element) {
        if (element.addEventListener)
	        element.addEventListener('DOMMouseScroll', this.localwheel, false);
	    element.onmousewheel = this.localwheel;
        element.mousewheelhandler = handler;
    }  
    else {
        if (window.addEventListener)
            window.addEventListener('DOMMouseScroll', this.globalwheel, false);
        window.onmousewheel = document.onmousewheel = this.globalwheel;
        g_mouseWheelListeners[g_mouseWheelListeners.length] = handler;
    }  
}

function setEventBubble(e, bubble) {
    if (!bubble) {
        // IE
        if (document.all) {
            window.event.cancelBubble = true;
            window.event.returnValue = false;
        }
        
        // FireFox, NetScape 6.0
	    else if (e.preventDefault) {
	        e.preventDefault();  
	    }
    }
}

document.onmousedown = function(e) {
    var bubbleEvent = true;
    
    for (var i = 0; i < g_mouseDownListeners.length; i++) {
        bubbleEvent = bubbleEvent && g_mouseDownListeners[i]();    
    }
    
    setEventBubble(e, bubbleEvent);
}

document.onmouseup = function(e) {
    var bubbleEvent = true;
    
    for (var i = 0; i < g_mouseUpListeners.length; i++) {
        bubbleEvent = bubbleEvent && g_mouseUpListeners[i]();        
    } 
    
    setEventBubble(e, bubbleEvent);       
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// To capture the mouse cooridinates we must handle the global onmousemove event of the entire 
// document and handle it correctly depending on the browser.
/////////////////////////////////////////////////////////////////////////////////////////////////////

document.onmousemove = function(e) {
	// IE
	if (document.all) {		
		// Have to handle both cases of IE (strict or non-strict) modes
		var iebody = getDocumentElement();
		
		g_mouse.x = event.x + iebody.scrollLeft;
		g_mouse.y = event.y + iebody.scrollTop;
		
		// IE has a quirky mode of starting the actual content at offset(2,2)
        if (iebody.clientLeft > 0) g_mouse.x -= iebody.clientLeft;
        if (iebody.clientTop > 0) g_mouse.y -= iebody.clientTop;

		
		// In IE elements with relative position style show up with a relative position for the mouse
		if (event.srcElement.className == 'RelativePosition') {
			g_mouse.x += getElementX(event.srcElement);
			g_mouse.y += getElementY(event.srcElement);
		}
		
		g_mouse.relativeX = g_mouse.x - iebody.scrollLeft;
		g_mouse.relativeY = g_mouse.y - iebody.scrollTop;
		
	}
	// FireFox, NetScape 6.0
	else if (document.getElementById) {
		g_mouse.x = e.pageX;
		g_mouse.y = e.pageY;
		g_mouse.relativeX = g_mouse.x - window.pageXOffset;
		g_mouse.relativeY = g_mouse.y - window.pageYOffset;
	}
	
	// Bubble this event to all listeners
	var bubbleEvent = true;
	for (i = 0; i < g_mouseMoveListeners.length; i++) {
		bubbleEvent = bubbleEvent && g_mouseMoveListeners[i]();
	}
	setEventBubble(e, bubbleEvent);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

function registerScrollListener(handler) {
    g_scrollListeners[g_scrollListeners.length] = handler;
}

window.onscroll = function(e) {
    // IE
	if (document.all) {		
		// Have to handle both cases of IE (strict or non-strict) modes
		var iebody = getDocumentElement();
	
	    g_scroll.x = iebody.scrollLeft;
	    g_scroll.y = iebody.scrollTop;
	}
	else {
	    g_scroll.x = window.pageXOffset;
	    g_scroll.y = window.pageYOffset;
	}
	
	var bubbleEvent = true;
	for (i = 0; i < g_scrollListeners.length; i++) {
	    bubbleEvent = bubbleEvent && g_scrollListeners[i]();
	}
	setEventBubble(e, bubbleEvent);
}

function getDocumentElement() {
    // IE
    if (document.all) {
        return (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body;
    }
    else {
        return document.documentElement;
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Finds the coordinates of the browser window
/////////////////////////////////////////////////////////////////////////////////////////////////////
function getBrowserX() {
    if (document.all) return top.screenLeft;
    else return top.screenX;
}

function getBrowserY() {
    if (document.all) return top.screenTop;
    else return top.screenY;
}

function getBrowserWidth() {
    if (top.outerWidth) return top.outerWidth;
    else return top.document.body.clientWidth;

}

function getBrowserHeight() {
    if (top.outerHeight) return top.outerHeight;
    else return top.document.body.clientHeight;
}

function PopupPointCenteredOnBrowser(width, height) {
    if (top.outerWidth) {
        this.top = getBrowserY() + ((getBrowserHeight() - height) / 2);
        this.left = getBrowserX() + ((getBrowserWidth() - width) / 2);
    }
    // Opera forces popup windows to be inside the tab client area
    else if (window.opera) {
        this.top = (top.document.body.clientHeight - height) / 2;
        this.left = (top.document.body.clientWidth - width) / 2;
    }    
    // IE doesn't allow you to find the actual window size, only the body size
    // so we just center on the screen
    else {
        this.top = (screen.availHeight - height) / 2;
        this.left = (screen.availWidth - width) / 2;
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Finds the X coordinate of the element from the left most edge of the window
/////////////////////////////////////////////////////////////////////////////////////////////////////
function getElementX(element) {
	var x = 0;
	
	while (element.offsetParent) {
		x += element.offsetLeft;
		element = element.offsetParent;
	}
	
	return x;
}// getElementX
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Sets the X coordinate of the element from the left most edge of the window
/////////////////////////////////////////////////////////////////////////////////////////////////////
function setElementX(element, x) {
	element.style.left = x + 'px';
}// setElementX
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Finds the Y coordinate of the element from the left most edge of the window
/////////////////////////////////////////////////////////////////////////////////////////////////////
function getElementY(element) {
	var y = 0;
	
	while (element.offsetParent) {
		y += element.offsetTop;
		element = element.offsetParent;
	}

	return y;
}// getElementY
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Sets the Y coordinate of the element from the left most edge of the window
/////////////////////////////////////////////////////////////////////////////////////////////////////
function setElementY(element, y) {
	element.style.top = y + 'px';
}// setElementY
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Gets the width of the element
/////////////////////////////////////////////////////////////////////////////////////////////////////
function getElementWidth(element) {
	return Math.max(element.clientWidth, element.offsetWidth);
}// getElementWidth
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Sets the width of the element
/////////////////////////////////////////////////////////////////////////////////////////////////////
function setElementWidth(element, width) {
	element.style.width = width + 'px';
	
	// Make sure the actual width is acheived (things like borders and padding can throw it off)
	var offset = width - getElementWidth(element);
	width = width + offset;
	
	element.style.width = width + 'px';
}// setElementWidth
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Gets the height of the element
/////////////////////////////////////////////////////////////////////////////////////////////////////
function getElementHeight(element) {
	return Math.max(element.clientHeight, element.offsetHeight);
}// getElementHeight
/////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////
// Sets the height of the element
/////////////////////////////////////////////////////////////////////////////////////////////////////
function setElementHeight(element, height) {
	element.style.height = height + 'px';
	
	// Make sure the actual height is acheived (things like borders and padding can throw it off)
	var offset = height - getElementHeight(element);
    height = height + offset;
		
	element.style.height = height + 'px';
}// setElementHeight
/////////////////////////////////////////////////////////////////////////////////////////////////////

function setGrabCursor(element, url) {
    // IE
    if (document.all) {                                    // include this for IE 6 bug 
        element.style.cursor = (url)? "url('" + url + "'), '" + url + "', grab, move" : "grab, move";
    }
    
    // Mozilla
    else {
        element.style.cursor = "-moz-grab";
    }
}

function setGrabbingCursor(element, url) {
    // IE
    if (document.all) {                                    // include this for IE 6 bug
        element.style.cursor = (url)? "url('" + url + "'), '" + url + "', grabbing, move" : "grabbing, move";
    }
    
    // Mozilla
    else {
        element.style.cursor = "-moz-grabbing";
    }
}