/**
 * Common functions
 * -----------------------------------------------
 * @author        Filatov Dmitry <alpha@zforms.ru>
 * @version       0.5, 28.02.2009
 */

var Common = {

	Browser : {

		bIE      : !!(window.attachEvent && !window.opera),
		bOpera   : !!window.opera,
		bSafari  : /webkit/i.test(navigator.userAgent),
		bMozilla : /mozilla/i.test(navigator.userAgent) && !/(compatible|webkit)/i.test(navigator.userAgent),

		isIE : function() {

			return this.bIE;

		},

		isOpera : function() {

			return this.bOpera;

		},

		isSafari : function() {

			return this.bSafari;

		},

		isMozilla : function() {

			return this.bMozilla;

		}

	},

	// Common classes methods

	Class : {

		match : function(
			oElement,
			sClassName
			) {

			return oElement.className != '' && (' ' + oElement.className + ' ').indexOf(' ' + sClassName + ' ') > -1;

		},

		add : function(
			oElement,
			sClassName
			) {

			if(!this.match(oElement, sClassName)) {
				oElement.className += ' ' + sClassName;
			}

		},

		replace : function(
			oElement,
			sClassNameFrom,
			sClassNameTo,
			bToggle
			) {

			if(this.match(oElement, sClassNameFrom)) {
				oElement.className = (oElement.className.replace(new RegExp("(^|\\s+)(" + sClassNameFrom + "|" + sClassNameTo + ")($|\\s+)", "g"), "$1") + ' ' +

sClassNameTo).replace(/^\s+/, '');
			}
			else if(bToggle && this.match(oElement, sClassNameTo)) {
				oElement.className = (oElement.className.replace(new RegExp("(^|\\s+)(" + sClassNameTo + "|" + sClassNameFrom + ")($|\\s+)", "g"), "$1") + ' ' +

sClassNameFrom).replace(/^\s+/, '');
			}
			else {
				this.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 : {

		aObservers : [],

		TYPE_DOM_CONTENT_LOADED : 'DOMContentLoaded',

		add : function(
			mElement,
			mEventType,
			fEventFunction
			) {

			var i = 0;

			if(Common.Utils.isArray(mElement) || (mElement.item && mElement.length && !mElement.tagName)) {

				while(mElement[i]) {
					this.add(mElement[i++], mEventType, fEventFunction);
				}

				return;

			}

			if(Common.Utils.isArray(mEventType)) {

				while(mEventType[i]) {
					this.add(mElement, mEventType[i++], fEventFunction);
				}

				return;

			}

			if(mEventType == this.TYPE_DOM_CONTENT_LOADED) {
				return this.addDomContentLoaded(
					mElement,
					fEventFunction
					);
			}

			if(mElement.addEventListener) {
				mElement.addEventListener(
					mEventType,
					fEventFunction,
					false
					);
			}
			else if(mElement.attachEvent) {

				this.attachObserver(
					mElement,
					mEventType,
					fEventFunction
					);

				mElement.attachEvent('on' + mEventType, fEventFunction);

			}

		},

		remove : function(
			mElement,
			mEventType,
			fEventFunction
			) {

			var i = 0;

			if(Common.Utils.isArray(mElement) || (mElement.item && mElement.length && !mElement.tagName)) {

				while(mElement[i]) {
					this.remove(mElement[i++], mEventType, fEventFunction);
				}

				return;

			}

			if(Common.Utils.isArray(mEventType)) {

				while(mEventType[i]) {
					this.remove(mElement, mEventType[i++], fEventFunction);
				}

				return;

			}

			if(mEventType == this.TYPE_DOM_CONTENT_LOADED) {
				return this.removeDomContentLoaded(
					mElement,
					fEventFunction
					);
			}

			if(mElement.removeEventListener) {
				mElement.removeEventListener(
					mEventType,
					fEventFunction,
					false
					);
			}
			else if(mElement.detachEvent) {
				mElement.detachEvent(
					'on' + mEventType,
					fEventFunction
					);
			}

		},

		addDomContentLoaded : function(
			oElement,
			fEventFunction
			) {

			if(document.addEventListener && !/webkit/i.test(navigator.userAgent)) {
				document.addEventListener(
					this.TYPE_DOM_CONTENT_LOADED,
					fEventFunction,
					false
					);
			}
			else {

				if(this.aObservers.indexOfByFunction(
					this.TYPE_DOM_CONTENT_LOADED,
					function(aObserver, sEventType) {

						return aObserver[1] == sEventType;

					}
					) > -1) {

					this.attachObserver(
						oElement,
						this.TYPE_DOM_CONTENT_LOADED,
						fEventFunction
						);

					return;

				}

				this.attachObserver(
					oElement,
					this.TYPE_DOM_CONTENT_LOADED,
					fEventFunction
					);

				if(document.addEventListener) {

					setTimeout(
						function() {

							if(document.readyState == 'loaded' || document.readyState == 'complete') {
								Common.Event.fireDomContentLoaded();
							}
							else {
								setTimeout(arguments.callee, 10);
							}
						},
						10
						);
				}
				else {

					(function() {

						var oNodeReady = document.createElement('document:ready');

						try {

							oNodeReady.doScroll('left');
							oNodeReady = null;

							Common.Event.fireDomContentLoaded();

						}
						catch(oException) {
							setTimeout(arguments.callee, 10);
						}
					}
					)();

				}

			}

		},

		removeDomContentLoaded : function(
			oElement,
			fEventFunction
			) {

			if(document.addEventListener && !/webkit/i.test(navigator.userAgent)) {
				return document.removeEventListener(
					this.TYPE_DOM_CONTENT_LOADED,
					fEventFunction,
					false
					);
			}

			var aDomContentLoadedObservers = this.aObservers.filtrate(
				fEventFunction,
				function(aObserver, fEventFunction) {

					return aObserver[1] == Common.Event.TYPE_DOM_CONTENT_LOADED && aObserver[2] == fEventFunction;

				}
				);

			var i = 0;
			while(aDomContentLoadedObservers[i]) {
				this.aObservers.remove(aDomContentLoadedObservers[i++]);
			}

		},

		fireDomContentLoaded : function() {

			var aDomContentLoadedObservers = this.aObservers.filtrate(
				this.TYPE_DOM_CONTENT_LOADED,
				function(aObserver, sEventType) {

					return aObserver[1] == sEventType;

				}
				);

			var i = 0;
			while(aDomContentLoadedObservers[i]) {
				aDomContentLoadedObservers[i++][2]();
			}

		},

		attachObserver : function(
			oElement,
			sEventType,
			fEventFunction
			) {

			this.aObservers.push([oElement, sEventType, fEventFunction]);

			if(this.aObservers.length == 1) {
				this.add(
					window,
					'unload',
					function() {

						Common.Event.detachObservers();

					}
					);
			}

		},

		detachObservers : function() {

			while(this.aObservers[i]) {

				this.remove(
					this.aObservers[i][0],
					this.aObservers[i][1],
					this.aObservers[i][2]
					);

				this.aObservers[i++][0] = null;

			}

			this.aObservers.length = 0;

		},

		cancel : function(oEvent) {

			var oEvent = oEvent? oEvent : window.event;

			oEvent.cancelBubble = true;
			oEvent.returnValue = false;

			if(oEvent.cancelable){

				oEvent.preventDefault();
				oEvent.stopPropagation();

			}

			return false;

		},

		normalize : function(oEvent) {

			var oEvent = oEvent? oEvent : window.event;

			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
				oEvent = oEvent? oEvent : window.event,
				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 || document.body.parentElement.clientTop)) {

					var oBodyParent = document.body.parentElement;

					oResult.iLeft += oBodyParent.scrollLeft - oBodyParent.clientLeft;
					oResult.iTop += oBodyParent.scrollTop - oBodyParent.clientTop;

				}*/

				var oDocumentElement = document.documentElement;

				if(oDocumentElement) {

					oResult.iLeft += oDocumentElement.scrollLeft - oDocumentElement.clientLeft;
					oResult.iTop += oDocumentElement.scrollTop - oDocumentElement.clientTop;

				}

			}

			return oResult;

		}

	},


	// Common DOM's methods

	Dom : {

		NODE_TYPE_ELEMENT : 1,
		NODE_TYPE_TEXT    : 3,

		getUniqueId : function(oElement) {

			return Common.Utils.getUniqueId(oElement);

		},

		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) {

				var i = 0;
				while(oElement.attributes[i]) {
					if(oElement.attributes[i++].nodeName == sName) {
						return oElement.attributes[i - 1].nodeValue;
					}
				}

			}

			return oElement.getAttribute(sName);

		},

		createElement : function(
			sName,
			oProperties,
			sHtml
			) {

			var oResult;

			if(Common.Browser.isIE()) {

				var sElement = '<' + sName;

				if(oProperties) {
					oProperties.foreach(function(sKey, mValue) {
						if(typeof(mValue) != 'undefined') {
							sElement += ' ' + sKey + '="' + mValue + '"';
						}
					});
				}

				oResult = document.createElement(sElement + ' />');

			}
			else {

				oResult = document.createElement(sName);

				if(oProperties) {
					oProperties.foreach(function(sKey, mValue) {
						if(typeof(mValue) != 'undefined') {
							oResult.setAttribute(sKey, mValue);
						}
					});
				}

			}

			if(sHtml) {
				oResult.innerHTML = sHtml;
			}

			return oResult;

		},

		getElementsByClassName : function(
			oElement,
			sClassName,
			sTagName,
			bOnlyChildren
			) {

			if(document.querySelectorAll) { // if browser has native selector

				if(Common.Browser.isIE()) {
					this.getElementsByClassName = function(
						oElement,
						sClassName,
						sTagName,
						bOnlyChildren
						) {

						var
							aNodes = oElement.querySelectorAll(
								(bOnlyChildren? '>' : '') +
								(sTagName? sTagName : '') +
								'.' + sClassName
								),
							aResult = [],
							i = 0,
							oNode
							;

						while(oNode = aNodes[i++]) {
							aResult.push(oNode);
						}

						return aResult;

					};
				}
				else {
					this.getElementsByClassName = function(
						oElement,
						sClassName,
						sTagName,
						bOnlyChildren
						) {

						return [].slice.call(
							oElement.querySelectorAll(
								(bOnlyChildren? '>' : '') +
								(sTagName? sTagName : '') +
								'.' + sClassName
								),
								0
							);

					};
				}


			}
			else if(document.evaluate) { // if browser has xpath support
				this.getElementsByClassName = function(
					oElement,
					sClassName,
					sTagName,
					bOnlyChildren
					) {

					oQueryResult = document.evaluate(
						'./' + (bOnlyChildren? '' : '/') + (sTagName || '*') + '[contains(concat(\' \', @class, \' \'), \' ' + sClassName + ' \')]',
						oElement,
						null,
						XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
						null
						);

					var
						i = 0,
						aResult = [],
						oItem
						;
					while(oItem = oQueryResult.snapshotItem(i++)) {
						aResult.push(oItem);
					}

					return aResult;

				};
			}
			else {
				this.getElementsByClassName = function( // simple traversing
					oElement,
					sClassName,
					sTagName,
					bOnlyChildren
					) {

					var
						aResult = [],
						sTagName = sTagName || '*',
						i = 0,
						oChild
						;

					if(bOnlyChildren) {
						while(oChild = oElement.childNodes[i++]) {

							if(oChild.nodeType == this.NODE_TYPE_ELEMENT && (sTagName == '*' || oChild.tagName.toLowerCase() == sTagName) && Common.Class.match(oChild, sClassName)) {
								aResult.push(oChild);
							}

						}

						return aResult;

					}

					var aDescendants = sTagName == '*' && oElement.all? oElement.all : oElement.getElementsByTagName(sTagName);

					while(oChild = aDescendants[i++]) {
						if(Common.Class.match(oChild, sClassName)) {
							aResult.push(oChild);
						}
					}

					return aResult;

				}
			}

			return this.getElementsByClassName(oElement, sClassName, sTagName, bOnlyChildren);

		},

		setStyle : function(
			oElement,
			sCssText
			) {

			if(typeof(oElement.style.cssText) != 'undefined') {
				oElement.style.cssText = sCssText;
			}
			else {
				oElement.setAttribute(
					'style',
					sCssText
					);
			}

		},

		setOpacity : function(
			oElement,
			dValue
			) {

			if(oElement.runtimeStyle) {

				oElement.style.zoom = 1;
				oElement.style.filter = oElement.style.filter.replace(/alpha\([^)]*\)/,"") + "alpha(opacity=" + dValue * 100 + ")";

			}
			else {

				if(dValue == 1) {
					oElement.style.opacity = '';
				}
				else {
					oElement.style.opacity = dValue;
				}

			}

		}

	},

	// Common cookie's methods

	Cookie : {

		set : function(sName, sValue, sExpire, sPath) {

			document.cookie = sName + '=' + (window.encodeURI? encodeURI(sValue) : 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 window.decodeURI?
						decodeURI(document.cookie.substring(iOffset, iEnd)) :
						unescape(document.cookie.substring(iOffset, iEnd))
						;

				}
			}

			return '';

		}

	},

	// Common object's methods

	Object : {

		extend : function(
			oDestination,
			oSource,
			bReplace
			) {

			if(!oSource) {
				return oDestination;
			}

			var oDestination = oDestination || {};

			for(var i in oSource) {

				if((bReplace || typeof(oDestination[i]) == 'undefined') && typeof(oSource[i]) != 'undefined') {
					oDestination[i] = oSource[i];
				}
			}

			return oDestination;

		}

	},

	Observable : {

		aObservers : [],

		attach : function(
			mEventType,
			mObserver,
			mObservable
			) {

			var i = 0;

			if(Common.Utils.isArray(mEventType)) {

				while(mEventType[i]) {
					this.attach(mEventType[i++], mObserver, mObservable);
				}

				return;

			}

			if(Common.Utils.isArray(mObserver)) {

				while(mObserver[i]) {
					this.attach(mEventType, mObserver[i++], mObservable);
				}

				return;

			}

			if(Common.Utils.isArray(mObservable)) {

				while(mObservable[i]) {
					this.attach(mEventType, mObserver, mObservable[i++]);
				}

				return;

			}

			if(!this.aObservers[mEventType]) {
				this.aObservers[mEventType] = [];
			}

			var
				aObserversByType = this.aObservers[mEventType],
				sUniqueId = Common.Utils.getUniqueId(mObservable)
				;

			if(!aObserversByType[sUniqueId]) {
				aObserversByType[sUniqueId] = [];
			}

			aObserversByType[sUniqueId].push(mObserver);

		},

		detach : function(
			mEventType,
			mObserver,
			mObservable
			) {

			var i = 0;

			if(Common.Utils.isArray(mEventType)) {

				while(mEventType[i]) {
					this.detach(mEventType[i++], mObserver, mObservable);
				}

				return;

			}

			if(Common.Utils.isArray(mObserver)) {

				while(mObserver[i]) {
					this.detach(mEventType, mObserver[i++], mObservable);
				}

				return;

			}

			if(Common.Utils.isArray(mObservable)) {

				while(mObservable[i]) {
					this.detach(mEventType, mObserver, mObservable[i++]);
				}

				return;

			}

			var aObserversByType = this.aObservers[mEventType];

			if(!aObserversByType) {
				return;
			}

			var sUniqueId = Common.Utils.getUniqueId(mObservable);

			if(aObserversByType[sUniqueId]) {
				aObserversByType[sUniqueId].remove(mObserver);
			}

		},

		notify : function(
			sEventType,
			oObservable,
			mData
			) {

			var aObserversByType = this.aObservers[sEventType];

			if(!aObserversByType) {
				return;
			}

			var sUniqueId = Common.Utils.getUniqueId(oObservable);

			if(!aObserversByType[sUniqueId]) {
				return;
			}

			var
				i = 0,
				aObservers = aObserversByType[sUniqueId],
				fObserver
				;
			while(fObserver = aObservers[i++]) {
				fObserver(sEventType, oObservable, mData);
			}

		}

	},

	Utils : {

		oPopupDefaults : {

			iWidth      : 540,
			iHeight     : 600,
			sToolbar    : 'no',
			sMenubar    : 'no',
			sResizeable : 'yes',
			sScrollbars : 'yes',
			sStatus     : 'yes'

		},

		popup : function(
			sUrl,
			sName,
			oOptions
			) {

			oOptions = Common.Object.extend(
				Common.Utils.oPopupDefaults,
				oOptions,
				true
				);

			var iLeftOffset = screen.availWidth / 2 - oOptions.iWidth / 2;
			var iTopOffset = screen.availHeight / 2 - oOptions.iHeight / 2;

			oNewWindow = window.open(
				sUrl,
				'',
				'left=' + iLeftOffset + ', ' +
				'top = ' + iTopOffset + ', ' +
				'width=' + oOptions.iWidth + ', ' +
				'height=' + oOptions.iHeight + ', ' +
				'menubar=' + oOptions.sMenubar + ', ' +
				'toolbar=' + oOptions.sToolbar + ', ' +
				'resizable=' + oOptions.sResizeable + ', ' +
				'scrollbars=' + oOptions.sScrollbars + ', ' +
				'status=' + oOptions.sStatus
				);

			if(sUrl.match(/\.(gif|jpe?g|png)$/i)) {

				oNewWindow.document.open();

				oNewWindow.document.write('<html><head>' + (sName != ''? '<title>' + sName + '</title>' : '') + '</head><body style="background: #FFF; margin: 0; padding: 0;">' +
					'<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;

		},

		aNavigationLinks : [
			{
				sRel     : 'next',
				iKeyCode : 0x27,
				sHref    : ''
			},
			{
				sRel     : 'prev',
				iKeyCode : 0x25,
				sHref    : ''
			},
			{
				sRel     : 'up',
				iKeyCode : 0x26,
				sHref    : ''
			},
			{
				sRel     : 'down',
				iKeyCode : 0x28,
				sHref    : ''
			},
			{
				sRel     : 'start',
				iKeyCode : 0x24,
				sHref    : ''
			}
		],

		keyNavigationInit : function() {

			var
				aLinkElements = document.getElementsByTagName('link'),
				oLinkElement,
				i = 0,
				j = 0
				;

			while(oLinkElement = aLinkElements[i++]) {

				j = 0;

				while(this.aNavigationLinks[j]) {
					if(this.aNavigationLinks[j++].sRel === oLinkElement.rel) {

						this.aNavigationLinks[j - 1].sHref = oLinkElement.href;
						break;

					}
				}

			}

			Common.Event.add(
				document,
				'keydown',
				function(oEvent) {

					var oEvent = Common.Event.normalize(oEvent);

					if(!oEvent.ctrlKey) {
						return true;
					}

					var
						aLinks = Common.Utils.aNavigationLinks,
						i = 0
						;

					while(aLinks[i++]) {
						if(aLinks[i - 1].iKeyCode == oEvent.iKeyCode &&
							aLinks[i - 1].sHref != ''
							) {
							document.location = aLinks[i - 1].sHref;
						}
					}

				}
				);

		},

		getUniqueId : function(oObject) {

			if(oObject.uniqueID) {
				return oObject.uniqueID;
			}

			if(!arguments.callee.counter) {
				arguments.callee.counter = 0;
			}

			oObject.uniqueID = '__unique_id_' + arguments.callee.counter++;

			return oObject.uniqueID;

		},

		isArray : function(oObject) {

			return Object.prototype.toString.call(oObject) === "[object Array]";

		}

	}

};


/* Extensions */

Common.Object.extend(
	Object.prototype,
	{

		hasOwnProperty : function(sPropertyName) {

			return !(
    			'undefined' == typeof this[sPropertyName] ||
    			this.constructor &&
    			this.constructor.prototype[sPropertyName] &&
    			this[sPropertyName] === this.constructor.prototype[sPropertyName]
    			);

		},

		foreach : function(fFunction) {

			for(var mKey in this) {
				if(this.hasOwnProperty(mKey)) {
					fFunction(mKey, this[mKey]);
				}
			}

		}

	}
	);

Common.Object.extend(
	Function.prototype,
	{

		inheritTo : function(
			oOverride,
			oStatic
			) {

			var
				Base = this,
				Result = function() {

					if(this.__constructor) {
						this.__constructor.apply(this, arguments);
					}

				},
				Inheritance = function() {}
				;

			Common.Object.extend(
				Result,
				Base
				);

			Inheritance.prototype = this.prototype;

			Result.prototype = new Inheritance();
			Result.prototype.constructor = Result;
			Result.prototype.__self = Result;

			if(oOverride) {

				for(var i in oOverride) {

					if(typeof(Result.prototype[i]) == 'function') {

						(function(sMethodName) {

							Result.prototype[sMethodName] = function() {

								var __baseSaved = this.__base;
								this.__base = Base.prototype[sMethodName];
								var mReturn = oOverride[sMethodName].apply(this, arguments);
								this.__base = __baseSaved;
								return mReturn;

							};

						})(i);

					}
					else {
						Result.prototype[i] = oOverride[i];
					}

				}

			}

			if(oStatic) {
				Common.Object.extend(
					Result,
					oStatic,
					true
					);
			}

			return Result;

		},

		delay : function(
			iDelay,
			oScope,
			aArgs
			) {

			var oThis = this;

			setTimeout(
				function() {

					oThis.call(oScope || window, aArgs);

				},
				iDelay
				);

		}

	}
	);

Common.Object.extend(
	Array.prototype,
	{

		isEmpty : function() {

			return this.length == 0;

		},

		remove : function(mElement) {

			for(var i = 0; i < this.length; i++) {

				if(this[i] == mElement){

					this.splice(i, 1);
					break;

				}

			}

		},

		indexOf : function(mElement) {

			for(var i = 0; i < this.length; i++) {
				if(this[i] == mElement) {
					return i;
				}
			}

			return -1;

		},

		indexOfByFunction : function(
			mElement,
			fCompareFunction
			) {

			if(!fCompareFunction) {
				return this.indexOf(mElement);
			}

			for(var i = 0; i < this.length; i++) {
				if(fCompareFunction(this[i], mElement)) {
					return i;
				}
			}

			return -1;

		},

		contains : function(
			mElement,
			fCompareFunction
			) {

			return this.indexOfByFunction(mElement, fCompareFunction) > -1;

		},

		filtrate : function(
			mElement,
			fCompareFunction
			) {

			var aResult = [];

			for(var i = 0; i < this.length; i++) {
				if(fCompareFunction(this[i], mElement)) {
					aResult.push(this[i]);
				}
			}

			return aResult;

		},

		intersect : function(aArrayWith) {

			var aResult = [];

			for(var i = 0; i < aArrayWith.length; i++) {
				if(this.contains(aArrayWith[i])) {
					aResult.push(aArrayWith[i]);
				}
			}

			return aResult;

		},

		union : function(aArrayWith) {

			var aResult = [].concat(this);

			for(var i = 0; i < aArrayWith.length; i++) {
				if(!this.contains(aArrayWith[i])) {
					aResult.push(aArrayWith[i]);
				}
			}

			return aResult;

		},

		subtract : function(aArrayWith) {

			var aResult = [].concat(this);

			for(var i = 0; i < aArrayWith.length; i++) {
				if(this.contains(aArrayWith[i])) {
					aResult.remove(aArrayWith[i]);
				}
			}

			return aResult;

		},

		unique : function() {

			var
				aResult = [],
				i = -1,
				mItem
				;

			while((mItem = this[++i]) != null) {
				if(!this[i].__marked) {

					this[i].__marked = true;
					aResult.push(mItem);

				}
			}

			while(mItem = this[--i]) {
				this[i].__marked = undefined;
			}

			return aResult;

		}

	}
	);

Common.Object.extend(
	String.prototype,
	{

		stripTags : function() {

			return this.replace(/<\/?[^>]+>/gi, '');

  		},

  		formatNumber : function(
  			sGroupSeparator,
  			sFractionSeparator
  			) {

  			var
				sGroupSeparator = sGroupSeparator || ' ',
				sFractionSeparator = sFractionSeparator || ',',
				iFractionIndex = this.indexOf('.'),
				sFraction = iFractionIndex > -1? this.substring(iFractionIndex + 1) : '',
				sNumber = iFractionIndex > -1? this.substring(0, iFractionIndex) : this
				;

			if(sNumber.length < 5) {
				return sNumber + (iFractionIndex > -1? sFractionSeparator + sFraction : '');
			}

			var sResult = '';

			while(sNumber.length > 3) {

				sResult = sNumber.substring(sNumber.length - 3) + (sResult.length > 0? sGroupSeparator : '') + sResult;
				sNumber = sNumber.substring(0, sNumber.length - 3);

			}

			sResult = sNumber + sGroupSeparator + sResult + (iFractionIndex > -1? sFractionSeparator + sFraction : '');

			return sResult;

  		}

	}
	);

Common.Object.extend(
	Number.prototype,
	{

		toFixed : function(iTo) {

			var aParts = this.toString().split('.', 2);

			if(!aParts[1]) {
				return this;
			}

			return aParts[0] + '.' + Math.round(aParts[1] / Math.pow(10, aParts[1].length - iTo));

		},

		formatNumber : function(
  			sGroupSeparator,
  			sFractionSeparator
  			) {

			return this.toString().formatNumber(
  				sGroupSeparator,
  				sFractionSeparator
  				);

		}

	}
	);

function Abstract() {

	throw('abstract class');

}

Common.Utils.StringBuffer = Abstract.inheritTo(
	{
		__constructor : function(sValue) {

			this.aBuffer = [];

			if(sValue) {
				this.append(sValue);
			}

		},

		append : function(sValue) {

			this.aBuffer.push(sValue);

			return this;

		},

		get : function() {

			return this.aBuffer.join('');

		},

		clear : function() {

			this.aBuffer = [];

			return this;

		}

	}
	);

document.documentElement.id = 'with-js';

Common.Event.add(
	window,
	'error',
	function() {

		var oBody = document.getElementsByTagName('body')[0];

		if(!oBody) {
			return;
		}

		Common.Class.add(
			oBody,
			'with-js-error'
			);

	}
	);

Common.Event.add(
	document,
	Common.Event.TYPE_DOM_CONTENT_LOADED,
	function() {

		Common.Utils.keyNavigationInit();

	}
	);