/**

	Author: Urban Faubion
	Version: 0.6
	Description: An event driven Lightbox implementation requiring the Prototype version 1.6+ and the script.aculo.us version 1.8.1+ JavaScript libraries.

**/

var detect = navigator.userAgent.toLowerCase();
var OS,browser,version,total,thestring;

function getBrowserInfo() {
	if (checkIt('konqueror')) {
		browser = "Konqueror";
		OS = "Linux";
	}
	else if (checkIt('safari')) browser 	= "Safari"
	else if (checkIt('omniweb')) browser 	= "OmniWeb"
	else if (checkIt('opera')) browser 		= "Opera"
	else if (checkIt('webtv')) browser 		= "WebTV";
	else if (checkIt('icab')) browser 		= "iCab"
	else if (checkIt('msie')) browser 		= "Internet Explorer"
	else if (!checkIt('compatible')) {
		browser = "Netscape Navigator"
		version = detect.charAt(8);
	}
	else browser = "An unknown browser";

	if (!version) version = detect.charAt(place + thestring.length);

	if (!OS) {
		if (checkIt('linux')) OS 		= "Linux";
		else if (checkIt('x11')) OS 	= "Unix";
		else if (checkIt('mac')) OS 	= "Mac"
		else if (checkIt('win')) OS 	= "Windows"
		else OS 								= "an unknown operating system";
	}
}

function checkIt(string) {
	place = detect.indexOf(string) + 1;
	thestring = string;
	return place;
}

document.observe('dom:loaded', function(){
	getBrowserInfo();
	new Lightbox();
});

var Lightbox = Class.create({

	animate							: false,
	overlay							: null,
	lightbox 						: null,
	content_container 	: null,
	response						: null,
	resize_bfx					: null,
	min_position				: { x: 20, y: 20 },
	scroll_offsets			: null,

	initialize : function() {
		Lightbox.instance = this;
		this.insert_lightbox();
		this.resize_bfx = this.center.bindAsEventListener(this);
		this.actions();
		document.fire('lightbox:initialized');
	},	
	insert_lightbox : function() {
		
		// Code inserts html at the bottom of the page that looks similar to this:
		//
		//	<div id="overlay"></div>
		//	<div id="lightbox">
		//		<div id="lightbox_content"></div>
		//		<div id="lightbox_load_message">
		//			<p>Loading</p>
		//		</div>
		//	</div>
		
		bod = document.getElementsByTagName('body')[0];
		overlay = document.createElement('div');
		overlay.setAttribute('id','overlay');
		lb = document.createElement('div');
		lb.setAttribute('id','lightbox');
		lb.setAttribute('class', 'loading');
		lb.innerHTML	= '<div id="lightbox_content""></div>' +
								'<div id="lightbox_load_message">' +
							  '<p>Loading</p>' +
							  '</div>';
		bod.appendChild(overlay);
		bod.appendChild(lb);
		
		this.overlay = $('overlay');
		this.lightbox = $('lightbox');
		this.content_container = $('lightbox_content');
	},	
	hideSelects : function(visibility){
		$$('select').invoke('setStyle', {visibility: visibility})
	},	
	show : function(){
		this.prepareIE('show');
		[this.overlay, this.lightbox].invoke('setStyle',{ display:'block' });
	},
	hide : function(){
		this.prepareIE('hide');
		[this.overlay, this.lightbox].invoke('setStyle',{ display:'none' }); 
	},
	prepareIE: function(display_state){
		if(browser != 'Internet Explorer') return;
		if(version > 6) return;
		
		var height, overflow;
		if(display_state == 'show'){
			height = '100%';
			overflow = 'hidden';
			$$('select').invoke('setStyle', {visibility:'hidden'});
			this.scroll_offsets = document.viewport.getScrollOffsets();
			window.scrollTo(0,0);
		}else{
			height = 'auto';
			overflow = 'auto';
			$$('select').invoke('setStyle', {visibility:'visible'})
			window.scrollTo(this.scroll_offsets.left, this.scroll_offsets.top);
		}

		var bod = document.getElementsByTagName('body')[0];
		var htm = document.getElementsByTagName('html')[0];
		bod.style.height = htm.style.height = height;
		bod.style.overflow = htm.style.overflow = overflow;		
	},
	constrain_position : function(pos){
		pos.x = Math.max(this.min_position.x, pos.x);
		pos.y = Math.max(this.min_position.y, pos.y);
		return pos;
	},
	center : function(){
		var scroll_offsets = document.viewport.getScrollOffsets();
		var viewport_dimensions = document.viewport.getDimensions();
		var lightbox_dimensions = this.lightbox.getDimensions();
		var pos = {};
		pos.x = (viewport_dimensions.width - lightbox_dimensions.width) / 2;
		pos.y = (viewport_dimensions.height - lightbox_dimensions.height) / 2;
		pos = this.constrain_position(pos);
		pos.x = pos.x + scroll_offsets.left;
		pos.y = pos.y + scroll_offsets.top;
		this.lightbox.setStyle({ left : pos.x+'px', top : pos.y+'px' });
	},
	resize : function(){
		var scroll_offsets = document.viewport.getScrollOffsets();
		var viewport_dimensions = document.viewport.getDimensions();
		var content_dimensions = this.content_container.getDimensions();
		var pos = {};
		pos.x = (viewport_dimensions.width - content_dimensions.width) / 2;
		pos.y = (viewport_dimensions.height - content_dimensions.height) / 2;
		pos = this.constrain_position(pos);
		pos.x = pos.x + scroll_offsets.left;
		pos.y = pos.y + scroll_offsets.top;
		
		if(this.animate && Scriptaculous){
			new Effect.Parallel(
				[
					new Effect.Morph(this.lightbox,{
						sync	: true,	
						style	: { 
							height	: content_dimensions.height+'px',
							width		: content_dimensions.width+'px'
						}
					}),
					new Effect.Move (this.lightbox,{ 
						sync	: true,
						x			: pos.x, 
						y			: pos.y, 
						mode	: 'absolute'
					})
				],
				{ 
					duration:2,
					afterFinish:this.loaded.bindAsEventListener(this)
				}
			);
		}else{
			this.lightbox.setStyle({
				height	: content_dimensions.height+'px',
				width		: content_dimensions.width+'px',
				left		: pos.x+'px',
				top			: pos.y+'px'
			});
			this.loaded();
		}		
	},
	load: function(path) {
		this.loading();
		var options = {
			method		: 'get',
			onSuccess	: this.process_content.bindAsEventListener(this),
			onFailure	: function(transport){
				alert('Error loading file from server!');
			}
		}
		new Ajax.Request(path, options);
	},
	loaded : function(){
		var content_dimensions = this.content_container.getDimensions();
		this.lightbox.removeClassName('loading');
		this.lightbox.addClassName('done');
		document.fire('lightbox:loaded');
	},
	loading : function(){
		this.lightbox.removeClassName('done');
		this.lightbox.addClassName('loading');
	},
	// Display Ajax response
	process_content : function(transport){
		var script = '<script type="text/javascript">';
		script += 'Lightbox.instance.actions(Lightbox.instance.content_container);';
		script += 'Lightbox.instance.resize();';
		script += '</script>';
		this.response = transport.responseText;
		this.content_container.update(this.response + script);
	},
	// Search through new links within the lightbox, and attach click event
	actions : function(context){
		var anchors = (context)? context.select('a') : $A(document.getElementsByTagName('a'));
		anchors.each(function(link){
			
			var rel_attributes = link.getAttribute('rel');
			var path = link.getAttribute('href');
			
			if(path && rel_attributes && (rel_attributes.include('lightbox'))){
				var action = rel_attributes.gsub('lightbox','').strip();
				Event.observe(link,'click', Lightbox.instance[action].bind(Lightbox.instance, path));
				link.onclick = function(){ return false; }
			}
		});
		
	},	
	open : function(path){
		Event.observe(window, 'resize', this.resize_bfx);
		this.hideSelects('hidden');
		this.center();
		this.load(path);
		this.show();
		document.fire('lightbox:open');
	},	
	close : function(){
		Event.stopObserving(window, 'resize', this.resize_bfx);
		this.content_container.update();
		this.hideSelects("visible");
		this.hide();
		document.fire('lightbox:close');
	},
	// for inserting new content into the open lightbox
	insert : function(path, params){
		this.content_container.update();
		this.load(path, params);
	}
		
});
