/* Prototypes */

String.prototype.ltrim = function()
{
    return this.replace(/^[ ]+/, '');
}

String.prototype.rtrim = function()
{
    return this.replace(/[ ]+$/, '');
}

String.prototype.trim = function()
{
    return this.ltrim().rtrim();
}

/**
* Tests a string to see if it ends with the specified value
* @param val {String}	Required - The string to compare
* @return {Boolean}		true or false
**/
String.prototype.endsWith = function(val)
{
	if(val.length > this.length)
		return false;
	var compval = (val.length == this.length) ? this : this.substring( ( this.length - val.length) );
	return ( compval == val );
}

/**
* Tests a string to see if it ends with the specified value
* @param val {String}	Required - The string to compare
* @return {Boolean}		true or false
**/
String.prototype.startsWith = function(val)
{
	if(val.length > this.length)
		return false;
	var compval = (val.length == this.length) ? this : this.substring( 0, ( this.length - val.length) );
	return ( compval == val );
}

/// Clone properties as a new object
Object.prototype.clone = function()
{
	var obj = new Object();
	for(var property in this) {
		obj[property] = this[property];
	}
	return obj;
}

/**************************************************************************
 * CLASS NAME ADDITION AND REMOVAL
 * Functions add and remove classNames from elements' className space separated list.
 * Used instead of changing the className property (which would overwrite any existing
 * assigned classes) of an element.
 * RETURNS: Void;
 *******************************************************************************/
Object.prototype.addClassName = function(className) {
	var elem = this;
	if (elem == null)
    {
        elem = parent[elem];
    }

	if(!elem.hasClassName(className))
	    elem.className = (elem.className + " " + className).trim();
}

Object.prototype.removeClassName = function(className) {
	/// Does this object type have a class name?
	if(!this.className) return;
    this.className = this.className.replace(className, "").trim();
}

/*******************************************************************************
 * hasClassName(element,cl):Boolean
 * Performs a check on [element] to test if it has [cl] in it's className string.
 * RETURNS: Boolean;
 *******************************************************************************/
Object.prototype.hasClassName = function(cl){
	if (this.className === null)
		return false;
	var classes = this.className.split(" ");
	for (i in classes) {
		if (classes[i] == cl)
			return true;
	}
	return false;
}

function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
		element = document.getElementById(element);
		if (arguments.length == 1)
		return element;
		elements.push(element);
	}
	return elements;
}

/// Want to do something with document.getElementsByTagName("*")


/// Quirks Mode!
function sendRequest(url,callback,postData) {
	var req = createXMLHTTPObject();
	if (!req) return;
	var method = (postData) ? "POST" : "GET";
	req.open(method,url,true);
	req.setRequestHeader('User-Agent','XMLHTTP/1.0');
	if (postData)
		req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	req.onreadystatechange = function () {
		if (req.readyState != 4) return;
		if (req.status != 200 && req.status != 304) {
//			alert('HTTP error ' + req.status);
			return;
		}
		callback(req);
	}
	if (req.readyState == 4) return;
	req.send(postData);
}

var XMLHttpFactories = [
	function () {return new XMLHttpRequest()},
	function () {return new ActiveXObject("Msxml2.XMLHTTP")},
	function () {return new ActiveXObject("Msxml3.XMLHTTP")},
	function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
	var xmlhttp = false;
	for (var i=0;i<XMLHttpFactories.length;i++) {
		try {
			xmlhttp = XMLHttpFactories[i]();
		}
		catch (e) {
			continue;
		}
		break;
	}
	return xmlhttp;
}

function addEventSimple(obj,evt,fnc)
{
	if(obj.addEventListener)
		obj.addEventListener(evt, fnc, false);
	else if(obj.attachEvent)
		obj.attachEvent('on'+evt, fnc);
}

function removeEventSimple(obj,evt,fnc)
{
	if(obj.removeEventListener)
		obj.removeEventListener(evt,fnc,false);
	else if(obj.detachEvent)
		obj.detachEvent('on'+evt,fnc);
}

function findPos(obj, stopAtElem) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
			if(stopAtElem && obj === stopAtElem)
				break;
		}
	}
	return [curleft,curtop];
}

function getPageSize()
{
	var x,y;
	var test1 = document.body.scrollHeight;
	var test2 = document.body.offsetHeight
	if (test1 > test2) // all but Explorer Mac
	{
		x = document.body.scrollWidth;
		y = document.body.scrollHeight;
	}
	else // Explorer Mac;
		 //would also work in Explorer 6 Strict, Mozilla and Safari
	{
		x = document.body.offsetWidth;
		y = document.body.offsetHeight;
	}
	return [ x, y ];
}

function getViewPortSize()
{
	var x,y;
	if (self.innerHeight) // all except Explorer
	{
		x = self.innerWidth;
		y = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight)
		// Explorer 6 Strict Mode
	{
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	else if (document.body) // other Explorers
	{
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return [ x, y ];
}

/**************************************************************************
 * CLASS NAME ADDITION AND REMOVAL
 * Functions add and remove classNames from elements' className space separated list.
 * Used instead of changing the className property (which would overwrite any existing
 * assigned classes) of an element.
 * RETURNS: Void;
 *******************************************************************************/
function addClassName (elem, theClassName) {
    if (elem == null)
    {
        elem = parent[elem];
    }
    removeClassName (elem, theClassName);
    elem.className = (elem.className + " " + theClassName).trim();
}

function removeClassName (elem, theClassName) {
    elem.className = elem.className.replace(theClassName, "").trim();
}

/*******************************************************************************
 * hasClassName(element,cl):Boolean
 * Performs a check on [element] to test if it has [cl] in it's className string.
 * RETURNS: Boolean;
 *******************************************************************************/
function hasClassName(element, cl){
	if ((element.className === null) || (typeof element == 'undefined'))
		return false;
	var classes = element.className.split(" ");
	for (i in classes) {
		if (classes[i] == cl)
			return true;
	}
	return false;
}


/**
* Takes the current an array of objects that contain an identifier and a parent-identifier and creates a graph
* @param idFieldName {String}			Required - The identifier/primary key for the record
* @param parentIdFieldName {String}		Required - The parent key reference
* @param rootValue {Object}				Optional - The parent key's value if it is a root node in the graph. Default value is null
* @param childObjectName {String}		Optional - A name to give the collection of child object that will be added to your Objects. Default: "Children"
* @param searchArray {Array}			Optional - The orginal master list to be search. Used here as a reference for the recursion
* @return {Array}						Returns an array/graph of objects organized as a graph
**/
Array.prototype.convertToHierarchicalObject = function(idFieldName, parentIdFieldName, rootValue, childObjectName, searchArray)
{
	var obj = new Array();
	var srcArray = searchArray || this;
	childObjectName = childObjectName || "Children";

	for(var i = 0; i < srcArray.length; i++)
	{
		if(srcArray[i][parentIdFieldName] == rootValue)
		{
			srcArray[i][childObjectName] = new Array();
			obj.push(srcArray[i]);
		}
	}

	for(var i = 0; i < obj.length; i++)
	{
		obj[i][childObjectName] = obj.convertToHierarchicalObject(idFieldName, parentIdFieldName, obj[i][idFieldName], childObjectName, srcArray);
	}

	return obj;
}

/**
* Creates a document element with extra features
* @author	Robert W. Baskette
* @param type {String}		Required - The type of element. e.g. 'div'
* @param id {String}		Optional - The ID of the new element
* @param className {String}	Optional - The class name(s) to associate with the element
* @param html {String}		Optional - The innerHTML to give the element
* @param style {String}		Optional - Contents of the style attribute
*/
function createElement(type, classNames, id, html, style)
{
	var elem = document.createElement(type);
	if(classNames) elem.className = classNames;
	if(id) elem.id = id;
	if(html) elem.innerHTML = html;
	if(style)
	{
		if(!elem.getAttribute("cssText")) {
			elem.style.cssText = style;
		}
		else
			elem.setAttribute("style", style);
	}
	return elem;
}

/**
 * Returns whether or not an array element contains a value
 * @param val {Object}		Required - The value to search for in the array.
 * @param strict {Boolean}	Optional - Use a strict comparison
 * @retun {Boolean}		Returns true if the val is in an array otherwise false.
 */
Array.prototype.contains = function(val, strict)
{
	for(var i = 0; i < this.length; i++)
	{
		if(strict)
		{
			if(this[i] === val)
				return true;
		}
		else
		{
			if(this[i] == val)
				return true;
		}
	}
	return false;
}

/**
 * Filters an array.
 * @param filterFnc {function}	Required - A function that accepts an element of the array and returns true if there is match, false otherwise
 * @param , {Object]			Optional - An optional set of arguments to the filterFnc in printf style.
 */
Array.prototype.filter = function(filterFnc)
{
	if(!typeof(filterFnc) == 'function')
		return null;

	var evalArgs = new String("");
	if(arguments.length > 1)
	{
		for(var i = 1; i < arguments.length; i++)
		{
			evalArgs += ", arguments[" + i.toString() + "]";
		}
	}

	var retval = new Array();
	for(var i = 0; i < this.length; i++)
	{
		if( eval( "filterFnc(this[i]" + evalArgs + ")" ) )
			retval.push(this[i]);
	}

	return retval;
}


/**
 * Functions to make it difficult for users to select, copy, paste text/images from the site
 */
 
function norightclick(e){

	var e = e || window.event;
	var evtTarget = e.target || e.srcElement;

	if (e.which){
		if (e.which == 2 || e.which == 3)
		return false;
	}
	else if (e.button == 2 || e.button == 3){
		e.cancelBubble = true
		e.returnValue = false;
		return false;
	}
}
function nocontextmenu(e){
	var e = e || window.event;
	var evtTarget = e.target || e.srcElement;

	e.cancelBubble = true
	e.returnValue = false;
	return false;
}

addEventSimple(document, 'dragstart',function(e) { return false; });
addEventSimple(document, 'selectstart',function(e) {

	var e = e || window.event;
	var evtTarget = e.target || e.srcElement

	return false;

});
addEventSimple(document, 'contextmenu',nocontextmenu);
addEventSimple(document, 'mousedown',norightclick);

