/* v.1.5 |05.04.2011*/
/*
 *  added: clone(); megre();
 *  updated: getByClass(); - now it use getElementsGetByClassName if it is exist
 *  updated: animation(); - now it is can get all arguments in oject
 *  added: altReq(); - equal to newXMLHTTPRequest but with short name and ability to get all arguments in object  
 * 
 * */
/* v.1.46|24.01.2011*/
/*
 * fixed: startWorkingBoxAnimation();
 * now it checkDimmer all the time
 **/
/* v.1.45|05.01.2011*/
/*
 * added: xml2arr();
 * !!! now first argument for Animation funct must be an object {'par':val, ...}
 **/
/* v.1.44|24.12.2010*/
/*
 * added: nextEl();prevEl();
 **/
/* v.1.43|08.12.2010*/
/*
 * added additional condition for 'if' cause in getByClass();
 * optimized regular expression in getByClass();
 * added: inArray();
 **/
/* v.1.42|04.12.2010*/
/*
 * added alt name for createXmlHttpRequestObject | request;
 **/
/* v.1.41|30.11.2010*/
/*
 * added: clearNode();
 **/
var cm = common = new function(){
	var me = this;
	/***************************** Working box animation ******************************/
	var dimmers = new Array();
	this.dimmerOpacity = 0.6;
	this.dimmerColor = '#fff';
	var startWorkingBoxAnimation = this.startWorkingBoxAnimation = function(){
		for(var i = 0, ln = arguments.length; i < ln; i++){
			var tmp = arguments[i];
			(function(){
				var id = tmp;
				var owner = null;
				if(!(owner = getEl(id)))
					return false;
				if(!dimmers[id])
				{
					dimmers[id] = {};
					dimmers[id].node = Node('div', {'class':'cmWorkingBoxAnimation', 'style':'display:block;'});
					/*{'style':'background-color:'+me.dimmerColor+';display:block;position:absolute;z-index:9000'},
					cm.Node('span', {'style':'position:relative;'},
					'Loading...')*/
					dimmers[id].a = new Animation(dimmers[id].node);
					dimmers[id].owner = owner;
					dimmers[id].interval = null;
					dimmers[id].start = function(){
						if(dimmers[id].interval == null)
						{
							checkDimmer(dimmers[id])
							dimmers[id].interval = window.setInterval(function(){checkDimmer(dimmers[id]);}, 100);
						}
					};
					dimmers[id].stop = function(){
						window.clearInterval(dimmers[id].interval);
						dimmers[id].interval = null;
					};
					setOpacity(dimmers[id].node, 0);			
				}
				dimmers[id].start();
				document.body.appendChild(dimmers[id].node);
				dimmers[id].a.go({'opacity':me.dimmerOpacity}, 200, 'simple');
			})();
		}
	};
	var stopWorkingBoxAnimation = this.stopWorkingBoxAnimation = function(){
		for(var i = 0, ln = arguments.length; i < ln; i++){
			var id = arguments[i];
			if(!(dimmers[id] && dimmers[id].node.parentNode))
				continue;
			(function(){
				var dimmer = dimmers[id];
				dimmer.a.go({'opacity':0}, 200, 'simple', function(){
					if(dimmer.node.parentNode)
						dimmer.node.parentNode.removeChild(dimmer.node);
					dimmer.stop();
				});
			})();
		}
	}
	var checkDimmer = function(dimmer){
		dimmer.node.style.width = dimmer.owner.offsetWidth + 'px';
		dimmer.node.style.height = dimmer.owner.offsetHeight + 'px';
		
		dimmer.node.style.textAlign = 'center';
		dimmer.node.style.fontSize = '20px';
		
		//dimmer.node.getElementsByTagName('span')[0].style.top = parseInt(dimmer.owner.offsetHeight/2 - 20) + 'px';
		
		dimmer.node.style.top = getY(dimmer.owner) + 'px';
		dimmer.node.style.left = getX(dimmer.owner) + 'px';
	}
	/****************************** Overlay *****************************/
	var Overlay = this.Overlay = function(){
		var o = {
			'onDimmerClose' : false,
			'closeBtn' : false,
			'top' : '100px',
			'opacity' : 0.25,
			'animSpeed' : 200
		};
		var tmp = arguments[0]||{};
		for(var i in tmp){
			o[i] = tmp[i];
		}
		var me = this;
		me.closed = true; 
		var main = cm.Node('div', {'class':'oo'});
		var closeBtn = cm.Node('div', {'class':'oo-c', 'style':'display:' + (o.closeBtn? 'block' : 'none')});
		var container = cm.Node('div', {'class':'oo-d', 'style':'visibility:hidden;'},
						closeBtn,
						me.title = cm.Node('div', {'class':'title'}),
						me.content = cm.Node('div', {'class':'descr'})
					);
		container.style.width = o.width||'';
		var dimmer = cm.Node('div', {'class':'oo-bg'});
		main.appendChild(dimmer);
		main.appendChild(container);
		var anim = {
			'container' : new cm.Animation(container),
			'dimmer' : new cm.Animation(dimmer)
		};
		setOpacity(dimmer, 0);
		
		me.open = function(){
			if(!me.closed)
				return false
				
			me.closed = false;
			document.body.insertBefore(main, document.body.firstChild);
			
			container.style.top = -(container.offsetHeight + 10) + 'px';
			container.style.left = '50%';
			container.style.marginLeft = -container.offsetWidth/2 + 'px';
			container.style.visibility = 'visible';
			
			anim.container.go({'top' : o.top}, o.animSpeed, 'acceleration');
			anim.dimmer.go({'opacity': o.opacity}, o.animSpeed, 'simple');
		}
		me.close = function(){
			if(me.closed)
				return false 
				
			me.closed = true;
			anim.dimmer.go({'opacity': 0}, o.animSpeed, 'simple', function(){
				document.body.removeChild(main);
			});
			anim.container.go({'top':-(container.offsetHeight + 10) + 'px'}, o.animSpeed, 'inhibition', function(){
				container.style.visibility = 'hidden';
			});
		}
		dimmer.onclick = o.onDimmerClose? me.close : null;
		closeBtn.onclick = o.closeBtn? me.close : null;
	}
	/****************************** Grid list *****************************/
	//Required GridLit styles.
	var gridList = this.gridList = function(o){
		var me = this;
		var colums = o;
		var data = [];
		var ascendingSymbol = cm.Node('div', {'class':'cmGridListAscending'});
		/*search*/
		var searchValue = '';
		var searchColumn = '';
		/*sort*/
		var ascending = 1;
		var sortCol = '';
		/*pagination*/
		var rPerPage = 10;
		var dFrom = 0;
		
		var node = {};
		
		me.set = function(o){
			data = [];
			for(var i = 0, ln = o.length; i < ln; i++){
				data.push(o[i]);
			}
			return true;
		}
		
		me.render = function(){
			node['container'] = cm.Node('div', {'class':'cmGridListContainer'},
						cm.Node('div'),
						cm.Node('div', {'class':'cmGridListTableContainer'},
								cm.Node('table', {'cellpadding':0, 'cellspacing':0, 'border':0, 'class':'cmGridListTable'},
										node['head'] = cm.Node('thead', {'class':'cmGridListHeader'}, createHeader()),
										node['body'] = cm.Node('tbody', {'class':'cmGridListRows'})
										)),
						cm.Node('div', cm.Node('div', {'class':'cmGridListPages'}))
					);
			
			return node['container'];
		}
		var createHeader = function(){
			var row = cm.Node('tr');
			for(var i in colums){
				var col = null;
				row.appendChild(colums[i].node = cm.Node('td', cm.Node('div', colums[i].title)));
				colums[i].node.style.width = colums[i].width? colums[i].width : ''; 
				(function(){
					var k = i;
					colums[i].node.onclick = function(){
						clickSort(colums[k])
						return true;
					}
				})();
			}
			return row;
		}
		var clickSort = function(column){
			var name = column.sort.name||column.name;
			var type = column.sort.type;
			ascending = sortCol == name ? ascending * -1 : 1; 
			sortCol = name;
			
			ascendingSymbol.className = ascending == 1? 'cmGridListAscending-asc' : 'cmGridListAscending-desc';
			column.node.appendChild(ascendingSymbol);
			
			sort(name, type);
			me.list();
		}
		var sort = function(name, type){
			switch(type){
				case 'text':
					data.sort(function(a, b){
						var x = a[name].toLowerCase();
						var y = b[name].toLowerCase();
						return y.replace(/\s/, '') == ''? 0 : (x < y ? -1 * ascending : (x > y ? 1 * ascending : 0));
					});
				break;
				case 'numeric':
					data.sort(function(a, b){
						var x = parseInt(a[name]);
						var y = parseInt(b[name]);
						return (x < y ? 1 * ascending : (x > y ? -1 * ascending : 0));
					});
				break;
			}
			return true;
		}
		
		var createPagination = function(){
			var pCount = Math.ceil( data.length / rPerPage );
			if(pCount < 2)
				return false;
			dFrom = pCount <= 1 ? 0  : dFrom;
			var cPage = Math.ceil( dFrom / rPerPage );
			var paginationContainer = cm.getByClass(node['container'], 'cmGridListPages'); 
			for(var k = 0, lnk = paginationContainer.length; k < lnk; k++){	
				clearNode(paginationContainer[k]);
				for(var i = 0; i < pCount; i++){
					if(!((i == 0 || i == pCount - 1) || (i >= cPage - 1 && i <= cPage + 1))){
						if( i == 1 && cPage > 2)
						{
							var p = cm.Node('div', '...');
							(function(){
								p.onclick = function(){
									dFrom = parseInt(cPage/2) * rPerPage;
									list();
								}
							})();
							paginationContainer[k].appendChild(p);
						}
						else if( i == pCount - 2 && cPage < pCount - 3 ){
							var p = cm.Node('div', '...');
							(function(){
								p.onclick = function(){
									dFrom = (parseInt(cPage + pCount - 1) / 2) * rPerPage;
									list();
								}
							})();
							paginationContainer[k].appendChild(p);
						}
						continue;
					}
					var p = cm.Node('div', i == cPage? '<b>' + (i + 1) + '</b>' : i + 1 );
					(function(){
						var cp = i;
						p.onclick = function(){
							dFrom = cp * rPerPage;
							list();
						}
					})();
					paginationContainer[k].appendChild(p);
				}
			}/*
			setInnerHTML(dFromContainer, parseInt(tabs[currentTab].dFrom + 1));
			setInnerHTML(dToContainer, parseInt(tabs[currentTab].dFrom + tabs[currentTab].rPerPage > data.length? data.length : tabs[currentTab].dFrom + tabs[currentTab].rPerPage));
			setInnerHTML(dOfContainer, parseInt(data.length));*/
		}
		
		var list = me.list = function(){
			cm.clearNode(node['body']);
			createPagination();
			for(var n = 0, ln = rPerPage; n < ln; n++){
				var i = n + dFrom;
				if(!data[i])
					break;
				var row = cm.Node('tr', {'class': (n%2? 'cmGridListEvenRow' : '')});
				for(var k in colums){
					data[i][colums[k].name] = data[i][colums[k].name]||'';
					var tmp = null;
					row.appendChild(cm.Node('td', tmp = cm.Node('div',
							{'class':'cmGridListEvenCellContent', 'style':'width:' + (colums[k].width? (parseInt(colums[k].width) - 7 )+ 'px' : '')},
							data[i][colums[k].name])));
					row.onmouseover = function(){
						this.style.backgroundColor = '#e8f4ff';//'#ffff99'; 
					}
					if(colums[k]['white-space']){
						switch(colums[k]['white-space']){
							case 'nowrap':
								tmp.title = data[i][colums[k].name];
							default:
								tmp.style.whiteSpace = colums[k]['white-space'];
						}
					}else{
						tmp.title = data[i][colums[k].name];
					}
					if(colums[k].handler){
						(function(){
							var c = i;
							var e = k;
							tmp.onclick = function(){
								colums[e].handler(data[c]);
							}
							tmp.className = 'cmGridListEvenCellContent cmGridListLink';
						})();
					}
					row.onmouseout = function(){
						this.style.backgroundColor = '';
					}
				}
				node['body'].appendChild(row);
			}
			if(!n)
				node['body'].appendChild(cm.Node('tr', {'class': (n%2? 'cmGridListEvenRow' : '')}, cm.Node('td', {'colspan':colums.length}, cm.Node('div',
						{'class':'cmGridListEvenCellContent'}, 'No entries.'))));
		}
	}
	
	/****************************** Hash function *****************************/
	var loadHashData = this.loadHashData = function(){
		var hash = document.location.hash.replace('#','').split('&');
		window.userRequest = {};
		for(var i = 0; hash.length > i; i++){
			window.userRequest[hash[i].split('=')[0]] = hash[i].split('=')[1]; 
		}
		return true;
	}
	var reloadHashData = this.reloadHashData = function(){
		var hash = '#';
		for(var name in window.userRequest){
			hash += name + '=' + window.userRequest[name];
		}
		document.location.hash = hash;
		return true;
	}
	/****************************** AJAX *****************************/
	var createXmlHttpRequestObject = this.createXmlHttpRequestObject = function(){
		var xmlHttp;
		
		try	{
			xmlHttp = new XMLHttpRequest();
		}
		catch(e){
			var XmlHttpVersions = new Array("MSXML2.XMLHTTP.6.0",
			"MSXML2.XMLHTTP.5.0",
			"MSXML2.XMLHTTP.4.0",
			"MSXML2.XMLHTTP.3.0",
			"MSXML2.XMLHTTP",
			"Microsoft.XMLHTTP");
			for (var i=0; i<XmlHttpVersions.length && !xmlHttp; i++)
			{
				try
				{
					xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
				}
				catch (e) {}
			}
		}
		if (!xmlHttp)
			alert("Error creating the XMLHttpRequest object.");
		else
			return xmlHttp;
	}
	var newXMLHTTPRequest = this.newXMLHTTPRequest = this.request = function(req, params, method, handler, type){
		var type = (type && type.toLowerCase() == 'text')? 'responseText' : 'responseXML';
		var url = (method == 'POST' || method == 'post')? req : req + params;
		var httpRequestObject = createXmlHttpRequestObject();
		httpRequestObject.open(method, url, true);
		httpRequestObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		httpRequestObject.onreadystatechange = (handler != null)? function(){ if (httpRequestObject.readyState == 4) { handler(httpRequestObject[type])}} : null;
		(method == 'POST' || method == 'post')? httpRequestObject.send(params) : httpRequestObject.send(null);
	}
	var altReq = this.altReq = function(){
		var o = merge({
				'handler' : null,
				'url' : '',
				'type' : 'xml',
				'method' : 'post',
				'params' : ''
		}, arguments[0]);
		var type = (o.type && o.type.toLowerCase() == 'text')? 'responseText' : 'responseXML';
		var method = o.method || 'post';
		var params = o.params || '';
		var url = (method.toLowerCase() == 'post')? o.url : o.url + params;
		var httpRequestObject = createXmlHttpRequestObject();
		httpRequestObject.open(method, url, true);
		httpRequestObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		httpRequestObject.onreadystatechange = (o.handler)? function(){ if (httpRequestObject.readyState == 4) { o.handler(httpRequestObject[type])}} : null;
		return (method.toLowerCase() == 'post')? httpRequestObject.send(params) : httpRequestObject.send(null);
	}
	var xml2arr = this.xml2arr = function(o){
		o = o.nodeType == 9? firstEl(o) : o;
		if(o.nodeType == 3 ||o.nodeType == 4)
			return o.nodeValue;
		else if(o.nodeType == 1){
			var res = {};
			res[o.tagName] = {};
			for(var i = 0, ln = o.childNodes.length; i < ln; i++){
				var childs = arguments.callee(o.childNodes[i]);
				if(typeof(childs) == 'object'){
					for(var key in childs){
						if(!res[o.tagName][key])
							res[o.tagName][key] = childs[key];
						else if(res[o.tagName][key]){
							if(!res[o.tagName][key].push)
								res[o.tagName][key] = [res[o.tagName][key], childs[key]];
							else
								res[o.tagName][key].push(childs[key]);
						}
					}
				}
				else
				{
					res[o.tagName] = childs;
				}
			}
			res[o.tagName] = ln? res[o.tagName] : '';
			return res;
		}
	}
	var responseInArray = this.responseInArray = function(xmldoc)
	{
		var response = xmldoc.getElementsByTagName('response')[0];
		var data = new Array();
		for(var i = 0; response.childNodes.length > i; i++){
			if(response.childNodes[i].nodeType != 1)
				continue;
			var kids = response.childNodes[i].childNodes;
			var tmp = new Array();
			for(var k = 0; kids.length > k; k++){
				if(kids[k].nodeType == 1)
					tmp[kids[k].tagName] = kids[k].firstChild? kids[k].firstChild.nodeValue : '';
			}
			data.push(tmp);
		}
		return data;
	}
	var getTxtVal = this.getTxtVal = function(o){return o.nodeType == 1 && o.firstChild? o.firstChild.nodeValue : '';}
	/****************************** Note *****************************/
	var showNote = this.showNote = function(txt){
		if(typeof(noteDiv) == 'undefined'){
			noteDiv = Node('div', {'class':'notification'});
			noteAnim = new Animation(noteDiv);
			setOpacity(noteDiv, 0);
			document.body.appendChild(noteDiv);
		}
		
		noteDiv.style.display = 'block';
		noteDiv.innerHTML = txt;
		noteDiv.style.top = (getBodyScrollTop() -  noteDiv.offsetHeight + (document.documentElement.clientHeight)/2) + 'px';
		noteDiv.style.left = (screen.width - noteDiv.offsetWidth)/2 + 'px';
		noteAnim.go({'style':{'opacity':0.8}, 'duration':500, 'anim':'simple', 'onStop' : function(){
			window.setTimeout(function(){noteAnim.go({'style': {'opacity':0}, 'duration' : 500, 'anim' : 'simple', 'handler' : function(){noteDiv.style.display = 'none';}})}, 2000);
		}});
	}
	/****************************** Scroll *****************************/
	var getBodyScrollTop = this.getBodyScrollTop = function()
	{
		return self.pageYOffset || (document.documentElement && document.documentElement.scrollTop) || (document.body && document.body.scrollTop);
	}

	/****************************** Events ******************************/
	var getEvent = this.getEvent = function(e){return e || event;}
	var getObjFromEvent = this.getObjFromEvent = function(e){return  e.target || e.srcElement;}
	var addEvent = this.addEvent = function(elem, type, handler){try{elem.addEventListener(type, handler, true);}catch(e){elem.attachEvent("on"+type, handler);}}
	var removeEvent = this.removeEvent = function(elem, type, handler){try{elem.removeEventListener(type, handler, true);}catch(e){elem.detachEvent("on"+type, handler);}}
	var onload = this.onload = function(handler){try{addEvent(window, 'load', handler);}catch(e){}};
	/****************************** Get Element Adjustments ******************************/
	var getX = this.getX = function(o){var x=0;while(o){x+=o.offsetLeft;o=o.offsetParent;}return x;}
	var getY = this.getY = function(o){var y=0;while(o){y+=o.offsetTop;o=o.offsetParent;}return y;}	
	/******************************** Get Element ********************************/
	var getEl = this.getEl = function(id){return document.getElementById(id);};
	var getByClass = this.getByClass = function(){
		var o = typeof(arguments[0]) == 'object' && arguments[0].nodeType == 1? arguments[0] : document;
		var str = o == arguments[0]? arguments[1] : arguments[0];
		if(o.getElementsByClassName)
			return o.getElementsByClassName(str);
		var n = new RegExp('(?:\\s|^)' + str + '(?=\\s|$)');
		var nodes = o.getElementsByTagName('*');
		var rValue = [];
		for(var d in nodes){
			if(nodes[d] && nodes[d].nodeType == 1 && n.test(nodes[d].className))
				rValue.push(nodes[d]);
		}
		return rValue;
	}
	var getIFrameDOM = this.getIFrameDOM = function (o){
		return o.contentDocument ||o.document;
	}
	/******************************** Node classes *******************************/
	var replaceClass = this.replaceClass = function(o, oldOne, newOne){
		removeClass(o.className, oldOne).className = o.className.replace(new RegExp('(?:\\s|^)' + oldOne + '(?=\\s|$)', 'g'), newOne)
		return o;
	}
	var removeClass = this.removeClass = function(o, str){
		o.className = o.className.replace(new RegExp('(?:\\s|^)' + str + '(?=\\s|$)', 'g'), '')
		return o;
	}
	var addClass = this.addClass = function(o, str){
		removeClass(o.className, str).className = (o.className.length > 0? ' ' : '') + str;  
		return o;
	}
	var isClass = this.isClass = function(o, str){
		return (new RegExp('(?:\\s|^)' + str + '(?=\\s|$)')).test(nodes[d].className);
	}
	/******************************** Set opacity ********************************/
	var setOpacity = this.setOpacity = function(elem, val){
		if(elem){
			if(document.all)
				elem.style.filter = "alpha(opacity=" + (Math.floor(val * 100)) + ")";
			else
				elem.style.opacity = val;
		}
	}
	/******************************** Node builder ********************************/
	var Node = this.Node = function(){
		var el = document.createElement(arguments[0]);
		if(typeof arguments[1] == "object" && !arguments[1].nodeType){
			for(var i in arguments[1]){
				if(i == 'style')
					el.style.cssText = arguments[1][i];
				else if(i == 'class')
					el.className = arguments[1][i];
				else
					el.setAttribute(i, arguments[1][i]);
					
			}
			i = 2;
		}
		else
			i = 1;
			
		for(var ln = arguments.length; i < ln; i++)	{
			if(typeof arguments[i] == 'string' || typeof arguments[i] == 'number')
				el.innerHTML = arguments[i];//el.appendChild(document.createTextNode(arguments[i]));
			else
				el.appendChild(arguments[i]);
		}
		return el;
	}
	/******************************** Nodes ********************************/
	var nextEl = this.nextEl = function (o){
		var c = o;
		do{c = c.nextSibling;}while(c && c.nodeType != 1);
		return c;
	}

	var prevEl = this.prevEl = function(o){
		var c = o;
		do{c = c.previousSibling;}while(c && c.nodeType != 1);
		return c;
	}
	var firstEl = this.firstEl = function(o){
		return o.firstChild.nodeType == 1? o.firstChild : nextEl(o.firstChild);
	}
	var clearNode = this.clearNode = function(o){
		while(o.firstChild){
			o.removeChild(o.firstChild);
		}
		return o;
	}
	/***************************** Arrays & Objects *****************************/
	var merge = this.merge = function(c, n){
		var stack = arguments[0];
		for(var k = 1, ln = arguments.length; k < ln; k++){
			var object = arguments[k];
			if(!object){continue;}
			for(var i in object){
				stack[i] = (typeof(stack[i]) == 'object' && typeof(object[i]) == 'object' && object[i] && !object[i].nodeType)?
						arguments.callee(stack[i], object[i]) : stack[i] = object[i]; 
			}
		}
		return stack;
	}
	var clone = this.clone = function(o, copyNode){
		var n = {};
		for(var i in o){
			n[i] = (o[i] && typeof(o[i]) == 'object')? (o[i].nodeType? (copyNode? o[i].cloneNode : o[i]) : arguments.callee(o[i])) : o[i];
		}
		return n;
	}
	var inArray = this.inArray = function(needle, arr){
		var flag = false;
		for(var i in arr){
			if(arr[i] === needle){
				flag = true;
				break;
			}
		}
		return flag;
	}
	/******************************** Animation ********************************/
	var Animation = this.Animation = function(o){
		var obj = o;
		var processes = new Array()
		this.go = function(){
			var pId = Math.random()
			var properties = new Array();
			var argObj = (arguments.length == 1 && typeof(arguments[0]));
			
			var endVal = argObj? arguments[0].style : arguments[0];
			var duration = (argObj? arguments[0].duration : arguments[1]) || 0;
			var delta = (argObj? eval(arguments[0].anim) : eval(arguments[2])) || simple;
			var onStop = (argObj? arguments[0].onStop : arguments[3]) || function(){};
			
			for(var name in endVal){
				var value = endVal[name] + '';
				var tmp = new Array();
					tmp['name'] = name;
					tmp['new'] = tmp['name'].match(/color/i)?
						(!value.match(/rgb/i)? hex2rgb(value.match(/[\w\d]+/)[0]) : Array(parseInt(value.match(/\d+/g)[0]), parseInt(value.match(/\d+/g)[1]), parseInt(value.match(/\d+/g)[2])))
						:
						value.replace(/[^\-0-9\.]/g,'');
					tmp['dimension'] = value.match(/\d+(\D*)/)[1];
					tmp['old'] = getStyle(obj, tmp);
				properties.push(tmp);
			}
	
			var start = new Date().getTime();
			var procLn = processes.length;
			for(var i = 0; i < procLn; i++){
				processes[i][1] = false;
			}
			processes.push(new Array(pId, true));
			setTimeout(function(){
				var processId = pId;
				var procLn = processes.length;
				for(var i = 0; i < procLn; i++){
					if(processes[i][0] == processId && !processes[i][1]){
						processes.splice(i,1);
						return false;
					}
					else if(processes[i][0] == processId && processes[i][1])
						break;
				}
	
				var now = (new Date().getTime()) - start;
				var progress = now / duration;
				if(progress < 1)
				{
					for(var i = 0, ln = properties.length; i < ln; i++){
						var val = (properties[i]['new'] - properties[i]['old']) * delta(progress) + properties[i]['old'];
						if(properties[i]['name'] == 'opacity')
							setOpacity(obj, val);
						else if(properties[i]['name'].match(/color/i)){
							var r = parseInt((properties[i]['new'][0] - properties[i]['old'][0]) * delta(progress) + properties[i]['old'][0]);
							var g = parseInt((properties[i]['new'][1] - properties[i]['old'][1]) * delta(progress) + properties[i]['old'][1]);
							var b = parseInt((properties[i]['new'][2] - properties[i]['old'][2]) * delta(progress) + properties[i]['old'][2]);
							obj.style[properties[i]['name']] = rgb2hex(r, g, b);
						}
						else{
							obj.style[properties[i]['name']] = parseInt(val) + properties[i]['dimension'];
						}
					}
					setTimeout(arguments.callee, 10);
				}
				else{
					for(var i = 0, ln = properties.length; i < ln; i++){
						if(properties[i]['name'] == 'opacity')
							setOpacity(obj, properties[i]['new']);
						else if(properties[i]['name'].match(/color/i))
							obj.style[properties[i]['name']] = rgb2hex(properties[i]['new'][0], properties[i]['new'][1], properties[i]['new'][2]);
						else
							obj.style[properties[i]['name']] = properties[i]['new'] + properties[i]['dimension'];
					}
					processes.splice(i,1);
					onStop();
				}
			}, 10);
		}
		var simple = function(progress){
			return progress;
		}
		var inhibition = function(progress){
			return 1 - acceleration(1 - progress);
		}
		var acceleration = function(progress){
			return Math.pow(progress, 3);
		}
		var smooth = function(progress){
			return (progress < 0.5)? acceleration(2 * progress) / 2 : 1 - acceleration(2 * (1 - progress)) / 2;
		}
	
		var getStyle = function(o, old){
			switch(old['name']){
				case 'width':
				case 'height':
				case 'top':
				case 'left':
					var Name = old['name'].charAt(0).toUpperCase() + old['name'].substr(1, old['name'].length-1);
					if(old['dimension'] == '%' && !o.style[old['name']].match(/%/)){
						var el = (o.parentNode.tagName.match(/body/i) || Name.match(/top|left/i))? 'client' : 'offset';
						var pv = (Name.match(/width|left/i))? o.parentNode[el + 'Width'] : o.parentNode[el + 'Height'];
						return 100 * ( o['offset' + Name] / pv );
					}
					else if((old['dimension'] == '%' && o.style[old['name']].match(/%/))
							|| (old['dimension'] == 'px' && o.style[old['name']].match(/px/)))
						return parseInt(o.style[old['name']]);
					return o['offset' + Name];
				break;
				case 'opacity':
					if(document.all){
						var reg = /alpha\(opacity=(.*)\)/;
						var res = reg.exec(o.style.filter);
						return (res)? res[1] / 100 : 1;
					}
					else{
						var val = parseFloat(o.style.opacity);
						return (!isNaN(val))? val : 1;
					}
				break;
				default:
					if(old['name'].match(/color/i)){
						
						if(o.style[old['name']].match(/rgb/i))
							return Array(parseInt(o.style[old['name']].match(/\d+/g)[0]), parseInt(o.style[old['name']].match(/\d+/g)[1]), parseInt(o.style[old['name']].match(/\d+/g)[2]));	
						return hex2rgb(o.style[old['name']].match(/[\w\d]+/)[0]);	
					}
					
					if(o.style[old['name']])
						return parseInt(o.style[old['name']]);
				return 0;
			}
		}
		var setOpacity = function(elem, val){
			if(elem){
				if(document.all)
					elem.style.filter = "alpha(opacity=" + (Math.floor(val * 100)) + ")";
				else
					elem.style.opacity = val;
			}
		}
	
		var rgb2hex = function (r, g , b){
			var rgb= new Array(r, g, b);
			for(i in rgb){
				rgb[i]=Number(rgb[i]).toString(16);	
				if(rgb[i] == '0')
					rgb[i] = '00';
				else if(rgb[i].length == 1)
					rgb[i] = '0' + rgb[i];
			}
			return '#'+rgb.join('');
		}
		var hex2rgb = function(hex){
			return(function(v){return [v >> 16 & 255, v >> 8 & 255, v & 255];})(parseInt(hex, 16));
		}
	
	}
	var rgb2hex = this.rgb2hex = function (r, g , b){
		var rgb= new Array(r, g, b);
		for(i in rgb){
			rgb[i]=Number(rgb[i]).toString(16);	
			if(rgb[i] == '0')
				rgb[i] = '00';
			else if(rgb[i].length == 1)
				rgb[i] = '0' + rgb[i];
		}
		return '#'+rgb.join('');
	}
	/******************************** Cookie ********************************/
	this.getCookie = function(name){
	    var matches = document.cookie.match(new RegExp(
	      "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
	    ))
	    return matches ? decodeURIComponent(matches[1]) : undefined 
	}
	this.setCookie = function(name, value, props){
	    props = props || {}
	    var exp = props.expires
	    if (typeof exp == "number" && exp) {
	        var d = new Date()
	        d.setTime(d.getTime() + exp*1000)
	        exp = props.expires = d
	    }
	    if(exp && exp.toUTCString) { props.expires = exp.toUTCString() }
	 
	    value = encodeURIComponent(value)
	    var updatedCookie = name + "=" + value
	    for(var propName in props){
	        updatedCookie += "; " + propName
	        var propValue = props[propName]
	        if(propValue !== true){ updatedCookie += "=" + propValue }
	    }
	    document.cookie = updatedCookie
	}
	this.deleteCookie = function(name){
	    setCookie(name, null, { expires: -1 })
	}
}
