Array.prototype.forEach = function(callback, thisObj) {
	var scope = thisObj || window;
	for ( var i = 0, ii = this.length; i < ii; ++i)
		callback.call(scope, this[i], i, this);
};

Array.prototype.every = function(callback, thisObj) {
	var scope = thisObj || window;
	for ( var i = 0, ii = this.length; i < ii; ++i)
		if (!callback.call(scope, this[i], i, this)) return false;
	return true;
};

Array.prototype.some = function(callback, thisObj) {
	var scope = thisObj || window;
	for ( var i = 0, ii = this.length; i < ii; ++i)
		if (callback.call(scope, this[i], i, this)) return true;
	return false;
};

Array.prototype.map = function(callback, thisObj) {
	var scope = thisObj || window;
	var a = [];
	for ( var i = 0, ii = this.length; i < ii; ++i)
		a.push(callback.call(scope, this[i], i, this));
	return a;
};

Array.prototype.filter = function(callback, thisObj) {
	var scope = thisObj || window;
	var a = [];
	for ( var i = 0, ii = this.length; i < ii; ++i) {
		if (!callback.call(scope, this[i], i, this)) continue;
		a.push(this[i]);
	}
	return a;
};

Array.prototype.indexOf = function(el, start) {
	start = start || 0;
	for ( var i = start, ii = this.length; i < ii; ++i)
		if (this[i] === el) return i;
	return -1;
};

Array.prototype.lastIndexOf = function(el, start) {
	start = start || this.length;
	if (start >= this.length) start = this.length;
	if (start < 0) start = this.length + start;
	for ( var i = start; i >= 0; --i)
		if (this[i] === el) return i;
	return -1;
};

Array.forEach = function(object, callback, thisObj) {
	Array.prototype.forEach.call(object, callback, thisObj);
};

Array.map = function(object, callback, thisObj) {
	return Array.prototype.map.call(object, callback, thisObj);
};

Array.filter = function(object, callback, thisObj) {
	return Array.prototype.filter.call(object, callback, thisObj);
};

Array.indexOf = function(object, el, start) {
	return Array.prototype.indexOf.call(object, el, start);
};

if (typeof HTMLElement != "undefined" && !HTMLElement.prototype.insertAdjacentElement) {
	var emptyTags = ["IMG", "BR", "INPUT", "META", "LINK", "PARAM", "HR"];
	
	HTMLElement.prototype.insertAdjacentElement = function(where, parsedNode) {
		switch (where) {
			case "beforeBegin":
				this.parentNode.insertBefore(parsedNode, this);
				break;
			case "afterBegin":
				this.insertBefore(parsedNode, this.firstChild);
				break;
			case "beforeEnd":
				this.appendChild(parsedNode);
				break;
			case "afterEnd":
				if (this.nextSibling) this.parentNode.insertBefore(
						parsedNode,
						this.nextSibling);
				else this.parentNode.appendChild(parsedNode);
				break;
		}
	};
	
	HTMLElement.prototype.insertAdjacentHTML = function(where, str) {
		var range = this.ownerDocument.createRange();
		range.setStartBefore(this);
		var parsedHTML = range.createContextualFragment(str);
		this.insertAdjacentElement(where, parsedHTML);
	};
	
	HTMLElement.prototype.insertAdjacentText = function(where, str) {
		var parsedText = document.addTextNode(str);
		this.insertAdjacentElement(where, parsedText);
	};
	
	HTMLElement.prototype.__defineSetter__("innerText", function(str) {
		this.textContent = str;
	});
	
	HTMLElement.prototype.__defineGetter__("innerText", function() {
		return this.textContent;
	});
	
	HTMLElement.prototype.__defineGetter__("outerHTML", function() {
		var tagName = this.tagName.toLowerCase();
		var str = "<" + tagName;
		Array.forEach(this.attributes, function(el) {
			str += " " + el.name + "=\"" + el.value + "\"";
		});
		if (emptyTags.indexOf(tagName) != -1) return str + ">";
		return str + ">" + this.innerHTML + "</" + tagName + ">";
	});
	
	HTMLElement.prototype.__defineSetter__("outerHTML", function(str) {
		var range = this.ownerDocument.createRange();
		range.setStartBefore(this);
		var parsedHTML = range.createContextualFragment(str);
		this.parentNode.replaceChild(parsedHTML, this);
	});
}

Number.prototype.toCurrency = function(symbol) {
	return (symbol ? symbol : "$") + this.withCommas();
};

Number.prototype.withCommas = function() {
	var x = 6, y = parseFloat(this).toFixed(2).toString().reverse();
	while (x < y.length) {
		y = y.substring(0, x) + "," + y.substring(x);
		x += 4;
	}
	return y.reverse();
};

Object.prototype.count = function() {
	var i = 0;
	for ( var property in this) {
		if (this.hasOwnProperty(property)) i++;
	};
	return i;
};

Object.prototype.getPropertyAtIndex = function(index) {
	var i = 0;
	for ( var property in this) {
		if (this.hasOwnProperty(property)) {
			if (i == index) return this[property];
			i++;
		}
	}
	return undefined;
};

Object.prototype.toArray = function() {
	if (this.length && this.length > 0) {
		function getChildNode(el) {
			return el;
		}
		
		return Array.map(this, getChildNode);
	}
};

String.prototype.convertLineBreaks = function(str) {
	return this.replace(/\n|\r\n/g, str || "<br>");
};

String.prototype.reverse = function() {
	return this.split("").reverse().join("");
};

String.prototype.setLeadingZeros = function(len) {
	len = len - this.length;
	var zeros = "";
	var i = 0;
	while (i < len) {
		zeros += "0";
		i++;
	}
	return zeros += this;
};

String.prototype.toBoolean = function() {
	return this.match(/true|true|1|-1|yes|yes/) != null;
};

String.prototype.toBooleanSymbol = function() {
	return this.toBoolean() ? "x" : "";
};

String.prototype.toTitleCase = function() {
	var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)";
	var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)";
	var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0;
	while (true) {
		var m = split.exec(this);
		parts.push(this.substring(index, m ? m.index : this.length).replace(
				/\b([A-Za-z][a-z.'Õ]*)\b/g,
				function(all) {
					return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all);
				}).replace(RegExp("\\b" + small + "\\b", "ig"), lower).replace(
				RegExp("^" + punct + small + "\\b", "ig"),
				function(all, punct, word) {
					return punct + upper(word);
				}).replace(RegExp("\\b" + small + punct + "$", "ig"), upper));
		index = split.lastIndex;
		if (m) parts.push(m[0]);
		else break;
	}
	return parts.join("").replace(/ V(s?)\. /ig, " v$1. ").replace(
			/(['Õ])S\b/ig,
			"$1s").replace(/\b(AT&T|Q&A)\b/ig, function(all) {
		return all.toUpperCase();
	});
	
	function lower(word) {
		return word.toLowerCase();
	}
	
	function upper(word) {
		return word.substr(0, 1).toUpperCase() + word.substr(1);
	}
};

String.prototype.trim = new Function("return this.replace(/\\s+$|^\\s*/gi,'');");

String.prototype.truncate = function(len) {
	return this.length > len ? this.substr(0, len) + "..." : this;
};

var Innecto = {
	$: function(id) {
		return document.getElementById(id);
	},
	agent: function() {
		var opera = typeof opera != "undefined";
		var ie = !opera && navigator.userAgent.indexOf("MSIE") != -1;
		var safari = !opera && navigator.userAgent.indexOf("WebKit") != -1;
		var gecko = !opera && navigator.product == "Gecko" && !safari;
		return {
			IE: ie,
			GECKO: gecko,
			OPERA: opera,
			SAFARI: safari
		};
	}(),
	boundingRectangle: function(el) {
		var doc = Innecto.agent.SAFARI ? document.body : document.documentElement;
		var rectangle = el.getBoundingClientRect();
		this.bottom = rectangle.bottom;
		this.left = rectangle.left - doc.clientLeft + doc.scrollLeft;
		this.right = rectangle.right;
		this.top = rectangle.top - doc.clientTop + doc.scrollTop;
	},
	guid: function() {
		return "element-" + new Date().getTime();
	},
	queryString: function(url) {
		var searchLocation = url.indexOf("?");
		if (searchLocation == -1) return [];
		
		function queryString(el) {
			el = el.split("=");
			return [el[0], el[1]];
		}
		
		return url.slice(searchLocation + 1).split("&").map(queryString);
	},
	style: {
		get: function(el, cssAttribute) {
			if (el.currentStyle) {
				if (cssAttribute == "opacity") {
					var filter = el.currentStyle.filter;
					return parseInt(String(filter).slice(
							filter.indexOf("=") + 1,
							filter.length - 1)) / 100;
				}
				else return el.currentStyle[cssAttribute];
			}
			else return document.defaultView.getComputedStyle(el, "")[cssAttribute];
		},
		set: function(el, cssAttribute, cssValue) {
			if (cssAttribute == "opacity" && String(el.style.opacity) == "undefined") el.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + cssValue * 100 + ")";
			else el.style[cssAttribute] = cssValue;
		}
	},
	styleClass: {
		add: function(el, className) {
			el.className += (el.className == "" ? "" : " ") + className;
		},
		exist: function(el, className) {
			return el.className.split(" ").indexOf(className) != -1;
		},
		get: function(el) {
			return el.className;
		},
		remove: function(el, className) {
			function removeClass(str) {
				return str != className;
			}
			
			el.className = el.className.split(" ").filter(removeClass)
					.join(" ");
		},
		set: function(el, className) {
			el.className = className;
		},
		swap: function(el, fromClassName, toClassName) {
			el.className = el.className.replace(fromClassName, toClassName);
		},
		toggle: function(el, firstClassName, secondClassName) {
			if (this.exist(el, firstClassName)) this.swap(
					el,
					firstClassName,
					secondClassName);
			else this.swap(el, secondClassName, firstClassName);
		}
	}
};