Object.extend = function(dest, source, replace) {
	for(var prop in source) {
		if(replace == false && dest[prop] != null) { continue; }
		dest[prop] = source[prop];
	}
	return dest;
};

Object.extend(Object.prototype, {
	clone:function() {
		var destination = new this.constructor;
		for (var property in this) destination[property] = this[property];
		return destination;
	}
}, false);

Object.extend(window, {
	$: function() {
		var elements = [];
		for(var i=0; i<arguments.length; i++) {
			var e = arguments[i];
			if(typeof e == 'string') {
				e = document.getElementById(e);
			}
			if(arguments.length == 1) {
				return e;
			}
			elements.push(e);
		}
		return elements;
	},
	Class: {
		create: function() {
			return function() {
				if(typeof this.initialize == "function") {
					this.initialize.apply(this, arguments);
				}
			};
		}
	},
	addNamespace:function(ns) {
		var nsParts = ns.split(".");
		var root = window;
		for(var i=0; i<nsParts.length; i++) {
			if(typeof root[nsParts[i]] == "undefined") {
				root[nsParts[i]] = {};
			}
			root = root[nsParts[i]];
		}
	}
}, false);

Object.extend(Function.prototype, {
	apply: function(o, a) {
		var r, x = "__fapply";
		if(typeof o != "object") { o = {}; }
		o[x] = this;
		var s = "r = o." + x + "(";
		for(var i=0; i<a.length; i++) {
			if(i>0) { s += ","; }
			s += "a[" + i + "]";
		}
		s += ");";
		eval(s);
		delete o[x];
		return r;
	},
	bind: function(o) {
		// Init object storage.
		if(!Function.__objs) {
			Function.__objs = [];
			Function.__funcs = [];
		}
		
		// Make sure the object has an id and is stored in the object store.
		var objId = o.__oid;
		if(!objId) {
			Function.__objs[objId = o.__oid = Function.__objs.length] = o;
		}

		var funcId = this.__fid;
		if(!funcId) {
			Function.__funcs[funcId = this.__fid = Function.__funcs.length] = this;
		}

		if(!o.__closures) {
			o.__closures = [];
		}

		var closure = o.__closures[funcId];
		if(closure) {
			return closure;
		}

		o = null;

		return Function.__objs[objId].__closures[funcId] = function() {
			return Function.__funcs[funcId].apply(Function.__objs[objId], arguments);
		};
	},
	getArguments: function() {
		var args = [];
		for(var i=0; i<this.arguments.length; i++) {
			args.push(this.arguments[i]);
		}
		return args;
	}
}, false);

Object.extend(Array.prototype, {
	addRange: function(items) {
		if(items.length > 0) {
			for(var i=0; i<items.length; i++) {
				this.push(items[i]);
			}
		}
	},
	clear: function() {
		this.length = 0;
		return this;
	},
	indexOf:function(o){
		for(var i=0;i<this.length;i++){
			if(this[i]==o) return i;
		}
		return -1;
	},
	remove:function(index){
		if(index>=this.length || index<0) return this.length;
		for(var i=index+1;i<this.length;i++)
		{
			this[i-1] = this[i];
		}
		this.length = this.length - 1;
		return this.length;
	}
}, false);

Object.extend(String.prototype, {
	trimLeft: function() {
		return this.replace(/^\s*/,"");
	},
	trimRight: function() {
		return this.replace(/\s*$/,"");
	},
	trim: function() {
		return this.trimRight().trimLeft();
	},
	endsWith: function(s) {
		if(this.length == 0 || this.length < s.length) { return false; }
		return (this.substr(this.length - s.length) == s);
	},
	startsWith: function(s) {
		if(this.length == 0 || this.length < s.length) { return false; }
		return (this.substr(0, s.length) == s);
	},
	split: function(c) {
		var a = [];
		if(this.length == 0) return a;
		var p = 0;
		for(var i=0; i<this.length; i++) {
			if(this.charAt(i) == c) {
				a.push(this.substring(p, i));
				p = ++i;
			}
		}
		a.push(s.substr(p));
		return a;
	},
	indexOfNearest:function(symbolList, startIndex){
		var ret=this.length;
		for(var i=0;i<symbolList.length;i++) if(this.indexOf(symbolList[i],startIndex)<ret && this.indexOf(symbolList[i],startIndex)!=-1) ret =  this.indexOf(symbolList[i],startIndex);
		return ret==this.length?-1:ret;
	},
	In:function(){
		var s = "";
		for(var i=0;i<arguments.length;i++)
		{
			if (s != "") { s+="|"; }
			s += "^" + arguments[i] + '$';
		}
		var reg = new RegExp(s, 'gi');
		return reg.test(this);
	}
}, false);

Object.extend(String, {
	format: function(s) {
		for(var i=1; i<arguments.length; i++) {
			s = s.replace("{" + (i -1) + "}", arguments[i]);
		}
		return s;
	},
	isNullOrEmpty: function(s) {
		if(s == null || s.length == 0) {
			return true;
		}
		return false;
	},
	repeat:function(s, c){
		var ret = '';
		for(var i=0;i<c;i++) ret += s;
		return ret;
	}
}, false);

/*

	var addNamespace = function(ns) {
		var nsParts = ns.split(".");
		var root = window;
		for(var i=0; i<nsParts.length; i++) {
			if(typeof root[nsParts[i]] == "undefined") {
				root[nsParts[i]] = {};
			}
			root = root[nsParts[i]];
		}
	};
*/
	if(typeof addEvent == "undefined")
		addEvent = function(o, evType, f, capture) {
			if(o == null) { return false; }
			if(o.addEventListener) {
				o.addEventListener(evType, f, capture);
				return true;
			} else if (o.attachEvent) {
				var r = o.attachEvent("on" + evType, f);
				return r;
			} else {
				try{ o["on" + evType] = f; }catch(e){}
			}
	};

	if(typeof removeEvent == "undefined")
		removeEvent = function(o, evType, f, capture) {
			if(o == null) { return false; }
			if(o.removeEventListener) {
				o.removeEventListener(evType, f, capture);
				return true;
			} else if (o.detachEvent) {
				o.detachEvent("on" + evType, f);
			} else {
				try{ o["on" + evType] = function(){}; }catch(e){}
			}
	};

