/**
 * Common functions
 * -----------------------------------------------
 * @author        Filatov Dmitry <alpha@design.ru>
 * @version       0.1, 19.02.2007 
 */

var Common = {

	// Common classes methods
	
	Class : {
		
		match : function(	
			oElement,
			sClassName
			) {
	
			return (oElement.className && oElement.className.match(new RegExp('(^|\\s+)' + sClassName + '($|\\s+)')))? true : false;	
		
		},
		
		add : function(
			oElement,
			sClassName
			) {

			if(!Common.Class.match(oElement, sClassName)) {
				oElement.className += ' ' + sClassName;
			}
			
		},
		
		replace : function(
			oElement,
			sClassNameFrom,
			sClassNameTo
			) {
			
			if(Common.Class.match(oElement, sClassNameFrom)) {
				oElement.className = (oElement.className.replace( new RegExp("(^|\\s+)(" + sClassNameFrom + "|" + sClassNameTo + ")($|\\s+)", "g"), "$1" ) + ' ' + sClassNameTo ).replace( /^\s+/, '');
			}
			else {
				Common.Class.add(oElement, sClassNameTo);
			}			
			
		},
		
		remove : function(
			oElement,
			sClassName
			) {
	
			oElement.className = oElement.className.replace(new RegExp('(.*)(^|\\s+)(' + sClassName + ')($|\\s+)(.*)'), '$1$4$5').replace(/(^)\s/, '$1');	
			
		}
		
	},
		
	
	// Common event's methods
	
	Event : {
	
		iGuid : 1,
	
		add : function(
			oElement,
			sEventType,
			fEventFunc,
			bCapture
			) {

			var fEventFunc = fEventFunc.closure(oElement);
				
			if(oElement.addEventListener) {
				oElement.addEventListener(
					sEventType,
					fEventFunc,
					bCapture? true : false
					);
			}
			else {				
			
				function handle(oEvent) {
					
					var
						oEvent = oEvent || window.event,
						bReturnValue = true,
						aHandlers = oElement.aEvents[oEvent.type]
						;
									
					for(var i in aHandlers) {
			
						if(!Array.prototype[i]) {
			
							oElement.$$fEventFunc = aHandlers[i];
				
							if(oElement.$$fEventFunc(oEvent) === false) {
								bReturnValue = false;
							}
				
						}
			
					}
			
					if(oElement.$$fEventFunc) {
						oElement.$$fEventFunc = null;
					}
			
					return bReturnValue;
					
				}
				
				if(!fEventFunc.$$guid) {
					fEventFunc.$$guid = Common.Event.iGuid++;
				}
				
				if(!oElement.aEvents) {
					oElement.aEvents = [];
				}
				
				var aHandlers = oElement.aEvents[sEventType];
				
				if(!aHandlers) {
					
					aHandlers = oElement.aEvents[sEventType] = [];
					
					if(oElement['on' + sEventType]) {					
						aHandlers[0] = oElement['on' + sEventType];
					}
					
					oElement['on' + sEventType] = handle;
					
				}	
				
				aHandlers[fEventFunc.$$guid] = fEventFunc;
				
			}
	
		},	

		remove : function(
			oElement,
			sEventType,
			fEventFunc,
			bCapture
			) {
	
			var fEventFunc = fEventFunc.closure(oElement);
				
			if(oElement.removeEventListener) {
				oElement.removeEventListener(
					sEventType,
					fEventFunc,
					bCapture? true : false
					);
			}
			else if(oElement.aEvents && oElement.aEvents[sEventType] && fEventFunc.$$guid) {
				delete oElement.aEvents[sEventType][fEventFunc.$$guid];
			}
			
		},
		
		cancel : function(oEvent){
					
			oEvent.cancelBubble = true;
			
			if(oEvent.cancelable){
				
				oEvent.preventDefault();
				oEvent.stopPropagation();
				
			}
			
			return false;
			
		},
		
		normalize : function(oEvent){
						
			var oEvent = oEvent?
				oEvent :
				(window.event? window.event : null)
				;
			
			if(oEvent && oEvent.srcElement && !window.opera) {
				oEvent.target = oEvent.srcElement;				
			}
			
			if(oEvent){
				
				oEvent.iKeyCode = oEvent.keyCode?
					oEvent.keyCode :
					(oEvent.which? oEvent.which : null)
					;
							
				if(oEvent.wheelDelta) {
									
					oEvent.iMouseWheelDelta = oEvent.wheelDelta / 120;
					
					if(window.opera) {
						oEvent.iMouseWheelDelta *= -1;
					}
					
				}
				else if(oEvent.detail) {
					oEvent.iMouseWheelDelta = -oEvent.detail / 3;
				}
				
			}
			
			return oEvent;
		
		},
		
		getAbsoluteCoords : function(oEvent) {

			var oResult = {
				iLeft : 0,
				iTop  : 0
			};

			if(oEvent.pageX || oEvent.pageY) {
  
				oResult.iLeft = oEvent.pageX;
				oResult.iTop = oEvent.pageY;
				
			}
			else if(oEvent.clientX || oEvent.clientY) {
	
				oResult.iLeft = oEvent.clientX + document.body.scrollLeft - document.body.clientLeft;
				oResult.iTop = oEvent.clientY + document.body.scrollTop - document.body.clientTop;

				if(document.body.parentElement && document.body.parentElement.clientLeft) {
		
					var oBodyParent = document.body.parentElement;
		
					oResult.iLeft += oBodyParent.scrollLeft - oBodyParent.clientLeft;
					oResult.iTop += oBodyParent.scrollTop - oBodyParent.clientTop;  
			
				}
		
			}
			
			return oResult;
			
		}
		
	},	
	
	
	// Common DOM's methods
	
	Dom : {
			
		getAbsoluteCoords : function(oElement) {
			
			var oResult = {
				iTop  : 0,
				iLeft : 0
				};
	
			while(oElement) {
	
				oResult.iTop += oElement.offsetTop;
				oResult.iLeft += oElement.offsetLeft;
		
				oElement = oElement.offsetParent;
		
			}
		
			return oResult;
			
		},				
				
		getAttribute : function(
			oElement,
			sName
			) {			
				
			if(oElement.attributes) {			
				for(var i = 0; i < oElement.attributes.length; i++){
					if(oElement.attributes[i].nodeName == sName) {
						return oElement.attributes[i].nodeValue;
					}				
				}				
			}
			
			return oElement.getAttribute(sName);

		}				
		
	},
	
	
	// Common cookie's methods
	
	Cookie : {
	
		set : function(sName, sValue, sExpire, sPath) {
		
			document.cookie = sName + '=' + escape(sValue)
				+ ((sExpire == null)? '' : ('; expires=' + sExpire.toGMTString()))
				+ ((sPath == null)? '' : ('; path=' + sPath));
		
		},
		
		get : function(sName) {
		
			var sSearch = sName + '=';
			
			if(document.cookie.length > 0) {
			
				var iOffset = document.cookie.indexOf(sSearch);
				
				if(iOffset != -1) {
				
					iOffset += sSearch.length;
			
					var iEnd = document.cookie.indexOf(';', iOffset);
			
					if(iEnd == -1) {
						iEnd = document.cookie.length;
					}
					
					return unescape(document.cookie.substring(iOffset, iEnd));
					
				}
			}
			
			return '';			
		
		}
	
	},
	
	
	// Common object's methods

	Object : {
				
		extend : function(
			oSource,
			oDestination
			) {				
		
			for(var i in oSource) {		
				oDestination[i] = oSource[i];
			}
		
			return oDestination;
		
		}
		
	},
	

	Utils : {
	
		oPopupDefaults : {	
	
			iWidth      : 540,
			iHeight     : 600,
			sToolbar    : 'no',
			sMenubar    : 'no',
			sResizeable : 'yes',
			sScrollbars : 'yes',
			sStatus     : 'yes'
	
		},
	
		popup : function(
			sUrl,
			sName,
			oOptions,
			bReplace
			) {
		
			oOptions = Common.Object.extend(
				oOptions,
				Common.Utils.oPopupDefaults
				);
		
			var iLeftOffset = screen.availWidth / 2 - oOptions.iWidth / 2;
			var iTopOffset = screen.availHeight / 2 - oOptions.iHeight / 2;			
		
			oNewWindow = window.open(
				sUrl,
				sName,
				'left=' + iLeftOffset + ', ' +
				'top = ' + iTopOffset + ', ' +
				'width=' + oOptions.iWidth + ', ' +
				'height=' + oOptions.iHeight + ', ' +
				'resizable=' + oOptions.sResizeable + ', ' +
				'toolbar=' + oOptions.sToolbar + ', ' +
				'scrollbars=' + oOptions.sScrollbars + ', ' +
				'status=' + oOptions.sStatus
				);
			
			if(sUrl.match(/\.(gif|jpe?g|png)$/i)) {
		
				oNewWindow.document.open();
			
				oNewWindow.document.write('<html><head></head>' +
					'<body style="background: #FFF; margin: 0px; padding: 0px;">' +
					'<table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%"><tr><td align="center">' + 
					'<img src="' + sUrl + '" </td></tr></table></body></html>'
					);
				
				oNewWindow.document.close();
		
			}
			
			oNewWindow.focus();				
			
			return false;
			
		}
		
	}

}


/* Extensions */

if(!Function.prototype.call) { // emulating call function for browser have no native support for it		
	Function.prototype.call = function() {
		
		var
			oObject = arguments[0],
			aArguments = [],
			oResult
			;	
		
		oObject.fFunction = this;
			
		for(var i = 1; i < arguments.length; i++) {
			aArguments[aArguments.length] = 'arguments[' + i + ']';		
		}
		
		eval('oResult = oObject.fFunction(' + aArguments.join(',') + ')');
		
		oObject.fFunction = null;
		
		return oResult;
			
	};		
}

if(!Function.prototype.apply) {
	Function.prototype.apply = function () { // emulating apply function for browser have no native support for it
    
		var
			oContext,
			oOldProperty,
			aArguments = [],
			oResult			
			;
				    	
    	oContext = arguments.length == 0? window : arguments[0];    	
    	
    	oOldProperty = oContext.__temp;
    	
    	oContext.__temp = this;
    
    	for(var i = 0; i < arguments[1].length; i++) {
    		aArguments[aArguments.length] = 'arguments[1][' + i + ']';
    	}
    	
    	oResult = eval('oContext.__temp(' + aArguments.join(',') + ')');
    	
    	oContext.__temp = oOldProperty;
    	
    	return oResult;
    
	}	
}

Function.prototype.inheritFrom = function(BaseClass) { // inheritance's method
		
	var Inheritance = function() {};
			
	Inheritance.prototype = BaseClass.prototype;

	this.prototype = new Inheritance();
	this.prototype.constructor = this;
	this.baseConstructor = BaseClass;
	this.superClass = BaseClass.prototype;
			
};

Function.prototype.closure = function(obj) { // method for prevent IE memory leaks in closure  
  
	if(!window.__objs) {
    	window.__objs = [];
    	window.__funs = [];
  	}
  
	var
		fun = this,
  		objId = obj.__objId
  		;
	
  	if(!objId) {
    	__objs[objId = obj.__objId = __objs.length] = obj;
  	}
  
  	var funId = fun.__funId;
  	
  	if(!funId) {
    	__funs[funId = fun.__funId = __funs.length] = fun;
  	}
  
  	if(!obj.__closures) {
		obj.__closures = [];
  	}
  
	var closure = obj.__closures[funId];
	
  	if(closure) {
    	return closure;
  	}    
  
	obj = null;
	fun = null;
  
	return __objs[objId].__closures[funId] = function() {
    	return __funs[funId].apply(__objs[objId], arguments);
  	};
  	
};

if(!Array.prototype.push) {	
	Array.prototype.push = function() {				
				
		for(var i = 0; i < arguments.length; i++) {			
			this[this.length] = arguments[i];
		}		
		
	}	
}

if(!Array.prototype.splice) {	
	Array.prototype.splice = function() {
						
		if(arguments[0] > this.length - 1) {			
			return;
		}
		
		var iRemovedCount = arguments[0] + arguments[1] > this.length?
			this.length - arguments[0] :
			arguments[1]
			;
		
		if(iRemovedCount > 0) {
					
			for(var i = arguments[0]; i < this.length; i++) {			
				this[i] = this[i + iRemovedCount];			
			}
		
			this.length = this.length - iRemovedCount;
			
		}
		
		var iNewCount = arguments.length - 2;
						
		if(iNewCount > 0) {
			
			var
				iLastIndex = this.length - 1,
				iNewLastIndex = iLastIndex + iNewCount
				;			
			
			for(var i = iLastIndex, j = 0; i >= arguments[0]; i--, j++) {				
				this[iNewLastIndex - j] = this[i];								
			}
			
			for(var i = 0; i < iNewCount; i++) {									
				this[arguments[0] + i] = arguments[i + 2];		
			}
			
		}				
		
	};	
}

Array.prototype.remove = function(mElement){
	
	for(var i = 0; i < this.length; i++) {
		
		if(this[i] == mElement){
			
			this.splice(i, 1);
			break;
			
		}
		
	}
	
};

Array.prototype.contains = function(mElement){
	
	var iFoundedIndex = -1;
	
	for(var i = 0; i < this.length; i++) {
		
		if(this[i] == mElement){
			
			iFoundedIndex = i;
			break;
			
		}
		
	}
	
	return iFoundedIndex;
	
};

if(!Object.prototype.hasOwnProperty) {
  Object.prototype.hasOwnProperty = function(sPropertyName) {
  	
    return !(
    	'undefined' == typeof this[sPropertyName] ||
    	this.constructor &&
    	this.constructor.prototype[sPropertyName] &&
    	this[sPropertyName] === this.constructor.prototype[sPropertyName]
    	);
    
  }
}
