/**
 * @author Zozzz <vezox@citromail.hu>
 */
function isElement(object) 
{
    return object && object.nodeType == 1;
}

function isArray(object)
{
    return object && object.constructor === Array;
}  

function isFunction(object)
{
    return typeof object == "function";
}

function isString(object)
{
    return typeof object == "string";
}

function isBoolean(object)
{
	return typeof object == "boolean";
}

function isNumber(object) 
{
    return typeof object == "number";
}

function isUndefined(object)
{
    return typeof object == "undefined";
}

function isObject(object)
{
	return typeof object == "object";
}

function isEmpty(object)
{
	return isUndefined(object) || isNull(object);
}

function isNull(object)
{
	return object === null;
}

function isNodeList(object)
{
	return !isEmpty(object) && object instanceof HTMLNodeList;
}

function extend(dest, source)
{
	for(var x in source)
		dest.prototype[x] = source[x];	
}

function $(id)
{
	return document.getElementById(id);
}

function $X(str, cache, elm)
{
	cache = isUndefined(cache) ? true : cache;
	return Xpath.parse(str, cache, elm);
}

function getURLParam(strParamName)
{
	var strReturn 	= "";
	var strHref 	= window.location.href;
	if (strHref.indexOf("?") > -1) 
	{
		var strQueryString 	= strHref.substr(strHref.indexOf("?")).toLowerCase();
		var aQueryString 	= strQueryString.split("&");
		for (var iParam = 0; iParam < aQueryString.length; iParam++) 
		{
			if (aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1) 
			{
				var aParam 	= aQueryString[iParam].split("=");
				strReturn 	= aParam[1];
				break;
			}
		}
	}
	return unescape(strReturn);
}

function getBrowser()
{
	var name = navigator.appName;
	var ver = navigator.appVersion;
	if(name == 'Microsoft Internet Explorer')
	{
		var r = new RegExp(/MSIE\s(\d{1})/);
		ver = r.exec(ver)[1];
	}
	if(name == 'Opera')
	{
		var r = new RegExp(/\d{1}\.\d{2}/);
		ver = parseFloat(r.exec(ver));
	}
	
	return { 'name'		: name,
			 'ver'		: ver,
			 'ie'		: (name == 'Microsoft Internet Explorer' ? true : false) && !((window['opera'] && opera.buildNumber)),
			 'ff'		: (name == 'Netscape' ? true : false) && !((window['opera'] && opera.buildNumber)),
			 'op'		: (name == 'Opera' ? true : false),
			 'safari'	: navigator.userAgent.indexOf('Safari') > -1 && navigator.userAgent.indexOf('Chrome') == -1
			}
}

function setStyle(obj, style)
{
    var valid = ['width','height','top','bottom','backgroundImage','backgroundPosition'];
	for(var i in style)
    {
        if(!isFunction(style[i]) && isString(i))
        {
            obj.style[i] = style[i];
        }		
    }
}

function disableSelection(target)
{
	if(isElement(target))
	{
		target.onselectstart 			= function() { return false; };
		target.unselectable 			= "on";
		target.style['MozUserSelect'] 	= "none";
		target.style['KHTMLUserSelect'] = "none";
		target.style['UserSelect'] 		= "none";
	}
}

function enableSelection(target)
{
	if(isElement(target))
	{
		target.onselectstart 			= null;
		target.unselectable 			= "off";
		target.style['MozUserSelect'] 	= "normal";
		target.style['KHTMLUserSelect'] = "normal";
		target.style['UserSelect'] 		= "normal";
		
		if(getBrowser().ff)
		{
			var style = target.getAttribute('style');
			target.setAttribute('style', style.replace(/-moz-user-select: none;/ig, ''));
		}
	}
}

function boxIntercept(bound1, bound2, returnIntercept)
{
	var dx = Math.abs(bound1.width / 2 - bound2.width / 2 + (bound1._x - bound2._x));
	var dy = Math.abs(bound1.height / 2 - bound2.height / 2 + (bound1._y - bound2._y));
	return ((dx <= (bound1.width + bound2.width) / 2) && (dy <= (bound1.height + bound2.height) / 2) ? true : false);
}

function pointInBox(bound, point, offset, t)
{
	if( !bound ) return false;
	if( !offset ) offset = {};
	var left 	= bound._x + (offset._x ? offset._x : 0);
	var top		= bound._y + (offset._y ? offset._y : 0);
	var right	= bound._x + bound.width + (offset.width ? offset.width : 0) + (offset._x ? offset._x : 0);
	var bottom	= bound._y + bound.height + (offset.height ? offset.height : 0) + (offset._y ? offset._y : 0);
	return (left <= point._x && point._x <= right && top <= point._y && point._y <= bottom ? true : false);
}

function getMouseCoords(e)
{
	if(window.event)
	{
		var x  = e.clientX + getScrollLeft();
		var y  = e.clientY + getScrollTop();         	
	}
	else
	{
		var x  = e.pageX;
		var y  = e.pageY;
	}
	return {_x:x,_y:y}
}

function getInfo(oo)
{
	var o = null;
	if(isElement(oo)) var o = oo;
	if(isString(oo)) var o = $(oo);
	if(isElement(o)) return{
		left	:intVal(o.offsetLeft),
		top		:intVal(o.offsetTop),
		width	:intVal(o.offsetWidth),
		height	:intVal(o.offsetHeight),
		bottom	:intVal(o.offsetTop)+intVal(o.offsetHeight),
		right	:intVal(o.offsetLeft)+intVal(o.offsetWidth),
		obj		:o
	}
}

function prevSibling(obj)
{
    try
	{
		var ie = getBrowser().ie;
		if(ie)
		{
			return obj.previousSibling;
		}
		else
		{
			if(!isUndefined(obj.previousSibling)) return obj.previousSibling.previousSibling;
		}
	}catch(e){}
}

function nextSibling(obj)
{
    try
	{
		var ie = getBrowser().ie;
		if(ie)
		{
			return obj.nextSibling;
		}
		else
		{
			if(!isUndefined(obj.nextSibling)) return obj.nextSibling.nextSibling;
		}
	}catch(e){}
}

function insertAfter(parent, node, referenceNode)
{
	if( !(nextElm = nextSibling(referenceNode)) )
		parent.appendChild(node);
	else
		parent.insertBefore(node, nextElm);
}

function intVal(p)
{
	if(p === 0) return 0;
	
	p = p.toString();
	p = p._replace(',', '.');
	p = p._replace('.', '');
	p = p._replace(' ', '');
	var r = parseInt(p, 10);
	return ( !isEmpty(r) && !isNaN(r) ? r : 0);
}

function getElementsByClassName(className, tag, elm, returnFirst, noProto)
{
	tag 				= tag || "*";
	elm 				= elm || document;
	var testClass 		= new RegExp("(^|\s+)" + className + "(\s+|$)");
	var elements 		= (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements 	= [];
	var current			= null;
	var length = elements.length;
	for(var i=0; i<length; i++)
	{
		current = elements[i];
		//if(testClass.test(current.className))
		if(current.className && (' '+current.className+' ').indexOf(' '+className+' ') > -1)
		{
			if(!noProto)DOMElement.proto(current);
			if(returnFirst) return current;
			returnElements.push(current);
		}
	}
	
	if(returnElements.length != 0)
		return new HTMLNodeList(returnElements);
	
	return new HTMLNodeList(new Array());		
}

function getBounds(element)
{
	var coords = { _x: 0, _y: 0, width: 0, height:0, obj:element };
	if( typeof element != 'object' || element.nodeType != 1) return coords;
	
	coords.width	= element.offsetWidth;
	coords.height	= element.offsetHeight;
	
	while (element)
	{
		coords._x += element.offsetLeft;
		coords._y += element.offsetTop;
		element = element.offsetParent;
	}	
	return coords;	
}

function copyElement(o_from, o_to)
{
    if(typeof o_from == 'string') o_from = $(o_from);
    if(typeof o_to == 'string') o_to = $(o_to);
	if(!isElement(o_from) || !isElement(o_to)) return null;    
    
    var clone = o_from.cloneNode(true);
    clone.removeAttribute('id');
    o_to.appendChild(clone);
    return clone;
}

function fullCloneElement(obj)
{
	var bounds	= getBounds(obj);
	var style	= {left:'0px', top:'0px', width:bounds.width+'px', height:bounds.height+'px', minHeight:bounds.height+'px', maxHeight:bounds.height+'px', minWidth:bounds.width+'px', maxWidth:bounds.width+'px', padding:'0px', margin:'0px'};
	var elm		= obj.parentNode;
	var nodeList= new Array();
	
	while(elm && elm.nodeName && elm.nodeName.toUpperCase() != 'BODY')
	{
		nodeList.push({nodeName:elm.nodeName, id:elm.getAttribute('id'), style:elm.getAttribute('style'), className:elm.className});
		elm = elm.parentNode;
	}
	
	elm = null;
	for(var i=nodeList.length-1 ; i>=0 ; i--)
	{
		var curr = nodeList[i];
		var node = document.createElement(curr.nodeName);
		if(curr.id)			node.setAttribute('id', curr.id);
		if(curr.style)		node.setAttribute('style', curr.style);
		if(curr.className)	node.className = curr.className;
		setStyle(node, style);
		if(elm)	elm.appendChild(node);
		else	topNode = node;
		elm = node;
	}
	var copy = obj.copyTo(elm);
	copy.setAttribute('id', obj.getAttribute('id'));
	topNode.original = copy;
	return topNode;
}

function getElementsByFilter(elm, filter)
{
	if(!isElement(elm) || !elm) elm = document;
	if(!isObject(filter) || isNull(filter)) return new HTMLNodeList(new Array());
	
	var elmList = null;
	
	for(var k in filter)
	{
		if(isFunction(filter[k])) continue;
		switch(k)
		{
			case 'id':
				if(!isNodeList(elmList)) var elmList = getElementsByTagNameList(elm, ['*']);
				var elmList = elmList.getElementsById(filter.id);
			break;
		
			case 'tagName':
				if(isNodeList(elmList))
					var elmList = elmList.getElementsByTagName(filter.tagName);
				else
					var elmList = getElementsByTagNameList(elm, filter.tagName);
			break;
		
			case 'className':
				if(!isNodeList(elmList)) var elmList = getElementsByTagNameList(elm, ['*']);
				var elmList = elmList.getElementsByClassName(filter.className);
			break;
		
			case 'attrib':
				if(!isNodeList(elmList)) var elmList = getElementsByTagNameList(elm, ['*']);
				var elmList = elmList.getElementsByAttribute(filter.attrib);
			break;
		}
	}
	
	return elmList;
}

function getParentBy(elm, what, value)
{
	if(!isElement(elm)) return null;
	var ret = null;
	switch(what)
	{
		default:
			while(isElement(elm) && elm[what] != value)
			{
				elm = elm.parentNode;
				ret = elm;
			}
		break;
	
		case 'tagName':
			var v = value.toLowerCase();
			elm = ret = elm.parentNode;
			
			while( elm && elm.tagName.toLowerCase() != v )
			{
				elm = elm.parentNode;
				ret = elm;
			}
		break;

		case 'attribute':
			var aname 	= value[0];
			var avalue	= value[1];
			while(isElement(elm) && elm.getAttribute(aname) != avalue)
			{
				elm = elm.parentNode;
				ret = elm;
			}
		break;
	
		case 'className':
			if(elm[what].indexOf(value) != -1)
				return elm;
			
			while(isElement(elm) && elm[what].indexOf(value) == -1)
			{
				elm = elm.parentNode;
				ret = elm;
			}
		break;
	}
	return ret;
}

function getElementsByTagNameList(elm, list)
{
	var ret 	= new Array();
		elm		= elm || document;
		list	= isString(list) ? [list] : list;
	for(var i=0 ; i<list.length ; i++)
	{
		var curr = elm.getElementsByTagName(list[i]);
		for(var k=0 ; k<curr.length ; k++)
		{
			ret.push(curr[k]);
		}
	}
	return new HTMLNodeList(ret);
}

function getScroll(elm)
{
	elm = (isElement(elm)) ? elm : document.documentElement;
	return {top: elm.scrollTop, left: elm.scrollLeft};
}

if(isUndefined(JS_DUMP_ENABLE)) var JS_DUMP_ENABLE = true;

function dump(data, name, tabName, clearAll, header, type, alwaysOnTop, enableStateChange)
{
	if(!JS_DUMP_ENABLE) return false;
	if(dumpWindow)
	{
		tabName		= isUndefined(tabName) ? 'js' : tabName;
		
		dumpWindow.dump(
			{text:data, name:name, header:header, type:type},
			{name:tabName, alwaysOnTop:alwaysOnTop, enableStateChange:enableStateChange},
			clearAll
		);
	}
}

var _DBL_CLICK_TEMP = null;
function evtRename(obj, cb, min, max)
{
	var interval_min = isUndefined(min) ? 1 : min;
	var interval_max = isUndefined(max) ? 2 : min;
	
	addEvent(obj, 'click', null, function()
	{
		if(!isNull(_DBL_CLICK_TEMP) && _DBL_CLICK_TEMP)
		{
			if(_DBL_CLICK_TEMP.elm !== obj)
			{
				clearInterval(_DBL_CLICK_TEMP.t_min);
				clearInterval(_DBL_CLICK_TEMP.t_max);
				_DBL_CLICK_TEMP = null;
			}
			else if(_DBL_CLICK_TEMP.validSecondClick)
			{
				clearInterval(_DBL_CLICK_TEMP.t_min);
				clearInterval(_DBL_CLICK_TEMP.t_max);
				cb.execute(obj);
				_DBL_CLICK_TEMP = null;
			}
		}
		
		if(isNull(_DBL_CLICK_TEMP))
		{
			_DBL_CLICK_TEMP	= new Object();
			_DBL_CLICK_TEMP = {
				elm					: obj,
				validSecondClick	: false,
				mouseMoved			: false,
				startCheck			: true,
				cb					: cb,
				t_min				: setTimeout('_DBL_CLICK_TEMP.validSecondClick=true;', interval_min*1000),
				t_max				: setTimeout('_DBL_CLICK_TEMP.validSecondClick=false; if(!_DBL_CLICK_TEMP.mouseMoved){ _DBL_CLICK_TEMP.cb.execute(_DBL_CLICK_TEMP.elm);}; _DBL_CLICK_TEMP = null;', interval_max*1000)
			};
		}
	});
	
	addEvent(document, 'mousemove', null, function(e)
	{
		if(isObject(_DBL_CLICK_TEMP) && !isNull(_DBL_CLICK_TEMP))
		{
			if(isElement(_DBL_CLICK_TEMP.elm) && _DBL_CLICK_TEMP.startCheck)
			{
				_DBL_CLICK_TEMP.mouseMoved = true;
			}
		}
	});
}

function createRenameInputField(elm, value, events, style)
{
	var input 			= create.input.text('renameField', value, 'input-text', style, elm);
		input.oldValue	= value;
	
	if(events)
	{
		addEvent(input, 'keypress', null, function(e)
		{
			var evt = e || window.event;
			if(evt.keyCode == 13)
				if(events.Enter instanceof CallBack)
					events.Enter.execute({elm:elm, input:input, value:input.value, changed:(input.oldValue == input.value ? false : true)});
			
			if(evt.keyCode == 27)
				if(events.Escape instanceof CallBack)
					events.Escape.execute({elm:elm, input:input, value:input.value, changed:(input.oldValue == input.value ? false : true)});
		});
		
		addEvent(input, 'blur', null, function(e)
		{
			if(events.onblur instanceof CallBack)
				events.onblur.execute({elm:elm, input:input, value:input.value, changed:(input.oldValue == input.value ? false : true)});
		});
	}
	return input;
}

function oc(a)
{
  var o = {};
  for(var i=0;i<a.length;i++)
  {
    o[a[i]]='';
  }
  return o;
}

var create =
{
	element: function(tagName, id, txt, cn, style, parent, select)
	{
		var e = document.createElement(tagName);
		if(id) e.id = id;
		if(txt) e.innerHTML = txt;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		DOMElement.proto(e);
		if(!select)disableSelection(e);
		if(isElement(parent)) parent.appendChild(e);
		return e;
	},
	
	input:
	{
		hidden:function(name, value, parent)
		{
			var e = document.createElement('input');
			e.type = 'hidden';
			e.name = name;
			if(value)e.value = value;
			DOMElement.proto(e);
			if(isElement(parent)) parent.appendChild(e);
			return e;
		},
		text:function(name, value, cn, style, parent)
		{
			var e = document.createElement('input');
			e.type = 'text';
			e.name = name;
			if(value) e.value = value;
			if(cn) e.className = cn;
			if(style) setStyle(e, style);
			DOMElement.proto(e);
			if(isElement(parent)) parent.appendChild(e);
			return e;
		},
		password:function(name, value)
		{
			var e = document.createElement('input');
			e.type = 'password';
			e.name = name;
			if(value)e.value = value;
			DOMElement.proto(e);
			return e;
		}
	},
	
	div:function(id, txt, cn, style, parent, select)
	{
		var e = document.createElement('div');
		if(id) e.id = id;
		if(txt) e.innerHTML = txt;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		DOMElement.proto(e);
		if(!select)disableSelection(e);
		if(isElement(parent)) parent.appendChild(e);
		return e;
	},
	
	iframe:function(id, transparent, cn, style, parent, select)
	{
		var e = document.createElement('iframe');
		DOMElement.proto(e);
		if(id) {e.id = id; e.name = id};
		if(cn) e.className = cn;
		if(style) e.setStyle(style);
		if(!select)disableSelection(e);
		if(transparent)
		{
			e.setStyle({filter: 'alpha(opacity=0)',	opacity: '0'});
		}
		if(isElement(parent)) parent.appendChild(e);
		return e;
	},
	
	img:function(id, src, cn, style, parent, attrib)
	{
		var e = document.createElement('img');
		DOMElement.proto(e);
		if(getBrowser().ie && getBrowser().ver < 7 && src.split('.').pop().toUpperCase() == 'PNG')
		{
			style = isObject(style) ? style : new Object();
			style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+src+"', sizingMethod='scale')";
			src = _URL_ROOT+'images/1x1.gif';
		}
		if(attrib) e.addAttribs(attrib);
		e.src = src;
		if(id) e.id = id;
		if(cn) e.className = cn;
		if(style) e.setStyle(style);
		if(isElement(parent)) parent.appendChild(e);
		return e;
	},
	
	span:function(id, txt, cn, style)
	{
		var e = document.createElement('span');
		if(id) e.id = id;
		if(txt) e.innerHTML = txt;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		DOMElement.proto(e);
		disableSelection(e);
		return e;
	},
	
	table:function(id, cn, style, parent, attrib)
	{
		var e = document.createElement('table');
		var b = document.createElement('tbody');
		if(id) e.id = id;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		if(parent) parent.appendChild(e);
		DOMElement.proto(e);
		if(attrib) e.addAttribs(attrib);
		disableSelection(e);
		e.appendChild(b);		
		return b;
	},
	
	tr:function(id, cn, style, parent, attrib)
	{
		var e = document.createElement('tr');
		if(id) e.id = id;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		if(isElement(parent)) parent.appendChild(e);
		DOMElement.proto(e);
		if(attrib) e.addAttribs(attrib);
		disableSelection(e);
		return e;
	},
	
	td:function(id, cn, style, parent, attrib)
	{
		var e = document.createElement('td');
		if(id) e.id = id;
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		if(isElement(parent)) parent.appendChild(e);
		DOMElement.proto(e);
		if(attrib) e.addAttribs(attrib);
		disableSelection(e);
		return e;
	},
	
	box: function(cn, style, bound, parent)
	{
		var e = document.createElement('div');
		style = isEmpty(style) ? new Object() : style;
		style.width = bound.width + 'px';
		style.height = bound.height + 'px';
		style.left = bound._x + 'px';
		style.top = bound._y + 'px';
		style.position = 'absolute';
		if(cn) e.className = cn;
		if(style) setStyle(e, style);
		if(isElement(parent)) parent.appendChild(e);
		DOMElement.proto(e);
		disableSelection(e);
		return e;
	}
}


var dbg =
{
	fnTime	: new Object(),
	
	getTime: function(time)
	{
		var date 	= new Date();
		var sec		= date.getSeconds();
		var msec	= parseFloat('0.'+date.getMilliseconds(), 10);
		
		if(time)
		{
			var sec2	= time.getSeconds();
			var msec2	= parseFloat('0.'+time.getMilliseconds(), 10);
			
			return (sec+msec) - (sec2+msec2);
		}	
		return sec+msec;
	},
	
	functionSumTime: function(name, time)
	{
		if(isString(name))
		{
			if(isUndefined(this.fnTime[name]))
			{
				this.fnTime[name] = new Array();
				var self = this;
				addEvent(window, 'load', null, function(){ dump(self.fnTime) });
			}
			this.fnTime[name].push(this.getTime(time));
		}
	}
}
