/**
 * @author Matthew Grdinic - info@formboss.net
 * @class: Callout
 * @category Display Logic
 * @classDescription A class to implemennt 'lightbox' logic for image and other media.
 * @version 1.0
 * @date October/18/2009
 * 
 * USAGE
 * 1. Include scripts on your page:
<script src="js/prototype.js" type="text/javascript"></script>
<script src="js/scripty/scriptaculous.js?load=effects" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="js/callout/callout.css"/>
<script src="js/callout/callout.js" type="text/javascript"></script>
 * 
 * Change all leading paths to match your own.
 * 
 * 
 * 2. Assign element callout class and type definition
 *
 * IMAGE
 *	<img src="callout-1_thumb.png" width="347" height="241" class="js-callout" type="image" dimx="596" dimy="396" scale="false" />
 * 
 * FLASH VIDEO (.swf)
 * <img src="video/conditional-page_thumb.png" width="277" height="186" class="js-callout" type="flash" dimx="804" dimy="540" scale="false" />
 *
 * 3. Element Types
 * 
 * -Images
 * Images need to have a thumb and full size component. The thumb
 * must be named the same as the full-size, but with _thumb appended to 
 * the file name.
 */
var Callout = Class.create();

Callout.prototype = {
		
	// vars for the class 
	_active:false,
	_ready:true, // can we open an item?
	_scaleFactory: new Array(),
	
	// init the prototype
	initialize:function(options){
		this.options = Object.extend({
			scaleInSpeed:.3,
			scaleOutSpeed:.3,
			fadeInSpeed:.02, // default .01
			fadeOutSpeed:.3,
			opacity:0.8,
			padding:0, // set to 1 to act as border
			animationStyle:'default',
			scaleToCenter:true,
			className:'js-callout',
			_tpl: { 
				overlay :'<div id="callout_overlay" style="background-image: url(/js/callout/black.png); display:none; opacity:0; width:100%; cursor:pointer; "/>',
				viewer : '<div id="callout_viewer" style="width:1px; height:1px; padding:10px; position:absolute; top:1px; left:1px; display:none; padding:0px; border:0px #ededed solid; background-color:#acacac; z-index:999;"></div>'
			}

		} , options || {} );
		
		this._bindElements();
		this._insertOverlay();
		this._insertViewer();
		
	},
	
	_insertOverlay:function(){
		
		if (typeof container == 'undefined' ) container = document.body;
		if (null == (this.container = $(container))) throw("container is not valid");
	
		container.insert(this.options._tpl.overlay);
		
		// set height
		$('callout_overlay').setStyle({height:document.body.offsetHeight + 'px'});
		
		// event listener
		$('callout_overlay').observe('click', this._activate.bindAsEventListener(this, 'hide'));
	},
	
	_insertViewer: function(){
		
		if (typeof container == 'undefined' ) container = document.body;
		if (null == (this.container = $(container))) throw("container is not valid");
		
		container.insert(this.options._tpl.viewer);
	},
	
	_bindElements:function(){
		$$('.'+this.options.className).each(function(i){
			// add observer
			i.observe('click', this._activate.bindAsEventListener(this, 'show'));
			// add cursor
			i.setStyle({cursor:'pointer'});
		}.bind(this));
	},
	
	_activate:function(e, action){
		e.stop(); // only 1 event!
		if(!this._ready) { return false; }
		if(this._active){
			this._hide(e);
		} else {
			this._show(e);
		}
	},
	
	_show:function(e){
		var elt = e.element();
		this._active = true;
		this._ready = false;
		
		// build item
		eltName = '';
		attr = elt.getAttribute('type');
		
		switch(attr){
			case 'image' :
				newEltName = elt.getAttribute('src').replace('_thumb', '');
				
				// scale?
				scale = elt.getAttribute('scale');
				
				// if not set (true by default for images)
				scale == null ? scale = 'true' : scale = scale;
				
				var endDims;
				startDims = elt.getDimensions();
				
				// store start dims for scale down
				p = elt.cumulativeOffset();
				this._scaleFactory = {width:startDims.width, height:startDims.height, left:p.left, top:p.top};
			

				// pre-load new item if needed
				loaded = false;
				
				for(i=0; i < document.images.length; i++){
					if(document.images[i].src == newEltName){
						loaded = true;
						sendDims = {width:document.images[i].width, height:document.images[i].height};
					}
				}

				if(!loaded){
					
					// showing loader
					
					var img = new Image();
					img.src = newEltName;
					
					new PeriodicalExecuter(function(i){
						if(img.naturalWidth != "undefined" && img.complete){
							i.stop();
							
							endDims = {width:img.width, height:img.height};
							
							this._display(elt, newEltName, startDims, endDims, scale);
							
						}
					}.bind(this), .1);

					// hide loader
				}

				break;
				
			case 'flash' :
				
				// replace name
				newEltName = elt.getAttribute('src').replace('_thumb', '');
				newEltName = newEltName.split('.')[0] + '.swf';
				
				// scale?
				scale = elt.getAttribute('scale');
				
				// if not set (false by default for swf)
				scale == null ? scale = 'false' : scale = scale;
				
				startDims = elt.getDimensions();
				endDims = {width:elt.getAttribute('dimx'), height:elt.getAttribute('dimy')};
				
				// store start dims for scale down
				p = elt.cumulativeOffset();
				this._scaleFactory = {width:startDims.width, height:startDims.height, left:p.left, top:p.top};

				this._display(elt, newEltName, startDims, endDims, scale);
				
				break;
		}

		
	},
	
	_display: function(elt, newEltName, startDims, endDims, scale){
		
		// get item type
		attr = elt.getAttribute('type');
		
		switch(attr){
		
			case 'image' :
			
				// place callout viewer on top of everything
				$('callout_viewer').setStyle({zIndex:995});

				// inject hi-res item into viewer
				newItem = new Element('img', 
						{'class':this.options.className, 'src':newEltName}
				).observe('click', this._activate.bindAsEventListener(this, 'hide'));
				
				// image inherits width and height for easy resize
				newItem.setStyle({position:'relative', width:'100%', height:'100%', cursor:'pointer'});
				
				$('callout_viewer').clonePosition(elt);
				
				// insert item into tpl
				$('callout_viewer').update(newItem);
				
				// 'replace' current item (just showing in exact same spot)
				$('callout_viewer').show();
				
				break;
				
			case 'flash' :
				
				// place callout viewer on top of everything
				$('callout_viewer').setStyle({zIndex:995});

				// workaround to get item to scale up on IE, use div instead of object element
				var swfItem = $(document.createElement('div'));
				
				swfItem.setAttribute('id', 'callout_media');
				swfItem.setAttribute('name', 'callout_media');
				swfItem.setAttribute('classid', 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000');				
				swfItem.setAttribute('class', this.options.className);

				swfItem = this._addParamToObject('allowScriptAccess', 'sameDomain', swfItem);
				swfItem = this._addParamToObject('movie', newEltName, swfItem);
				
					var newItem = $(document.createElement('embed'));
					newItem.setAttribute('id', 'callout_media_item');
					newItem.setAttribute('name', 'callout_media_item');
					newItem.setAttribute('class', this.options.className);
					newItem.setAttribute('src', newEltName);
					newItem.setAttribute('type', 'application/x-shockwave-flash');
					newItem.setAttribute('allowScriptAccess', 'sameDomain');

				swfItem.appendChild(newItem);

				newItem.observe('click', this._activate.bindAsEventListener(this, 'hide'));
				
				// item inherits width and height of container for easy(er) resize
				newItem.setStyle({position:'relative', width:'100%', height:'100%'});
				
				$('callout_viewer').clonePosition(elt);
				
				// insert item into tpl
				$('callout_viewer').update(newItem);

				$('callout_viewer').show();
			
				var movie = getFlashObj('callout_media_item');

				break;
				
		} // end type switch
				
			// animate item 
			switch(this.options.animationStyle){
			
				case 'default' :
				
					// do not let image be bigger than viewport
					width = myWindowSize.width() - (this.options.padding * 2);
					height = myWindowSize.height() - (this.options.padding * 2);
					
					// add padding + scale if asked
					if(scale == 'true') {
						endDims.width = endDims.width + (this.options.padding * 2);
						endDims.height = endDims.height + (this.options.padding * 2);
					}
					
					if(width < endDims.width){
						ratio = endDims.width / endDims.height;
						endDims.width = (width - 50);
						endDims.height = endDims.width/ratio;
					}
					
					if(height < endDims.height){
						ratio = endDims.height / endDims.width;
						endDims.height = (height - 50);
						endDims.width = endDims.height/ratio;
					}
					

					if(this.options.scaleToCenter){
						// find center of screen
						posX = (width / 2) - (endDims.width / 2);
						posY = document.viewport.getScrollOffsets().top + (document.viewport.getHeight() / 2) - (endDims.height / 2);
					} else {
						posX = ''; posY = '';
					}
					
					// show overlay
					$('callout_overlay').show();
					
					// aniamate object
					new Effect.Morph('callout_overlay', {
						duration: this.options.fadeInSpeed,
						style:	'opacity:'+this.options.opacity,
						afterFinish: function(){
							// viewer
							new Effect.Parallel([
				          		    new Effect.Morph('callout_viewer', {
				          		    	sync: true,
				          		    	style:	'left:'+posX+'px;'+
				          		    			'top:'+posY+'px;'+
				          		    			'width:'+endDims.width+'px;'+
				          		    			'height:'+endDims.height+'px;'+
				          		    			'padding:'+this.options.padding+'px;'				          		    	
				          		    	})
				          		], {
				          			duration:this.options.scaleInSpeed,
				          			afterFinish: function(){
										// ready for another round?
										mycallout._ready = true;
									}
				          		});
						}.bind(this)
					
					});
					
					break;
					
			} // animation style switch
			
			
		
	},
	
	//--------------------------------//
	
	_hide:function(e){
		
		this._active = false;
		this._ready = false;
		
		// new code
		var elt = e.element();

		// build original item
		eltName = '';
		switch(elt.nodeName){
			case 'IMG' :
				
				break;			
		}
		
		// animate item out
		new Effect.Parallel([
		    // item holder
		    new Effect.Morph('callout_viewer', {
		    	sync: true, 
		    	style:	'left:'+this._scaleFactory.left+'px;'+
		    			'top:'+this._scaleFactory.top+'px;'+
		    			'width:'+this._scaleFactory.width+'px;'+
		    			'height:'+this._scaleFactory.height+'px;'+
		    			'padding:0px;'
		    	})
		    
		], {
			// after scale down, hide the overlay and return low-src item by fading out hi-src
			duration:this.options.scaleOutSpeed,
			
			afterFinish: function(){
				
				new Effect.Parallel([
				    // hide overlay    
					new Effect.Morph('callout_overlay', { 
							style:	'opacity:0',
							afterFinish:function(){}
					})
				], {
					duration: this.options.fadeOutSpeed,
					afterFinish:function(){
						$('callout_overlay').hide(); // animate out...
						
						// remove dom element to stop movies in IE, reinsert dom back in for next viewer...
						new Effect.Fade('callout_viewer', { 
							duration:.1,
							afterFinish:function(){ $('callout_viewer').remove(); mycallout._ready = true; mycallout._insertViewer();}
						});
					}
				});	
			}.bind(this)
			
		});
	
	},
	
	
	
	//
	//  Add a param to an object dynamically created
	//
	_addParamToObject : function(name, value, object, id) {
		var param = $(document.createElement('param'));
		param.setAttribute('value', value);
		param.setAttribute('name', name);
		if (id) {
			param.setAttribute('id', id);
		}
		object.appendChild(param);
		return object;
	}
	
};


document.observe("dom:loaded", function(){
	mycallout = new Callout();
	myWindowSize = new WindowSize();
});


/**
 * Utility
 */
var WindowSize = Class.create({
    width: function()
    {
        var myWidth = 0;
        if (typeof(window.innerWidth) == 'number')
        {
            //Non-IE
            myWidth = window.innerWidth;
        }
        else if (document.documentElement && document.documentElement.clientWidth)
        {
            //IE 6+ in 'standards compliant mode'
            myWidth = document.documentElement.clientWidth;
        }
        else if (document.body && document.body.clientWidth)
        {
            //IE 4 compatible
            myWidth = document.body.clientWidth;
        }
        return myWidth;
    },
    height: function()
    {
        var myHeight = 0;
        if (typeof(window.innerHeight) == 'number')
        {
            //Non-IE
            myHeight = window.innerHeight;
        }
        else if (document.documentElement && document.documentElement.clientHeight)
        {
            //IE 6+ in 'standards compliant mode'
            myHeight = document.documentElement.clientHeight;
        }
        else if (document.body && document.body.clientHeight)
        {
            //IE 4 compatible
            myHeight = document.body.clientHeight;
        }
        return myHeight;
    }
});

function getFlashObj(movie){
   if (window.document[movie]) {
      return window.document[movie];
   }
   if (navigator.appName.indexOf("Microsoft Internet")==-1) {
      if (document.embeds && document.embeds[movie]) {
         return document.embeds[movie]; 
      }
   } else {
      return document.getElementById(movie);
   }
}