/*
	Script: Lightbox.js
	Author: Regina Luk
*/
/*
	Class: Lightbox
	Makes an in-page "lightbox" type overlay for anything.
	
	Searches the page for anchors with 'rel' of this.options.keyword.  Gets content from the href of the anchor via Ajax.  Request data returned is expected to be a JSON object.  Content to be inserted into lightbox should be returned as 'content'.  Ex: request['content'].  If the request doesn't return any data, or anything in 'content', then close the lightbox and send the person to the url.

	Arguments:
		element - html element containing all of the scrolled items and controls
		options - scroll options

	Options:
		keyword -
			Keyword to look for in rel attribute of anchors on the page
			default: 'lightbox'
		defaultHeight -
			Used as height of lightbox if the contents of the lightbox is not styled with a height or width
			default:  400
		defaultWidth -
			Used as width of lightbox if the contents of lightbox is not styled with a height or width
			default: 600
		defaultCloseClass -
			If the lightbox contents do not have a close button, we will be adding a <div><a href="#close"><b>Close</b></a></div> to the lightbox with this as the class name of the div
			default: 'close'
		showLoading -
			Boolean used to determine whether or not to show a div depicting loading status
			default: true
		overlayOpacity -
			Opacity of the overlaying div that covers the rest of the page behind the lightbox
			default: '0.7'
		adUnitSelector -
			CSS selector used to target ads loaded in iframes
			default: 'div.ad_unit iframe'

	Example:
		(start code)
		<script type="text/css">
			#cne_lightbox .overlay,
			#cne_lightbox .loading,
			#cne_lightbox .content{position:absolute;top:0;left:0;z-index:99999998;}
			#cne_lightbox_base{position:absolute;top:0;left:0;z-index:99999997;}
			#cne_lightbox .overlay{background:#000;height:0;margin:0;padding:0;width:100%;}
			#cne_lightbox .loading {background:url(http://image.com.com/filmspot/images/indicator.gif) no-repeat 0 0;margin:0;padding:0;height:128px;width:128px;}
			#cne_lightbox .content {background-color:#999;margin:0;z-index:99999999;}
			#cne_lightbox .content .close{background:#ccc;padding:2px 5px;text-align:right;}
		</script>

		This <a href="http://www.filmspot.com/pages/signup/" rel="cne_lightbox">anchor</a> will open up in a lightbox.

		<!-- it is very important to put this code at the bottom most part of the page, before the closing </body> tag or this will cause a DOM error in IE. -->
		<script type="text/javascript">
			window.addEvent('domready', function() {
				new Lightbox({
					'keyword':'cne_lightbox'
				});
			});
		</script>

		<!-- this is the code that will be inserted into the DOM -->
		<!--
			<div id="cne_lightbox">
				<div class="overlay"></div>
				<div class="loading"></div>
				<div class="content"></div>
			</div>
			<iframe id="cne_lightbox_base" scrolling="no" frameborder="0" src="javascript:;"></iframe>
		-->
		(end)
*/

var Lightbox = new Class({
	options: {
		'keyword':'lightbox',
		'defaultHeight': 400,
		'defaultWidth':600,
		'defaultCloseClass':'close',
		'showLoading':true,
		'overlayOpacity':'0.7',
		'adUnitSelector':'div.ad_unit'
	},

	initialize: function(options) {
		this.lightbox = {};
		this.hasLightbox = false;
		this.anchors = $$('a[rel]');

		if ($chk(options)) this.setOptions(this.options, options);

		this.anchors.each( function(anchor) {
			var lightboxValues = {};
			if (anchor.getProperty('rel').indexOf(this.options.keyword) >= 0)
			{
				if (!this.hasLightbox) this.lightbox = this.createLightbox();
				// find out what class we will be adding to content
				lightboxValues.type = this.parseType(anchor.getProperty('rel'));
				lightboxValues.url = anchor.getProperty('href');
				anchor.addEvent('click', function(e) {
					e = new Event(e);
					this.showLightbox(lightboxValues);
					e.stop();
				}.bind(this));
			}
		}.bind(this));
	},
	
	parseType: function(string) {
		var substrings = string.split(' ');
		var type = '';
		substrings.some( function(substring) {
			if (substring.indexOf(':') > 0) {
				var string_set = substring.split(':');
				// grab only the first instance of width and height in the string passed in
				if ((string_set[0] == 'type') && !$chk(type)) {
					type = string_set[1];
				}
			}
			return ($chk(type));
		});
		if ($chk(type)) {
			return type;
		} else {
			return false;
		}
	},
	
	createLightbox: function() {
		if (!this.hasLightbox && !$('cne_lightbox'))
		{
			//dbug.log('createLightbox');
			var lightbox = {};
			lightbox.container = new Element('div').setProperty('id','cne_lightbox');
			lightbox.overlay = new Element('div').addClass('overlay').setStyles({'display':'none','opacity':this.options.overlayOpacity}).injectInside(lightbox.container);
			if (this.options.showLoading) lightbox.loading = new Element('div').addClass('loading').setStyle('display','none').injectAfter(lightbox.overlay);
			lightbox.content = new Element('div').addClass('content').setStyle('display','none').injectAfter(lightbox.overlay);
			// this iframe would be used to block any iframe or select elements from appearing above the lightbox in IE6
			lightbox.baseLayer = new Element('iframe').setProperties({
				'src':'javascript:;',
				'frameborder':'0',
				'scrolling':'no',
				'id':'cne_lightbox_base'
			}).setStyles({
				'display':'none'
			});
			lightbox.baseLayer.injectAfter($E('body').getLast());
			lightbox.container.injectAfter(lightbox.baseLayer);
			this.hasLightbox = true;
			return lightbox;
		}
		return false;
	},

	showLightbox: function(lightboxValues) {
		var windowPos = window.getSize();
		var lightboxContent = new Ajax(lightboxValues.url, {
			method: 'post',
			onRequest: function() {
				this.toggleAdObjects('hide');
				this.lightbox.loading.setStyle('display','block');
				this.centerItem(this.lightbox.loading);
			}.bind(this),
			onFailure: function() {
				//dbug.log('failed');
				alert('lightbox failed');
				this.hideLightbox(lightboxValues);
			}.bind(this),
			onSuccess: function(results) {
				this.lightbox.loading.setStyle('display','none');
				this.showContent(results,lightboxValues);
			}.bind(this)
		});
		// overlay
		this.lightbox.overlay.setStyles({
			'display':'block',
			'height':windowPos.scrollSize.y + 'px'
		});

		lightboxContent.request();
	},
	
	showContent: function(results,lightboxValues) {
		results = Json.evaluate(results);

		// if the request did not return anything, then send the user to the url
		if (!$chk(results)) {
			alert('no data returned from request');
			this.hideLightbox(lightboxValues);
			return false;
		}
		
		// if the request did not return content, don't do anything
		if ($chk(results['content'])) {
			this.lightbox.content.setHTML(results['content']);
		} else {
			alert('request failed to return lightbox content');
			this.hideLightbox(lightboxValues);
			return false;
		}

		// look for the string 'close' in the rel attribute of anchors and add hideLightbox event to onclick for the anchor
		var hasClose;
		var closeAnchors = this.lightbox.content.getElements('a[rel]');

		if (closeAnchors.length > 0) {
			closeAnchors.each( function(anchor) {
				if (anchor.getProperty('rel').indexOf('close') >= 0)
				{
					anchor.addEvent('click', function(e) {
						e = new Event(e);
						this.hideLightbox(lightboxValues);
						e.stop();
					}.bind(this));
					hasClose = true;
				}
			}.bind(this));
			if (!$chk(hasClose)) {
				this.insertClose(lightboxValues);
			}
		} else {
			this.insertClose(lightboxValues);
		}

		// set content
		if ($chk(lightboxValues.type)) this.lightbox.content.addClass(lightboxValues.type);
		this.lightbox.content.setStyles({'display':'block','visibility':'hidden','height':'auto','width':'auto'});
		// find content size and set as default size if size is 0x0
		lightboxValues.size = this.lightbox.content.getSize().size;
		if (lightboxValues.size.x == 0 || lightboxValues.size.y == 0) lightboxValues.size = {'x':this.options.defaultWidth,'y':this.options.defaultHeight};
		// set iframe behind lightbox to hide browser objects from showing through
		this.lightbox.content.setStyles({'height':lightboxValues.size.y+'px','width':lightboxValues.size.x+'px'});
		this.lightbox.baseLayer.setStyles({'display':'block','height':lightboxValues.size.y+'px','width':lightboxValues.size.x+'px'});
		this.centerItem(this.lightbox.baseLayer);
		this.centerItem(this.lightbox.content);
		this.lightbox.content.setStyle('visibility','visible');

		window.addEvent('scroll', this.reCenterLightbox.bind(this)).addEvent('resize', this.reCenterLightbox.bind(this));
	},
	
	insertClose: function(lightboxValues) {
		new Element('b').setHTML('Close').injectInside(new Element('a').setProperty('href','#close').addEvent('click', function(e) {
			e = new Event(e);
			this.hideLightbox(lightboxValues);
			e.stop();
		}.bind(this)).injectInside(new Element('div').addClass('close').injectInside(this.lightbox.content)));
	},
	
	hideLightbox: function(lightboxValues) {
		this.lightbox.overlay.setStyles({'display':'none'});
		this.lightbox.content.setStyles({'display':'none'});
		this.lightbox.content.setHTML('');
		if ($chk(lightboxValues.type)) this.lightbox.content.removeClass(lightboxValues.type);
		this.lightbox.baseLayer.setStyles({'display':'none','height':'auto','width':'auto'});
		window.removeEvent('scroll').removeEvent('resize');
		this.toggleAdObjects('show');
	},

	centerItem: function(item) {
		var itemPos = item.getSize();
		var windowPos = window.getSize();
		var newPos = {
			'x': ((windowPos.size.x-itemPos.size.x)/2 + windowPos.scroll.x).toInt(),
			'y': ((windowPos.size.y-itemPos.size.y)/2 + windowPos.scroll.y).toInt()
		};

		//dbug.log('element: %o\nitemPos: %o\nwindowScroll: %o\nwindowScrollSize: %o\nwindowSize: %o\nnewPos: %o',item,itemPos.size,windowPos.scroll,windowPos.scrollSize,windowPos.size,newPos);

		item.setStyles({
			'top': newPos.y + 'px',
			'left': newPos.x + 'px'
		});
	},
	
	reCenterLightbox: function() {
		if ( this.lightbox.overlay.getStyle('display') != 'none' ) {
			var windowPos = window.getSize();
			this.lightbox.overlay.setStyle('height',windowPos.scrollSize.y + 'px');
			this.centerItem(this.lightbox.content);
			this.lightbox.baseLayer.setStyle('visibility','hidden');
			this.centerItem(this.lightbox.baseLayer);
			this.lightbox.baseLayer.setStyle('visibility','visible');
		}
	},
	
	/*
		- used to toggle flash and other iframes used for ads
		- keeps flash + iframes from showing above lightbox
	*/
	toggleAdObjects: function(action) {
		var visibility = (action == 'show') ? 'visible' : 'hidden';
		// get all objects and embeds on the page, and all embeds, iframes, and tables inside the adUnits
		var elements = $$('object','embed',this.options.adUnitSelector);
		elements.each( function(adUnit) {
			// not using setStyle here b/c it breaks on objects and embeds in IE
			adUnit.style.visibility = visibility;
		});
	}
});

Lightbox.implement(new Options);
