
/*
Author   : Simon-Pierre Alepin
Created  : 2009/11/25
Modified : 2010/01/05
Version  : 0.5
simon@bamstrategy.com / spalepin@gmail.com

V0.4
Added method setLoadingImage( url )
-Will automatically set the content div with the loading image aligned centered X and Y

Added method setLoadingContent( html )
-Will set the content div html for customised loading

Added method showLoading()
-Simply show the loading content

//////////////////////////////////
new xOverlayControl(  );

#OPTIONS
-visibility [ visible | hidden ]
-valign [ top | bottom | middle | ]
-halign [ top | bottom | middle | ]
-position [ auto | { top, right, left, bottom  } ]
-color (overlay color)
-opacity [ ]
-overlay_id
-content_id
-duration_in
-duration_out

*/

var xOverlayControl = new Class(
{
	initialize : function( options )		
	{
		//Set the default options if values are missing
		this.getDefaultOptions( options );
		
		//By returning this, you allow the class to have chainable methods		
		return this;
	},
	
	getDefaultOptions : function( options )
	{
		this.valign       = ( options.valign == null || ( options.valign != 'top' && options.valign != 'middle' && options.valign != 'bottom' ) ) ? 'middle' : options.valign;
		this.halign       = ( options.halign == null || ( options.halign != 'left' && options.halign != 'middle' && options.halign != 'right' ) ) ? 'middle' : options.halign;
		this.color        = ( options.color == null )             ? '#000000' : options.color;
		this.opacity      = ( options.overlay_opacity == null )   ? '0.75'    : options.overlay_opacity;
		this.duration_in  = ( options.duration_in == null )       ? '250'     : options.duration_in;
		this.duration_out = ( options.duration_out == null )      ? '250'     : options.duration_out;
		this.position     = ( options.position == null ||  options.position == 'auto' ) ? 'auto' : options.position;
		this.isIE6		  = ( this.getIEBrowserVersion() == 6 )   ? true      : false;
		this.windowSizes  = this.xDocSize();
		this.contentAjax  = '';
		this.setSelect    = 'none';
		this.overlay      = null;	
		this.content      = null;
		this.contentHTML  = null;
		this.iframe       = null;
		
		this.loadingImageUrl = null;
		this.loading         = null;
	},
	
	getOverlayStyles : function()
	{
		var styles = 
		{
			position   : 'absolute',
			top        : '0px',
			left       : '0px',
			background : this.color,
			width      : '100%',
			height     : '100%',
			opacity    : this.opacity,
			display    : 'none',
			'z-index'  : '99998'			
		};
		
		return styles;
	},
	
	getContentStyles : function()
	{
		var styles = 
		{
			position   : 'absolute',
			top        : '0px',
			left       : '0px',
			display    : 'none',
			opacity    : 0,
			'z-index'  : '99999'
		};
		
		return styles;
	},	
	
	setOverlay : function( options )
	{
		var styles   = this.getOverlayStyles();		
		this.overlay = new Element( 'div', options );	
		this.overlay.setStyles( styles );
		
		//Binds this object with the function, that way you can kep using this.variableName
		var resizeCB = this.setOverlaySizeContentPosition.bind( this );
		
		//Call cuntion on window resize
		window.addEvent( 'resize', resizeCB );
		
		//The overlay div in the body DOM
		$( document.body ).adopt( this.overlay );
		
		//By returning this, you allow the class to have chainable methods
		return this;
	},	
	
	setContent : function( options )
	{
		if( this.content == null )	
		{
			//Create a new dev and insert it into the body DOM
			this.content = new Element( 'div' , options );		
			$( document.body ).adopt( this.content );
			this.contentHTML = options.html;
			//Get content predefined style and apply it to the div
			var styles   = this.getContentStyles();	
			this.content.setStyles( styles );
			
			//Set the Overlay/Content position/size
			this.setOverlaySizeContentPosition();
		}
		
		//By returning this, you allow the class to have chainable methods		
		return this;
	},
	
	setContentAjax : function( url, data, method, options )
	{
		//Create the content div if not already created
		this.setContent( options );
		
		//Empty the inner html of the content div
		this.content.set( 'html', '' );
		
		//Set default value if null
		var method  = ( method == '' || method == null || method == "undefined" ) ? 'post' : method;
		var data    = ( data == '' || data == null || data == "undefined" )       ? {}     : data;
		
		var setHTML = this.setContentHTML.bind( this );
		
		//Create new ajax request
		var req = new Request({
			method     : method,
			url        : url,
			data       : data,			
			onComplete : setHTML
		}).send();

		//By returning this, you allow the class to have chainable methods
		return this;
	},
	
	setContentHTML : function( html )
	{
		//Set the response text as innerhtml of the content div
		this.contentHTML = html;
		this.content.set( 'html', this.contentHTML );
		
		//Set the Overlay/Content position/size
		this.setOverlaySizeContentPosition();		
	},
	
	setLoadingImage : function( url )
	{
		this.loadingImageUrl = url;
		this.setLoadingContent( { id:'overlay_loading', html:'<table width="100%" height="100%"><tr><td><img src="'+ url +'" border="0" /></td></tr></table>' } );
		return this;
	},
	
	setLoadingContent : function( options )
	{
		//this.loading = html;
		this.loading = new Element( 'div' , options );		
		$( document.body ).adopt( this.loading );
		//this.contentHTML = options.html;
		//Get content predefined style and apply it to the div
		var styles   = this.getContentStyles();	
		this.loading.setStyles( styles );
		
		//Set the Overlay/Content position/size
		this.setOverlaySizeContentPosition();		
		
		return this;
	},	
	
	showLoading : function( duration, animateOverlay )
	{
		this.content.setStyle( 'display',  'none');
		this.showDiv( duration, this.loading, animateOverlay );
	},
	
	hideLoading : function( duration, animateOverlay )
	{
		this.content.setStyle( 'display',  'none');
		this.hideDiv( duration, this.content, animateOverlay );		
	},
	
	show : function( duration, animateOverlay )
	{
		try{this.loading.setStyle( 'display',  'none');}catch(e){}
		this.showDiv( duration, this.content, animateOverlay );
	},
	
	showDiv : function( duration, container, animateOverlay )
	{
		//This is to fix a bug in FF3 
		// Can't get the size of the element if display is set to none
		
		var aniOverlay = ( animateOverlay == null || animateOverlay == "undefined" ) ? true:false;
		container.setStyles( { display : 'block', opacity : 0 } );
		//alert('animateOverlay:'+animateOverlay+' aniOverlay:'+aniOverlay);
		//Set the Overlay/Content position/size
		this.setOverlaySizeContentPosition();
		
		this.setSelect = 'none';
		var time       = ( duration != null ) ? duration : this.duration_in;
		this.hideIE6Select();
		this.animateOpacity( container.get( 'id' ),  time, 0, 1, false );
		if( aniOverlay == true )
		{		
			//alert('ani');
			this.animateOpacity( this.overlay.get( 'id' ),  time, 0, this.opacity, false );
		}

		//By returning this, you allow the class to have chainable methods
		return this;		
	},

	hide : function( duration, animateOverlay )
	{
		try{this.loading.setStyle( 'display',  'none');}catch(e){}
		this.hideDiv( duration, this.content, animateOverlay );
	},
	
	hideDiv : function( duration, container, animateOverlay )
	{
		var aniOverlay = ( animateOverlay == null || animateOverlay == "undefined" || animateOverlay == true || animateOverlay == '' ) ? true:false;
		var time       = ( duration != null ) ? duration : this.duration_out;
		this.setSelect = 'block';
		this.animateOpacity( container.get( 'id' ),  time, 1, 0, true );
		if( aniOverlay == true )
		{
			this.animateOpacity( this.overlay.get( 'id' ),  time, this.opacity, 0, false );
		}
		
		//By returning this, you allow the class to have chainable methods		
		return this;		
	},

	hideIE6Select : function()
	{
		if( this.isIE6 == true )
		{
			$$( 'select' ).setStyle( 'display',  'none');
		}	
	},

	setIE6Select : function()
	{
		if( this.isIE6 == true )
		{
			try
			{
				$$( 'select' ).setStyle( 'display',  this.setSelect );
			}catch(e)
			{
			};			
		}	
	},
	
	animateOpacity : function( id, duration, from, to, isContentFix )
	{
		
		var contentFix = this.setIE6Select.bind( this );
				
		$( id ).setStyle( 'opacity', from );
		$( id ).setStyle( 'display', 'block' );
				
		if( isContentFix == true )
		{
			contentFix = this.setContentHideDisplayFix.bind( this );			
		}
		
		//Assign duration and onComplete options to tween method
		$( id ).set( 'tween', { duration:duration, onComplete: contentFix } );
		
		//Tween opacity for that element
		$( id ).tween( 'opacity', [ from, to ] );
	},
	
	setContentHideDisplayFix : function()
	{
		this.content.setStyles( { display : 'none', opacity : 0 } );
		this.setIE6Select();
	},
	
	setOverlaySizeContentPosition : function()
	{	
		this.setSizePosition( this.loading );
		this.setSizePosition( this.content );		
	},
	
	setSizePosition : function( container )
	{
		//container = ( container == null || container == "undefined" ) ? this.content:container;
		//Get the full height and full width of the current page
		this.windowSizes = this.xDocSize();
		
		//Set the width and height of the overlay
		this.overlay.setStyles( { width : this.windowSizes.w + 'px', height : this.windowSizes.h + 'px' } );
		
		//When the content is set and position is auto
		if( this.position == 'auto' && container != null )
		{
			var styles 		 = {};
			
			//Get content div width and height
			var contentSizes = container.getSize();
			
			//Get the viewable size of the browser window
			var viewableSize = $( window.document ).getSize();
			
			if( this.valign == 'middle' )
			{
				styles.top = ( ( viewableSize.y - contentSizes.y ) / 2 ) + $( window ).getScroll().y + 'px';
			}
			
			if( this.valign == 'bottom' )
			{
				styles.top = ( viewableSize.y - contentSizes.y )  +  $( window ).getScroll().y + 'px';
			}	
			
			if( this.halign == 'middle' )
			{
				styles.left  = ( ( viewableSize.x - contentSizes.x ) / 2 ) + $( window ).getScroll().x + 'px';
			}	
			
			container.setStyles( styles );
		}			
	},
	
	getIEBrowserVersion : function()
	{
		var appVer = navigator.appVersion.toLowerCase();
		var iePos  = appVer.indexOf( 'msie' );
		
		if( appVer.indexOf( 'msie' ) != -1 )
		{
			var is_minor = parseFloat( appVer.substring( iePos + 5, appVer.indexOf( ';', iePos ) ) );
			var version  = parseInt( is_minor );
		}
		
		if( navigator.appName.substring( 0,9 ) == 'Microsoft' )
		{
			return version;
		}
		else
		{
			return false;
		} 	
	},
	
	xDocSize : function()
	{
	  var b   = document.body, e = document.documentElement;
	  var esw = 0, eow = 0, bsw = 0, bow = 0, esh = 0, eoh = 0, bsh = 0, boh = 0;
	  
	  if( e ) 
	  {
		esw = e.scrollWidth;
		eow = e.offsetWidth;
		esh = e.scrollHeight;
		eoh = e.offsetHeight;
	  }
	  
	  if( b )
	  {
		bsw = b.scrollWidth;
		bow = b.offsetWidth;
		bsh = b.scrollHeight;
		boh = b.offsetHeight;
	  }
	  
	  return { w : Math.max( esw, eow, bsw, bow ), h : Math.max( esh, eoh, bsh, boh ) };
	}	

});

