 function isArray(testObject) {
	return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
}

Array.prototype.compare = function(testArr) { 
	if (this.length != testArr.length) {
		return false;
	}
	for (var i = 0; i < testArr.length; i++) {
		if (this[i].compare) {
			if (!this[i].compare(testArr[i])){
				return false;
			}
		}
		if (this[i] !== testArr[i]) {
			return false;
		}
	}
	return true;
}

if (!Array.prototype.every) {
	Array.prototype.every = function(func /* [, thisContext] */) {
		var len = this.length;
		if (typeof func != "function") {
			throw new TypeError();
		}
		var thisp = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this && !func.call(thisContext, this[i], i, this)) {
				return false;
			}
		}
		return true;
	}
}

if (!Array.prototype.filter) {  
	Array.prototype.filter = function(func /* [, thisContext] */) {
		var len = this.length;
		if (typeof func != "function")  {
			throw new TypeError();
		}
		var result = new Array();
		var thisContext = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this) {
				var val = this[i];
				if (func.call(thisContext, val, i, this)) {
					result.push(val);     
				}
			}   
		} 
		return result; 
	}
}

Array.prototype.find = function(searchFor) {  
	var returnArray = false;
	for (i=0; i<this.length; i++) {
		if (typeof(searchFor) == 'function') {
			if (searchStr.test(this[i])) {
				if (!returnArray) {
					returnArray = [];
				}
				returnArray.push(i);
			} 
		} else {
			if (this[i] === searchFor) {
				if (!returnArray) {
					returnArray = [];
				}
				returnArray.push(i); 
			}
		}
	}
	return returnArray;
}

if (!Array.prototype.forEach) {
	Array.prototype.forEach = function(func /* [, thisContext] */)  {
		var len = this.length;
		if (typeof func != "function") {
			throw new TypeError();
		}
		var thisContext = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this) {
				func.call(thisContext, this[i], i, this);
			}
		}
	}
}

if (!Array.prototype.map) {
	Array.prototype.map = function(func /* [, thisContext] */)  {
		var len = this.length;  
		if (typeof func != "function")  {
			throw new TypeError();  
		}
		var result = new Array(len);  
		var thisContext = arguments[1];   
		for (var i = 0; i < len; i++)    {   
			if (i in this)   {
				result[i] = func.call(thisContext, this[i], i, this);   
			}
		}
		return result;
	}
}

Array.prototype.shuffle = function () {
	for(var rnd, tmp, i=this.length; i; rnd=parseInt(Math.random()*i), tmp=this[--i], this[i]=this[rnd], this[rnd]=tmp);
}

if (!Array.prototype.some) {
	Array.prototype.some = function(func /* [, thisContext] */) {
		var len = this.length;
		if (typeof func != "function") {
			throw new TypeError();
		}
		var thisContext = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this && func.call(thisContext, this[i], i, this)) {
				return true;
			}
		}
		return false;
	}
}

Array.prototype.sortNum = function() {
	return this.sort(function (a, b) {return a-b});
}

String.prototype.collapse = function() {
	return this.replace(/\s\s+/g, ' ');
}

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+U$/g,"");
}

String.prototype.ltrim = function() {
	return this.replace(/^\s+/g,"");
}

String.prototype.rtrim = function() {
	return this.replace(/\s+U$/g,"");
}

String.prototype.toNumber = function() {
	return this.replace(/([^0-9\.\-])/g,'') * 1;
}

Number.prototype.format = function(decimal) {
	x = new String(this.toFixed(decimal)).split('.');
	x1 = x[0];
	x2 = (x.length > 1) ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, 'U$1' + ',' + 'U$2');
	}
	return x1 + x2;
}

function walkTree(e, callback) {
	if (e) {
		for(var n=e.firstChild; n; n=n.nextSibling){
			walkTree(n, callback);
		}
		callback(e);
	}
}

function U$() {
	var results = [];
	var args = Array.prototype.slice.apply(arguments);

	args.map(function(element) {

		if (typeof(element) == 'string'){
			element = document.getElementById(element);
		}
		results.push(element);
	});

	return (results.length == 1) ? results[0] : results;
}

function U$T() {
	var results = [];
	var args = Array.prototype.slice.apply(arguments);
	args.map(function(tag) {
		var tags = document.getElementsByTagName(tag);
		for (var i=0; i < tags.length; i++) {
			results.push(tags[i]);
		}
	});
	return results;
}

function U$V(e){
	e = U$(e);

	switch (e.type) {
		case 'radio': case 'checkbox': {
			return e.checked;
		}
		case 'text': case 'hidden': case 'textarea': case 'password': {
			return e.value;
		}
		case 'select-one': {
			return (e.selectedIndex < 0) ? null : e.value;
		}
		case 'select-multiple': {
			var values = new Array();
			for (var i=0; i < e.options.length; i++) {
				values[values.length] = e.options[i].value;
			}
			return (values.length == 0) ? null : values.toString();
		}
		return e.value;
	}
}

function U$F(x) {
	if (typeof(x) == 'function') {return x()}
	return x;
}

function U$U$(className, context) {
	context = context || document;
	var nodeList;

	if (context == document || context.nodeType == 1) {
		if (typeof(document.evaluate) == 'function') {
			var xpath = document.evaluate(".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]", context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
			var els = [];
			for (var i = 0, l = xpath.snapshotLength; i < l; i++) {
				els.push(xpath.snapshotItem(i));
			}
			return els;
		} else {
			nodeList = context.getElementsByTagName('*');
		}
	} else {
		nodeList = context;
	}

	var re = new RegExp('(^|\\s)' + className + '(\\s|U$)');
	return nodeList.filter(function(node) {
		return node.className.match(re);
	});
}

function createStyleSheet() {

	var styleSheetElement = document.createElement("style");
	styleSheetElement.type = "text/css";
	document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
	
	var styleSheet;
	for(i = 0; i<document.styleSheets.length; i++) {
		if (!document.styleSheets[i].disabled) {
			styleSheet = document.styleSheets[i];
		}
	}

	return styleSheet;
}

if (typeof(window.getComputedStyle) == 'undefined') {
	window.getComputedStyle = function(e) {
		return e.currentStyle;
	}
}

function setCSS (selector, style, styleSheet) {//selector, style [,styleSheet]

	if (!document.styleSheets && !styleSheet) {return}	
	var mediaType;

	if (!styleSheet) {
		if(document.styleSheets.length > 0) {
			for(i = 0; i<document.styleSheets.length; i++) {
				if (document.styleSheets[i].disabled) {continue}
				var media = document.styleSheets[i].media;
				mediaType = typeof(media);

				if(mediaType == "string") {//IE
					if(media == "" || media.indexOf("screen") != -1) {
						styleSheet = document.styleSheets[i];
					}
				} else if(mediaType == "object") {
					if(media.mediaText == "" || media.mediaText.indexOf("screen") != -1) {
						styleSheet = document.styleSheets[i];
					}
				}
			}
		}
	}

	if (!styleSheet) {
		styleSheet = createStyleSheet();
		if (!styleSheet) {return}
	}
	
	var rules = (styleSheet.cssRules) ? styleSheet.cssRules: styleSheet.rules;

	//delete existing rule
	for(i = 0; i<rules.length; i++) {
		if(rules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
			if (styleSheet.deleteRule) {
				styleSheet.deleteRule(i);	
			} else {
				styleSheet.removeRule(i);
			}
		}
	}
	
	//add replacement
	if (style) {
		if (styleSheet.cssRules) {
			styleSheet.insertRule(selector + "{" + style + "}", styleSheet.cssRules.length);
		} else {
			styleSheet.addRule(selector, style);
		}
	}
}

function XMLHttpObject() {
	if (typeof(XMLHttpRequest) != 'undefined') {
		return new XMLHttpRequest();
	} else {
		/*@cc_on
			@if (@_jscript_version >= 5)
				try {
					return new ActiveXObject("Msxml2.XMLHTTP");
				} catch (ex){
					try {
						return new ActiveXObject("Microsoft.XMLHTTP");
					} catch (ex2){
						return false;
					}
				}
			@end
		@*/
	}
	return false;
}

function HttpRequest() {//[callback function, [,passthrough object]] url [,name, value ...] [, value]
	if (!arguments.length) {return null}

	var callback, passthrough, params = '';
	if ((typeof(arguments[0]) == 'function') && (arguments.length != 1)) {callback = arguments[0]}

	var begin = (callback) ? 2 : 1;
	if (callback && ((arguments.length > 2) && (typeof(arguments[1]) == 'object'))) {
		passthrough = arguments[1];
		begin ++;
	}

	for (var i = begin; i < arguments.length; i++) {
		if (params) {params += '&'}
		if ((i+1) < arguments.length) {
			params += escape(U$F(arguments[i]));
			i++;
		} else {
			params += 'param';
		}
		params += '=' + escape(U$F(arguments[i]).toString());
	}

	var XMLHttp = XMLHttpObject();
	if (!XMLHttp) {return null}
	
	try {
		XMLHttp.open((params) ? 'POST' : 'GET', U$F(arguments[begin-1]), (callback) ? true : false);
		if (params) {XMLHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')}
		if (callback) {XMLHttp.onreadystatechange = function() {if (XMLHttp.readyState == 4) {callback(XMLHttp, passthrough); XMLHttp = null}}}
		XMLHttp.send(params);	
		return (callback) ? true : XMLHttp;
	} catch(ex) {}

	return null;
}

/*
	newXMLDocument()

	W3C DOM's are extended with these methods/properties from the MSXML DOM:
		XMLDocument.loadXML(XMLText)
		XMLDocument.transformNode(XSLDOM) (Document only extended)	
		Element.selectSingleNode(Xpath)
		Element.selectNodes(XPath)
		Element.xml
		Node.text	
*/

function newXMLDocument() {
	if (document.implementation && document.implementation.createDocument) {
		return document.implementation.createDocument('', '', null);
	} else {
		/*@cc_on
			@if (@_jscript_version >= 5)
				try {
					return new ActiveXObject("MSXML2.DOMDocument.4.0");
				} catch (ex){
					try {
						return new ActiveXObject("MSXML2.DOMDocument");
					} catch (ex) {
						try {	
							return new ActiveXObject("Microsoft.XMLDOM");
						} catch (ex2){
						return false;
					}
				}
			}
			@end
		@*/
	}
	return false;
}

function insertAfter(newChild, refChild) {
	if (refChild.nextSibling) {
		return refChild.parentNode.insertBefore(newChild, refChild.nextSibling);
	} else {
		return refChild.parentNode.appendChild(newChild);
	}
}

function NSResolver(prefix) {
	switch (prefix) {
		case 'SOAP-ENV' : return 'http://schemas.xmlsoap.org/soap/envelope/';
	}
	return null;
}

if (typeof(XMLDocument) != 'undefined') {
	XMLDocument.prototype.loadXML = function (text) {
		var xml = (new DOMParser()).parseFromString(text, "text/xml");
		while (this.hasChildNodes()) {
			this.removeChild(this.lastChild);
		}
		for (var i = 0; i < xml.childNodes.length; i++) {
			this.appendChild(this.importNode(xml.childNodes[i], true));
		}
	};
		
	XMLDocument.prototype.transformNode = function(stylesheet) {
		var result = document.implementation.createDocument('', '', null);
		try {
			new XSLTProcessor().transformDocument(this, stylesheet, result, null);
		} catch(ex) {
			return false;
		}
		try {
			return new XMLSerializer().serializeToString(result);
		} catch(ex) {
			return false;
		}
	}
		
	XMLDocument.prototype.selectNodes = Element.prototype.selectNodes = function(XPath, NSResolver) {
		var result = [];
		result.item = function(index){return result[index]}
		try {
			var doc = (this.implementation ? this : this.ownerDocument);
			var nodes = doc.evaluate(XPath, this, NSResolver, 5, null);
			var node = nodes.iterateNext();
			while(node) {
				result[result.length] = node;
				node = nodes.iterateNext();
			}
		} catch(ex) {
			return false;
		}
		return result;
	}
	
	XMLDocument.prototype.selectSingleNode = Element.prototype.selectSingleNode = function(XPath, NSResolver) {
		try {
			var result = (this.implementation ? this : this.ownerDocument);
			return result.evaluate(XPath, this, NSResolver, 9, null).singleNodeValue;
		} catch(ex) {
			return false;
		}
	}
	
	XMLDocument.prototype.__defineGetter__("xml", function (){
		try {
			return (new XMLSerializer()).serializeToString(this);
		} catch(ex) {
			return false;
		}
	});
	
	Element.prototype.__defineGetter__("xml", function (){
		try {
			return (new XMLSerializer()).serializeToString(this);
		} catch(ex) {
			return false;
		}
	});
	
	Node.prototype.__defineGetter__("text", function()
	{
		try {
			var result = '';
			if(this.nodeType==3) {return this.nodeValue}
			if(this.hasChildNodes()) {
				var children = this.childNodes;
				for(var i=0;i<children.length;i++) {
					var n = children[i];
					if(n.nodeType == 1 && n.hasChildNodes()) {result += n.text}
					if(n.nodeType == 3 || n.nodeType == 4) {result += n.nodeValue}
				}
			}
			return result;
		} catch(ex) {
			return false;
		}
	});					
}

Event = {
	add : function(el, type, func) {	
		el = U$(el);
		if (!func.U$U$guid) {func.U$U$guid = Event._guid++}
		if (!el.events) {el.events = {}}
		var handlers = el.events[type];
		if (!handlers) {
			handlers = el.events[type] = {};
			if (el["on" + type]) {
				handlers[0] = el["on" + type];
			}
		}
		handlers[func.U$U$guid] = func;
		el["on" + type] = Event._handleEvent;
  		if (!Event.observers) {Event.observers = []}
  		Event.observers.push([el, type, func, false]);
	},

	remove : function(el, type, func) {
		el = U$(el);
		if (el.events && el.events[type]) {delete el.events[type][func.U$U$guid]}
		for (var i = 0; i < Event.observers.length; i++) {
			if (Event.observers[i]) {
				if ((Event.observers[i][0] == el) && (Event.observers[i][1] == type) && (Event.observers[i][2] == func)) {
					delete Event.observers[i];		
				}
			}
		}
	},

	_handleEvent : function(e) {
		var returnValue = true;
		e = e || Event._fixEvent(window.event);
		//e.key is unreliable on keypressed events, try and use keyup events
		e.key = (e.charCode) ? e.charCode : (e.keyCode) ? e.keyCode : (e.which) ? e.which : null;

		var handlers = this.events[e.type], el = U$(this);

		for (var i in handlers) {	
			el.U$U$handleEvent = handlers[i];		
			if (el.U$U$handleEvent(e) === false) {returnValue = false}
		}
		return returnValue;
	},

	_fixEvent : function(e) {
		e.preventDefault = Event._preventDefault;
		e.stopPropagation = Event._stopPropagation;
		return e;
	},

	_preventDefault : function() { this.returnValue = false },

	_stopPropagation : function() { this.cancelBubble = true },

	_guid : 1,

	onDOMReady : function(f) {
		if (!this._readyCallbacks) {
			var domReady = this._domReady;
			if (domReady.done) {return f()}
			if (document.addEventListener) {document.addEventListener("DOMContentLoaded", domReady, false)}
			/*@cc_on @*/
				/*@if (@_win32)
					document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
					document.getElementById("__ie_onload").onreadystatechange = function() {
						if (this.readyState == "complete") { domReady() }
					};
			/*@end @*/
			if (/WebKit/i.test(navigator.userAgent)) {
				this._timer = setInterval(function() {
					if (/loaded|complete/.test(document.readyState)) {domReady()}
				}, 10);
			}
			Event.add(window, 'load', domReady);
			Event._readyCallbacks =  [];
		}
		Event._readyCallbacks.push(f);
	},

	_domReady : function() {
		if (arguments.callee.done) {return}
		arguments.callee.done = true;
		if (Event._timer) {clearInterval(Event._timer)}
		Event._readyCallbacks.forEach(function(f) {
			f();
		});
		Event._readyCallbacks = null;
	},

	unload : function() {
		if (!Event.observers) {return}
		Event.observers.forEach(function(e) {
			Event.remove.apply(Event, e);
		});
	}
}

if (navigator.appVersion.match(/\bMSIE\b/)) {Event.add(window, 'unload', Event.unload)}
