
/**
 * Trims this string and returns new value
 * @return trimmed string
 * @type boolean
 */
String.prototype.trim = function() 
{
  	return this.replace(/^\s*|\s*$/g,"");
};


/**
 * Test if the argument is undefined
 * @param {Object} v any variable
 * @return true if the argument is undefined
 * @type boolean
 */
function isUndef( v )
{
	return typeof (v) == "undefined";
}

/**
 * Test if the argument is a function
 * @param {Object} v any variable
 * @return true if the argument is a function
 * @type boolean
 */
function isFunction( v )
{
	return typeof (v) == "function";
}


/**
 * Test if the argument is a string
 * @param {Object} v any variable
 * @return true if the argument is a string
 * @type boolean
 */
function isString( v )
{
	return typeof (v) == "string";
}

/**
 * Test if the argument is a number
 * @param {Object} v any variable
 * @return true if the argument is a number
 * @type boolean
 */
function isNumber( v )
{
	return typeof (v) == "number";
}

/**
 * Test if the argument is an object
 * @param {Object} v any variable
 * @return true if the argument is an object
 * @type boolean
 */
function isObject( v )
{
	return typeof (v) == "object";
}


/**
 * Test if the argument is an array
 * @param {Object} v any variable
 * @return true if the argument is array
 * @type boolean
 */
function isArray( v )
{
	return typeof (v) == "object" && v != null && v.constructor == Array;
}

/**
 * Test if the object is null or undefined (useful for checking optional arguments)
 * @return true if the object is null or undefined
 * @type boolean
 */
function isNun( obj ) 
{
	return ( isUndef( obj ) || obj === null );
}
/**
 * Define our own encodeURIComponent if it does not yet exist
 */
if ( isUndef(encodeURIComponent) )
{
	function encodeURIComponent(str) {
    	return escape(str).
			replace(/\+/g, "%2B").
			replace(/\"/g,"%22").
			replace(/\'/g, "%27").
			replace(/\//g,"%2F");
	 }
}

/**
 * Define our own decodeURIComponent if it does not yet exist
 */
if ( isUndef(decodeURIComponent) )
{
	function decodeURIComponent(str) {
	    return unescape(str.
	    	replace(/%2F/g,"/").
	    	replace(/%27/g, "'").
	    	replace(/%22/g,'"').
	        replace(/%2B/g, "+") );
	 }
}
/**
 * Same as document.createElement with the added ability to accept attributes in alternating name/pair arguments
 */
function $CE(tag) {
	var elem = document.createElement(tag);
	for (var i=2; i<arguments.length; i+=2) 
	{
		var name = arguments[i-1];
		var value = arguments[i];
		if (name && value) 
		{
			elem.setAttribute(name,value);
		}
	}
	return elem;
}
/**
 * Same as document.createTextNode
 */
function $CT(txt) {
	return document.createTextNode(txt);
}

/**
 * Adds "px" to the pixel value.
 */
function $px(pixel) {
	return pixel + "px";
}

/**
 *	Require that the specified resource is defined
 */
function require()
{
	for (var i=0;i<arguments.length;i++)
	{
		var name = arguments[i];
		var resource = eval(name);
		if (isUndef(resource))
		{
			if (Logger && Logger.error)
			{
				Logger.error("Resource required: " + name);
			}
		}
	}

}
/**
 * Get the dimensions of the browser's viewable area
 */
window.getClientDimensions = function()
{
	var dim = {};
	if (self.innerWidth)
	{
		dim.width = self.innerWidth;
		dim.height = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientWidth)
	{
		dim.width = document.documentElement.clientWidth;
		dim.height = document.documentElement.clientHeight;
	}
	else if (document.body)
	{
		dim.width = document.body.clientWidth;
		dim.height = document.body.clientHeight;
	}
	return dim;
}

Ajax.Request.prototype.evalResponse = function() {};

Function.prototype.bindWithArgs = function(obj)
{
	if (arguments.length > 1)
	{
		var args = [];
		for (var i=1;i<arguments.length;i++)
		{
			args[i-1] = arguments[i];
		}
		var f = this;
		return (function() { f.apply(this,args) }).bind(obj);
	}
	else return this.bind(obj);
}

Function.prototype.bindAsEventListenerWithArgs = function(obj)
{
	if (arguments.length > 1)
	{
		var args = [];
		for (var i=1;i<arguments.length;i++)
		{
			args[i-1] = arguments[i];
		}
		var f = this;
		return (function(evt) { f.apply(this,[evt].concat(args)) }).bindAsEventListener(obj);
	}
	else return this.bind(obj);
}

Element.replaceFirstChild = function(elem,node)
{
	if (elem.firstChild)
	{
		Element.remove(elem.firstChild);
	}
	elem.appendChild(node);
	/*
	if (elem.firstChild) elem.replaceChild(node,elem.firstChild);
	else elem.appendChild(node);
	*/
}

Element.removeChildNodes = function(elem)
{
	for (var i=elem.childNodes.length;i>=0;i=i-1)
	{
		//Logger.debug('type: ' + typeof(elem.childNodes[i]));
		if (elem.childNodes[i])	elem.removeChild(elem.childNodes[i]);
	}
};

Element.getTagName = function(elem)
{
	if (elem.nodeType == 1) return elem.tagName.toLowerCase();
	else return '';
}

Position.calculatedOffsetFrom = function(element, parent) 
{
	var valueT = 0, valueL = 0;
	do {
	    p = Element.getStyle(element, 'position');
	    //Logger.debug('calculatedOffsetFrom: ' + element.tagName + ',' + p + ',' + element.offsetParent + ',' +element.offsetTop );
	    /*
	    if (p == 'relative' || p == 'absolute') 
	    {
		      valueT += parseInt(Element.getStyle(element,'top'))  || 0;
		      valueL += parseInt(Element.getStyle(element,'left'))  || 0;
		 }
	      else
	      {

		      
	     }
	     */
		valueT += element.offsetTop  || 0;
		valueL += element.offsetLeft || 0;
	   element = element.offsetParent || element.parentNode;
	} while (element && element!=parent);
	return [valueL, valueT];
}



Date.prototype.setIso8601 = function (string) {
    var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
        "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
        "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    var d = string.match(new RegExp(regexp));

    var offset = 0;
    var date = new Date(d[1], 0, 1);

	// set the time as UTC
    if (d[3]) { date.setUTCMonth(d[3] - 1); }
    if (d[5]) { date.setUTCDate(d[5]); }
    if (d[7]) { date.setUTCHours(d[7]); }
    if (d[8]) { date.setUTCMinutes(d[8]); }
    if (d[10]) { date.setUTCSeconds(d[10]); }
    if (d[12]) { date.setUTCMilliseconds(Number("0." + d[12]) * 1000); }
	// apply the timezone offset

    if (d[14]) {
        offset = (Number(d[16]) * 60) + Number(d[17]);
        offset *= ((d[15] == '-') ? 1 : -1);
    }

    time = (Number(date) + (offset * 60 * 1000));
    //date.setTime(Number(time));
 	this.setTime(Number(time));
    return this;

}

Date.patterns = {
    ISO8601Long:"Y-m-d H:i:s",
    ISO8601Short:"Y-m-d",
    ShortDate: "n/j/Y",
    LongDate: "l, F d, Y",
    FullDateTime: "l, F d, Y g:i:s A",
    MonthDay: "F d",
    ShortTime: "g:i A",
    LongTime: "g:i:s A",
    SortableDateTime: "Y-m-d\\TH:i:s",
    UniversalSortableDateTime: "Y-m-d H:i:sO",
    YearMonth: "F, Y"
};

Logger = false;

var $V = function(element, minLength)
{
	var value = $F(element);
	
	if (!minLength) minLength = 1;
	
	return !( isUndef( value ) || (value === null) || (value.trim().length < minLength));
};

var $S = function(value)
{
	return ( isUndef( value ) || (value === null) ) ? '' : value;
};
