// Namespace related methods

if(!window.addNamespace) {
	window.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]];
		}
	}
}

// Browser related properties

addNamespace("MS.Browser");
MS.Browser.isIE = (window.navigator.appName.toLowerCase().indexOf('explorer') != -1 || window.navigator.appName.toLowerCase().indexOf('msie') != -1 );

// Debugging

addNamespace("MS.Debug");
MS.Debug.enabled = false;
MS.Debug.trace = function(s){}

// JavaScript classes related methods

var Class = {
	create: function() {
		return function() {
			if(typeof this.initialize == "function")
				this.initialize.apply(this, arguments);
		}
	}
}

Object.extend = function(dest, source, override) {
	for(prop in source) {
		if(override || typeof dest[prop] == "undefined")
			dest[prop] = source[prop];
	}
	return dest;
}

Object.prototype.extend = function(o, override) {
	return Object.extend.apply(this, [this, o, override != false]);
}

function With(o, p) {
	for(var prop in p) {
		o[prop] = p[prop]; 
	}
}

// Event and function related methods

function isFunc(f) {
	return (f != null && typeof f == "function");
}

Function.prototype.getArguments = function() {
	var args = [];
	for(var i=0; i<this.arguments.length; i++)
		args.push(this.arguments[i]);
	return args;
};

Function.prototype.bind = function(o) {
	if(!window.__objs) {
		window.__objs = [];
		window.__funcs = [];
	}

	var objId = o.__oid;
	if(!objId)
		__objs[objId = o.__oid = __objs.length] = o;

	var me = this;
	var funcId = me.__fid;
	if(!funcId)
		__funcs[funcId = me.__fid = __funcs.length] = me;

	if(!o.__closures)
		o.__closures = [];

	var closure = o.__closures[funcId];
	if(closure)
		return closure;

	o = null;
	me = null;

	return __objs[objId].__closures[funcId] = function() {
		return __funcs[funcId].apply(__objs[objId], arguments);
	};
}

Function.prototype.bindAsEventListener = function(o) {
	if(!window.__objs) {
		window.__objs = [];
		window.__funcs = [];
	}

	var objId = o.__oid;
	if(!objId)
		__objs[objId = o.__oid = __objs.length] = o;

	var me = this;
	var funcId = me.__fid;
	if(!funcId)
		__funcs[funcId = me.__fid = __funcs.length] = me;

	if(!o.__closures)
		o.__closures = [];

	var closure = o.__closures[funcId];
	if(closure)
		return closure;

	o = null;
	me = null;
	
	return __objs[objId].__closures[funcId] = function(event) {
		return __funcs[funcId].call(__objs[objId], event || window.event);
	};
}

function addEvent(o, evType, f, capture) {
	if(o.addEventListener) {
		o.addEventListener(evType, f, capture);
		return true;
	} else if (o.attachEvent) {
		var r = o.attachEvent("on" + evType, f);
		return r;
	} else {
		// alert("Handler could not be attached");
	}
} 

function removeEvent(o, evType, f, capture) {
	if(o.removeEventListener) {
		o.removeEventListener(evType, f, capture);
		return true;
	} else if (o.detachEvent) {
		var r = o.detachEvent("on" + evType, f);
		return r;
	} else {
		// alert("Handler could not be removed");
	}
}

// JavaScript prototype extension

String.prototype.extend({
	endsWith: function(s) {
		return (this.substr(this.length - s.length) == s);
	},
	startsWith: function(s) {
		return (this.substr(0, s.length) == s);
	},
	trimLeft: function() {
		return this.replace(/^\s*/,"");
	},
	trimRight: function() {
		return this.replace(/\s*$/,"");
	},
	trim: function() {
		return this.trimRight().trimLeft();
	},
	format: function(s) {
		for(var i=1; i<arguments.length; i++) {
			s = s.replace("{" + (i -1) + "}", arguments[i]);
		}
		return s;
	2}
}, false);

Array.prototype.extend({
	push: function(o) {
		this[this.length] = o;
	}
}, false);

// Helper methods

Position = {
	getLocation: function(ele) {
		var offsetX = 0;
		var offsetY = 0;
		var parent;

		for(parent=ele; parent; parent=parent.offsetParent) {
			if(parent.offsetLeft)
				offsetX += parent.offsetLeft;
			if(parent.offsetTop)
				offsetY += parent.offsetTop;
		}

		return {x:offsetX,y:offsetY};
	},
	getBounds: function(ele) {
		var offset = Position.getLocation(ele);
		var width = ele.offsetWidth;
		var height = ele.offsetHeight;

		return {x:offset.x, y:offset.y, width:width, height:height};
	}
};

