String.format = function(tmpl) {
	for(var i=1; i<arguments.length; i++) {
		re = new RegExp('\\\{' + (i-1) + '\\\}', 'gi');
		tmpl = tmpl.replace(re, arguments[i]);
	}
	return tmpl;
}

Number.formatDecimal = function(value, length) {
	var value	= parseInt(value).toString();
	var zero	= '00000000000000000';
	
	if(value.length > length)
		return value;
	else
		return zero.substr(0, length - value.length) + value;
} 

String.toJSON = function(str) {
	var _isd = null;
	
	if(typeof str == 'string') {
		try {
			eval('_isd=' + str);
		} catch(e) {}
	}
	
	return _isd;
}

String.toQueryString = function(obj) {
	var data = [], key;
	
	for(key in obj) {
		if(obj.hasOwnProperty(key)) data.push(key + '=' + obj[key]);
	};
	
	return data.join('&');
}

if(!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(value) {
		for(var i=0, length=this.length; i<length; i++) {
			if(this[i] == value) return i;
		}
		return -1;
	}
}

String.prototype.endsWith = function(str) {
	return (this.toLowerCase().substring(this.length - str.length) == str.toLowerCase());
}

jQuery.fn.extend({
	// Bind method/function to scope
	'hitch': function(scope, method, argv) {
		return jQuery.hitch(scope, method, argv);
	},
	
	// Helper to bind ENTER press in input field
	'enter': function(fn, steals) {
		return this.keypress(function(event) {
			if(event.which == 13) {
				fn(event);
				if(steals == true) event.stopPropagation();
			}
		});
	},
	
	'disable': function(disable) {
		return this.each(function() {
			if(disable == true) 
				$(this).attr('disabled', true).addClass('disabled');
			else
				$(this).removeAttr('disabled').removeClass('disabled');	
		})
	},
	
	// Set/unset checked for input[type=checkbox]
	'checked': function(checked) {
		return this.each(function() { this.checked = checked; });
	},
	
	'moveTo': function(x, y) {
		return this.each(function() { 
			$(this).css('left', x).css('top', y);
		});
	},
	
	'resizeTo': function(w, h) {
		return this.each(function() { 
			//$(this).css('width', w).css('height', h);
			$(this).width(w).height(h);
		});
	},
	
	'realWidth': function() {
		return this.width() 
			+ (parseInt(this.css('margin-left')) 	|| 0)
			+ (parseInt(this.css('padding-left'))  	|| 0)
			+ (parseInt(this.css('border-left'))  	|| 0)
			+ (parseInt(this.css('border-right'))  	|| 0)
			+ (parseInt(this.css('padding-right')) 	|| 0)
			+ (parseInt(this.css('margin-right')) 	|| 0);
	},
	
	'realHeight': function() {
		return this.height() 
			+ (parseInt(this.css('margin-top'))  	|| 0)
			+ (parseInt(this.css('padding-top'))  	|| 0)
			+ (parseInt(this.css('border-top'))  	|| 0)
			+ (parseInt(this.css('border-bottom')) 	|| 0)
			+ (parseInt(this.css('padding-bottom'))	|| 0)
			+ (parseInt(this.css('margin-bottom'))	|| 0);
	}

});

jQuery.byId = function(id) {
	return $(String.format('#{0}', id));
}

jQuery.hitch = function(scope, method, argv) {
	return (function() {
		var _argv = (argv || []).concat(jQuery.makeArray(arguments));
		
		if(typeof method == 'string' && typeof scope[method] == 'function') {
			return scope[method].apply(scope, _argv);
		} else
		
		if(typeof method == 'function') {
			return method.apply(scope, _argv);
		}
	});
}

jQuery.createElement = function(tag, attr, callback) {
	var node = document.createElement(tag);
	
	$.each(attr, function(key, value) {
		node[key] = value;
	});
	
	function onLoad() {
		node.onload = null;
		node.onreadystatechange = null;
		
		if($.isFunction(callback)) callback(node);
	}
	
	if(jQuery.browser.msie) {
		node.onreadystatechange = function() {
			if(node.readyState == 'loaded' || node.readyState == 'complete') onLoad();
		}
	}
	else {
		node.onload = onLoad;
	}
	
	return node;
}