/*
	JSAPI
	2002 Florian Hoech
	
	jsapi/core.js
	
	Dependencies:
		NONE
*/

// Array methods
var p=Array.prototype
if(!p.pop) p.pop=function() {
	var e=this[this.length-1]
	this.splice(this.length-1,1)
	return e
}
if(!p.push||(p.push && [].push(0)==0)) p.push = function() {
	/*
		Adds one or more elements to the end of an array
		Returns the new length of the array
	*/
	for(var i=0;i<arguments.length;i++) this[this.length]=arguments[i]
	return this.length
}
if(!p.shift) p.shift=function() {
	var e=this[0]
	this.splice(0,1)
	return e
}
if(!p.splice||(p.splice && [true].splice(0,1)==true)) p.splice = function(index,howMany){
	/*
		Removes / adds elements to an array
		Returns an array containing the removed elements
	*/
	if(arguments.length == 0) return index
	if(typeof index != "number") index = 0
	if(index < 0) index = Math.max(0,this.length + index)
	if(index > this.length) {
		if(arguments.length > 2) index = this.length
		else return []
	}
	if(arguments.length < 2) howMany = this.length-index
	howMany = (typeof howMany == "number") ? Math.max(0,howMany) : 0
	var removedElements = this.slice(index,index+howMany)
	var elementsToMove = this.slice(index+howMany)
	this.length = index
	for(var i=2;i<arguments.length;i++) this[this.length] = arguments[i]
	for(var i=0;i<elementsToMove.length;i++) this[this.length] = elementsToMove[i]
	return removedElements
}
//if(!p.toSource)
p.toSource = function(collapse,src) {
	var oindex=Object._temp.push(this)
	var str=""
	for (var i=0;i<this.length;i++) {
		if (str) str+=","+(collapse?" ":"\n")
		var v=this[i]
		if (v!=null) {
			if (typeof v=="function" || typeof v=="object") {
				var vindex=Object._temp.indexof(v)
				if (typeof v.toSource=="function") {
					if (vindex>-1) v="#"+(vindex+1)+"#"
					else {
						if (typeof v=="function") v="#"+Object._temp.push(v)+"="+v.toSource(collapse)
						else {
							if (v.toSource!=Array.prototype.toSource && v.toSource!=Object.prototype.toSource) {
								v="#"+Object._temp.push(v)+"="+v.toSource()
							}
							else v=v.toSource(collapse,this)
						}
					}
				}
				else {
					if (vindex>-1) v="#"+(vindex+1)+"#"
					else v="#"+Object._temp.push(v)+"={}"
				}
			}
			else if (typeof v!="number") v='"'+String.escape(v)+'"'
			str+=v
		}
	}
	if (str) str=(collapse?"":"\n")+str.indent(collapse?0:4)+(collapse?"":"\n")
	if (!src) Object._temp=[]
	return "#"+(oindex)+"=["+str+"]"
}
p.add = function(index,element) {
	/*
		Adds elements to an array if they are not already in the array
		Returns an array containing the added elements (if no elements were added the array will be empty)
	*/
	if (index==null||typeof index!="number") index=this.length
	var a=arguments
	var r=[]
	for (var i=1;i<a.length;i++) {
		//for (var p in this) if (this[p]==a[i]) return r
		if (a[i] && a[i].id && this[a[i].id]==a[i]) break
		this.splice(index+(i-1),0,a[i])
		if (a[i] && a[i].id) this[a[i].id]=this[index+(i-1)]
		r.push(a[i])
	}
	return r
}
p.clear = function() { // Removes all elements and assigns null to all properties of an array
	this.splice(0,this.length)
	var p=Array.prototype
	for (var i in this) if (this[i]!=null && (p[i]==null || this[i]!=p[i] || typeof this[i]!="function")) this[i]=null
	return this
}
/*p.clone = function(clonechildren,src) { // Returns a copy of an array
	var r=[]
	for (var i in this) r[i]=this[i]
	return r
}*/
p.getprimitive = function() { return '[object Array (length:'+this.length+')]' }
p.indexof = function(e) {
	for (var i=0;i<this.length;i++) if (this[i]==e) return i
	return -1
}
p.initialize = function() { // Removes all elements and properties of an array
	this.splice(0,this.length)
	var p=Array.prototype
	for (var i in this) if (p[i]==null || this[i]!=p[i] || typeof this[i]!="function") delete this[i]
	return this
}
p.remove = function(element) {
	/*
		Removes elements from an array
		Returns an array containing the removed elements
	*/
	var a=arguments
	var r=[]
	for (var i=0;i<a.length;i++) {
		for (var j=this.length-1;j>=0;j--) if (this[j]==a[i]) {
			if (this[j].id && this[this[j].id]) {
				this[this[j].id]=null
				delete this[this[j].id]
			}
			r.push(this.splice(j,1)[0])
			break
		}
	}
	return r
}
p.replace = function(search,substitute) {
	/*
		Replaces an array element with another element
		Returns an array containing the replaced elements (if no elements were replaced the array will be empty)
	*/
	var r=[]
	for (var i=0;i<this.length;i++) if (this[i]==search) {
		if (this[i].id && this[this[i].id]) delete this[this[i].id]
		r.push(this[i]=substitute)
		if (this[i].id) this[this[i].id]=this[i]
		break
	}
	return r
}
p.toobject = function() {
	var o={}
	var p=this.constructor.prototype
	for (var i in this) if (p[i]==null || this[i]!=p[i] || typeof this[i]!="function") o[i]=this[i]
	return o
}

// Boolean methods
p=Boolean.prototype
if(!p.toSource) p.toSource = function() { return '(new Boolean('+this+'))' }

// Date object
Date.days=new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
Date.months=new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")

// Date methods
p=Date.prototype
if(!p.getMilliseconds) p.getMilliseconds = function() { return this.getTime()-Date.parse(this.toString()) }
if(!p.toSource) p.toSource = function(m) { return '(new Date('+(m?this.getFullYear()+","+this.getMonth()+","+this.getDate()+","+
this.getHours()+","+this.getMinutes()+","+this.getSeconds()+","+this.getMilliseconds():this.getTime())+'))' }
p.clone = function() { return new Date(this.getYear(),this.getMonth(),this.getDate(),this.getHours(),this.getMinutes(),this.getSeconds()) }
p.getdayname = function() { return Date.days[this.getDay()] }
p.getfullday = function() { // returns a string
	var v=this.getDate()
	return v>9?""+v:"0"+v
}
p.getfullmonth = function() { // returns a string
	var v=this.getMonth()+1
	return v>9?""+v:"0"+v
}
p.getmonthname = function() { return Date.months[this.getMonth()] }

// Exception
function Exception(value) {
	this.value=value
}

// Exception methods
p=Exception.prototype
p.toString = function() { return this.value }
p.getprimitive = function() { return '[object Exception (value:"'+this.value+'")]' }

// Function methods
p=Function.prototype
//if(!p.toSource) p.toSource = function() { return '('+this+')' }
p.toSource = function(collapse) {
	var v=this+""
	v=v.replacelinebreaks("\n")
	v=v.replacetabs("    ") // replace tabs with spaces
	if (v.charAt(0)=="\n") v=v.substring(1) // remove leading newline
	if (v.charAt(v.length-1)=="\n") v=v.substring(0,v.length-1) // remove trailing newline
	v=v.substring(0,v.length-1) // remove trailing "}"
	if (v.charAt(v.length-1)=="\n") v=v.substring(0,v.length-1) // remove trailing newline
	v=v.replace(/\/\/.*\n/g,"\n") // remove singleline comments
	v=v.replace(/\n    /g,"\n") // unindent
	v=v.replace(/\n/g,"\n    ") // indent
	v=v.replace(/\n\s*\n/g,"\n") // remove empty lines
	if (collapse) {
		v=v.replace(/\n\s*/g,"\n") // remove whitespace at beginning of line
		v=v.replace(/\n/g,"; ") // replace newline with "; "
		v=v.replace(/;;/g,";") // replace ";;" with ";"
		v=v.replace(/\{;/g,"{") // replace "{;" with "{"
		v=v.replace(/\};/g,"}") // replace "};" with "}"
		v=v.replace(/\{ /g,"{") // replace "{ " with "{"
		v=v.replace(/ \}/g,"}") // replace " }" with "}"
	}
	return '('+v+(!collapse?"\n":"")+'})'
}
p.clone = function() { return this }
p.getprimitive = function() { return "[object Function]" }
p.getname = function() {
	var str=this+""
	var findex=str.indexOf("function")
	var nindex=str.indexOf("(")
	if (findex+8==nindex) return ""
	return str.substring(findex+9,nindex)
}

// Number
Number.frombinary=function(binary) {
	binary+=""
	var l=binary.length
	var digit
	var i
	var decimal=0
	var power=l-1
	for (i=0; i<l; i++) {
		digit=binary.substring(i,i+1)
		if(digit!="0" && digit!="1") return NaN
	}
	for (i=0; power>=0; power--, i++) {
		digit=parseInt(binary.substring(i,i+1))
		decimal+=digit*Math.pow(2,power)
	}
	return decimal
}
Number.fromhex=function(hex) { return new Number("0x"+hex) }

// Number methods
p=Number.prototype
if(!p.toSource) p.toSource = function() { return '(new Number('+this+'))' }
p.fill=function(l) {
	var n=this+""
	while (n.length<l) n="0"+n
	return n
}
p.lead=function(l) {
	var n=this+""
	var i=0
	while (i==0) {
		i=n.indexOf("0")
		if (i==0) {
			n=n.substr(i+1)
			if (l>=0) l--
		}
	}
	if (l==null) l=1
	n="0".repeat(l)+n
	return n
}
p.tobinary=function(l) {
	var binary=this.toString(2)
	/*var decimal=parseInt(this)
	var binary=""
	var digit
	var i=0
	var j=0
	var temp
 	while (Math.pow(2,j)<=this) j++
	i=j-1
 	while(i!=-1) {
		temp=Math.floor(decimal/Math.pow(2,i))
		if (temp!=0) {
			decimal-=temp*Math.pow(2,i)
			digit="1"
		}
    	else digit="0"
		binary+=digit
    	i--
	}*/
	while (binary.length<l) binary="0"+binary
	return binary
}
p.tofloat=function(l,parsefloat) {
	var n=this+""
	var isfloat=n.indexOf(".")>=0
	if (!isfloat) n+="."
	var i=n.indexOf(".")
	var ipart=n.substr(0,i)
	var fpart=n.substr(i+1)
	if (!l) l=fpart.length||1
	if (parseInt(fpart.charAt(l))>=5) {
		var zeros=""
		while (fpart.charAt(0)=="0" && l>1) {
			fpart=fpart.substr(1)
			zeros+="0"
		}
		fpart=zeros+(parseInt(fpart.substr(0,l-zeros.length))+1)
		n=ipart+"."+fpart
	}
	for (var j=0; j<l-fpart.length; j++) n+="0"
	n=n.substr(0,i+1+l)
	return parsefloat?parseFloat(n):n
}
p.tohex=function(uppercase) {
	var hex=this.toString(16)
	/*var hex=""
	for(var c=this; c!=0; c>>=4) hex="0123456789abcdef".charAt(c % 16)+hex*/
	return uppercase?hex.toUpperCase():hex
}

// Object
Object._temp=[]
Object._history=[]

// Object methods
p=Object.prototype
//if(!p.toSource)
p.toSource = function(collapse,src) {
	if (this.constructor==Boolean) return '(new Boolean('+this+'))'
	if (this.constructor==Date) return '(new Date('+this.getTime()+'))'
	if (this.constructor==Function) return '('+this+')'
	if (this.constructor==Number) return '(new Number('+this+'))'
	if (this.constructor==RegExp) return this
	if (this.constructor==String) return '(new String("'+String.escape(this)+'"))'
	if (Object._temp.indexof(this)>=0) return
	var oindex=Object._temp.push(this)
	var p=this.constructor.prototype
	var str=""
	for (var i in this) {
		var v=this[i]
		if (p[i]==null || v!=p[i] || this==p || typeof v!="function") {
			if (str) str+=","+(collapse?" ":"\n")
			if (v!=null) {
				if (typeof v=="function" || typeof v=="object") {
					var vindex=Object._temp.indexof(v)
					if (typeof v.toSource=="function") {
						if (vindex>-1) v="#"+(vindex+1)+"#"
						else {
							if (typeof v=="function") v="#"+Object._temp.push(v)+"="+v.toSource(collapse)
							else {
								//Object._history.add(null,i)//DEBUG
								//alert("BEFORE "+Object._history.join(":"))//DEBUG
								if (v.toSource!=Array.prototype.toSource && v.toSource!=Object.prototype.toSource) {
									v="#"+Object._temp.push(v)+"="+v.toSource()
								}
								else v=v.toSource(collapse,this)
								//alert("AFTER "+Object._history.join(":"))//DEBUG
								//Object._history.remove(i)//DEBUG
							}
						}
					}
					else {
						if (vindex>-1) v="#"+(vindex+1)+"#"
						else v="#"+Object._temp.push(v)+"={}"
					}
				}
				else if (typeof v!="number") v='"'+String.escape(v)+'"'
			}
			v+="" // convert to string
			str+=i+":"+(collapse?v:"\n"+v.indent())
		}
	}
	if (str) str=(collapse?"":"\n")+str.indent(collapse?0:4)+(collapse?"":"\n")
	if (!src) Object._temp=[]
	return "#"+oindex+"={"+str+"}"
}
p.clear = function() { // Assigns null to all properties of an object
	var p=this.constructor.prototype
	for (var i in this) if (this[i]!=null && (p[i]==null || this[i]!=p[i] || typeof this[i]!="function")) this[i]=null
	return this
}
p.clone = function(clonechildren,src) { // Returns a copy of an object
	var o=new this.constructor()
	Object._temp.push(o)
	Object._temp.push(this)
	var p=this.constructor.prototype
	for (var i in this) {
		var v=this[i]
		if (p[i]==null || v!=p[i] || this==p || typeof v!="function") {
			if (clonechildren && v!=null && (typeof v=="function" || typeof v=="object") && (v.toSource==Array.prototype.toSource || v.toSource==Function.prototype.toSource || v.toSource==Object.prototype.toSource)) {
				var vindex=Object._temp.indexof(v)
				if (vindex>-1) v=Object._temp[vindex-1]
				else {
					if (v.clone) v=v.clone(clonechildren,this)
					else {
						Object._temp.push({})
						v=Object._temp[Object._temp.push(v)-2]
					}
				}
			}
			o[i]=v
		}
	}
	//o.constructor=this.constructor
	o.toSource=this.toSource
	o.toString=this.toString
	o.valueOf=this.valueOf
	if (!src) Object._temp=[]
	return o
}
p.getproperties = function() { return getpropertiesof(this) }
p.getprimitive = function() { 
	var n=(this.constructor&&this.constructor.getname)?this.constructor.getname():""
	return "[object"+(n?" "+n:"")+"]"
}
p.inherit = function() {
	/*
		First argument: object from which to inherit
		Optional following argument(s): properties to inherit as string
		Example: myobj.inherit(anotherobj[,"property1","method1","property2",...])
	*/
	var a=arguments
	var o=a[0]
	if (typeof o=="function") {
		var str=""
		this._OBJECT_INHERIT_FUNCTION=o
		for (var i=1; i<a.length; i++) {
			if (str) str+=","
			str+="a["+i+"]"
		}
		eval("this._OBJECT_INHERIT_FUNCTION("+str+")")
		delete this._OBJECT_INHERIT_FUNCTION
	}
	else {
		if (a.length>1) for (var i=1; i<a.length; i++) this[a[i]]=o[a[i]]
		else {
			for (var i in o) this[i]=o[i]
			this.toSource=o.toSource
			this.toString=o.toString
			this.valueOf=o.valueOf
		}
	}
	return this
}
p.inheritmethods = function() { // Arguments: object(s) from which to inherit methods
	// Example: myobj.inheritmethods(obj1[,obj2,...])
	var a=arguments
	for (var i=0;i<a.length;i++) {
		for (var j in a[i]) if (typeof a[i][j] == "function") this[j]=a[i][j]
		this.toSource=a[i].toSource
		this.toString=a[i].toString
		this.valueOf=a[i].valueOf
	}
	return this
}
p.initialize = function() { // Removes all properties of an object
	var p=this.constructor.prototype
	for (var i in this) if (p[i]==null || this[i]!=p[i] || typeof this[i]!="function") delete this[i]
	return this
}
p.listproperties = function() { return listpropertiesof(this) }
p.join = function(d) {
	if (!d) d=","
	var str=""
	var p=this.constructor.prototype
	for (var i in this) if (p[i]==null || this[i]!=p[i] || typeof this[i]!="function") {
		if (str!="") str+=d
		str+=this[i]
	}
	return str
}
p.setprototype = function() {
	var a=arguments
	var p=this.prototype?this:this.constructor
	for (var i=0;i<a.length;i++) {
		var o=a[i].prototype?a[i]:a[i].constructor
		p.prototype = new o()
		p.prototype.constructor = p
	}
	return this
}
p.toarray = function() {
	var r=[]
	if (this.length) for (var i=0;i<this.length;i++) r[i]=this[i]
	else {
		var p=this.constructor.prototype
		for (var i in this) {
			if (typeof i=="number") r.push(this[i])
			else if (p[i]==null || this[i]!=p[i] || typeof this[i]!="function") r[i]=this[i]
		}
	}
	return r
}

// Property
function Property(id,value) {
	this.id=id
	this.value=value
}
p=Property.prototype
p.toString = function() {
	var str = ""
	var v=this.value
	if (v!=null && (typeof v=="object" || typeof v=="function" || typeof v=="string")) v=getprimitiveof(v)
	str+=this.id+":"+v
	return str
}
p.getprimitive = function() { return '[object Property (id:"'+this.id+'")]' }

// RegExp methods
p=RegExp.prototype
if(!p.toSource) p.toSource = function() { return this }
p.clone = function() { return new RegExp(this.source,(this.global?"g":"")+(this.ignoreCase?"i":"")) }

// String
String.escape = function(str) { return (str+""||"").escape() }
String.unescape = function(str) { return (str+""||"").unescape() }
String.escapecodes=[
	// ampersand
	["\x26","\\x26","&amp;"],
	// umlauts
	["\xC4","\\xC4","&Auml;"],
	["\xD6","\\xD6","&Ouml;"],
	["\xDC","\\xDC","&Uuml;"],
	["\xE4","\\xE4","&auml;"],
	["\xF6","\\xF6","&ouml;"],
	["\xFC","\\xFC","&uuml;"],
	// quotes
	["\x22",'\\"'  ,"&quot;"],
	["\x27","\\'"  ,"'"],
	// <> brackets
	/*["\x3C","\\x3C","&lt;"],
	["\x3E","\\x3E","&gt;"],*/
	// special chars
	["\x89","\\x89","&permil;"],
	["\x8B","\\x8B","&lsaquo;"],
	["\x96","\\x96","&ndash;"],
	["\x97","\\x97","&mdash;"],
	["\x99","\\x99","&trade;"],
	["\x9B","\\x9B","&rsaquo;"],
	["\xA1","\\xA1","&iexcl;"],
	["\xA2","\\xA2","&cent;"],
	["\xA3","\\xA3","&pound;"],
	["\xA4","\\xA4","&curren;"],
	["\xA5","\\xA5","&yen;"],
	["\xA6","\\xA6","&brvbar;"],
	["\xA7","\\xA7","&sect;"],
	["\xA8","\\xA8","&uml;"],
	["\xA9","\\xA9","&copy;"],
	["\xAA","\\xAA","&ordf;"],
	["\xAB","\\xAB","&laquo;"],
	["\xAC","\\xAC","&not;"],
	["\xAD","\\xAD","&shy;"],
	["\xAE","\\xAE","&reg;"],
	["\xAF","\\xAF","&macr;"],
	["\xB0","\\xB0","&deg;"],
	["\xB1","\\xB1","&plusmn;"],
	["\xB2","\\xB2","&sup2;"],
	["\xB3","\\xB3","&sup3;"],
	["\xB4","\\xB4","&acute;"],
	["\xB5","\\xB5","&micro;"],
	["\xB6","\\xB6","&para;"],
	["\xB7","\\xB7","&middot;"],
	["\xB8","\\xB8","&cedil;"],
	["\xB9","\\xB9","&sup1;"],
	["\xBA","\\xBA","&ordm;"],
	["\xBB","\\xBB","&raquo;"],
	["\xBC","\\xBC","&frac14;"],
	["\xBD","\\xBD","&frac12;"],
	["\xBE","\\xBE","&frac34;"],
	["\xBF","\\xBF","&iquest;"],
	["\xC0","\\xC0","&Agrave;"],
	["\xC1","\\xC1","&Aacute;"],
	["\xC2","\\xC2","&Acirc;"],
	["\xC3","\\xC3","&Atilde;"],
	["\xC4","\\xC4","&Auml;"],
	["\xC5","\\xC5","&Aring;"],
	["\xC6","\\xC6","&AElig;"],
	["\xC7","\\xC7","&Ccedil;"],
	["\xC8","\\xC8","&Egrave;"],
	["\xC9","\\xC9","&Eacute;"],
	["\xCA","\\xCA","&Ecirc;"],
	["\xCB","\\xCB","&Euml;"],
	["\xCC","\\xCC","&Igrave;"],
	["\xCD","\\xCD","&Iacute;"],
	["\xCE","\\xCE","&Icirc;"],
	["\xCF","\\xCF","&Iuml;"],
	["\xD0","\\xD0","&ETH;"],
	["\xD1","\\xD1","&Ntilde;"],
	["\xD2","\\xD2","&Ograve;"],
	["\xD3","\\xD3","&Oacute;"],
	["\xD4","\\xD4","&Ocirc;"],
	["\xD5","\\xD5","&Otilde;"],
	["\xD6","\\xD6","&Ouml;"],
	["\xD7","\\xD7","&times;"],
	["\xD8","\\xD8","&Oslash;"],
	["\xD9","\\xD9","&Ugrave;"],
	["\xDA","\\xDA","&Uacute;"],
	["\xDB","\\xDB","&Ucirc;"],
	["\xDC","\\xDC","&Uuml;"],
	["\xDD","\\xDD","&Yacute;"],
	["\xDE","\\xDE","&THORN;"],
	["\xDF","\\xDF","&szlig;"],
	["\xE0","\\xE0","&agrave;"],
	["\xE1","\\xE1","&aacute;"],
	["\xE2","\\xE2","&acirc;"],
	["\xE3","\\xE3","&atilde;"],
	["\xE4","\\xE4","&auml;"],
	["\xE5","\\xE5","&aring;"],
	["\xE6","\\xE6","&aelig;"],
	["\xE7","\\xE7","&ccedil;"],
	["\xE8","\\xE8","&egrave;"],
	["\xE9","\\xE9","&eacute;"],
	["\xEA","\\xEA","&ecirc;"],
	["\xEB","\\xEB","&euml;"],
	["\xEC","\\xEC","&igrave;"],
	["\xED","\\xED","&iacute;"],
	["\xEE","\\xEE","&icirc;"],
	["\xEF","\\xEF","&iuml;"],
	["\xF0","\\xF0","&eth;"],
	["\xF1","\\xF1","&ntilde;"],
	["\xF2","\\xF2","&ograve;"],
	["\xF3","\\xF3","&oacute;"],
	["\xF4","\\xF4","&ocirc;"],
	["\xF5","\\xF5","&otilde;"],
	["\xF6","\\xF6","&ouml;"],
	["\xF7","\\xF7","&divide;"],
	["\xF8","\\xF8","&oslash;"],
	["\xF9","\\xF9","&ugrave;"],
	["\xFA","\\xFA","&uacute;"],
	["\xFB","\\xFB","&ucirc;"],
	["\xFC","\\xFC","&uuml;"],
	["\xFD","\\xFD","&yacute;"],
	["\xFE","\\xFE","&thorn;"],
	["\xFF","\\xFF","&yuml;"],
	// linebreaks
	["\r\n","\\r\\n","<br>"], // Windows
	["\n"  ,"\\n"  ,"<br>"], // Unix/Linux/Mac OS X
	["\r"  ,"\\r"  ,"<br>"] // Mac OS 9
]

// String methods
var p=String.prototype, l=location
if(!p.toSource) p.toSource = function() { return '(new String("'+String.escape(this)+'"))' }
p.escape = function() {
	str=this
	/*str=str.replace(/\\r/g,"\\\\r")
	str=str.replace(/\\t/g,"\\\\t")
	str=str.replace(/\n/g,"\\n")
	str=str.replace(/\r/g,"\\r")
	str=str.replace(/\t/g,"\\t")
	str=str.replace(/\\?\"/g,'\\\"')
	str=str.replace(/\\?\'/g,"\\\'")*/
	var c=String.escapecodes
	for (var i=0;i<c.length;i++) str=str.replace(new RegExp(c[i][0],"g"),c[i][1])
	return str
}
p.unescape = function() {
	str=this
	var c=String.escapecodes
	for (var i=0;i<c.length;i++) str=str.replace(new RegExp("\\"+c[i][1],"g"),c[i][0])
	return str
}
p.clone = function() { return new String(this) }
p.fromhtml=function() {
	var txt=this
	txt=txt.replace(/<br>&nbsp;<br>/g,"<br><br>")
	var c=String.escapecodes
	for (var i=0;i<c.length;i++) txt=txt.replace(new RegExp(c[i][2],"g"),c[i][0])
	return txt
}
p.getfile = l.getfile = function() {
	var s = this+""
	var i = s.lastIndexOf("/")
	var j = s.lastIndexOf("\\")
	if (i<0 && j<0) return null
	if (j > i) i=j
	return s.substring(i+1)
}
p.getpath = l.getpath = function() {
	var s = this+""
	var i = s.lastIndexOf("/")
	var j = s.lastIndexOf("\\")
	if (i<0 && j<0) return null
	if (j > i) i=j
	return s.substring(0,i+1)
}
p.getprimitive = function() { return '"'+String.escape(this)+'"' }
p.getsearchargument = l.getsearchargument = function(i) { return this.getsearcharguments()[i] }
p.getsearcharguments = l.getsearcharguments = function() {
	var s = this+""
	var a = []
	var i = s.indexOf('?')
	if (i>-1) {
		var b = s.substring(i+1).split('&')
		for (var i=0;i<b.length;i++) {
			var c = b[i].split('=')
			a.add(null,new Property(c[0],c[1]))
		}
	}
	return a
}
p.indent = function(howMany,indent) {
	if (howMany==null) howMany=4
	if (indent==null) indent=" "
	var indentstr=""
	for (var i=0; i<howMany; i++) indentstr+=indent
	var str=indentstr+this
	str=str.replacelinebreaks("\n")
	str=str.replace(/\n/g,"\n"+indentstr)
	return str
}
p.repeat = function(n) {
	var str=""
	for (var i=0;i<n;i++) str+=this
	return str
}
p.replacelinebreaks = function(d) {
	var search
	if (d==null) d=" "
	// CR LF = Windows
	// CR = Mac OS 9
	// LF = Unix/Linux/Mac OS X
	var str=this.replace(/\r\n/g,"\n") // replace CR LF with LF
	str=str.replace(/\r/g,"\n") // replace CR with LF
	return str.replace(/\n/g,d) // replace LF
}
p.replacetabs = function(d) {
	if (d==null) d=" "
	return this.replace(/\t/g,d)
}
p.reverse=function() {
	var txt=""
	for (var i=this.length-1;i>=0;i--) txt+=this.charAt(i)
	return txt
}
p.sort=function(fn,d) {
	if (!d) d="\n"
	var a=this.replacelinebreaks("\n").split(d)
	return (fn?a.sort(fn):a.sort()).join(d)
}
/*p.sort=function(i,d) {
	if (!d) d="\n"
	return this.replacelinebreaks("\n").split(d).sort(function(a,b) {
		if (i) { // ignore case
			 if (a.toLowerCase()<b.toLowerCase()) return -1
			 if (a.toLowerCase()>b.toLowerCase()) return 1
		}
		else {
			 if (a<b) return -1
			 if (a>b) return 1
		}
		return 0
	}).join(d)
}*/
p.striphtml=function() {
	var txt=String.unescape(this)
	var c=String.escapecodes
	for (var i=0;i<c.length;i++) txt=txt.replace(new RegExp(c[i][2],"g"),c[i][0])
	var i=j=0
	while (i>-1 && j>-1) {
		i=txt.indexOf("<")
		j=txt.indexOf(">")
		if (i<j) {
			var tagname=txt.substring(i+1,j-1)
			if (tagname.indexOf("<")<0) txt=txt.substring(0,i)+txt.substring(j+1)
			else txt=txt.substring(0,i)+txt.substring(i+1)
		}
		else {
			txt=txt.substring(0,j)+txt.substring(j+1)
		}
	}
	i=j=0
	while (i>-1 || j>-1) {
		i=txt.indexOf("<")
		j=txt.indexOf(">")
		if (i>-1) txt=txt.substring(0,i)+txt.substring(i+1)
		if (j>-1) txt=txt.substring(0,j)+txt.substring(j+1)
	}
	return txt
}
p.todate=function(){
    var str=this
    var lang=navigator.userLanguage||navigator.language
    en=lang?lang.indexOf("en")>=0:null
    var date=Date.parse(str)
    if (!isNaN(date)) return new Date(date)
    var parts=str.split(" "),y,month,d,h,m,s,ms
    for (var i=parts.length-1;i>=0;i--){
        if (parts[i].indexOf(".")>-1) delim="."
        else if (parts[i].indexOf("/")>-1) delim="/"
        else if (parts[i].indexOf("-")>-1) delim="-"
        else if (parts[i].indexOf(":")>-1) delim=":"
        else delim=null
        parts[i]=delim?parts[i].split(delim):[parts[i]]
        if (delim==":"){
            for (var j=0;j<parts[i].length;j++) parts[i][j]=parseInt(parts[i][j])
            if (parts[i][0]<=24) h=parts[i][0]
            if (parts[i][1]<60) m=parts[i][1]
            if (parts[i][2]<60) s=parts[i][2]
            if (parts[i][3]<1000) ms=parts[i][3]
            parts.splice(i,1)
        }
    }
    for (var i=0;i<parts.length;i++) for (var j=0;j<parts[i].length;j++){
        var n=parts[i][j]
        if (isNaN(parseInt(n))){
            n=n.toLowerCase()
            if (n.charAt(0)=="j") month=1
            else if (n.charAt(0)=="f") month=2
            else if (n.indexOf("may")==0||n.indexOf("mai")==0) month=5
            else if (n.charAt(0)=="m") month=3
            else if (n.indexOf("ap")==0) month=4
            else if (n.indexOf("jun")==0) month=6
            else if (n.charAt(0)=="j") month=7
            else if (n.indexOf("au")==0) month=8
            else if (n.charAt(0)=="s") month=9
            else if (n.charAt(0)=="o") month=10
            else if (n.charAt(0)=="n") month=11
            else if (n.charAt(0)=="d") month=12
        }
        else{
            n=parseInt(n)
            if (n>31||(month&&day)) y=n    // assume this is the year
            else{
                // could be day or month
                if (n>12||j==2) {   // assume this is the day
                    d=n
                    if (!month&&j>0&&parts[i][j-1]<=12) month=parts[i][j-1]
                        // assume us/english date format (month/day)
                }
                else if (en){
                    if (!month) month=n
                    else if (!d) d=n
                }
                else {
                    if (!d) d=n
                    else if (!month) month=n
                }
            }
        }
    }
    var today=new Date()
    y=y||today.getFullYear()
    month=(month||today.getMonth()+1)-1
    d=d||today.getDate()
    h=h||0
    m=m||0
    s=s||0
    ms=ms||0
    return new Date(y,month,d,h,m,s,ms)
}
p.tohtml=function() {
	var txt=String.unescape(this)
	var c=String.escapecodes
	for (var i=0;i<c.length;i++) txt=txt.replace(new RegExp(c[i][0],"g"),c[i][2])
	txt=txt.replace(/  /g,"&nbsp; ")
	txt=txt.replace(/<br><br>/g,"<br>&nbsp;<br>")
	if (txt.charAt(txt.length-1)==" ") txt=txt.substring(0,txt.length-1)+"&nbsp;"
	return txt
}
p.trim=function(l) {
	if (this.length>l) return this.substr(0,l)+"..."
	return this
}

// Top-level methods and properties
if (!window.navigator) window.navigator={}
if (!window.Infinity) window.Infinity=Number.POSITIVE_INFINITY
if (!window.NaN) window.NaN=Number.NaN
if (!window.undefined) window.undefined=window.undefined

function getpropertiesof(o) {
	var p,r=[],v
	if (o.constructor) {
		p=o.constructor.toSource(true).search(/\(function.*\(\) \{\[native code\]\}\)/g)==0?{}:o.constructor.prototype
	}
	else p={}
	for (var i in o) {
		if (window.ua && (ua.ie5 || ua.ns5)) {
			eval("try { v=o[i] } catch(e) { v=new Exception(e) }")
		}
		else v=o[i]
		if (p[i]==null || v!=p[i] || o==p || typeof v!="function") r.push(new Property(i,v))
	}
	return r
}
function getprimitiveof(o) {
	if (o.getprimitive) return o.getprimitive()
	var n=(o.constructor&&o.constructor.getname)?o.constructor.getname():""
	return "[object"+(n?" "+n:"")+"]"
}
function isNumber(n) { return !isNaN(parseInt(n)) }
function listpropertiesof(o) {
	var r=getpropertiesof(o)
	if (r.length) r=r.sort().join("\n")
	return r
}

// Clean-Up
l = null
p = null

// EOF
