/**
 * All code hand-crafted by Rahmin Pavlovic
 *
 * Copyright 2006 (Though utilizes routines I first started in 1999-2000)
 *
 */


/**
 * JavaScript String class extensions
 *
 */

// trim all whitespace surrounding a  string
String.prototype.trim=function() {
	str=this.replace(/^\s+/,'');
	return str.replace(/\s+$/,'');
}

// capitalize first letter in string, lowercase the rest
String.prototype.ucfirst=function() {
	return this.charAt(0).toUpperCase() + this.substring(1,this.length).toLowerCase();
}

// routine to add slashes to string
String.prototype.addSlashes=function() {
	return this.replace(/\'/, "\\\'");
}


/**
 * JavaScript Array class extensions
 *
 */

// returns the index of an array element, -1 if element not found
Array.prototype.indexOf=function(el) {
	for(var n=0; n<this.length; n++) {
		if(this[n]==el) {
			return n;
		}
	}
	return -1;
}

// search each array element for existence of string (case-sensitive), returns array index or -1
Array.prototype.search=function(str) {
	for(var n=0; n<this.length; n++) {
		if(this[n].indexOf(str)!=-1) {
			return n;
		}
	}
	return -1;
}

// search each array element for existence of string (case-insensitive), returns array index or -1
Array.prototype.searchNoCase=function(str) {
	for(var n=0; n<this.length; n++) {
		if(this[n].toLowerCase().indexOf(str.toLowerCase())!=-1) {
			return n;
		}
	}
	return -1;
}

// see if array contains an item
Array.prototype.contains=function(el) {
	return this.indexOf(el)!=-1;
}

// return last item from array
Array.prototype.last=function() {
	return this[this.length-1];
}

// routine to clear an array
Array.prototype.clear=function() {
	this.length=0;
	return this;
}

// native sorting routine is alpha-based ('10, 11, 12' will come after '1'), create true numerical sort
Array.prototype.nsort=function() {
	minor=[];
	major=[];

	// split array into two arrays (a 1 char array, and a 2+ char array)
	for(var i=0; i<this.length; i++) {
		if(this[i].toString().trim().length==1) {
			minor[minor.length]=this[i];
		}
		else {
			major[major.length]=this[i];
		}
	}

	minor.sort(); // sort 1 char array
	major.sort(); // sort 2+ char array
	this.clear(); // clear current array

	// rebuild current array
	for(var i=0; i<minor.length; i++) { this[this.length]=minor[i]; }
	for(var i=0; i<major.length; i++) { this[this.length]=major[i]; }

	// cleanup
	minor.clear();
	major.clear();
}

/**
 * JavaScript Object class extensions
 *
 */

// returns the key of an object based on its value
Object.prototype.getKey=function(el) {
	for(var n in this) {
		if(this[n]==el) {
			return n;
		}
	}
	return -1;
}


/**
 * DOM Routines
 *
 * create our own DOM object to centralize DOM-based routines
 *
 */

var DOM={};
DOM.getElementById=function(id) {
	if(document.getElementById) { return document.getElementById(id); }
	if(document.layers) { return document.layers[id]; }
	if(document.all) { return document.all[id]; }
	return null;
}
DOM.getElementsByTagName=function(tag, el) {
	var el=(el)? el : document;
	if(el.getElementsByTagName) { return el.getElementsByTagName(tag); }
	return null;
}
DOM.createElement=function(el) {
	if(document.createElement) { return document.createElement(el); }
	return null;
}
DOM.getTagNameFromElement=function(el) {
	if(el.tagName) { return el.tagName.toLowerCase(); }
	if(el) { return el.toString().toLowerCase(); }
	return null;
}


/**
 * DHTML Routines
 *
 * create our own DHTML object to centralize cross-browser DHTML routines
 *
 */

var DHTML={};

// routine to toggle display of (block) element
DHTML.toggle=function(id) {
	el=DOM.getElementById(id);
	if(el) {
		el.style.display=(el.style.display=='' || el.style.display=='block')?'none':'block';
	}
}
// centralize inner window width/height
DHTML.getInnerWidth=function() {
	if(window.innerWidth) { return innerWidth; }
	if(document.body.offsetWidth) { return document.body.offsetWidth; }
	return null;
}
DHTML.getInnerHeight=function() {
	if(window.innerHeight) { return innerHeight; }
	if(document.body.clientWidth) { return document.body.clientWidth; }
	if(document.body.offsetHeight) { return document.body.offsetHeight; }
	return null;
}

// centralize number of pixels scrolled to
DHTML.getScrollX=function() {
	if(window.pageXOffset) { return pageXOffset; }
	if(document.body.scrollLeft) { return document.body.scrollLeft; }
	if(document.documentElement.scrollLeft) { return document.documentElement.scrollLeft; }
	return null;
}
DHTML.getScrollY=function() {
	if(window.pageYOffset) { return pageYOffset; }
	if(document.body.scrollTop) { return document.body.scrollTop; }
	if(document.documentElement.scrollTop) { return document.documentElement.scrollTop; }
	return null;
}
DHTML.getPageX=function(el) {
	if(!e) { var e=window.event; }
	if(e.pageX) { return e.pageX; }
	if(e.clientX) { return e.clientX + DHTML.getScrollX(); }
	if(e.offsetLeft) { return e.offsetLeft; }
	return null;
}
DHTML.getPageY=function(e) {
	if(!e) { var e=window.event; }
	if(e.pageY) { return e.pageY; }
	if(e.clientY) { return e.clientY + DHTML.getScrollY(); }
	if(e.offsetTop) { return e.offsetTop; }
	return null;
}
DHTML.getElementByEvent=function(e) {
	el=null;
	if(!e) { var e=window.event; }
	if(e.target) { el=e.target; }
	if(e.srcElement) { el=e.srcElement; }
	if(el.nodeType==3) {
		el=el.parentNode;
	}
	return el;
}

// centralize keycode routiones
DHTML.getKeyCode=function() {
	return (event.keyCode)? event.keyCode : e.which;
}

// custom DHTML routines
DHTML.getRandomLeft=function() {
	var now=new Date();
	return (((now.getTime() * now.getSeconds()) / parseInt((now.getDay()+1) * 2)) % DHTML.getInnerWidth());
}
DHTML.getRandomTop=function() {
	var now=new Date();
	return (((now.getTime() * now.getSeconds()) / parseInt(now.getDay()+1)) % parseInt(DHTML.getInnerHeight() / 2));
}

/**
 * JSON Routines
 *
 * create our own JSON object to centralize cross-browser routines
 *
 */

var JSON={};

JSON.parse=function(code) {
	return eval('('+code+')');
}


/**
 * AJAX Routines
 *
 * create our own AJAX object to centralize cross-browser AJAX routines
 *
 */

var AJAX={};

// return HTTP responses
AJAX.ReadyState={};
AJAX.ReadyState['Uninitialized']=0;
AJAX.ReadyState['Loading']		=1;
AJAX.ReadyState['Loaded']		=2;
AJAX.ReadyState['Interactive']	=3;
AJAX.ReadyState['Complete']		=4;

// initialize cross-browser HTTP request
AJAX.getHTTPRequest=function() {
	if(window.XMLHttpRequest) { return new XMLHttpRequest(); }
	if(window.ActiveXObject) {
		try { return new ActiveXObject("Msxml2.XMLHTTP"); }
		catch(e) { return new ActiveXObject("Microsoft.XMLHTTP"); }
	}
	return null;
}

// send HTTP request
AJAX.sendHTTPRequest=function(url, params, method, contentType, HTTP_Request) {
	HTTP_Request=(!HTTP_Request)? AJAX.getHTTPRequest() : HTTP_Request;
	if(HTTP_Request) {
		method=(method)? method : 'post'; // default HTTP method
		contentType=(!contentType && method.toLowerCase()=='post')? "application/x-www-form-urlencoded" : contentType;

		HTTP_Request.onreadystatechange=AJAX.FileRequest.onReadyStateChange;
		HTTP_Request.open(method, url, 1);
		HTTP_Request.setRequestHeader("content-type", contentType);
		HTTP_Request.send(params);
	}
}

// Constructor to setup HTTP file requests
AJAX.FileRequest=function(url, onload, onerror, method, params, contentType) {
	this.url=url;
	this.params=(params)? params : null;
	this.method=(method)? method : 'get';

	this.url+=(this.params!=null && this.method.toLowerCase()=='get')?'?'+this.params:'';
	this.contentType=(contentType)? contentType : "application/x-www-form-urlencoded";
	this.contentType=(!this.contentType && this.method.toLowerCase()=='post')? "application/x-www-form-urlencoded" : this.contentType;

	this.request=null;
	this.response=null;
	this.onload=(onload)? onload : this.OnLoad;
	this.onerror=(onerror)? onerror : this.OnError;
	this.sendFileRequest();
}

// method to generate an HTTP request for selected file
AJAX.FileRequest.prototype.sendFileRequest=function() {
	this.request=AJAX.getHTTPRequest();
	if(this.request) {
		try {
			// pass reference of current instance to event handler
			ref=this;
			this.request.onreadystatechange=function() { ref.onReadyState.call(ref); }

			// open HTTP connection
			this.request.open(this.method, this.url, 1);

			// set content-type header
			if(this.contentType) { this.request.setRequestHeader('content-type', this.contentType); }

			// send request
			this.request.send(this.params);
		}
		catch(err) {
			alert('err 1')
			this.onerror.call(this);
		}
	}
}
AJAX.FileRequest.prototype.onReadyState=function() {
	if(this.request) {
		if(this.request.readyState == AJAX.ReadyState['Complete']) {
			if(this.request.status==200 || this.request.status==0) {
				this.response=this.request.responseText;
				this.onload.call(this);
			}
			else {
				alert('err 2')
				this.onerror.call(this);
			}
		}
		else {
			this.response=AJAX.ReadyState.getKey(this.request.readyState);
			//this.onload.call(this);
		}
	}
	else {
		alert('err 3')
		this.onerror.call(this);
	}
}
AJAX.FileRequest.prototype.OnError=function() {
	if(this.request) {
		alert(
			"Error fetching data"
			+ "\n\tReadyState: " + this.request.readyState
			+ "\n\tStatus: " + this.request.status
			+ "\n\tHeaders: " + this.request.getAllResponseHeaders()
		);
	}
}
AJAX.FileRequest.prototype.OnLoad=function() {
	if(this.request) {
		alert(this.response);
	}
}

// parse JS files for inclusion
AJAX.js_include=function(url) {
	new AJAX.FileRequest(url, AJAX.setJavaScript);
}
AJAX.setJavaScript=function() {
	if(this.request && this.response && (this.request.status==200 || this.request.status==0)) {
		eval(this.response);
	}
}

