/*
	   Name: DropBox - A MooTools v1.1+ Object by Mike Reid (www.pixelchutes.com)
	Version: 0.1.9 Beta
	   Date: 11:49 AM MST 6/22/2007 
	Revised: 11:52 AM MST 1/9/2008

 * Overlay technique adapted from ThickBox 3.1
 * By Cody Lindley (http://www.codylindley.com)
 * Copyright (c) 2007 cody lindley
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/

var DropBox = new Class({
	initialize: function(element, options, styles ) {

		// Default options
		this.options = Object.extend({
			transition:		Fx.Transitions.Bounce.easeOut,
			duration:		1500,
			wait:			false,
			autodrop:		true,
			delay:			0,
			autodropif:		function(){ return 1; },
			start:			'topCenter',
			end:			'center',
			closeSelectors:	'.close',
			opacity:		true,
			// Overlay Options
			overlay:		true,
			overlay_id:		'db_overlay',
			overlay_img:	'assets/images/macFFBgHack.png',
			overlay_css:	true,
			// Callbacks
			showCallback:	function(){},
			hideCallback:	function(){}
		}, options || {} );
			
		// Default styles
		this.styles = Object.extend({
			opacity:	0,
			width:		'500px',
			height:		'300px',
			overflow:	'hidden',
			visibility: 'hidden',
			position:	'absolute'
		}, styles || {} );

		this.element = $(element);
		
		// Abort if element not found
		if( !$defined(this.element) ) return false;

		// Init some attributes
		this.isdefined = true, this.active = 0, this.startCoords = {}, this.endCoords = {};

		// Apply default styles first so we can pre-position properly
		this.element.setStyles( this.styles );
		
		// Inject needed CSS for overlay
		if( this.options.overlay && this.options.overlay_css ) this.injectCSS();
		
		// Set the coordinates
		this.setCoordinates();

		// Position the DropBox
		this.element.setStyles( this.startCoords );
				
		// Create the FX
		this.fx = new Fx.Styles( this.element, this.options );
		
		// Reset active DropBox on window resize
		window.addEvent('resize', function(){
		    if( this.active ) ( this.reset.bind(this) ).delay( 150 );
		    
		}.bind(this));
		
		// Active DropBox follow on scroll (MouseWheel)
		document.addEvents({
			'mousewheel': function(){	
		    	if( this.active ) ( this.reset.bind(this) ).delay( 150 ); 		    
			}.bind(this),
			
			'keypress': function(e){
				if ( window.event ){
					var keyCode = window.event.keyCode;
				}else{
					var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
				}
				// Hide DropBox on Escape key
				if( keyCode == 27 ) if( this.active ) this.hide();
			}.bind(this)
		});
				
		// Active DropBox follow on scroll (Scroll)
		/*window.addEvent('scroll', function(){
			if( this.active ) ( this.reset.bind(this) ).delay( 150 ); 
		});*/
		window.onscroll = function(){
			if( this.active ) ( this.reset.bind(this) ).delay( 150 ); 
		}.bind(this);
		
		// Close selector handling
		this.element.getElementsBySelector( this.options.closeSelectors ).addEvents({
			'click' : this.hide.bind(this)
		});
		
		// AutoDrop?
		if( this.options.autodrop )
			// Conditional AutoDrop?
			if( this.options.autodropif() )
				// Delayed AutoDrop?
				this.delayShow( this.options.delay );
	},
		
	show: function( callback ){
		if(typeof callback != 'function') callback = this.options.showCallback;
		this.active = 1;
		this.setCoordinates(); // double check implementation (ensure center is based on current view, not window)
		this.showOverlay();
		this.fx.start( ( ( this.options.opacity ) ? Object.extend( { opacity: 1 }, this.endCoords ) : this.endCoords ) ).chain(callback);
	},
		
	hide: function( callback ){
		if(typeof callback != 'function') callback = this.options.hideCallback;
		this.active = 0;
		this.fx.start( ( ( this.options.opacity ) ? Object.extend( { opacity: 0 }, this.startCoords ) : this.startCoords ) ).chain(callback);
		this.hideOverlay();
	},
		
	toggle: function( show_callback, hide_callback ){
		if( !this.active ) this.show( show_callback ); else this.hide( hide_callback );
	},
		
	fadeDestroy: function(){
		this.active = 0;
		this.fx.start( ( ( this.options.opacity ) ? Object.extend( { opacity: 0 }, {} ) : {} ) );
		this.hideOverlay();		
		
		// Delete following fade out
		(this.destroy.bind(this)).delay( this.options.delay+1 );
	},
		
	destroy: function(){
		this.isdefined = false;
		this.element.remove();
	},
		
	reset: function(){
		this.show();
	},
		
	delayShow: function( ms ){
		( this.show.bind(this) ).delay( ms );
	},
				
	setCoordinates: function(){
		if( !$defined(this.element) ) return false;
		this.setStart();
		this.setEnd();
	},
		
	setStart: function(){
		// topLeft topCenter topRight
		// centerLeft center centerRight
		// bottomLeft bottomCenter bottomRight
		
		// Determine starting coordinates
		switch( this.options.start )
		{			
			/* Top */			
			case 'topLeft': 		this.startCoords = { top: -1-this.getTrueHeight()+'px', left: -1-this.getTrueWidth()+'px' }; break;
			case 'topCenter': 		this.startCoords = { top: -1-this.getTrueHeight()+'px', left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'topRight': 		this.startCoords = { top: -1-this.getTrueHeight()+'px', left: 1+window.getSize().size.x+'px' }; break;
				
			/* Center */			
			case 'centerLeft': 		this.startCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: -1-this.getTrueWidth()+'px' }; break;
			case 'center': 			this.startCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'centerRight': 	this.startCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: 1+window.getSize().size.x+'px' }; break;
			
			case 'centerInsideRight': 	this.startCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: window.getSize().size.x-this.styles.width.toInt()+'px' }; break;
			
			/* Bottom */			
			case 'bottomLeft': 		this.startCoords = { top: 1+(window.getSize().size.y), left: -1-this.getTrueWidth()+'px' }; break;
			case 'bottomCenter': 	this.startCoords = { top: 1+(window.getSize().size.y), left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'bottomRight': 	this.startCoords = { top: 1+(window.getSize().size.y), left: 1+window.getSize().size.x+'px' }; break;
			
			case 'bottomQuarterInsideRight': 	this.startCoords = { top: ((window.getSize().size.y/4)*3)-(this.getTrueHeight()/2)+'px', left: window.getSize().size.x-this.styles.width.toInt()+'px' }; break;

			case 'bottomTwentiethInsideRight': 	this.startCoords = { top: ((window.getSize().size.y/20)*19)-(this.getTrueHeight()/2)+'px', left: window.getSize().size.x-this.styles.width.toInt()+'px' }; break;

			default: alert('Invalid start parameter value.'); break;
		}
		
		//IE
		if(window.ie)
		{
			//strict mode
			if(!(document.documentElement.scrollTop == 0))
			{
				offsetY = document.documentElement.scrollTop;
				offsetX = document.documentElement.scrollLeft;
			}
			//quirks mode
			else
			{
				offsetY = document.body.scrollTop;
				offsetX = document.body.scrollLeft;
			}
		}
		//w3c
		else
		{
			offsetX = window.pageXOffset;
			offsetY = window.pageYOffset;
		}
		
		this.startCoords.top = this.startCoords.top.toInt()+offsetY;
		this.startCoords.left = this.startCoords.left.toInt()+offsetX;
	},

	setEnd: function(){
		// Determine ending coordinates
		switch( this.options.end )
		{
			/* Top */			
			case 'topLeft': 		this.endCoords = { top: '0px', left: '0px' }; break;
			case 'topCenter': 		this.endCoords = { top: '0px', left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'topRight': 		this.endCoords = { top: '0px', left: (window.getSize().size.x)-(this.getTrueWidth())+'px' }; break;
				
			/* Center */			
			case 'centerLeft': 		this.endCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: '0px' }; break;
			case 'center': 			this.endCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'centerRight': 	this.endCoords = { top: (window.getSize().size.y/2)-(this.getTrueHeight()/2)+'px', left: (window.getSize().size.x)-(this.getTrueWidth())+'px' }; break;
			
			/* Bottom */			
			case 'bottomLeft': 		this.endCoords = { top: (window.getSize().size.y)-(this.getTrueHeight())+'px', left: '0px' }; break;
			case 'bottomCenter': 	this.endCoords = { top: (window.getSize().size.y)-(this.getTrueHeight())+'px', left: (window.getSize().size.x/2)-(this.getTrueWidth()/2)+'px' }; break;
			case 'bottomRight': 	this.endCoords = { top: (window.getSize().size.y)-(this.getTrueHeight())+'px', left: (window.getSize().size.x)-(this.getTrueWidth())+'px' }; break;
				
			default: alert('Invalid end parameter value.'); break;	
		}
		// Make relative to current view

		//IE
		if(window.ie)
		{
			//strict mode
			if(!(document.documentElement.scrollTop == 0))
			{
				offsetY = document.documentElement.scrollTop;
				offsetX = document.documentElement.scrollLeft;
			}
			//quirks mode
			else
			{
				offsetY = document.body.scrollTop;
				offsetX = document.body.scrollLeft;
			}
		}
		//w3c
		else
		{
			offsetX = window.pageXOffset;
			offsetY = window.pageYOffset;
		}

		this.endCoords.top = this.endCoords.top.toInt()+offsetY;
		this.endCoords.left = this.endCoords.left.toInt()+offsetX;
	},
		
	getTrueHeight: function(){
		return (
			this.element.getStyle('padding-top').toInt() +
			this.element.getStyle('padding-bottom').toInt() +
			this.element.getStyle('margin-top').toInt() +
			this.element.getStyle('margin-bottom').toInt() +
			this.element.getStyle('border-top').toInt() +
			this.element.getStyle('border-bottom').toInt() +
			this.element.getStyle('height').toInt()
		);
	},

	getTrueWidth: function(){
		return (
			this.element.getStyle('padding-left').toInt() +
			this.element.getStyle('padding-right').toInt() +
			this.element.getStyle('margin-left').toInt() +
			this.element.getStyle('margin-right').toInt() +
			this.element.getStyle('border-left').toInt() +
			this.element.getStyle('border-right').toInt() +
			this.element.getStyle('width').toInt()
		);
	},

	showOverlay: function(){
		if( !$defined(this.element) || !this.options.overlay || ($defined(this.overlay) && this.overlay.active) ) return false;

		this.overlay = new Element('div', {
			'id' : 'db_overlay',
			'class' :  ( this.db_detectMacXFF() ? 'db_overlayMacFFBGHack' : 'db_overlayBG' ),
			'events': {
				'click': this.hide.bind(this)
		    }
			,'styles': ( this.db_detectMacXFF() ? {} : {'opacity':.75} )
		});

		this.overlay.active = true;
		this.overlay.dropbox = this;
	
		this.overlay.injectInside( $E('body') );
				
	},

	hideOverlay: function(){		
	    
	    if( !$defined(this.overlay) ) return false;

    	// Fade out the overlay
	    this.overlay.effect('opacity', {duration: 500}).custom( this.overlay.getStyle('opacity'), 0 ).chain(function(){
	    	this.active = false;
	        if( $(this.id) ) $(this.id).remove();
	    }.bind(this.overlay));
	    	    
	},
		
	// Thanks to Cody Lindley
	db_detectMacXFF: function(){
	  var userAgent = navigator.userAgent.toLowerCase();
	  if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
	    return true;
	  }
	},
			
	injectCSS: function( styles ){

		if( typeof styles == 'undefined' ) 
			var styles = "#db_overlay { position: fixed; z-index:100; top: 0px; left: 0px; height:100%; width:100%; } .db_overlayMacFFBGHack {background: url("+this.options.overlay_img+") repeat;} .db_overlayBG { background-color:#000; filter:alpha(opacity=75); -moz-opacity: 0.75; opacity: 0.75; } * html #db_overlay { position: absolute; height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'); }";
		
		var stylesheet = new Element('style', {
			'class': 'db_styles',
			'type': 'text/css'
		}).injectInside( $E('head') );

		if(window.ie)
			document.styleSheets[document.styleSheets.length-1].cssText = styles;
		else
			stylesheet.appendText(styles);
	}
});

/*
Changelog:
		0.1.9 Beta
			- Added callback support
			- Simplified some code and removed redundant function referencing
			
		0.1.8 Beta
			- Updated overlay logic so now overlay usage is now optional
			- Added overlay (boolean), overlay_id (string), overlay_img (string), and overlay_css (boolean) parameters								
			- Updated overlay positioning to pure CSS // Adapted from Cody Lindley's ThickBox 3.1
				+ Accompanying 'macFFBgHack.png' image file for FireFox/Mac Overlay Hack
			- Removed resizeOverlay()
			
		0.1.7 Beta
			- Added centerInsideRight and bottomQuarterInsideRight starting coordinates
			- Added fadeDestroy function

		0.1.6 Beta
			- Added overlayColor, overlayOpacity, overlayZIndex parameters
			- Added error checking when defined DropBox is not found in the DOM
		
		0.1.5 Beta
			- Added multiple closeSelectors support
			- Added closeSelectors parameter
			- Added opacity overlay:  hasOverlay, showOverlay(), hideOverlay(), resizeOverlay()
			- Added scroll tracking
			- Added delay() to resize and scroll events
			
		0.1.4 Beta
			- IE compatible; didn't like offsetY|X 

		0.1.3 Beta
			- Dropped Fx.Scroll
			- Ensure centered...
			
		0.1.2 Beta
			- Fx.Scroll added to scroll to page top (DropBox) on long pages

		0.1.1 Beta
			- Update start/end coordinates on window resize, only reset if DropBox is active
			- Added toggle function

		0.1.0 Beta
			- Ability to disable auto drop
			- Ability to delay auto drop
			- Ability to conditionally auto drop
		
		0.0.5 Alpha
			- Added dynamic start/end positions 
				topLeft topCenter topRight
				centerLeft center centerRight
				bottomLeft bottomCenter bottomRight
			
		0.0.3 Alpha
			- Break-out of options / styles
			
		0.0.1 Alpha
			- Inception

*/
