// A point structure
function Point(left, top) {
	this.left = left;
	this.top = top;
}

function KeyCodes(){}
KeyCodes.KEY_ENTER = 13;
KeyCodes.KEY_TAB = 9;
KeyCodes.KEY_DOWN = 40;
KeyCodes.KEY_UP = 38;
KeyCodes.KEY_ESCAPE = 27;
KeyCodes.KEY_ALT = 18;
KeyCodes.KEY_CTRL = 17;
KeyCodes.KEY_END = 35;
KeyCodes.KEY_HOME = 36;
KeyCodes.KEY_LEFT = 37;
KeyCodes.KEY_PAGEDOWN = 34;
KeyCodes.KEY_PAGEUP = 33;
KeyCodes.KEY_RIGHT = 39;
KeyCodes.KEY_SHIFT = 16;

function Events(){}
Events.ONKEYPRESS = 0x00100;
Events.ONKEYUP = 0x00200;
Events.ONKEYDOWN = 0x00080;
Events.ONFOCUS = 0x00800;

// Return the absolute position of an object on the page
function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return new Point(curleft,curtop);
}

// Use this string buffer when concatenation large numbers of small strings.
function StringBuffer() { 
	this.buffer = []; 
}

function StringBuffer( str ) { 
	this.buffer = [str]; 
}

StringBuffer.prototype.append = function append(string) { 
	this.buffer.push(string); 
	return this; 
}; 

StringBuffer.prototype.toString = function toString() { 
	return this.buffer.join(""); 
}; 

// Loads an XML object from a string
function LoadXMLFromString( markup ) {
    var xmlDocument = null;
    if (typeof DOMParser != 'undefined') {
        xmlDocument = new DOMParser().parseFromString(markup, 'application/xml');
    } else if (typeof ActiveXObject != 'undefined') {
        try {
            xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
            xmlDocument.loadXML(markup);
        } catch (e) {
        }
    }
    return xmlDocument;
}

// Removes leading whitespaces
function LTrim( value ) {
	var re = /\s*((\S+\s*)*)/;
	return value.replace(re, "$1");
}

// Removes ending whitespaces
function RTrim( value ) {
	var re = /((\s*\S+)*)\s*/;
	return value.replace(re, "$1");
}

// Removes leading and ending whitespaces
function trim( value ) {
	return LTrim(RTrim(value));
}

if ( !String.prototype.trim )
	String.prototype.trim = function() { return trim(this); };

function hasClass(object, className) {
	if ( object.className )
		return new RegExp('\\b' + className + '\\b').test(object.className);
	return false;
}

function addClass(object, className) {
	if (!hasClass(object, className))
		object.className += (object.className) ? (' ' + className) : (className);
}

function removeClass(object, className) {
	if ( hasClass(object, className )) {
		object.className = object.className.replace(new RegExp('\\s*\\b' + className + '\\b\\s*'), ' ');
		object.className = object.className.trim();
	}
}

function parseQueryString( arg1 ) {
	var queryString = arg1;
	var result = new Object(); // Hash map
	result.keySet = new Array();
    if (queryString.indexOf("?") == 0)
        queryString = queryString.substr(1);

    var items = queryString.split("&");
    for ( var i = 0; i < items.length; i++ ) {
        var pair = items[i].split("=");
        result[pair[0]] = window.decodeURIComponent(pair[1]);
        result.keySet[result.keySet.length] = pair[0];
    }
    return result;
}

function getInnerText( element ) {
	var result = "";
	if ( element.data != null )
		result = element.data;

	for (var i = 0; i < element.childNodes.length; i++)
		result = result + getInnerText(element.childNodes[i]);

	return result;
}

//Uses the identity operator to see if the array contains the element
function arrayContains(array, element) {
	for(var i=0; i<array.length; i++) {
		if(array[i] === element) return true;
	}
	return false;
}

//code stolen from: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD
function areArraysEqual(array1, array2) {
   var temp = new Array();
   if ( (!array1[0]) || (!array2[0]) ) { // If either is not an array
      return false;
   }
   if (array1.length != array2.length) {
      return false;
   }
   // Put all the elements from array1 into a "tagged" array
   for (var i=0; i<array1.length; i++) {
      key = (typeof array1[i]) + "~" + array1[i];
   // Use "typeof" so a number 1 isn't equal to a string "1".
      if (temp[key]) { temp[key]++; } else { temp[key] = 1; }
   // temp[key] = # of occurrences of the value (so an element could appear multiple times)
   }
   // Go through array2 - if same tag missing in "tagged" array, not equal
   for (var i=0; i<array2.length; i++) {
      key = (typeof array2[i]) + "~" + array2[i];
      if (temp[key]) {
         if (temp[key] == 0) { return false; } else { temp[key]--; }
      // Subtract to keep track of # of appearances in array2
      } else { // Key didn't appear in array1, arrays are not equal.
         return false;
      }
   }
   // If we get to this point, then every generated key in array1 showed up the exact same
   // number of times in array2, so the arrays are equal.
   return true;
}
