MO = {};

MO.Dom = function()
{
	var ua = navigator.userAgent.toLowerCase();
	var isOpera = (ua.indexOf('opera') > -1);
	var isSafari = (ua.indexOf('safari') > -1);
	var isGecko = isMozilla = (ua.indexOf('gecko') > -1);
	var isFirefox = (ua.indexOf('firefox') > -1);
	var isIE = (window.ActiveXObject);
	var isIE7 = isIE && (ua.indexOf( 'msie 7' ) >= 0);

	var sDocMode = document.compatMode || '';	

	if ( document.ELEMENT_NODE == null )
	{
		document.ELEMENT_NODE = 1;
		document.TEXT_NODE = 3;
	}
	
	//uniqueid
	var sUniqueIdPrefix = 'MO_';
	var nUniqueId = 0;
	//
	//like YUI - branch at load time
	if( document.defaultView && document.defaultView.getComputedStyle )
	{//W3C
		getStyle = function( hEl, sStyle )
		{
			sStyle = MO.Util.toCamelCase( sStyle );
			var hStyle = document.defaultView.getComputedStyle( hEl, null );
			if( hStyle )
			{
				return hEl.style[ sStyle ] || hStyle[ sStyle ];
			}
		}
	}
	else if( document.documentElement.currentStyle && isIE )
	{//IE
		getStyle = function( hEl, sStyle )
		{
			sStyle = MO.Util.toCamelCase( sStyle );
			if( sStyle.toLowerCase() == 'opacity' )
			{
				var nOpacity = 100;
				try
				{
					nOpacity = hEl.filters['DXImageTransform.Microsoft.Alpha'].opacity;
				}
				catch( e )
				{
					try
					{
						nOpacity = hEl.filters( 'alpha' ).opacity;
					}
					catch( e )
					{
					}
				}
				return nOpacity / 100;
			}
			else
			{
				var hStyle = hEl.currentStyle;
				if( hStyle )
				{
					return hEl.style[ sStyle ] || hStyle[ sStyle ];
				}
			}
		}
	}
	else
	{
		getStyle = function( hEl, sStyle )
		{
			return hEl.style[ MO.Util.toCamelCase( sStyle ) ];
		}
	}
	
	if( isIE )
	{
		setStyle = function( hEl, sStyle, sValue )
		{
			if( sStyle == 'opacity' )
			{
				if( typeof hEl.style.filter == 'string' )
				{
					hEl.style.filter = 'alpha(opacity=' + parseFloat( sValue ) * 100 + ')';
					if( !hEl.currentStyle || !hEl.currentStyle.hasLayout )
					{
						hEl.style.zoom = 1;
					}
				}
			}
			else
			{
				sStyle = MO.Util.toCamelCase( sStyle );
				hEl.style[ sStyle ] = sValue;
			}
			return sValue;
		}
	}
	else
	{
		setStyle = function( hEl, sStyle, sValue )
		{
			sStyle = MO.Util.toCamelCase( sStyle );
			hEl.style[ sStyle ] = sValue;
			return sValue;
		}
	}

	//return an object
	var cDomObject =  {
		getUniqueId : function()
		{	
			var hDate = new Date();
			return sUniqueIdPrefix + (nUniqueId++) + "_" + hDate.getTime();
		},
		get : function( hElement )
		{
			if( !hElement )
			{
				return null;
			}
			//regular element
			if( hElement.nodeType )
			{
				return hElement;
			}
			else if( typeof( hElement ) == 'string' )
			{
				return document.getElementById( hElement );
			}
			else
			{
				var hElements = [];
				for( var nI = 0; nI < hElement.length; nI++ )
				{
					hElements[ hElements.length ] = MO.Dom.get( hElement[ nI ] );
				}
				var hCollection = new MO.Collection();
				return hCollection.copy( hElements );
			}
			return hElement;
		},
		getElementsBySelector : function( sSelector, hParentNode )
		{
			hParentNode = ( typeof hParentNode != 'undefined' ) ? hParentNode : document.body;
			var aSelectorData;
			var aAttributeData;
			var sAttribute;
			var sAREx;

			var hSelectorRegEx = /(([^\[]*)\[?(.*)\]$)|([a-z0-9_\-]*)/i;
			var hAttributeRegEx = /([a-z0-9_]*)([\*\^\$]?)(=?)(.*)/i;

			var hResultCollection = null;

			if( hSelectorRegEx.test( sSelector ) )
			{
				aSelectorData = hSelectorRegEx.exec( sSelector );
				var sSelector = aSelectorData[ 2 ] || aSelectorData[ 4 ];
				
				if( sSelector != '' )
				{
					hGroup = hParentNode.getElementsByTagName( sSelector.toLowerCase() )
					var hCollection = new MO.Collection();
					hCollection.copy( hGroup );

					if( aSelectorData[ 3 ] == '' )
					{
						hResultCollection = hCollection.filter( function( hElement, hString )
																{
																	return ( hElemet.tagName.toLowerCase() == hString );
																}, aSelectorData[ 2 ].toLowerCase() );
					}
					else
					{
						aAttributeData = hAttributeRegEx.exec( aSelectorData[ 3 ] );
						if( aAttributeData[ 1 ] == 'class' )
						{
							aAttributeData[ 1 ] = 'className'
						}
						hResultCollection = hCollection.filter( function( hElement, hAttributeData )
																{
																	//var sAttribute = hElement.getAttribute( hAttributeData.sAttrName );
																	var sAttribute = MO.Dom.getAttribute( hElement, hAttributeData.sAttrName ) ? MO.Dom.getAttribute( hElement, hAttributeData.sAttrName ) : MO.Dom.getProperty( hElement, hAttributeData.sAttrName );

																	if( sAttribute == null || sAttribute.length == 0 )
																	{
																		return false;
																	}

																	if( hAttributeData.sParam == '=' )
																	{
																		switch( hAttributeData.sModifier )
																		{
																			case '' :	if( sAttribute == hAttributeData.sAttrValue )
																						{
																							return true;
																						}
																						break;
																			case '^' :	if( sAttribute.indexOf( hAttributeData.sAttrValue ) == 0 )
																						{
																							return true;
																						}
																						break;
																			case '$' :	if( sAttribute.lastIndexOf( hAttributeData.sAttrValue ) == sAttribute.length - hAttributeData.sAttrValue.length )
																						{
																							return true;
																						}
																						break;
																			case '*' :	if( sAttribute.indexOf( hAttributeData.sAttrValue ) > -1 )
																						{
																							return true;
																						}
																						break;
																		}
																	}
																	else
																	{
																		return true;
																	}
																}, {sAttrName:aAttributeData[ 1 ], sAttrValue:aAttributeData[4], sParam:aAttributeData[ 3 ], sModifier:aAttributeData[ 2 ]} );
					}
				}
			}
			return hResultCollection;
		},
		getElementsByClassName : function( sClassName, hParentNode, sTagName )
		{
			var hClassElements = new Array();
			hNode = hParentNode || document.body;
			sTag = sTagName || '*';
			
			var hElements = hNode.getElementsByTagName( sTag );
			var nElementsLength = hElements.length;
			
			var hPattern = new RegExp( "(^|\\s)"+sClassName+"(\\s|$)" )
			for ( var nI = 0, nJ = 0; nI < nElementsLength; nI++ ) 
			{
				if ( hPattern.test( hElements[ nI ].className ) ) 
				{
					hClassElements.push( hElements[ nI ] );
				}
			}
			return hClassElements;
		},
		getParentBy : function( hEl, sAttribute, sValue )
		{
			var f = function( hEl )
			{
				var hP = hEl;
				var sVal = null;
				while ( hP && hP != document.documentElement )
				{
					sVal = MO.Dom.getAttribute( hP, sAttribute ) ? MO.Dom.getAttribute( hP, sAttribute ) : MO.Dom.getProperty( hP, sAttribute );
					if( sVal )
					{
						if( typeof sValue != undefined )
						{
							if( sValue == sVal )
							{
								return hP;
							}
						}
						else
						{
							return hP;
						}
					}
					hP = hP.parentNode ? hP.parentNode : null;
				}
			};
			return MO.Dom.apply( hEl, f );
		},
		//not bulletproof!!!
		// http://tobielangel.com/2007/1/11/attribute-nightmare-in-ie
		getAttribute : function( hEl, sAttribute )
		{
			var f = function( hEl )
			{
				return hEl.getAttribute( sAttribute, 2 );
			};
			return MO.Dom.apply( hEl, f );
		},
		getProperty : function( hEl, sProperty )
		{
			var f = function( hEl )
			{
				return hEl[ sProperty ];
			};
			return MO.Dom.apply( hEl, f );
		},
		getXY : function( hEl )
		{
            hEl = MO.Dom.get( hEl );
			var f = function( hEl )
			{
				if( hEl.parentNode === null || hEl.offsetParent == null || getStyle( hEl, 'display' ) == 'none' )
				{
					return false;
				}
				var hBox, hParentNode;
				var aPos = [];
				if( hEl.getBoundingClientRect )
				{
					hBox = hEl.getBoundingClientRect();
					var hDoc = document;
					if( !this.inDocument( hEl ) && parent.document != hDoc )
					{
						hDoc = parent.document;
						if( !this.isAncestor( hDoc.documentElement, hEl ) )
						{
							return false;
						}
					}
					return [ hBox.left + this.getScrollLeft(), hBox.top + this.getScrollTop() ];
				}
				else
				{
					hParentNode = hEl.offsetParent;
					aPos = [ hEl.offsetLeft, hEl.offsetTop ];
					if( hParentNode != hEl )
					{
						while( hParentNode )
						{
							aPos[ 0 ] += hParentNode.offsetLeft;
							aPos[ 1 ] += hParentNode.offsetTop;
							hParentNode = hParentNode.offsetParent;
						}
					}
					if( isSafari && this.getStyle( hEl, 'position' ) == 'absolute' )
					{
						aPos[ 0 ] -= document.body.offsetLeft;
						aPos[ 1 ] -= document.body.offsetTop;
					}		
				}
				//now accomodate for scrolling
				hParentNode = null;
				if( hEl.parentNode )
				{
					hParentNode = hEl.parentNode;
				}
				while( hParentNode && hParentNode.tagName.toUpperCase() != 'BODY' && hParentNode.tagName.toUpperCase() != 'HTML' )
				{
					if( this.getStyle( hParentNode, 'display' ) != 'inline' )
					{
						aPos[ 0 ] -= hParentNode.scrollLeft;
						aPos[ 1 ] -= hParentNode.scrollTop;
					}
					hParentNode = hParentNode.parentNode ? hParentNode.parentNode : null;
				}
				return aPos;
			};
			return MO.Dom.apply( hEl, f );
		},
		getX : function( hEl )
		{
			var f = function( hEl )
			{
				return this.getXY( hEl )[ 0 ];
			};
			return MO.Dom.apply( hEl, f );			
		},
		getX : function( hEl )
		{
			var f = function( hEl )
			{
				return this.getXY( hEl )[ 1 ];
			};
			return MO.Dom.apply( hEl, f );
		},
		//relative
		getPosition : function( hEl )
		{
			var f = function( hEl )
			{
				var aPos = [ 0, 0 ];
				while( hEl )
				{
					aPos[ 0 ] += hEl.offsetLeft;
					aPos[ 1 ] += hEl.offsetTop;
					hEl = hEl.offsetParent;
					if( hEl )
					{
						var sPos = MO.Dom.getStyle( hEl, 'position' );
						if( sPos == 'relative' || sPos == 'absolute' )
						{
							break;
						}
					}
				}
				return aPos;
			};
			return MO.Dom.apply( hEl, f );
		},
		getSize : function( hEl )
		{
			var f = function( hEl )
			{
				var aSize;
				if( MO.Dom.getStyle( hEl, 'display' ) != 'none' )
				{
					if( MO.Dom.isBorderBox( hEl ) )
					{
						aSize = [ hEl.offsetWidth, hEl.offsetHeight ];
					}
					else
					{
						aSize = [ hEl.clientWidth, hEl.clientHeight ];
					}
				}
				else
				{
					var sVis = MO.Dom.getStyle( hEl, 'visibility' );
					var sPos = MO.Dom.getStyle( hEl, 'position' );
					MO.Dom.setStyle( hEl, 'display', '' );
					if( MO.Dom.isBorderBox( hEl ) )
					{
						aSize = [ hEl.offsetWidth, hEl.offsetHeight ];
					}
					else
					{
						aSize = [ hEl.clientWidth, hEl.clientHeight ];
					}
					MO.Dom.setStyle( hEl, 'display', 'none' );
					MO.Dom.setStyle( hEl, 'visibility', sVis );
					MO.Dom.setStyle( hEl, 'position', sPos );					
				}
				return aSize;
			};
			return MO.Dom.apply( hEl, f );
		},
		setSize : function( hEl, aSize )
		{
			var f = function( hEl )
			{
				if( aSize[ 0 ] )
				{
					hEl.style.width = aSize[ 0 ] + 'px';
				}
				if( aSize[ 1 ] )
				{
					hEl.style.height = aSize[ 1 ] + 'px';
				}
			};
			return MO.Dom.apply( hEl, f );
		},
		getBorders : function( hEl, sBorders )
		{
			var f = function()
			{
			};
			return MO.Dom.apply( hEl, f );
		},
		getPaddings : function( hEl, sBorders )
		{
			var f = function()
			{
			};
			return MO.Dom.apply( hEl, f );
		},
		//pass an array [left, top], or you can leave one of the values null
		//yahoo has an retry option
		setXY : function( hEl, aPos, bRelative )
		{
			if( typeof bRelative == undefined )
			{
				bRelative = false;
			}

			var f = function( hEl )
			{
				var sStylePos = this.getStyle( hEl, 'position' );
				if( sStylePos == 'static' )
				{
					sStylePos = 'relative';
					this.setStyle( hEl, 'position', sStylePos );
				}
				
				var aCPos = this.getXY( hEl );
				if( aCPos === false ) 
				{
					return false;
				}
				
				var aCDelta = [ parseInt( this.getStyle( hEl, 'left' ) ), parseInt( this.getStyle( hEl, 'top' ) ) ];
				if( isNaN( aCDelta[ 0 ] ) )
				{
					aCDelta[ 0 ] = ( sStylePos == 'relative' ) ? 0 : hEl.offsetLeft;
				}
				if( isNaN( aCDelta[ 1 ] ) )
				{
					aCDelta[ 1 ] = ( sStylePos == 'relative' ) ? 0 : hEl.offsetTop;
				}
				
				if( aPos[ 0 ] !== null && !isNaN( aPos[ 0 ] ) )
				{
					if( !bRelative ) hEl.style.left = aPos[ 0 ] - aCPos[ 0 ] + aCDelta[ 0 ] + 'px';
					else hEl.style.left = aPos[ 0 ] + 'px';
				}
				if( aPos[ 1 ] !== null && !isNaN( aPos[ 1 ] ) )
				{
					if( !bRelative ) hEl.style.top = aPos[ 1 ] - aCPos[ 1 ] + aCDelta[ 1 ] + 'px';
					else hEl.style.top = aPos[ 1 ] + 'px';
				}
			};
			return MO.Dom.apply( hEl, f );
		},
		setX : function( hEl, nX )
		{
			var f = function( hEl )
			{
				return this.setXY( hEl, [ nX, null ] );
			};
			return MO.Dom.appply( hEl, f );
		},
		setY : function( hEl, nY )
		{
			var f = function( hEl )
			{
				return this.setXY( hEl, [ null, nY ] );
			};
			return MO.Dom.appply( hEl, f );
		},
		getViewportHeight : function() 
		{
			var nHeight = -1;
			if ( (sDocMode || isIE) && !isOpera ) 
			{
				switch ( sDocMode ) 
				{ // (IE, Gecko)
					case 'CSS1Compat': // Standards mode
						nHeight = document.documentElement.clientHeight;
					break;

					default: // Quirks
						nHeight = document.body.clientHeight;
				}
			} 
			else 
			{ // Safari, Opera
				nHeight = self.innerHeight;
			}

			return nHeight;
		},
		getViewportWidth : function() 
		{
			var nWidth = -1;
			if ( sDocMode || isIE ) 
			{ // (IE, Gecko, Opera)
				switch ( sDocMode ) 
				{
					case 'CSS1Compat': // Standards mode
						nWidth = document.documentElement.clientWidth;
					break;

					default: // Quirks
						nWidth = document.body.clientWidth;
				}
			} 
			else
			{ // Safari
				nWidth = self.innerWidth;
			}
			return nWidth;
		},
		getDocumentHeight : function()
		{
			var nHeight = -1;
			switch ( sDocMode ) 
			{ // (IE, Gecko)
				case 'CSS1Compat': // Standards mode
					nHeight = document.documentElement.scrollHeight;
				break;

				default: // Quirks
					nHeight = document.body.scrollHeight;
			}

			return Math.max( nHeight, this.getViewportHeight() );
		},
		getDocumentWidth : function()
		{
			var nWidth = -1;
			switch ( sDocMode ) 
			{ // (IE, Gecko)
				case 'CSS1Compat': // Standards mode
					nWidth = document.documentElement.scrollWidth;
				break;

				default: // Quirks
					nWidth = document.body.scrollWidth;
			}

			return Math.max( nWidth, this.getViewportWidth() );
		},
		getScrollTop : function()
		{
			return document.documentElement.scrollTop || document.body.scrollTop;
		},
		getScrollLeft : function()
		{
			return document.documentElement.scrollLeft || document.body.scrollLeft;
		},
        isAncestor: function( hParent, hEl ) 
		{
            hParent = MO.Dom.get( hParent );
            if ( !hParent || !hEl ) 
			{ 
				return false; 
			}
            
            var f = function( hEl ) {
                if ( hParent.contains && !isSafari ) 
				{ // safari "contains" is broken
                    return hParent.contains( hEl );
                }
                else if ( hParent.compareDocumentPosition ) 
				{
                    return !!( hParent.compareDocumentPosition( hEl ) & 16 );
                }
                else { // loop up and test each parent
                    var hP = hEl.parentNode;
                    
                    while ( hP ) 
					{
                        if ( hP == hParent )
						{
                            return true;
                        }
                        else if ( !hP.tagName || hP.tagName.toUpperCase() == 'HTML') 
						{
                            return false;
                        }
                        
                        hP = hP.parentNode;
                    }
                    return false;
                }     
            };
            return MO.Dom.apply( hEl, f );      
        },
        inDocument: function( hEl ) 
		{
            var f = function( hEl ) 
			{
                return this.isAncestor( document.documentElement, hEl );
            };
            
            return MO.Dom.apply( hEl, f );
        },
		isBorderBox : function( hEl )
		{
			return ( ( document.all && !isIE7 ) || 
					 ( isGecko && this.getStyle( hEl, 'MozBoxSizing' ) == 'border-box' ) ||
					 ( !isSafari && this.getStyle( hEl, 'boxSizing' ) == 'border-box' ) );
		},
		hasClass : function( hEl, sClassName )
		{
			sClassName = sClassName.replace( /^\s*|\s*$/g, '' );
			sClassName = sClassName.toLowerCase();
			var f = function( hEl )
			{
				if( hEl[ 'className' ].toLowerCase().indexOf( sClassName ) >= 0 )
				{
					return true;
				}
				else
				{
					return false;
				}
			};
			return MO.Dom.apply( hEl, f );
		},
		addClass : function( hEl, sClassName )
		{
			sClassName = sClassName.replace( /^\s*|\s*$/g, '' );
			var f = function( hEl )
			{
				if( MO.Dom.hasClass( hEl, sClassName ) )
				{
					return;
				}
				else
				{
					hEl.className = [ hEl[ 'className' ], sClassName ].join( ' ' );
				}
			}
			return MO.Dom.apply( hEl, f );
		},
		removeClass : function( hEl, sClassName )
		{
			sClassName = sClassName.replace( /^\s*|\s*$/g, '' );
			var sClassRegExp = new RegExp( '(^|\\s+)' + sClassName + '(\\s+|$)', 'g' );
			var f = function( hEl )
			{
				if( !MO.Dom.hasClass( hEl, sClassName ) )
				{
					return;
				}
				else
				{
					hEl[ 'className' ] = hEl[ 'className' ].replace( sClassRegExp, ' ' );
				}
			}
			return MO.Dom.apply( hEl, f );
		},
		getClasses : function( hEl, sClassName )
		{
			//trim
			sClassName = sClassName.replace( /^\s*|\s*$/g, '' );
			var f = function( hEl )
			{
				var sClassNames = hElement.className;
				var aClassNames = sClassNames.split( ' ' );
				if( typeof aClassNames != 'object' )
				{
					aClassNames = [ sClassNames ];
				}
				for( var nI = 0; nI < aClassNames.length; nI++ )
				{
					//trim
					aClassNames[ nI ] = aClassNames[ nI ].replace( /^\s*|\s*$/g, '' );
					if( aClassNames[ nI ].indexOf( sClassName ) < 0 )
					{
						delete( aClassNames[ nI ] );
					}
				}
				return aClassNames.join( ' ' ).replace( /^\s*|\s*$/g, '' ).split( ' ' );
			};
			
		},
		getStyle : function( hEl, sStyleSelector )
		{
			var f = function( hEl )
			{
				return getStyle( hEl, sStyleSelector );
			}
			return MO.Dom.apply( hEl, f );
		},
		setStyle : function( hEl, sStyleSelector, sStyleValue )
		{
			var f = function( hEl )
			{
				return setStyle( hEl, sStyleSelector, sStyleValue );
			}
			return MO.Dom.apply( hEl, f );
		},
		apply : function( hElements, hFunction )
		{
			if( !hElements )
			{
				return null;
			}
			else if( hElements.tagName && !hElements.length )
			{
				return hFunction.call( MO.Dom, hElements );
			}
			else if( typeof hElements == 'string' )
			{
				return hFunction.call( MO.Dom, MO.Dom.get( hElements ) );
			}
			else if( hElements.apply )
			{ //this is a collection
				return hElements.apply( hFunction, MO.Dom );
			}
			else
			{ //assume we have an array, so we create a collection
				var hCollection = new MO.Collection();
				hCollection.copy( hElements );
				return hCollection.apply( hFunction, MO.Dom );
			}
		}
	}
	return cDomObject;
}();

MO.DomExt = function()
{
	var CH_BORDERS = { 'l':'borderLeftWidth', 'r':'borderRightWidth', 't':'borderTopWidth', 'b':'borderBottomWidth' };
	var CH_PADDINGS = { 'l':'paddingLeft', 'r':'paddingRight', 't':'paddingTop', 'b':'paddingBottom' };
	var CH_MARGINS = { 'l':'marginLeft', 'r':'marginRight', 't':'marginTop', 'b':'marginBottom' };
	
	var hDomExt = {
		getAllNodeText : function( hEl )
		{
			var f = function( hEl )
			{
				var sText = '';
				for( var nI = 0; nI < hEl.childNodes.length; nI++ )
				{
					if( hEl.childNodes[ nI ].nodeType == document.TEXT_NODE )
					{
						sText += hEl.childNodes[ nI ].nodeValue;
					}
					else
					{
						sText += MO.DomExt.getAllNodeText( hEl.childNodes[ nI ] );
					}
				}
				return sText;
			};
			return MO.Dom.apply( hEl, f );
		},
		getBorderWidth : function( hEl, sBorder )
		{
			var f = function( hEl )
			{
				var nR = 0;
				for( var hI in CH_BORDERS )
				{
					if( sBorder.indexOf( hI ) >=0 )
					{
						nR += parseInt( MO.Dom.getStyle( hEl, CH_BORDERS[ hI ] ) );
					}
				}
				return nR;
			};
			return MO.Dom.apply( hEl, f );			
		},
		getPaddingWidth : function( hEl, sPadding )
		{
			var f = function( hEl )
			{
				var nR = 0;
				for( var hI in CH_PADDINGS )
				{
					if( sPadding.indexOf( hI ) >=0 )
					{
						nR += parseInt( MO.Dom.getStyle( hEl, CH_PADDINGS[ hI ] ) );
					}
				}
				return nR;
			};
			return MO.Dom.apply( hEl, f );			
		},
		getMarginWidth : function( hEl, sMargin )
		{
			var f = function( hEl )
			{
				var nR = 0;
				for( var hI in CH_PADDINGS )
				{
					if( sMargin.indexOf( hI ) >=0 )
					{
						nR += parseInt( MO.Dom.getStyle( hEl, CH_MARGINS[ hI ] ) );
					}
				}
				return nR;
			};
			return MO.Dom.apply( hEl, f );			
		},		initPositioned : function( hEl, f )
		{
			var f = function( hEl )
			{
				var sPos = MO.Dom.getStyle( hEl, 'position' );
				if( !sPos || sPos == 'static' )
				{
					MO.Dom.setStyle( hEl, 'position', 'relative' );
					//MO.Dom.setXY( hEl, [ 0, 0 ] );
				}
			}
			return MO.Dom.apply( hEl, f );			
		},
		//rethink this
		setAbsolutePositioned : function( hEl )
		{
			var f = function( hEl )
			{
				var sPos = MO.Dom.getStyle( hEl, 'position' );
				if( sPos == 'absolute' )
				{
					return false;
				}
				//var aPos = MO.Dom.getPosition( hEl );
				var aPos = MO.Dom.getXY( hEl );
				var aSize = MO.Dom.getSize( hEl );
				MO.Dom.setStyle( hEl, 'position', 'absolute' );
				MO.Dom.setXY( hEl, aPos );
				MO.Dom.setSize( hEl, [ aSize[ 0 ], aSize[ 1 ] ] );
			};
			return MO.Dom.apply( hEl, f );
		},
		setRelativePositioned : function( hEl )
		{
		}
	};
	return hDomExt;
}();

MO.Event = function()
{
	var getReal = function( hE )
	{
		if( hE )
		{
			return hE.nodeType == document.TEXT_NODE ? hE.parentNode : hE;
		}
		else
		{
			return null;
		}
	};

	var hEvent = {
		//save and cache the loaded events so later they can be unloaded
		addEvent : function()
		{
			if( window.addEventListener )
			{
				return function( hEl, sEv, hHandler, bCapture )
				{
					hEl.addEventListener( sEv, MO.Event.encapsulateEventHandler( hHandler ), bCapture );
				};
			}
			else if( window.attachEvent )
			{
				return function( hEl, sEv, hHandler, bCapture )
				{
					hEl.attachEvent( 'on' + sEv, MO.Event.encapsulateEventHandler( hHandler ) );
				};
			}
			else 
			{
				return function()
				{
				};
			}
		}(),
		removeEvent : function()
		{
			if ( window.removeEventListener ) 
			{
				return function ( hEl, sEv, hHandler, bCapture )
				{
					hEl.removeEventListener( sEv, hHandler, bCapture );
				};
			} 
			else if ( window.detachEvent )
			{
				return function( hEl, sEv, hHandler, bCapture ) 
				{
					hEl.detachEvent( 'on' + sEv, hHandler );
				};
			} 
			else 
			{
				return function(){};
			}
		},
		encapsulateEventHandler : function( hHandler )
		{
			return function( hE )
			{
				hE = MO.Event.getEvent( hE );
				hHandler.call( hE.target, hE.e );
			};
		},
		getEvent : function( hE )
		{
			hE = hE || window.event;
			return 	{
				e: hE,
				type: hE.type,
				button: ( hE.which ) ? hE.which : hE.button,
				key: ( hE.which ) ? hE.which : hE.keyCode,
				target: getReal( hE.target || hE.srcElement ),
				currentTarget: getReal( hE.currentTarget || hE.srcElement ),
				from: ( hE.originalTarget ) ? hE.originalTarget : ( hE.fromElement ) ? hE.fromElement : null,
				to: ( hE.currentTarget ) ? hE.currentTarget : ( hE.toElement ) ? hE.toElement : null,
				x: ( hE.layerX ) ? hE.layerX : ( hE.offsetX ) ? hE.offsetX : null,
				y: ( hE.layerY ) ? hE.layerY : ( hE.offsetY ) ? hE.offsetY : null,
				screenX: hE.screenX,
				screenY: hE.screenY,
				pageX: ( hE.pageX ) ? hE.pageX : ( hE.clientX + ( document.documentElement.scrollLeft || document.body.scrollLeft ) ),
				pageY: ( hE.pageY ) ? hE.pageY : ( hE.clientY + ( document.documentElement.scrollTop || document.body.scrollTop ) )
			}			
		},
		cancelEvent : function( hE )
		{
			this.cancelBubble( hE );
			this.preventDefault( hE );
			return false;
		},
		cancelBubble : function( hE )
		{
			if( hE.stopPropagation )
			{
				hE.stopPropagation();
			}
			else
			{
				hE.canceBubble = true;
			}
		},
		preventDefault : function( hE )
		{
			if( hE.preventDefault )
			{
				hE.preventDefault();
			}
			else
			{
				hE.returnValue = false;
			}
		},
		DomLoaded : 
		{
			onload: [],
			loaded: function()
			{
				if ( arguments.callee.done )
				{
					return
				}
				arguments.callee.done = true
				for ( i = 0; i < MO.Event.DomLoaded.onload.length; i++ )
				{
					MO.Event.DomLoaded.onload[i]()
				}
			},
			load: function( handler )
			{
				this.onload.push( handler )
				
				if ( document.addEventListener ) 
				{
					document.addEventListener( "DOMContentLoaded", MO.Event.DomLoaded.loaded, null )
				}
				if ( /KHTML|WebKit/i.test( navigator.userAgent ) )
				{ 
					var _timer = setInterval( function()
					{
						if ( /loaded|complete/.test( document.readyState ) )
						{
							clearInterval( _timer )
							delete _timer
							MO.Event.DomLoaded.loaded()
						}
					}, 10 )
				}
				/*@cc_on @*/
				/*@if (@_win32)
				var proto = "src='javascript:void(0)'"
				if ( location.protocol == "https:" ) proto = "src=//0"
				document.write( "<scr"+"ipt id=__ie_onload defer " + proto + "><\/scr"+"ipt>" )
				var script = document.getElementById( "__ie_onload" )
				script.onreadystatechange = function() 
				{
				    if (this.readyState == "complete") 
					{
						MO.Event.DomLoaded.loaded()
					}
				}
				/*@end @*/
			   MO.Event.addEvent( window, 'load', MO.Event.DomLoaded.loaded );
			}
}
	};
	return hEvent;
}();

MO.Event.customEvent = function( sType, hScope )
{
	this.sType = sType;
	this.hScope = hScope || window;
	//an array with subscribed listeners
	this.subscribers = [];
	this.returnValue = true;
	this.cancelBubble = false;
	this.eventData = null;
}

MO.Event.customEvent.error = function()
{
	this.description = "custom event error";
}

MO.Event.customEvent.prototype = {
	fire : 	function()
			{
				var hResult = true;
				this.returnValue = true;
				this.cancelBubble = false;
				this.eventData = null;
				var hArgs = [];
				var nLen = this.subscribers.length;
				if( nLen == 0 )
				{
					return hResult;
				}
				var nI;
				for( nI = 0; nI < arguments.length; nI++ )
				{
					hArgs.push( arguments[ nI ] );
				}

				for( nI = 0; nI < nLen; nI++ )
				{
					if( this.subscribers[ nI ] )
					{
						var hScope = this.subscribers[ nI ].bOverride ? this.subscribers[ nI ].hObject : this.hScope;
						hResult = this.subscribers[ nI ].hListener.call( hScope, this, hArgs, this.subscribers[ nI ].hObject );
						if( this.cancelBubble )
						{
							break;
						}
					}
				}
				return hResult;
			},
	subscribe	:
			function( hListener, hObject, bOverride )
			{
				if( !hListener )
				{
					throw( new MO.Event.customEvent.error() )
				}
				this.subscribers.push( new MO.Event.eventSubscriber( hListener, hObject, bOverride ) );
			},
	unsubscribe	:
			function( hListener, hObject )
			{
				var nLen = this.subscribers.length;
				for( var nI = 0; nI < nLen; nI++ )
				{
					if( this.subscribers[ nI ] && this.subscribers[ nI ].contains( hListener, hObject ) )
					{
						this._delete( nI );
						return true;
					}
				}
				return false;
			},
	_delete		:
			function( nI )
			{
				var hSub = this.subscribers[ nI ];
				if( hSub )
				{
					delete hSub.hListener;
					delete hSub.hObject;
				}
				this.subscribers.splice( nI, 1 );
			}
}

MO.Event.eventSubscriber = function( hListener, hObject, bOverride )
{
	this.hListener = hListener;
	this.hObject = hObject || null;
	this.bOverride = bOverride;
}

MO.Event.eventSubscriber.prototype.contains = function( hListener, hObject )
{
	if( this.hListener == hListener && this.hObject == hObject )
	{
		return true;
	}
	return false;
}

MO.CSS = function()
{
	var hCSS = {
		getStyleSheets : function()
		{
			return document.styleSheets;
		},
		getStyleSheetByTitle : function( sTitle )
		{
			for( var nI = 0; nI < document.styleSheets.length; nI++ )
			{
				if( document.styleSheets[ nI ].title == sTitle )
				{
					return this.getStyleSheet( document.styleSheets[ nI ] );
				}
			}
		},
		getStylesheetById : function( sId )
		{
			var hSS = MO.Dom.get( sId );
			return this.getStyleSheet( hSS );
		},
		isStyleSheet : function( hElement )
		{
			if( hElement && ( hElement.tagName == 'LINK' || hElement.tagName == 'STYLE' || hElement.sheet || hElement.styleSheet ) )
			{
				return true;
			}
			return false;
		},
		getStyleSheet : function( hStyleSheetNode )
		{
			if( this.isStyleSheet( hStyleSheetNode ) )
			{
				//sheet - Mozilla, styleSheet - IE
				return hStyleSheetNode.sheet || hStyleSheetNode.styleSheet;
			}
			else
			{
				return null;
			}
		},
		getRules : function( hStyleSheet )
		{
			//cssRules - Mozilla, rules - IE
			return hStyleSheet.cssRules || hStyleSheet.rules;
		},
		getImportedStyleSheet : function( hStyleSheet, nIndex )
		{
			var hSSObject = hStyleSheet;
			if( hSSObject )
			{
				var hImports;
				if( hSSObject.imports )
				{
					hImports = new MO.Collection();
					hImports.copy( hSSObject.imports );
				}
				else
				{
					var hStyleRules = hSSObject.cssRules;
					var hRules = new MO.Collection();
					hRules.copy( hStyleRules );
					var f = function( hRule )
					{
						if( hRule.type == hRule.IMPORT_RULE )
						{
							return true;
						}
						else
						{
							return false;
						}
					}
					hImports = hRules.filter( f );
				}
				var hSS = hImports.getAt( nIndex );
				return hSS.styleSheet || hSS;
			}
			else
			{
				return null;
			}
		},
		getRule : function( hStyleSheet, sSelector )
		{
			var hRules = new MO.Collection();
			hRules.copy( this.getRules( hStyleSheet ) );
			var f = function( hRule )
			{
				if( hRule.selectorText == sSelector )
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			hRules = hRules.filter( f );
			return hRules.getAt( 0 );
		}
	};
	return hCSS;
}();

MO.Object = function()
{
	var cObject = {
		//create a subclas of a class,
		//you can call the base class contructor through baseContructor.call
		//or call the base class through baseClass property
		inherit : function( cBaseClass, cSubClass )
		{
			inherit = function() {};
			inherit.prototype = cBaseClass.prototype;
			cSubClass.prototype = new inherit();
			cSubClass.prototype.constructor = cSubClass;
			cSubClass.baseConstructor = cBaseClass;
			cSubClass.baseClass = cBaseClass.prototype;
		},
		extend : function( hSource, hDestination )
		{
			for( var hProperty in hDestination )
			{
				hSource[ hProperty ] = hDestination[ hProperty ];
			}
			return hSource;
		},
		callInContext : function( hObject, hFunction )
		{
			return function()
			{
				var hArguments = aruments.splice( 0, 2 );
				hFunction.call( hObject, hArguments );
			}
		}
	};
	return cObject;
}();

MO.Util = function()
{
	var hUtil = 
	{
		toCamelCase : function( sString )
		{
			sString = sString.replace( /[\-\.]/g, ' ' );
			var aStr = sString.split( ' ' );
			for( var nI = 0; nI < aStr.length; nI++ )
			{
				aStr[ nI ].replace( /^\s+|\s+$/, '' );
				if( nI > 0 )
				{
					aStr[ nI ] = aStr[ nI ].charAt( 0 ).toUpperCase() + aStr[ nI ].substr( 1 );
				}
			}
			return aStr.join( '' );
		}
	}
	return hUtil;
}();

MO.Element = function()
{
	var hElement = {
	};
	return hElement;
}();

MO.Collection = function()
{
	this.hCollection = [];
};

MO.Collection.prototype = {
	copy : function( hArray )
	{
		for( var nI = 0; nI < hArray.length; nI++ )
		{
			this.hCollection[ this.hCollection.length ] = hArray[ nI ];
		}
		return this;
	},
	append : function( hElement )
	{
		this.hCollection.push( hElement );
		return this;
	},
	getAt : function( nIndex )
	{
		if( this.hCollection.length <= nIndex )
		{
			return null;
		}
		else
		{
			return this.hCollection[ nIndex ];
		}
	},
	getLength : function()
	{
		return this.hCollection.length;
	},
	apply : function( hFunction, hScope )
	{
		hScope = hScope || this;
		var hNewCollection = new MO.Collection();
		for( var hI in this.hCollection )
		{
			if( typeof this.hCollection[ hI ] != 'function' )
			{
				hNewCollection.append( hFunction.call( hScope, this.hCollection[ hI ] ) );
			}
		};
		return hNewCollection;
	},
	filter : function( hFilterFunction, hFilter, hScope )
	{
		hScope = hScope || this;
		var hNewCollection = new MO.Collection();
		for( var hI in this.hCollection )
		{
			if( typeof this.hCollection[ hI ] != 'function' && hFilterFunction.call( hScope, this.hCollection[ hI ], hFilter ) )
			{
				hNewCollection.append( this.hCollection[ hI ] );
			}
		}
		return hNewCollection;
	}
}

MO.DelayedExecution = function( hFunction, hScope, hArguments )
{
	this.hTimeout = null;
	this.hFunction = hFunction;
	this.hScope = hScope;
	this.hArguments = hArguments;
	this.delay = function( nTimeDelay )
	{
		if( this.hTimeout )
		{
			window.clearTimeout( this.hTimeout );
		}
		var hF = this.hFunction;
		var hS = this.hScope;
		var hA = this.hArguments;
		this.hTimeout = window.setTimeout( function() { hF.call( hS, hA ); }, nTimeDelay );
	}
	this.cancel = function()
	{
		if( this.hTimeout != null )
		{
			window.clearTimeout( this.hTimeout );
			this.hTimeout = null;
		}
	}
};

MO.PeriodicalExecution = function( hFunction, hScope, hArguments )
{
	this.hTimeout = null;
	this.hFunction = hFunction;
	this.hScope = hScope;
	this.hArguments = hArguments;
	this.start = function( nTimeDelay )
	{
		if( this.hTimeout )
		{
			window.clearTimeout( this.hTimeout );
		}
		var hF = this.hFunction;
		var hS = this.hScope;
		var hA = this.hArguments;
		var hPE = this;
		this.hTimeout = window.setTimeout( function() { hF.call( hS, hA ); hPE.start(); }, nTimeDelay );
	}
	this.stop = function()
	{
		if( this.hTimeout != null )
		{
			window.clearTimeout( this.hTimeout );
			this.hTimeout = null;
		}
	}
}
