// Statics and other utils
// Hans Dybkjær 2008-06-16
//////////////////////////////////////////////////////////////////
// Browser dependent junk
var Browser = {};
	// Browser independent event targets
	// In: eventobject e: The object of the event
	// Return: Node: the HTML target node
Browser.Target = function(e)
	{
		var target = (e.target) ? e.target : e.srcElement;
		// if (target.nodeType == 3) // defeat Safari bug
		// target = target.parentNode;
		return target;
	}

	// Repair IE event object
	// In: object e: event or IE junk
	// Return: Event object: proper event object
Browser.EventRepair = function(e)
	{
		return (e) ? e : window.event;
	}
	
	// Return event key code
	// In: object e: event
	// Return: Event object: proper event object
Browser.KeyCode = function(e)
	{
		var code;
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		return code;
	}
	// Return event key code
	// In: object e: event
	// Return: Event object: proper event object
Browser.KeyChar = function(e)
	{
		return String.fromCharCode(Browser.KeyCode(e));
	}


	// Mouse clicks, property "button":
	// W3C serious Junk:
	//    * Left button : 0
	//    * Middle button : 1
	//    * Right button : 2
	// IE Exactly what we need:
	//    * Left button : 1
	//    * Middle button : 4
	//    * Right button : 2

	// Check for right click
	// In: object e: event
	// Return: bool: true iff rightclick
Browser.isRightClick = function(e)
	{
		var rightclick = e.button ? (e.button == 2) : false; // old netscape uses e.which == 3, ignore this 
		return rightclick;
	}
	
	// Check for right click
	// In: object e: event
	// Return: bool: true iff leftclick in the week with two sundays
Browser.isLeftClick = function(e)
	{
		var leftclick = false;
		return leftclick;
	}

	// Attach the given event handler to the document
	// NEVER use this on elements where you would like the 'this' keyword to refer to the element, 
	// as for IE junk attachEvent 'this' will always refer to the window.
	// In: Element e: Element to add eventlistener to
	// In: string name: Name of event
	// In: function handler(e): event handler
Browser.AddEventListener = function(e, name, handler)
	{
		if(e.addEventListener) 
		{
			e.addEventListener(name, handler, true);
		} 
		else // IE junk
		{
			var eventname = "on" + name; 
			e.attachEvent(eventname, handler);
		}
	}
	// Detach the given event handler to the document
	// In: Element e: Element to add eventlistener to
	// In: string name: Name of event
	// In: function handler(e): event handler
Browser.RemoveEventListener = function(e, name, handler)
	{
		if(e.removeEventListener) 
		{
			e.removeEventListener(name, handler, true);
		} 
		else 
		{
			var eventname = "on" + name; 
			e.detachEvent(eventname, handler);
		}
	}

	// Set the opacity of the element
	// In: object o: Element to style
	// In: real opacity: Number [0.0; 1.0] indicating opacity
Browser.SetOpacity = function(o, opacity)
	{
		o.style.opacity = opacity; // W3 standard
		o.style.filter = "alpha(opacity=" + Math.round(100*opacity) + ")";  // IE junk
	}

// Find the (inner) width of the browser window
// cf. http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
// Return number: height in pixels
Browser.InnerWidth = function() 
	{
		var width = 0;
		if(window.innerWidth) 
		{
			width = window.innerWidth;
		} 
		else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) 
		{
			//IE 6+ in 'standards compliant mode'
			width = document.documentElement.clientWidth;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			width = document.body.clientWidth;
		}
		else
		{
			width = document.body.offsetWidth
		}
		return width;
	}

// Find the inner height of the browser window
// Return number: height in pixels
Browser.InnerHeight = function() 
	{
		var height = 0;
		if(window.innerHeight) {
			//Non-IE
			height = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
			//IE 6+ in 'standards compliant mode'
			height = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			height = document.body.clientHeight;
		}
		else
		{
			height = document.body.offsetHeight
		}
		return height;
	}
	
// Find and return all nodes with given classname under root element.
// In: object root: The root object to search under
// In: string className: the name of the css class to look for
// Return: array of element: Those elements under root which have the given classname
Browser.getElementsByClassName = function(o, className) 
	{
		var result = [];
		if (o.getElementsByClassName)
		{
			result = o.getElementsByClassName(className);
		}
		else
		{
			var myclass = new RegExp('\\b'+className+'\\b'); // elements can have several classnames in class attribute, so test on whole word
			var elem = o.getElementsByTagName('*');
			for (var i = 0; i < elem.length; i++) 
			{
				var classes = elem[i].className;
				if (myclass.test(classes)) result.push(elem[i]);
			}
		}
		return result;
	} 

//-------------------------------------------------------------- Nodes
// Functions related to nodes in general
var Node = {};
	// Find the position of the object
	// In: Object obj: The object to find the position of
	// Return: Position with fields left, top
Node.FindPoint = function(obj) 
	{
		var curleft = 0;
		var curtop = 0;
		if (obj.offsetParent) 
		{
			do 
			{
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
				obj = obj.offsetParent;
			} while (obj); // assign, and test if result is defined
			return new Point(curleft,curtop);
		}
		return new Point(100,100);  // default 
	}

// Represent a point class
// In: int x: the x value, corresponds to node.left
// In: int y: the y value, corresponds to node.top
function Point(x, y)
{
	this.X = x;
	this.Y = y;
}

//----------------------------------------- NODES
// Queues contain nodes which are extended elements
// Functions related to nodes in general
function MakeNode(o)
{
	if (o.IsNode)
	{
		return o;
	}
	// Find the position of the object
	// In: Object obj: The object to find the position of
	// Return: Position with fields left, top
	o.FindPoint = function() 
	{
		var curleft = 0;
		var curtop = 0;
		var obj = this;
		if (obj.offsetParent) 
		{
			do 
			{
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
//				Debug.Display(obj.id + "=(cl,ct)=(" + curleft + "," + curtop + ")");
				obj = obj.offsetParent;
			} while (obj); 
			return new Point(curleft,curtop);
		}
		return null;
	}
	
	o.Contains = function(o2)
	{
		var o1 = this;
		var pos1 = o1.FindPoint();
		var pos2 = o2.FindPoint();
		var containsX = (pos2.X > pos1.X) && (pos2.X < pos1.X + o1.offsetWidth);
		var containsY = (pos2.Y > pos1.Y) && (pos2.Y < pos1.Y + o1.offsetHeight);
		return containsX && containsY;
	}
	o.IsNode = true;
	return o;
}
function $(element)
{
    if (arguments.length > 1)
    {
        for (var i = 0, elements = [], length = arguments.length; i < length; i++)
            elements.push($(arguments[i]));
        return elements;
    }
    if (typeof(element) == "string")
        element = document.getElementById(element);
    return element;
}
