/* $Id: lightbox.jquery.js,v 1.1.2.1 2008/04/17 22:08:47 gburns Exp $

Unobtrusive Accessible jQuery 1.2.1 drop downs.

Overview:
	jQuery.fn.lightbox()

Parameters:
	prepend: (String) String to prepend classes/id's
		Default: 'lightbox'
	width: (Float) Default width for lightbox
		Default: 400
	height: (Float) Default height for lightbox
		Default: 300
	opacity: (Float) Opacity for overlay
		Default: 0.8
	speed: (String) Animation speed for lightbox animations
		Default: 'slow'
	callback: (Function) Function to call after contents
		are loaded into into lightbox - NOTE: the callback
		function is called on each subsequent jquery.lightbox.load
		call within the same lightbox "instance"
	closecallback(closer): (Function) Function to call after lightbox
		is closed. Passes "closer" to function, which is the element
		that triggered the close.

Usage:
	JavaScript:
	$('selector').lightbox();

	If the 'selector' is an ancor tag, the link's location will open
	in a lightbox. If the selector is a form the form's action will
	open in a lightbox. If neither, it will search for anchor tags
	and form tags and attach lightbox methods to them.

	You can also use the jQuery.lightbox methods directly to incorrporate
	your own plugins:

	$('a#slideshow_link').bind('click', function() {
		$.lightbox.load(this.href, null, function() {
			$('.slideshow', $.lightbox.$content).slideshow();
		});
	});

"Magic" Classes:
	{prepend}_close: Anything with the prepend parameter concatinated
		with "_close" will call the jQuery.lightbox.hide() on click.

Author:
	gburns, lightbox

TODO:
	documentation
*/

jQuery.fn.lightbox = function(options) {
	jQuery.lightbox.set(options);
	jQuery.lightbox.create();
	var settings = jQuery.lightbox.getSettings();

	var img_search = /(\.jpg|\.jpeg|\.png|\.gif|\.bmp)$/;

	return this.each(function() {
		var $this = jQuery(this);

		if ( this.nodeName == 'A' ) {
			if ( this.href.match(img_search) ) {
				$this
					.bind('click', function() {
						jQuery.lightbox.showImage(this.href);
						return false;
					});
			} else {
				$this
					.bind('click', function() {
						jQuery.lightbox.load(this.href, null, settings.callback);
						return false;
					});
			}
		} else if ( this.nodeName == 'FORM' ) {
			$this
				.bind('submit', function() {
					if ( this.method.toUpperCase() == 'POST' ) {
						jQuery.lightbox.load(this.action, $this.serializeArray(), settings.callback);
					} else {
						var query = (( this.action.indexOf('?') != -1 ) ? '&' : '?') + $this.serialize();
						jQuery.lightbox.load(this.action + query, null, settings.callback);
					}
					return false;
				});
		}
	});
}

jQuery.lightbox = {
	showing: false,
	$content: null,
	$lightbox: null,
	$overlay: null,
	prepend: 'lightbox',
	width: 400,
	height: 300,
	opacity: 0.8,
	speed: 'slow',
	wrappers: ['n', 's', 'e', 'w', 'nw', 'ne', 'sw', 'se', 'content'],
	closing: false,
	callback: null,
	closecallback: null,

	// Used for overriding lightbox defaults
	getSettings: function(options) {
		var settings = jQuery.extend({
			width: jQuery.lightbox.width,
			height: jQuery.lightbox.height,
			prepend: jQuery.lightbox.prepend,
			opacity: jQuery.lightbox.opacity,
			speed: jQuery.lightbox.speed,
			callback: jQuery.lightbox.callback,
			wrappers: jQuery.lightbox.wrappers,
			closecallback: jQuery.lightbox.closecallback
		}, options || {});

		return settings;
	},

	// Set global params
	set: function(options) {
		var settings = jQuery.lightbox.getSettings(options);

		jQuery.lightbox.width = settings.width;
		jQuery.lightbox.height = settings.height;
		jQuery.lightbox.prepend = settings.prepend;
		jQuery.lightbox.opacity = settings.opacity;
		jQuery.lightbox.speed = settings.speed;
		jQuery.lightbox.wrappers = settings.wrappers;
		jQuery.lightbox.callback = settings.callback;
		jQuery.lightbox.closecallback = settings.closecallback;
	},

	// See if objects have been created
	isCreated: function() {
		if ( jQuery.lightbox.$content && jQuery.lightbox.$lightbox && jQuery.lightbox.$overlay ) return true;
	},

	// Create objects
	create: function() {
		if ( jQuery.lightbox.isCreated() ) return;

		var $body = jQuery('body');

		jQuery.lightbox.$overlay = jQuery('<div/>')
			.attr({id: jQuery.lightbox.prepend + '_overlay'})
			.css({
				position: 'absolute',
				top: 0,
				left: 0,
				opacity: 0,
				display: 'none',
				zIndex: 10000
				})
			.bind('click', function() {
				if ( !jQuery.lightbox.closing ) jQuery.lightbox.hide(this);
				});

		jQuery.lightbox.$lightbox = jQuery('<div/>')
			.attr({id: jQuery.lightbox.prepend + '_container'})
			.css({
				position: 'absolute',
				display: 'none',
				zIndex: 10001
				});

		var $container;
		var $old_container = jQuery.lightbox.$lightbox;
		var divs = jQuery.lightbox.wrappers;
		for ( var div in divs ) {
			$container = jQuery('<div/>').addClass(jQuery.lightbox.prepend + '_' + divs[div]);
			$old_container.append($container);
			$old_container = $container;
		}

		jQuery.lightbox.$content = $old_container;

		$body.append(jQuery.lightbox.$overlay);
		$body.append(jQuery.lightbox.$lightbox);
	},

	// Show objects
	show: function(options, callback) {
		var settings = jQuery.lightbox.getSettings(options);

		if ( jQuery.lightbox.showing ) return;
		jQuery.lightbox.showing = true;

		jQuery('iframe:visible, object:visible, embed:visible, select:visible')
			.attr({lightbox_hide: 'true'})
			.css({visibility: 'visible'});

		jQuery.lightbox.create();

		var dimensions = jQuery.lightbox.getPageDimensions();

		var $body = jQuery('body');

		jQuery.lightbox.$overlay
			.css({
				width: $body.fullWidth() + 'px',
				height: dimensions.ph + 'px',
				opacity: 0
				})
			.show();

		jQuery.lightbox.$lightbox
			.addClass(settings.prepend + '_loading')
			.css({
				opacity: 0
				});

		jQuery.lightbox.$content
			.css({
				width: settings.width + 'px',
				height: settings.height + 'px'
				});

		var scroll = jQuery.lightbox.getPageScroll();

		jQuery.lightbox.$lightbox
			.show()
			.css({
				top: parseInt((dimensions.vph - jQuery.lightbox.$lightbox.fullHeight()) / 2) + scroll.y + 'px',
				left: parseInt((dimensions.vpw - jQuery.lightbox.$lightbox.fullWidth()) / 2) + scroll.x + 'px'
				});

		jQuery('.' + settings.prepend + '_close', jQuery.lightbox.$content)
			.bind('click', function() {
				jQuery.lightbox.hide(this);
				return false;
			});

		if ( settings.speed ) {
			jQuery.lightbox.$overlay.animate({opacity: settings.opacity}, settings.speed, 'linear', function(){
				jQuery.lightbox.$lightbox.animate({ opacity: 1 }, settings.speed, 'linear', function() {
					if ( jQuery.browser.msie ) jQuery.lightbox.$lightbox[0].filters.alpha.enabled = false;
					if ( callback ) callback();
				});
			});
		} else {
			jQuery.lightbox.$lightbox.css({ opacity: 1 });
			if ( jQuery.browser.msie ) jQuery.lightbox.$lightbox[0].filters.alpha.enabled = false;
			if ( callback ) callback();
			jQuery.lightbox.$overlay.css({ opacity: settings.opacity });
		}
	},

	// Hide objects, clear content
	hide: function(closer) {
		var settings = jQuery.lightbox.getSettings();

		if ( jQuery.lightbox.$content && jQuery.lightbox.$lightbox && jQuery.lightbox.$overlay ) {
			jQuery.lightbox.closing = true;
			jQuery.lightbox.showing = false;

			if ( settings.speed ) {
				jQuery.lightbox.$lightbox.animate({ opacity: 0 }, settings.speed, function() {
					jQuery.lightbox.$lightbox.hide();
					jQuery.lightbox.$overlay.animate({ opacity: 0 }, settings.speed, function() {
						jQuery.lightbox.$overlay.hide();
						if ( settings.closecallback ) settings.closecallback(closer);
						jQuery.lightbox.$content.html('');
						jQuery.lightbox.closing = false;

						jQuery('iframe[lightbox_hide="true"], object[lightbox_hide="true"], embed[lightbox_hide="true"], select[lightbox_hide="true"]')
							.css({visibility: 'visible'});
					});
				});
			} else {
				jQuery.lightbox.$overlay.hide();
				jQuery.lightbox.$lightbox.hide();
				if ( settings.closecallback ) settings.closecallback(closer);
				jQuery.lightbox.$content.html('');
				jQuery.lightbox.closing = false;
						if ( jQuery.browser.msie ) {
							jQuery('select[lightbox_iehide="true"]')
								.show();
						}
			}
		}
	},

	// Show an image in content box
	// TODO: Figure out how to compensate for 404 errors
	showImage: function(href, speed) {
		jQuery.lightbox.show();

		var img = new Image();

		// once image is preloaded, resize image container
		img.onload = function() {
			jQuery.lightbox.resize({
				width: img.width,
				height: img.height,
				callback: function() { jQuery.lightbox.$content.append(img); }
				});
			img.onload = function(){}; // clear onLoad, IE behaves irratically with animated gifs otherwise

			jQuery.lightbox.$lightbox
				.removeClass(jQuery.lightbox.prepend + '_loading');
		};

		img.src = href;
	},

	// Load selected dom object
	showDom: function(selector, options, fn) {
		var $dom = jQuery(selector);
		if ( !$dom.length ) return;

		jQuery.lightbox.set(options);
		jQuery.lightbox.create();
		jQuery.lightbox.$content.append($dom);

		jQuery.lightbox.show(options, function() {
			jQuery.lightbox.$lightbox
				.removeClass(jQuery.lightbox.prepend + '_loading');
			if ( fn ) fn();
		});
	},

	// Load a remote url via jquery's load method
	load: function(href, data, callback, options) {
		var settings = jQuery.lightbox.getSettings(options);

		var $container = jQuery('<div/>');

		jQuery.lightbox.show(settings);

		if ( !href.match(/ +/) ) href += ' >:not(script)';

		$container.load(href, data, function() {
		/*$container.load(href + ' >:not(script)', data, function() {
			jQuery('title, meta', $container)
				.remove();*/

			jQuery.lightbox.$content.html($container.html());

			jQuery.lightbox.$lightbox
				.removeClass(settings.prepend + '_loading');

			jQuery('.' + settings.prepend + '_close', jQuery.lightbox.$content)
				.bind('click', function() {
					jQuery.lightbox.hide(this);
					return false;
				});

			if ( callback ) callback();
		});
	},

	// Resize lightbox object
	resize: function(options) {
		if ( !jQuery.lightbox.showing ) return;

		var settings = jQuery.extend({
			width: null,
			height: null,
			callback: null
		}, options || {});

		var dimensions = jQuery.lightbox.getPageDimensions();
		var scroll = jQuery.lightbox.getPageScroll();

		var lightbox_width_extra = jQuery.lightbox.$lightbox.fullWidth() - jQuery.lightbox.$content.innerWidth();
		var lightbox_height_extra = jQuery.lightbox.$lightbox.fullHeight() - jQuery.lightbox.$content.innerHeight();

		var to_x = parseInt((dimensions.vpw - settings.width - lightbox_width_extra) / 2) + scroll.x + 'px';
		var to_y = parseInt((dimensions.vph - settings.height - lightbox_height_extra) / 2) + scroll.y + 'px';

		if ( jQuery.lightbox.speed ) {
			jQuery.lightbox.$content.animate({ width: settings.width + 'px', height: settings.height + 'px' }, jQuery.lightbox.speed, settings.callback);
			jQuery.lightbox.$lightbox.animate({ left: to_x, top: to_y }, jQuery.lightbox.speed);
		} else {
			jQuery.lightbox.$content.css({ width: settings.width + 'px', height: settings.height + 'px' });
			jQuery.lightbox.$lightbox.css({ left: to_x, top: to_y });
			settings.callback();
		}
	},

	getPageDimensions: function() {
		var xScroll, yScroll;

		if ( window.innerHeight && window.scrollMaxY ) {	
			xScroll = document.body.scrollWidth;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if ( document.body.scrollHeight > document.body.offsetHeight ) { // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}

		var windowWidth, windowHeight;
		if ( self.innerHeight ) { // all except Explorer
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		} else if ( document.documentElement && document.documentElement.clientHeight ) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if ( document.body ) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}

		// for small pages with total height less then height of the viewport
		if ( yScroll < windowHeight ) {
			pageHeight = windowHeight;
		} else { 
			pageHeight = yScroll;
		}

		// for small pages with total width less then width of the viewport
		if ( xScroll < windowWidth ) {	
			pageWidth = windowWidth;
		} else {
			pageWidth = xScroll;
		}

		//arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
		return {pw: pageWidth, ph: pageHeight, vpw: windowWidth, vph: windowHeight};
		//arrayPageSize;
	},

	getPageScroll: function() {
		var xScroll, yScroll;

		if ( self.pageYOffset ) {
			yScroll = self.pageYOffset;
			xScroll = self.pageXOffset;
		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
			yScroll = document.documentElement.scrollTop;
			xScroll = document.documentElement.scrollLeft;
		} else if (document.body) {// all other Explorers
			yScroll = document.body.scrollTop;
			xScroll = document.body.scrollLeft;	
		}

		//arrayPageScroll = new Array(xScroll, yScroll) 
		return {x: xScroll, y: yScroll};
		//arrayPageScroll;
	}
}

// Full height/Full width
if ( !jQuery.fn.fullHeight ) {
	jQuery.fn.fullHeight = function() {
		var $this = jQuery(this[0]);
		return $this[0].clientHeight
		+ (parseInt($this.css('borderTopWidth')) || 0)
		+ (parseInt($this.css('borderBottomWidth')) || 0)
		+ (parseInt($this.css('marginTop')) || 0)
		+ (parseInt($this.css('marginBottom')) || 0);
	}

	jQuery.fn.fullWidth = function() {
		var $this = jQuery(this[0]);
		return $this[0].clientWidth
		+ (parseInt($this.css('borderLeftWidth')) || 0)
		+ (parseInt($this.css('borderRightWidth')) || 0)
		+ (parseInt($this.css('marginLeft')) || 0)
		+ (parseInt($this.css('marginRight')) || 0);
	}
}

if ( !jQuery.fn.innerHeight ) {
	jQuery.fn.innerHeight = function() {
		var $this = jQuery(this[0]);
		return $this[0].clientHeight
		- (parseInt($this.css('paddingTop')) || 0)
		- (parseInt($this.css('paddingBottom')) || 0);
	}

	jQuery.fn.innerWidth = function() {
		var $this = jQuery(this[0]);
		return $this[0].clientWidth
		- (parseInt($this.css('paddingLeft')) || 0)
		- (parseInt($this.css('paddingRight')) || 0);
	}
}