//Array functions
function $A(obj){
	var arr = [];
	for(var i = 0; i < obj.length; i++){
		arr.push(obj[i]);
	}
	return arr;
}
var $break = new Object();
var $continue = new Object();
Array.prototype.each = function(iterator){
	try{
		for(var i = 0; i < this.length; i++){
			try{
				iterator(this[i], i);
			}catch(e){
				if(e != $continue)
					throw e;
			}
		}
	}catch(e){
		if(e != $break)
			throw e;
	}
}
Array.prototype.random = function(){
	return this[Math.round(Math.random() * (this.length - 1))];
}
Array.prototype.last = function(){
	return this[this.length - 1];
}
Array.prototype.invert = function(){
	var new_arr = [];
	for(var i = this.length - 1; i >= 0; i --){
		new_arr.push(this[i])
	}
	return new_arr;
}
Array.prototype.remove = function(num){
	if(num >= this.length || num < 0)
		return;
	for(var i = num; i < this.length - 1; i++){
		this[i] = this[i+1];
	}
	this.pop();
}
Array.prototype.insert = function(value, position){
	position = position ? position : 0;
	if(position >= this.length){
		this.push(value);
		return;
	}
	for(var i = this.length - 1; i >= position; i--){
		this[i+1] = this[i];
	}
	this[position] = value;
}
if(typeof Array.prototype.indexOf == "undefined"){
	Array.prototype.indexOf = function(item){
		var index = -1;
		this.each(function(it, ind){
			if(it == item){
				index = ind;
				throw $break;
			}
		});
		return index;
	}
}
Array.prototype.toStart = function(item){
	var ind = this.indexOf(item);
	if(ind == -1){
		return false;
	}
	var itm = this[ind];
	var buff1 = this[0];
	var buff2 = this[0];
	for(var i = 1; i <= ind; i++){
		buff1 = this[i];
		this[i] = buff2;
		buff2 = buff1;
	}
	this[0] = itm;
}
Array.prototype.toEnd = function(item){
	var ind = this.indexOf(item);
	if(ind == -1){
		return false;
	}
	var itm = this[ind];
	for(var i = ind; i < this.length - 1; i++){
		this[i] = this[i + 1];
	}
	this[this.length - 1] = itm;
}
Array.prototype.previous = function(item){
	var ind = this.indexOf(item);
	if(ind <= 0){
		return false;
	}
	return this[ind - 1];
}
Array.prototype.next = function(item){
	var ind = this.indexOf(item);
	if(ind < 0 || ind == this.length - 1){
		return false;
	}
	return this[ind + 1];
}
Array.prototype.max = function(){
	var max = this[0];
	this.each(function(item){
		if(item > max){
			max = item;
		}
	});
	return max;
}
Array.prototype.min = function(){
	var min = this[0];
	this.each(function(item){
		if(item < min){
			min = item;
		}
	});
	return min;
}
//Number functions
Number.prototype.signOf = function(){
	if(this == 0){
		return 1;
	}else{
		return Math.abs(this) / this;
	}
}
Number.prototype.sq = function(){
	return this * this;
}


//String functions
String.prototype.camelize = function(){
	var arrThis = this.split('-');
	if(arrThis.length == 1){
		return this;
	}else{
		var wordCamelized = arrThis[0];
		var firstSymbol;
		for(var i = 1; i < arrThis.length; i++){
			firstSymbol = arrThis[i].substr(0, 1);
			arrThis[i] = arrThis[i].substr(1);
			arrThis[i] = firstSymbol.toUpperCase() + arrThis[i];
			wordCamelized+=arrThis[i];
		}
		return wordCamelized;
	}
}
String.prototype.s_each = function(iterator){
	var arr = this.split('');
	arr.each(iterator)
}
String.prototype.no_print_characters_only = function(){
	var ret = true;
	this.s_each(function(chr){
		if(chr.charCodeAt(0) >= 30){
			ret = false;
			throw $break;
		}
	});
	return ret;
}

//Object functions
function MergeObjects(obj1, obj2){
	for(var i in obj1){
		obj2[i] = obj1[i];
	}
	return obj2;
}


//DOM functions
function $(){
	if(arguments.length == 0){
		return false;
	}else if(arguments.length == 1){
		return _$(arguments[0]);
	}else{
		var arr = [];
		for(var i = 0; i < arguments.length; i++){
			var node = _$(arguments[i]);
			if(node){
				arr.push(node);
			}
		}
		if(arr.length){
			return arr;
		}else{
			return false;	
		}
	}
}
function _$(arg){
	if(typeof arg == "string"){
		return document.getElementById(arg);
	}else if(typeof arg == "object" && typeof arg.nodeType != "undefined"){
		return arg;
	}else{
		return false;
	}
}
function $T(tName, parent){
	parent = parent ? parent : document;
	return $A(parent.getElementsByTagName(tName));
}

function $F(ipt){
	ipt = $(ipt);
	var node_names = ["SELECT", "INPUT", "TEXTAREA"];
	var node_name = "";
	var types = [];
	var ret = true;
	for(var i = 0; i < node_names.length; i++){
		if(ipt.nodeName == node_names[i]){
			node_name = node_names[i];
		}
	}
	if(!node_name)
		return;

	return $F[node_name.toLowerCase()](ipt);
}
$F.select = function(objSel){
	if(!!objSel.value){
		return objSel.value;
	}else{
		var ops = $T("OPTION", objSel);
		return ops[objSel.selectedIndex].innerText;
	}
};
$F.textarea = function(objTArea){
	return objTArea.value;
};
$F.input = function(objIpt){
	return objIpt.value;
};
function $C(className, parent, tagName){
	parent = (parent) ? parent : document;
	tagName = tagName ? tagName : "*";
	var arr = [];
	var collection = $T(tagName, parent);
	for(var i = 0; i < collection.length; i++){
		if(hasClassName(collection[i], className)){
			arr.push(collection[i]);
		}
	}
	if(arr.length != 0){
		return arr;
	}else{
		return false;
	}
}
function $S(cssSelector){
	var arr = cssSelector.split(" ");
	for(var i = 0; i < arr.length; i++){
		var type = "_tag";
		if(arr[i].charAt(0) == "."){
			type = "_class";
		}else if(arr[i].charAt(0) == "#"){
			type = "_id";
		}
		$S[type](arr[i]);
	}
}
$S._tag = function(){};
$S._class = function(){};
$S._id = function(){};


function $TEXT(elem, no_text){
	if(!elem){
		return;
	}
	var arr = [];
	var children = $A(elem.childNodes);
	children.each(function(child){
		if(child.nodeType == 3){
			if(no_text){
				arr.push(child);
			}else{
				if(!child.nodeValue.no_print_characters_only()){
					arr.push(child);
				}
			}
		}
	});
	return arr;
}

//Function functions
Function.prototype.bind = function(){
	var _args = [];
	var _method = this;
	var _object = arguments[0];
	for(var i = 1; i < arguments.length; i++){
		_args.push(arguments[i]);
	}
	var retfunc = function(){
		return _method.apply(_object, $A(arguments).concat(_args));
	}
	retfunc.bound = $A(arguments);
	return retfunc;
}
Function.prototype.bindAvoidingEvent = function(){
	var _args = [];
	var _method = this;
	var _object = arguments[0];
	for(var i = 1; i < arguments.length; i++){
		_args.push(arguments[i]);
	}
	return function(){
		return _method.apply(_object, $A(_args).concat(arguments));
	}	
}
Function.prototype.bindArray = function(arr){
	alert("Bind: " + arr);
	var _args = [];
	var _method = this;
	var _object = arr[0];
	for(var i = 1; i < arr.length; i++){
		_args.push(arr[i]);
	}
	var retfunc = function(){
		return _method.apply(_object, $A(arguments).concat(arr));
	}
	retfunc.bound = _args;
	return retfunc;
}
Function.prototype.bindMore = function(){
	if(!this.bound){
		return;
	}
	return this.bindArray(this.bound.concat(arguments));
}

//Else functions
function _isChild(elem, parent){
	if(!elem)
		return false;
	var par = elem.parentNode;
	while(par && par != parent && par.tagName.toUpperCase() != "HTML"){
		par = par.parentNode;
	}
	return !par ? false : (par == parent);
}
function hasClassName(elem, className){
	var ret = false;
	var reg_className = new RegExp('^' + className + '$');
	var classes = elem.className.split(' ');
	classes.each(
		function(classN){
			if(classN.match(reg_className)){
				ret = true;
				throw $break;
			}
		}	
	)
	return ret;
}

//Debug functions
function toConsole(what, console){
	console = console ? console : typeof document.body != "undefined" ? document.body : null;
	if(!console){
		document.write(what);
	}
	var oDiv = document.createElement('DIV');
	oDiv.appendChild(document.createTextNode(what));
	console.appendChild(oDiv);
}
var print = toConsole;
function clearElem(elem){
	while(elem.firstChild){
		elem.removeChild(elem.firstChild);
	}
}
function Line(width, color, weight, parent){
	if(!width){
		width = 100;
	}
	if(!color){
		color = "#000";
	}	
	if(!weight){
		weight = 1;
	}
	if(!parent){
		parent = document.body;
	}
	var line = document.createElement("DIV");
	line.style.width = width + "px";
	line.style.border = "solid " + weight + "px " + color;
	line.style.margin = "5px 10px";
	line.style.fontSize = "0";
	parent.appendChild(line);
}
