/*	LIBRARY CONTENTS *********************************************
	
	WindowTools Methods
		addLoadEvent( func );
		client();
		launchWindow( url [, name [, width [, height [, resize [, scroll [, menu [, tools [, location [, status]]]]]]]]] );
	
	Array Methods
		Array.push((value_0 [,...,value_n]);
		Array.find( value [, start] );
		Array.has( value );
		Array.count( value );
		Array.remove( value [, all] );
		Array.min();
		Array.max();
	
	String Methods
		String.trim();
		String.wrap( left [, right] );
		String.zerofill( length );
		String.isEmpty( notrim );
	
	ObjectTools Methods
		Type
			isFunction( obj );
			isObject( obj );
			isArray( obj );
			isBoolean( obj );
			isNumber( obj );
			isString( obj );
			isNull( obj );
			isUndefined( obj );
			isUnknown( obj );
		Utility
			compareOptionTextAsc( obj_1, obj_2 );
			compareOptionTextDesc( obj_2, obj_1 );
		Element
			toggleChecked( obj );
			addOption( obj, text, value [, pos] );
			removeOptionValue( obj, value [, all] );
			removeOptionText( obj, text [, all] );
			sortOptions( obj [, asc] );
*/


//	WINDOWTOOLS METHODS -----------------------------------------------------

	function WindowTools() {}
	
	
	// Checks for any existing window.onload event handlers and appends the new [pFunc] to it.
	WindowTools.addLoadEvent = function( pFunc ) {
		var lOldLoad = window.onload;
		
		if (ObjectTools.Type.isFunction( lOldLoad )) {
			window.onload = function() {
				if (lOldLoad) loOldLoad();
				pFunc();
			}
		} else {
			window.onload = pFunc;
		}
	}
	
	
	// Returns client browser & platform spec properties
	WindowTools.client = function() {
		this.agent = navigator.userAgent.toLowerCase();
		this.name = navigator.appName.toLowerCase();
		this.version = parseFloat(navigator.appVersion.slice(0, navigator.appVersion.indexOf(' ')));
		
		this.isIE = (this.name.indexOf('microsoft internet explorer') >= 0);
		this.isMac = (this.agent.indexOf('mac') >= 0);
		this.isDOM = (document.getElementById) ? true : false;
		
		if (this.agent.indexOf('msie') >= 0) this.version = parseFloat(this.agent.slice(this.agent.indexOf('msie') + 5, this.agent.indexOf(';', this.agent.indexOf('msie') + 5)));
		
		return this;
	}


	// Launches new window named [pWindow], with location of [pURL].
	WindowTools.launchWindow = function( pURL, pWindow, pWidth, pHeight, pResize, pScroll, pMenu, pTools, pLocation, pStatus ) {
		if (ObjectTools.Type.isUnknown(pWindow)) pWindow = "_blank";
		if (ObjectTools.Type.isUnknown(pWidth)) pWidth = "800";
		if (ObjectTools.Type.isUnknown(pHeight)) pHeight = "600";
		if (ObjectTools.Type.isUnknown(pResize)) pResize = true;
		if (ObjectTools.Type.isUnknown(pResize)) pResize = true;
		if (ObjectTools.Type.isUnknown(pScroll)) pScroll = true;
		if (ObjectTools.Type.isUnknown(pMenu)) pMenu = true;
		if (ObjectTools.Type.isUnknown(pTools)) pTools = true;
		if (ObjectTools.Type.isUnknown(pLocation)) pLocation = true;
		if (ObjectTools.Type.isUnknown(pStatus)) pStatus = true;
		
		var lClient = new WindowTools.client();
		if (lClient.isMac && lClient.isIE && lClient.version >= 4 && lClient.version < 5) pHeight = parseInt(pHeight + 17);
		
		var lAttribs = 'width=' + pWidth + ',height=' + pHeight + ',resizable=' + Number(pResize) + ',scrollbars=' + Number(pScroll) + ',menubar=' + Number(pMenu) + ',toolbar=' + Number(pTools) + ',location=' + Number(pLocation) + ',status=' + Number(pStatus);
		var lWin = window.open(pURL, pWindow, lAttribs);
		
		if (lWin != null) {
			if (lWin.opener == null) lWin.opener = self;
		}
		
		if (lWin != null) lWin.focus();
		
		return lWin;
	}


//	ARRAY METHODS -----------------------------------------------------

	// Adds standard Array.push method to IE5.
	if (!Array.prototype.push) Array.prototype.push = function() { for (var i = 0; i < arguments.length; i++) this[this.length] = arguments[i]; return this.length; }
	
	
	// Searches Array for [value], starting at [start] (if provided).  Returns [value]'s first ordinal occurance if found, or FALSE if not.
	Array.prototype.find = function( pValue, pStart ) {
		var lOutput = false;
		if (ObjectTools.Type.isUnknown(pStart)) pStart = 0;
		
		for (var i = pStart; i < this.length; i++) {
			if (this[i] == pValue) {
				lOutput = i;
				break;
			}
		}
		
		return lOutput; 
	}
	
	
	// Returns TRUE if [value] is found in Array, or FALSE if not.
	Array.prototype.has = function( pValue ) { return this.find(pValue) !== false; }
	
	
	// Counts occurences of [value] in Array.
	Array.prototype.count = function( pValue ) {
		var liPos;
		var liStart = 0
		var liCount = 0;
		
		while ((liPos = this.find(pValue, liStart)) !== false) {
			liStart = liPos + 1;
			liCount++;
		}
		
		return liCount;
	}
	
	
	// Removes all occurences of [value] in Array.  If [all] is false, remove only first occurence.  Default for [all] is TRUE.
	Array.prototype.remove = function( pValue, pAll ) {
		while (this.has(pValue)) {
			if (pAll == null) pAll = true;
			this.splice(this.find(pValue), 1);
			if (!pAll) break;
		}
		
		return this;
	}
	
	
	// Returns the smallest item value in the Array
	Array.prototype.min = function() {
		if (!this.length) return null;
		
		var n = this[0];
		for (var i = 1; i < this.length; i++) if (n > this[i]) n = this[i];
		
		return n;
	}
	
	
	// Returns the graetest item value in the Array
	Array.prototype.max = function() {
		if (!this.length) return null;
		
		var n = this[0];
		for (var i = 1; i < this.length; i++) if (n < this[i]) n = this[i];
		
		return n;
	}
	
	
//	STRING METHODS -----------------------------------------------------

	// Removes starting and trailing spaces.
	String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,''); }
	
	
	// Returns a new string that prepends String w/ [left] and appends String w/ [right].  If [right] is not supplied, then [right] = [left].
	String.prototype.wrap = function( pLeft, pRight ) {
		if (ObjectTools.Type.isUnknown(pLeft)) throw 'String.wrap requires 1 argument';
		if (ObjectTools.Type.isUnknown(pRight)) pRight = pLeft;
		
		return pLeft + this + pRight;
	}
	
	
	// Return a ndw string that inserts the [str] at ordinal position [pos] in String.
	String.prototype.insert = function( pPos, pStr ) { return this.slice(0,pPos) + pStr + this.slice(pPos); }


	// Returns a new strign that prepends String w/ 0s until string reaches [length].
	String.prototype.zerofill = function( pLen ) {
		var lOutput = this;
		var lsign = /^[+-]/.test(lOutput) ? 1 : 0;
		
		while (lOutput.length < pLen) lOutput = lOutput.insert(lsign, '0');
		
		return lOutput;
	}
	
	
	// Returns TRUE if it's a zero-length-string.  The string is automatically trimmed unless optional parameter [trim] is set to FALSE.
	String.prototype.isEmpty = function( pTrim ) {
		if (pTrim == null) pTrim = true;
		return !(pTrim ? this.trim() : this).length;
	}
	
	
//  OBJECTTOOLS METHODS -----------------------------------------------------

	function ObjectTools() {}
	
	
	ObjectTools.Type = function() {}
	
	
	ObjectTools.Type.isFunction = function( obj ) { return (typeof obj == "function") }
	
	
	ObjectTools.Type.isObject = function( obj ) { return ((obj && typeof obj == "object") || this.isFunction(obj)) }
	
	
	ObjectTools.Type.isArray = function( obj ) { return (this.isObject(obj) && obj.constructor == Array) }
	
	
	ObjectTools.Type.isBoolean = function( obj ) { return (typeof obj == "boolean") }
	
	
	ObjectTools.Type.isNumber = function( obj ) { return (typeof obj == "number" && isFinite(obj)) }
	
	
	ObjectTools.Type.isString = function( obj ) { return (typeof obj == "string") }
	
	
	ObjectTools.Type.isNull = function( obj ) { return (typeof obj == "object" && !obj) }
	
	
	ObjectTools.Type.isUndefined = function( obj ) { return (typeof obj == "undefined") }
	
	
	ObjectTools.Type.isUnknown = function( obj ) { return (this.isUndefined(obj) || this.isNull(obj)) }
	
	
	ObjectTools.Element = function() {}
	
	
	// Alternates the checked property of the [pObj], based on it's current value.  Returns TRUE/FALSE indicating success.
	ObjectTools.Element.toggleChecked = function( pObj ) {
		var lOutput = false;
		
		if (ObjectTools.Type.isString(pObj)) pObj = document.getElementById(pObj);
		if (ObjectTools.Type.isObject(pObj)) {
			if (pObj.tagName == "INPUT" && pObj.type == "checkbox") {
				pObj.checked = !pObj.checked;
				lOutput = true;
			}
		}
		
		return lOutput;
	}	
	
	
	// Adds a new option with [pText] and [pValue] to [pObj].  This new option is added to the of [pPos] position (if supplied), otherwise it's added to the end.  Returns TRUE/FALSE indicating success.
	ObjectTools.Element.addOption = function( pObj, pText, pValue, pPos ) {
		var lOutput = false;
		
		if (ObjectTools.Type.isString(pObj)) pObj = document.getElementById(pObj);
		if (ObjectTools.Type.isObject(pObj)) {
			if (pObj.tagName == "SELECT") {
				pObj.options[pObj.options.length] = new Option(pText, pValue);
				
				if (ObjectTools.Type.isNumber(pPos)) {
					for (var i = pObj.options.length - 1; i >= pPos; i--) {
						pObj.options[i].value = (i == pPos) ? pValue : pObj.options[i - 1].value;
						pObj.options[i].text = (i == pPos) ? pText : pObj.options[i - 1].text;
						if (i == pObj.selectedIndex && i < pObj.options.length) pObj.selectedIndex++;
					}
					
				}
				
				lOutput = true;
			}
		}
		
		return lOutput;
	}
	
	
	// Removes options from [pObj] with a value of [pValue].  If [pAll] is FALSE (defaults to TRUE), then only the first occurance is removed.  Returns TRUE/FALSE indicating success.
	ObjectTools.Element.removeOptionValue = function( pObj, pValue, pAll ) {
		var lOutput = false;
		
		if (ObjectTools.Type.isUnknown(pAll)) pAll = true;
		if (ObjectTools.Type.isString(pObj)) pObj = document.getElementById(pObj);
		if (ObjectTools.Type.isObject(pObj)) {
			if (pObj.tagName == "SELECT") {
				for (var i = 0; i < pObj.options.length; i++) {
					if (pObj.options[i].value == pValue.toString()) {
						pObj.options[i] = null;
						if (!pAll) break;
					}
				}
				
				lOutput = true;
			}
		}
		
		return lOutput;
	}
	
	
	// Removes options from [pObj] with a text of [pText].  If [pAll] is FALSE (defaults to TRUE), then only the first occurance is removed.  Returns TRUE/FALSE indicating success.
	ObjectTools.Element.removeOptionText = function( pObj, pText, pAll ) {
		var lOutput = false;
		
		if (ObjectTools.Type.isUnknown(pAll)) pAll = true;
		if (ObjectTools.Type.isString(pObj)) pObj = document.getElementById(pObj);
		if (ObjectTools.Type.isObject(pObj)) {
			if (pObj.tagName == "SELECT") {
				for (var i = 0; i < pObj.options.length; i++) {
					if (pObj.options[i].text == pText.toString()) {
						pObj.options[i] = null;
						if (!pAll) break;
					}
				}
				
				lOutput = true;
			}
		}
		
		return lOutput;
	}
	
	
	// Sorts the Objects options based on the optional [asc] parameter.  Parameter [asc] defaults to TRUE.
	ObjectTools.Element.sortOptions = function( pObj, pAsc ) {
		var lOutput = false;
		
		if (ObjectTools.Type.isUnknown(pAsc)) pAsc = true;
		if (ObjectTools.Type.isString(pObj)) pObj = document.getElementById(pObj);
		if (ObjectTools.Type.isObject(pObj)) {
			if (pObj.tagName == "SELECT") {
				var lOptions = new Array(pObj.options.length);
				for (var i = 0; i < lOptions.length; i++) lOptions[i] = new Option(pObj.options[i].text, pObj.options[i].value, pObj.options[i].defaultSelected, pObj.options[i].selected);
				
				lOptions.sort((pAsc) ? ObjectTools.Utility.compareOptionTextAsc : ObjectTools.Utility.compareOptionTextDesc);
				
				pObj.options.length = 0;
				for (var i = 0; i < lOptions.length; i++) pObj.options[i] = lOptions[i];
				
				lOutput = true;
			}
		}
		
		return lOutput;
	}
	
	
	ObjectTools.Utility = function() {}
	
	
	ObjectTools.Utility.compareOptionTextAsc = function( pObjA, pObjB ) {
		var lOutput = null;
		
		if (ObjectTools.Type.isString(pObjA)) pObjA = document.getElementById(pObjA);
		if (ObjectTools.Type.isString(pObjB)) pObjB = document.getElementById(pObjB);
		if (ObjectTools.Type.isObject(pObjA) && ObjectTools.Type.isObject(pObjB)) {
			if (pObjA.tagName == "OPTION" && pObjB.tagName == "OPTION") lOutput = (isNaN(pObjA.text) && isNaN(pObjB.text)) ? (pObjA.text < pObjB.text ? -1 : (pObjA.text > pObjB.text ? 1 : 0)) : (parseFloat(pObjA.text) < parseFloat(pObjB.text) ? -1 : (parseFloat(pObjA.text) > parseFloat(pObjB.text) ? 1 : 0));
		}
		
		return lOutput;
	}
	
	ObjectTools.Utility.compareOptionTextDesc = function(b, a) { return this.compareOptionTextAsc(b, a); }
