// lightwindow.js v2.0
//
// Copyright (c) 2007 stickmanlabs
// Author: Kevin P Miller | http://www.stickmanlabs.com
//
// LightWindow is freely distributable under the terms of an MIT-style license.
//
// I don't care what you think about the file size...
//   Be a pro:
//	    http://www.thinkvitamin.com/features/webapps/serving-javascript-fast
//      http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files
//

/*-----------------------------------------------------------------------------------------------*/

if (typeof Effect == 'undefined')
throw ("lightwindow.js requires including script.aculo.us' effects.js library!");

// This will stop image flickering in IE6 when elements with images are moved
try {
	document.execCommand("BackgroundImageCache", false, true);
}
catch (e) {
}

var lightwindow = Class.create();
lightwindow.prototype = {
	//
	//	Setup Variables
	//
	element: null,
	contentToFetch: null,
	windowActive: false,
	dataEffects:[],
	dimensions: {
		cruft: null,
		container: null,
		viewport: {
			height: null,
			width: null,
			offsetTop: null,
			offsetLeft: null
		}
	},
	pagePosition: {
		x: 0,
		y: 0
	},
	pageDimensions: {
		width: null,
		height: null
	},
	preloadImage:[],
	preloadedImage:[],
	galleries:[],
	resizeTo: {
		height: null,
		heightPercent: null,
		width: null,
		widthPercent: null,
		fixedTop: null,
		fixedLeft: null
	},
	scrollbarOffset: 18,
	navigationObservers: {
		previous: null,
		next: null
	},
	containerChange: {
		height: 0,
		width: 0
	},
	activeGallery: false,
	galleryLocation: {
		current: 0,
		total: 0
	},
	//
	//	Initialize the lightwindow.
	//
	initialize: function (options) {
		this.options = Object.extend({
			resizeSpeed: 8,
			contentOffset: {
				height: 20,
				width: 20
			},
			dimensions: {
				image: {
					height: 250, width: 250
				},
				page: {
					height: 250, width: 250
				},
				inline: {
					height: 250, width: 250
				},
				media: {
					height: 250, width: 250
				},
				external: {
					height: 250, width: 250
				},
				titleHeight: 25
			},
			classNames: {
				standard: 'lightwindow',
				action: 'lightwindow_action'
			},
			fileTypes: {
				page:[ 'asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php4', 'php3', 'php', 'php5', 'phtml', 'rhtml', 'shtml', 'txt', 'vbs', 'rb'],
				media:[ 'aif', 'aiff', 'asf', 'avi', 'divx', 'm1v', 'm2a', 'm2v', 'm3u', 'mid', 'midi', 'mov', 'moov', 'movie', 'mp2', 'mp3', 'mpa', 'mpa', 'mpe', 'mpeg', 'mpg', 'mpg', 'mpga', 'pps', 'qt', 'rm', 'ram', 'swf', 'viv', 'vivo', 'wav'],
				image:[ 'bmp', 'gif', 'jpg', 'png', 'tiff']
			},
			mimeTypes: {
				avi: 'video/avi',
				aif: 'audio/aiff',
				aiff: 'audio/aiff',
				gif: 'image/gif',
				bmp: 'image/bmp',
				jpeg: 'image/jpeg',
				m1v: 'video/mpeg',
				m2a: 'audio/mpeg',
				m2v: 'video/mpeg',
				m3u: 'audio/x-mpequrl',
				mid: 'audio/x-midi',
				midi: 'audio/x-midi',
				mjpg: 'video/x-motion-jpeg',
				moov: 'video/quicktime',
				mov: 'video/quicktime',
				movie: 'video/x-sgi-movie',
				mp2: 'audio/mpeg',
				mp3: 'audio/mpeg3',
				mpa: 'audio/mpeg',
				mpa: 'video/mpeg',
				mpe: 'video/mpeg',
				mpeg: 'video/mpeg',
				mpg: 'audio/mpeg',
				mpg: 'video/mpeg',
				mpga: 'audio/mpeg',
				pdf: 'application/pdf',
				png: 'image/png',
				pps: 'application/mspowerpoint',
				qt: 'video/quicktime',
				ram: 'audio/x-pn-realaudio-plugin',
				rm: 'application/vnd.rn-realmedia',
				swf: 'application/x-shockwave-flash',
				tiff: 'image/tiff',
				viv: 'video/vivo',
				vivo: 'video/vivo',
				wav: 'audio/wav',
				wmv: 'application/x-mplayer2'
			},
			classids: {
				mov: 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
				swf: 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000',
				wmv: 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6'
			},
			codebases: {
				mov: 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
				swf: 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0',
				wmv: 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715'
			},
			viewportPadding: 10,
			EOLASFix: 'swf,wmv,fla,flv',
			overlay: {
				opacity: 0.7,
				image: 'images/black.png',
				presetImage: 'images/black-70.png'
			},
			skin: {
				main: '<div id="lightwindow_container" >' +
				'<div id="lightwindow_title_bar" >' +
				'<div id="lightwindow_title_bar_inner" >' +
				'<span id="lightwindow_title_bar_title"></span>' +
				'<a id="lightwindow_title_bar_close_link"></a>' +
				'</div>' +
				'</div>' +
				'<div id="lightwindow_stage" >' +
				'<div id="lightwindow_contents" >' +
				'</div>' +
				'<div id="lightwindow_navigation" >' +
				'<a href="#" id="lightwindow_previous" >' +
				'<span id="lightwindow_previous_title"></span>' +
				'</a>' +
				'<a href="#" id="lightwindow_next" >' +
				'<span id="lightwindow_next_title"></span>' +
				'</a>' +
				'<iframe name="lightwindow_navigation_shim" id="lightwindow_navigation_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>' +
				'</div>' +
				'<div id="lightwindow_galleries">' +
				'<div id="lightwindow_galleries_tab_container" >' +
				'<a href="#" id="lightwindow_galleries_tab" >' +
				'<span id="lightwindow_galleries_tab_span" class="up" >Galleries</span>' +
				'</a>' +
				'</div>' +
				'<div id="lightwindow_galleries_list" >' +
				'</div>' +
				'</div>' +
				'</div>' +
				'<div id="lightwindow_data_slide" >' +
				'<div id="lightwindow_data_slide_inner" >' +
				'<div id="lightwindow_data_details" >' +
				'<div id="lightwindow_data_gallery_container" >' +
				'<span id="lightwindow_data_gallery_current"></span>' +
				' of ' +
				'<span id="lightwindow_data_gallery_total"></span>' +
				'</div>' +
				'<div id="lightwindow_data_author_container" >' +
				'by <span id="lightwindow_data_author"></span>' +
				'</div>' +
				'</div>' +
				'<div id="lightwindow_data_caption" >' +
				'</div>' +
				'</div>' +
				'</div>' +
				'</div>',
				loading: '<div id="lightwindow_loading" >' +
				'<img src="../../images/ajax-loading.gif" alt="loading" />' +
				'<span>Chargement en cours... <a href="javascript: myLightWindow.deactivate();">Annuler</a></span>' +
				'<iframe name="lightwindow_loading_shim" id="lightwindow_loading_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>' +
				'</div>',
				iframe: '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' +
				'<html xmlns="http://www.w3.org/1999/xhtml">' +
				'<body>' +
				'{body_replace}' +
				'</body>' +
				'</html>',
				gallery: {
					top: '<div class="lightwindow_galleries_list">' +
					'<h1>{gallery_title_replace}</h1>' +
					'<ul>',
					middle: '<li>' +
					'{gallery_link_replace}' +
					'</li>',
					bottom: '</ul>' +
					'</div>'
				}
			},
			formMethod: 'get',
			hideFlash: false,
			hideGalleryTab: false,
			showTitleBar: true,
			animationHandler: false,
			navigationHandler: false,
			transitionHandler: false,
			finalAnimationHandler: false,
			formHandler: false,
			galleryAnimationHandler: false,
			showGalleryCount: true
		},
		options || {
		});
		this.duration = ((11 - this.options.resizeSpeed) * 0.15);
		this._setupLinks();
		this._getScroll();
		this._getPageDimensions();
		this._browserDimensions();
		this._addLightWindowMarkup(false);
		this._setupDimensions();
		this.buildGalleryList();
	},
	//
	//	Activate the lightwindow.
	//
	activate: function (e, link) {
		// Clear out the window Contents
		this._clearWindowContents(true);
		
		// Add back in out loading panel
		this._addLoadingWindowMarkup();
		
		// Setup the element properties
		this._setupWindowElements(link);
		
		// Setup everything
		this._getScroll();
		this._browserDimensions();
		this._setupDimensions();
		this._toggleTroubleElements('hidden', false);
		this._displayLightWindow('block', 'hidden');
		this._setStatus(true);
		this._monitorKeyboard(true);
		this._prepareIE(true);
		this._loadWindow();
	},
	//
	//	Turn off the window
	//
	deactivate: function () {
		// The window is not active
		this.windowActive = false;
		
		// There is no longer a gallery active
		this.activeGallery = false;
		if (! this.options.hideGalleryTab) {
			this._handleGalleryAnimation(false);
		}
		
		// Kill the animation
		this.animating = false;
		
		// Clear our element
		this.element = null;
		
		// hide the window.
		this._displayLightWindow('none', 'visible');
		
		// Clear out the window Contents
		this._clearWindowContents(false);
		
		// Stop all animation
		var queue = Effect.Queues.get('lightwindowAnimation').each(function (e) {
			e.cancel();
		});
		
		// Undo the setup
		this._prepareIE(false);
		this._setupDimensions();
		this._toggleTroubleElements('visible', false);
		this._monitorKeyboard(false);
	},
	//
	//  Initialize specific window
	//
	createWindow: function (element, attributes) {
		this._processLink($(element));
	},
	//
	//  Open a Window from a hash of attributes
	//
	activateWindow: function (options) {
		this.element = Object.extend({
			href: null,
			title: null,
			author: null,
			caption: null,
			rel: null,
			top: null,
			left: null,
			type: null,
			showImages: null,
			height: null,
			width: null,
			loadingAnimation: null,
			iframeEmbed: null,
			form: null
		},
		options || {
		});
		
		// Set the window type
		this.contentToFetch = this.element.href;
		this.windowType = this.element.type? this.element.type: this._fileType(this.element.href);
		
		// Clear out the window Contents
		this._clearWindowContents(true);
		
		// Add back in out loading panel
		this._addLoadingWindowMarkup();
		
		// Setup everything
		this._getScroll();
		this._browserDimensions();
		this._setupDimensions();
		this._toggleTroubleElements('hidden', false);
		this._displayLightWindow('block', 'hidden');
		this._setStatus(true);
		this._monitorKeyboard(true);
		this._prepareIE(true);
		this._loadWindow();
	},
	//
	//  Fire off our Form handler
	//
	submitForm: function (e) {
		if (this.options.formHandler) {
			this.options.formHandler(e);
		} else {
			this._defaultFormHandler(e);
		}
	},
	//
	//	Reload the window with another location
	//
	openWindow: function (element) {
		var element = $(element);
		
		// The window is active
		this.windowActive = true;
		
		// Clear out the window Contents
		this._clearWindowContents(true);
		
		// Add back in out loading panel
		this._addLoadingWindowMarkup();
		
		// Setup the element properties
		this._setupWindowElements(element);
		
		this._setStatus(true);
		this._handleTransition();
	},
	//
	//  Navigate the window
	//
	navigateWindow: function (direction) {
		this._handleNavigation(false);
		if (direction == 'previous') {
			this.openWindow(this.navigationObservers.previous);
		} else if (direction == 'next') {
			this.openWindow(this.navigationObservers.next);
		}
	},
	//
	//  Build the Gallery List and Load it
	//
	buildGalleryList: function () {
		var output = '';
		var galleryLink;
		for (i in this.galleries) {
			if (typeof this.galleries[i] == 'object') {
				output += (this.options.skin.gallery.top).replace('{gallery_title_replace}', unescape(i));
				for (j in this.galleries[i]) {
					if (typeof this.galleries[i][j] == 'object') {
						galleryLink = '<a href="#" id="lightwindow_gallery_' + i + '_' + j + '" >' + unescape(j) + '</a>';
						output += (this.options.skin.gallery.middle).replace('{gallery_link_replace}', galleryLink);
					}
				}
				output += this.options.skin.gallery.bottom;
			}
		}
		new Insertion.Top('lightwindow_galleries_list', output);
		
		// Attach Events
		for (i in this.galleries) {
			if (typeof this.galleries[i] == 'object') {
				for (j in this.galleries[i]) {
					if (typeof this.galleries[i][j] == 'object') {
						Event.observe($('lightwindow_gallery_' + i + '_' + j), 'click', this.openWindow.bind(this, this.galleries[i][j][0]), false);
						$('lightwindow_gallery_' + i + '_' + j).onclick = function () {
							return false;
						};
					}
				}
			}
		}
	},
	//
	//  Set Links Up
	//
	_setupLinks: function () {
		var links = $$('.' + this.options.classNames.standard);
		links.each(function (link) {
			this._processLink(link);
		}
		.bind(this));
	},
	//
	//  Process a Link
	//
	_processLink: function (link) {
		if ((this._fileType(link.getAttribute('href')) == 'image' || this._fileType(link.getAttribute('href')) == 'media')) {
			if (gallery = this._getGalleryInfo(link.rel)) {
				if (! this.galleries[gallery[0]]) {
					this.galleries[gallery[0]] = new Array();
				}
				if (! this.galleries[gallery[0]][gallery[1]]) {
					this.galleries[gallery[0]][gallery[1]] = new Array();
				}
				this.galleries[gallery[0]][gallery[1]].push(link);
			}
		}
		
		// Take care of our inline content
		var url = link.getAttribute('href');
		if (url.indexOf('?') > - 1) {
			url = url.substring(0, url.indexOf('?'));
		}
		
		var container = url.substring(url.indexOf('#') + 1);
		if ($(container)) {
			$(container).setStyle({
				display: 'none'
			});
		}
		
		Event.observe(link, 'click', this.activate.bindAsEventListener(this, link), false);
		link.onclick = function () {
			return false;
		};
	},
	//
	//	Setup our actions
	//
	_setupActions: function () {
		var links = $$('#lightwindow_container .' + this.options.classNames.action);
		links.each(function (link) {
			Event.observe(link, 'click', this[link.getAttribute('rel')].bindAsEventListener(this, link), false);
			link.onclick = function () {
				return false;
			};
		}
		.bind(this));
	},
	//
	//	Add the markup to the page.
	//
	_addLightWindowMarkup: function (rebuild) {
		var overlay = Element.extend(document.createElement('div'));
		overlay.setAttribute('id', 'lightwindow_overlay');
		// FF Mac has a problem with putting Flash above a layer without a 100% opacity background, so we need to use a pre-made
		if (Prototype.Browser.Gecko) {
			overlay.setStyle({
				backgroundImage: 'url(' + this.options.overlay.presetImage + ')',
				backgroundRepeat: 'repeat',
				height: this.pageDimensions.height + 'px'
			});
		} else {
			overlay.setStyle({
				opacity: this.options.overlay.opacity,
				backgroundImage: 'url(' + this.options.overlay.image + ')',
				backgroundRepeat: 'repeat',
				height: this.pageDimensions.height + 'px'
			});
		}
		
		var lw = document.createElement('div');
		lw.setAttribute('id', 'lightwindow');
		lw.innerHTML = this.options.skin.main;
		
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(overlay);
		body.appendChild(lw);
		
		if ($('lightwindow_title_bar_close_link')) {
			Event.observe('lightwindow_title_bar_close_link', 'click', this.deactivate.bindAsEventListener(this));
			$('lightwindow_title_bar_close_link').onclick = function () {
				return false;
			};
		}
		
		Event.observe($('lightwindow_previous'), 'click', this.navigateWindow.bind(this, 'previous'), false);
		$('lightwindow_previous').onclick = function () {
			return false;
		};
		Event.observe($('lightwindow_next'), 'click', this.navigateWindow.bind(this, 'next'), false);
		$('lightwindow_next').onclick = function () {
			return false;
		};
		
		if (! this.options.hideGalleryTab) {
			Event.observe($('lightwindow_galleries_tab'), 'click', this._handleGalleryAnimation.bind(this, true), false);
			$('lightwindow_galleries_tab').onclick = function () {
				return false;
			};
		}
		
		// Because we use position absolute, kill the scroll Wheel on animations
		if (Prototype.Browser.IE) {
			Event.observe(document, 'mousewheel', this._stopScrolling.bindAsEventListener(this), false);
		} else {
			Event.observe(window, 'DOMMouseScroll', this._stopScrolling.bindAsEventListener(this), false);
		}
		
		Event.observe(overlay, 'click', this.deactivate.bindAsEventListener(this), false);
		overlay.onclick = function () {
			return false;
		};
	},
	//
	//  Add loading window markup
	//
	_addLoadingWindowMarkup: function () {
		$('lightwindow_contents').innerHTML += this.options.skin.loading;
	},
	//
	//  Setup the window elements
	//
	_setupWindowElements: function (link) {
		this.element = link;
		this.element.title = null? '': link.getAttribute('title');
		this.element.author = null? '': link.getAttribute('author');
		this.element.caption = null? '': link.getAttribute('caption');
		this.element.rel = null? '': link.getAttribute('rel');
		this.element.params = null? '': link.getAttribute('params');
		
		// Set the window type
		this.contentToFetch = this.element.href;
		this.windowType = this._getParameter('lightwindow_type')? this._getParameter('lightwindow_type'): this._fileType(this.contentToFetch);
	},
	//
	//  Clear the window contents out
	//
	_clearWindowContents: function (contents) {
		// If there is an iframe, its got to go
		if ($('lightwindow_iframe')) {
			Element.remove($('lightwindow_iframe'));
		}
		
		// Stop playing an object if its still around
		if ($('lightwindow_media_primary')) {
			try {
				$('lightwindow_media_primary').Stop();
			}
			catch (e) {
			}
			Element.remove($('lightwindow_media_primary'));
		}
		
		// Stop playing an object if its still around
		if ($('lightwindow_media_secondary')) {
			try {
				$('lightwindow_media_secondary').Stop();
			}
			catch (e) {
			}
			Element.remove($('lightwindow_media_secondary'));
		}
		
		this.activeGallery = false;
		this._handleNavigation(this.activeGallery);
		
		if (contents) {
			// Empty the contents
			$('lightwindow_contents').innerHTML = '';
			
			// Reset the scroll bars
			$('lightwindow_contents').setStyle({
				overflow: 'hidden'
			});
			
			if (! this.windowActive) {
				$('lightwindow_data_slide_inner').setStyle({
					display: 'none'
				});
				
				$('lightwindow_title_bar_title').innerHTML = '';
			}
			
			// Because of browser differences and to maintain flexible captions we need to reset this height at close
			$('lightwindow_data_slide').setStyle({
				height: 'auto'
			});
		}
		
		this.resizeTo.height = null;
		this.resizeTo.width = null;
	},
	//
	//	Set the status of our animation to keep things from getting clunky
	//
	_setStatus: function (status) {
		this.animating = status;
		if (status) {
			Element.show('lightwindow_loading');
		}
		if (!(/MSIE 6./i.test(navigator.userAgent))) {
			this._fixedWindow(status);
		}
	},
	//
	//  Make this window Fixed
	//
	_fixedWindow: function (status) {
		if (status) {
			if (this.windowActive) {
				this._getScroll();
				$('lightwindow').setStyle({
					position: 'absolute',
					top: parseFloat($('lightwindow').getStyle('top')) + this.pagePosition.y + 'px',
					left: parseFloat($('lightwindow').getStyle('left')) + this.pagePosition.x + 'px'
				});
			} else {
				$('lightwindow').setStyle({
					position: 'absolute'
				});
			}
		} else {
			if (this.windowActive) {
				this._getScroll();
				$('lightwindow').setStyle({
					position: 'fixed',
					top: parseFloat($('lightwindow').getStyle('top')) - this.pagePosition.y + 'px',
					left: parseFloat($('lightwindow').getStyle('left')) - this.pagePosition.x + 'px'
				});
			} else {
				if ($('lightwindow_iframe')) {
					// Ideally here we would set a 50% value for top and left, but Safari rears it ugly head again and we need to do it by pixels
					this._browserDimensions();
				}
				$('lightwindow').setStyle({
					position: 'fixed',
					top: (parseFloat(this._getParameter('lightwindow_top'))? parseFloat(this._getParameter('lightwindow_top')) + 'px': this.dimensions.viewport.height / 2 + 'px'),
					left: (parseFloat(this._getParameter('lightwindow_left'))? parseFloat(this._getParameter('lightwindow_left')) + 'px': this.dimensions.viewport.width / 2 + 'px')
				});
			}
		}
	},
	//
	//	Prepare the window for IE.
	//
	_prepareIE: function (setup) {
		if (Prototype.Browser.IE) {
			var height, overflowX, overflowY;
			if (setup) {
				var height = '100%';
			} else {
				var height = 'auto';
			}
			var body = document.getElementsByTagName('body')[0];
			var html = document.getElementsByTagName('html')[0];
			html.style.height = body.style.height = height;
		}
	},
	_stopScrolling: function (e) {
		if (this.animating) {
			if (e.preventDefault) {
				e.preventDefault();
			}
			e.returnValue = false;
		}
	},
	//
	//	Get the scroll for the page.
	//
	_getScroll: function () {
		if (typeof (window.pageYOffset) == 'number') {
			this.pagePosition.x = window.pageXOffset;
			this.pagePosition.y = window.pageYOffset;
		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			this.pagePosition.x = document.body.scrollLeft;
			this.pagePosition.y = document.body.scrollTop;
		} else if (document.documentElement) {
			this.pagePosition.x = document.documentElement.scrollLeft;
			this.pagePosition.y = document.documentElement.scrollTop;
		}
	},
	//
	//	Reset the scroll.
	//
	_setScroll: function (x, y) {
		document.documentElement.scrollLeft = x;
		document.documentElement.scrollTop = y;
	},
	//
	//	Hide Selects from the page because of IE.
	//     We could use iframe shims instead here but why add all the extra markup for one browser when this is much easier and cleaner
	//
	_toggleTroubleElements: function (visibility, content) {
		
		if (content) {
			var selects = $('lightwindow_contents').getElementsByTagName('select');
		} else {
			var selects = document.getElementsByTagName('select');
		}
		
		for (var i = 0; i < selects.length; i++) {
			selects[i].style.visibility = visibility;
		}
		
		if (! content) {
			if (this.options.hideFlash) {
				var objects = document.getElementsByTagName('object');
				for (i = 0; i != objects.length; i++) {
					objects[i].style.visibility = visibility;
				}
				var embeds = document.getElementsByTagName('embed');
				for (i = 0; i != embeds.length; i++) {
					embeds[i].style.visibility = visibility;
				}
			}
			//var iframes = document.getElementsByTagName('iframe');
			//for (i = 0; i != iframes.length; i++) {
			//	iframes[i].style.visibility = visibility;
			//}
		}
	},
	//
	//  Get the actual page size
	//
	_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) {
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else {
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		
		var windowWidth, windowHeight;
		if (self.innerHeight) {
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) {
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) {
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}
		
		if (yScroll < windowHeight) {
			this.pageDimensions.height = windowHeight;
		} else {
			this.pageDimensions.height = yScroll;
		}
		
		if (xScroll < windowWidth) {
			this.pageDimensions.width = windowWidth;
		} else {
			this.pageDimensions.width = xScroll;
		}
	},
	//
	//	Display the lightWindow.
	//
	_displayLightWindow: function (display, visibility) {
		$('lightwindow_overlay').style.display = $('lightwindow').style.display = $('lightwindow_container').style.display = display;
		$('lightwindow_overlay').style.visibility = $('lightwindow').style.visibility = $('lightwindow_container').style.visibility = visibility;
	},
	//
	//	Setup Dimensions of lightwindow.
	
	//
	_setupDimensions: function () {
		
		var originalHeight, originalWidth;
		switch (this.windowType) {
			case 'page':
			originalHeight = this.options.dimensions.page.height;
			originalWidth = this.options.dimensions.page.width;
			break;
			
			case 'image':
			originalHeight = this.options.dimensions.image.height;
			originalWidth = this.options.dimensions.image.width;
			break;
			
			case 'media':
			originalHeight = this.options.dimensions.media.height;
			originalWidth = this.options.dimensions.media.width;
			break;
			
			case 'external':
			originalHeight = this.options.dimensions.external.height;
			originalWidth = this.options.dimensions.external.width;
			break;
			
			case 'inline':
			originalHeight = this.options.dimensions.inline.height;
			originalWidth = this.options.dimensions.inline.width;
			break;
			
			default:
			originalHeight = this.options.dimensions.page.height;
			originalWidth = this.options.dimensions.page.width;
			break;
		}
		
		var offsetHeight = this._getParameter('lightwindow_top')? parseFloat(this._getParameter('lightwindow_top')) + this.pagePosition.y: this.dimensions.viewport.height / 2 + this.pagePosition.y;
		var offsetWidth = this._getParameter('lightwindow_left')? parseFloat(this._getParameter('lightwindow_left')) + this.pagePosition.x: this.dimensions.viewport.width / 2 + this.pagePosition.x;
		
		// So if a theme has say shadowed edges, they should be consistant and take care of in the contentOffset
		$('lightwindow').setStyle({
			top: offsetHeight + 'px',
			left: offsetWidth + 'px'
		});
		
		$('lightwindow_container').setStyle({
			height: originalHeight + 'px',
			width: originalWidth + 'px',
			left: -(originalWidth / 2) + 'px',
			top: -(originalHeight / 2) + 'px'
		});
		
		$('lightwindow_contents').setStyle({
			height: originalHeight + 'px',
			width: originalWidth + 'px'
		});
	},
	//
	//	Get the type of file.
	//
	_fileType: function (url) {
		var image = new RegExp("[^\.]\.(" + this.options.fileTypes.image.join('|') + ")\s*$", "i");
		if (image.test(url)) return 'image';
		if (url.indexOf('#') > - 1 && (document.domain == this._getDomain(url))) return 'inline';
		if (url.indexOf('?') > - 1) url = url.substring(0, url.indexOf('?'));
		var type = 'unknown';
		var page = new RegExp("[^\.]\.(" + this.options.fileTypes.page.join('|') + ")\s*$", "i");
		var media = new RegExp("[^\.]\.(" + this.options.fileTypes.media.join('|') + ")\s*$", "i");
		if (document.domain != this._getDomain(url)) type = 'external';
		if (media.test(url)) type = 'media';
		if (type == 'external' || type == 'media') return type;
		if (page.test(url) || url.substr((url.length - 1), url.length) == '/') type = 'page';
		return type;
	},
	//
	//  Get file Extension
	//
	_fileExtension: function (url) {
		if (url.indexOf('?') > - 1) {
			url = url.substring(0, url.indexOf('?'));
		}
		var extenstion = '';
		for (var x = (url.length - 1);
		x > - 1; x--) {
			if (url.charAt(x) == '.') {
				return extenstion;
			}
			extenstion = url.charAt(x) + extenstion;
		}
	},
	//
	//	Monitor the keyboard while this lightwindow is up
	//
	_monitorKeyboard: function (status) {
		if (status) document.onkeydown = this._eventKeypress.bind(this); else document.onkeydown = '';
	},
	//
	//  Perform keyboard actions
	//
	_eventKeypress: function (e) {
		if (e == null) {
			var keycode = event.keyCode;
		} else {
			var keycode = e.which;
		}
		
		switch (keycode) {
			case 27:
			this.deactivate();
			break;
			
			case 13:
			return;
			
			default:
			break;
		}
		
		// Gotta stop those quick fingers
		if (this.animating) {
			return false;
		}
		
		switch (String.fromCharCode(keycode).toLowerCase()) {
			case 'p':
			if (this.navigationObservers.previous) {
				this.navigateWindow('previous');
			}
			break;
			
			case 'n':
			if (this.navigationObservers.next) {
				this.navigateWindow('next');
			}
			break;
			
			default:
			break;
		}
	},
	//
	//	Get Gallery Information
	//
	_getGalleryInfo: function (rel) {
		if (! rel) return false;
		if (rel.indexOf('[') > - 1) {
			return new Array(escape(rel.substring(0, rel.indexOf('['))), escape(rel.substring(rel.indexOf('[') + 1, rel.indexOf(']'))));
		} else {
			return false;
		}
	},
	//
	//	Get the domain from a string.
	//
	_getDomain: function (url) {
		var leadSlashes = url.indexOf('//');
		var domainStart = leadSlashes + 2;
		var withoutResource = url.substring(domainStart, url.length);
		var nextSlash = withoutResource.indexOf('/');
		var domain = withoutResource.substring(0, nextSlash);
		if (domain.indexOf(':') > - 1) {
			var portColon = domain.indexOf(':');
			domain = domain.substring(0, portColon);
		}
		return domain;
	},
	//
	//	Get the value from the params attribute string.
	//
	_getParameter: function (parameter, parameters) {
		if (! this.element) return false;
		if (parameter == 'lightwindow_top' && this.element.top) {
			return unescape(this.element.top);
		} else if (parameter == 'lightwindow_left' && this.element.left) {
			return unescape(this.element.left);
		} else if (parameter == 'lightwindow_type' && this.element.type) {
			return unescape(this.element.type);
		} else if (parameter == 'lightwindow_show_images' && this.element.showImages) {
			return unescape(this.element.showImages);
		} else if (parameter == 'lightwindow_height' && this.element.height) {
			return unescape(this.element.height);
		} else if (parameter == 'lightwindow_width' && this.element.width) {
			return unescape(this.element.width);
		} else if (parameter == 'lightwindow_loading_animation' && this.element.loadingAnimation) {
			return unescape(this.element.loadingAnimation);
		} else if (parameter == 'lightwindow_iframe_embed' && this.element.iframeEmbed) {
			return unescape(this.element.iframeEmbed);
		} else if (parameter == 'lightwindow_form' && this.element.form) {
			return unescape(this.element.form);
		} else {
			if (! parameters) {
				if (this.element.params) parameters = this.element.params; else return;
			}
			var value;
			var parameterArray = parameters.split(',');
			var compareString = parameter + '=';
			var compareLength = compareString.length;
			for (var i = 0; i < parameterArray.length; i++) {
				if (parameterArray[i].substr(0, compareLength) == compareString) {
					var currentParameter = parameterArray[i].split('=');
					value = currentParameter[1];
					break;
				}
			}
			if (! value) return false; else return unescape(value);
		}
	},
	//
	//  Get the Browser Viewport Dimensions
	//
	_browserDimensions: function () {
		if (Prototype.Browser.IE) {
			this.dimensions.viewport.height = document.documentElement.clientHeight;
			this.dimensions.viewport.width = document.documentElement.clientWidth;
		} else {
			this.dimensions.viewport.height = window.innerHeight;
			this.dimensions.viewport.width = document.width || document.body.offsetWidth;
		}
	},
	//
	//  Get the scrollbar offset, I don't like this method but there is really no other way I can find.
	//
	_getScrollerWidth: function () {
		var scrollDiv = Element.extend(document.createElement('div'));
		scrollDiv.setAttribute('id', 'lightwindow_scroll_div');
		scrollDiv.setStyle({
			position: 'absolute',
			top: '-10000px',
			left: '-10000px',
			width: '100px',
			height: '100px',
			overflow: 'hidden'
		});
		
		
		
		var contentDiv = Element.extend(document.createElement('div'));
		contentDiv.setAttribute('id', 'lightwindow_content_scroll_div');
		contentDiv.setStyle({
			width: '100%',
			height: '200px'
		});
		
		scrollDiv.appendChild(contentDiv);
		
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(scrollDiv);
		
		var noScroll = $('lightwindow_content_scroll_div').offsetWidth;
		scrollDiv.style.overflow = 'auto';
		var withScroll = $('lightwindow_content_scroll_div').offsetWidth;
		
		Element.remove($('lightwindow_scroll_div'));
		
		this.scrollbarOffset = noScroll - withScroll;
	},
	
	
	//
	//  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;
	},
	//
	//  Get the outer HTML of an object CROSS BROWSER
	//
	_outerHTML: function (object) {
		if (Prototype.Browser.IE) {
			return object.outerHTML;
		} else {
			var clone = object.cloneNode(true);
			var cloneDiv = document.createElement('div');
			cloneDiv.appendChild(clone);
			return cloneDiv.innerHTML;
		}
	},
	//
	//  Convert an object to markup
	//
	_convertToMarkup: function (object, closeTag) {
		var markup = this._outerHTML(object).replace('</' + closeTag + '>', '');
		if (Prototype.Browser.IE) {
			for (var i = 0; i < object.childNodes.length; i++) {
				markup += this._outerHTML(object.childNodes[i]);
			}
			markup += '</' + closeTag + '>';
		}
		return markup;
	},
	//
	//  Depending what type of browser it is we have to append the object differently... DAMN YOU IE!!
	//
	_appendObject: function (object, closeTag, appendTo) {
		if (Prototype.Browser.IE) {
			appendTo.innerHTML += this._convertToMarkup(object, closeTag);
			
			// Fix the Eolas activate thing but only for specified media, for example doing this to a quicktime film breaks it.
			if (this.options.EOLASFix.indexOf(this._fileType(this.element.href)) > - 1) {
				var objectElements = document.getElementsByTagName('object');
				for (var i = 0; i < objectElements.length; i++) {
					if (objectElements[i].getAttribute("data")) objectElements[i].removeAttribute('data');
					objectElements[i].outerHTML = objectElements[i].outerHTML;
					objectElements[i].style.visibility = "visible";
				}
			}
		} else {
			appendTo.appendChild(object);
		}
	},
	//
	//  Add in iframe
	//
	_appendIframe: function (scroll) {
		var iframe = document.createElement('iframe');
		iframe.setAttribute('id', 'lightwindow_iframe');
		iframe.setAttribute('name', 'lightwindow_iframe');
		iframe.setAttribute('src', 'about:blank');
		iframe.setAttribute('height', '100%');
		iframe.setAttribute('width', '100%');
		iframe.setAttribute('frameborder', '0');
		iframe.setAttribute('marginwidth', '0');
		iframe.setAttribute('marginheight', '0');
		iframe.setAttribute('scrolling', scroll);
		
		this._appendObject(iframe, 'iframe', $('lightwindow_contents'));
	},
	//
	//  Write Content to the iframe using the skin
	//
	_writeToIframe: function (content) {
		var template = this.options.skin.iframe;
		template = template.replace('{body_replace}', content);
		if ($('lightwindow_iframe').contentWindow) {
			$('lightwindow_iframe').contentWindow.document.open();
			$('lightwindow_iframe').contentWindow.document.write(template);
			$('lightwindow_iframe').contentWindow.document.close();
		} else {
			$('lightwindow_iframe').contentDocument.open();
			$('lightwindow_iframe').contentDocument.write(template);
			$('lightwindow_iframe').contentDocument.close();
		}
	},
	//
	//  Load the window Information
	//
	_loadWindow: function () {
		switch (this.windowType) {
			case 'image':
			
			var current = 0;
			var images =[];
			this.checkImage =[];
			this.resizeTo.height = this.resizeTo.width = 0;
			this.imageCount = this._getParameter('lightwindow_show_images')? parseInt(this._getParameter('lightwindow_show_images')): 1;
			
			// If there is a gallery get it
			if (gallery = this._getGalleryInfo(this.element.rel)) {
				for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
					if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > - 1) {
						break;
					}
				}
				if (this.galleries[gallery[0]][gallery[1]][current - this.imageCount]) {
					this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current - this.imageCount];
				} else {
					this.navigationObservers.previous = false;
				}
				if (this.galleries[gallery[0]][gallery[1]][current + this.imageCount]) {
					this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current + this.imageCount];
				} else {
					this.navigationObservers.next = false;
				}
				
				this.activeGallery = true;
			} else {
				this.navigationObservers.previous = false;
				this.navigationObservers.next = false;
				
				this.activeGallery = false;
			}
			
			for (var i = current; i < (current + this.imageCount);
			i++) {
				
				if (gallery && this.galleries[gallery[0]][gallery[1]][i]) {
					this.contentToFetch = this.galleries[gallery[0]][gallery[1]][i].href;
					
					this.galleryLocation = {
						current: (i + 1) /this.imageCount, total: (this.galleries[gallery[0]][gallery[1]].length)/ this.imageCount
					};
					
					if (! this.galleries[gallery[0]][gallery[1]][i + this.imageCount]) {
						$('lightwindow_next').setStyle({
							display: 'none'
						});
					} else {
						$('lightwindow_next').setStyle({
							display: 'block'
						});
						$('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i + this.imageCount].title;
					}
					
					if (! this.galleries[gallery[0]][gallery[1]][i - this.imageCount]) {
						$('lightwindow_previous').setStyle({
							display: 'none'
						});
					} else {
						$('lightwindow_previous').setStyle({
							display: 'block'
						});
						$('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i - this.imageCount].title;
					}
				}
				
				images[i] = document.createElement('img');
				images[i].setAttribute('id', 'lightwindow_image_' + i);
				images[i].setAttribute('border', '0');
				images[i].setAttribute('src', this.contentToFetch);
				$('lightwindow_contents').appendChild(images[i]);
				
				// We have to do this instead of .onload
				this.checkImage[i] = new PeriodicalExecuter(function (i) {
					if (!(typeof $('lightwindow_image_' + i).naturalWidth != "undefined" && $('lightwindow_image_' + i).naturalWidth == 0)) {
						
						this.checkImage[i].stop();
						
						var imageHeight = $('lightwindow_image_' + i).getHeight();
						if (imageHeight > this.resizeTo.height) {
							this.resizeTo.height = imageHeight;
						}
						this.resizeTo.width += $('lightwindow_image_' + i).getWidth();
						this.imageCount--;
						
						$('lightwindow_image_' + i).setStyle({
							height: '100%'
						});
						
						if (this.imageCount == 0) {
							this._processWindow();
						}
					}
				}
				.bind(this, i), 1);
			}
			
			
			break;
			
			case 'media':
			
			var current = 0;
			this.resizeTo.height = this.resizeTo.width = 0;
			
			// If there is a gallery get it
			if (gallery = this._getGalleryInfo(this.element.rel)) {
				for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
					if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > - 1) {
						break;
					}
				}
				
				if (this.galleries[gallery[0]][gallery[1]][current - 1]) {
					this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current - 1];
				} else {
					this.navigationObservers.previous = false;
				}
				if (this.galleries[gallery[0]][gallery[1]][current + 1]) {
					this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current + 1];
				} else {
					this.navigationObservers.next = false;
				}
				
				this.activeGallery = true;
			} else {
				this.navigationObservers.previous = false;
				this.navigationObservers.next = false;
				
				this.activeGallery = false;
			}
			
			
			if (gallery && this.galleries[gallery[0]][gallery[1]][current]) {
				this.contentToFetch = this.galleries[gallery[0]][gallery[1]][current].href;
				
				this.galleryLocation = {
					current: current + 1, total: this.galleries[gallery[0]][gallery[1]].length
				};
				
				if (! this.galleries[gallery[0]][gallery[1]][current + 1]) {
					$('lightwindow_next').setStyle({
						display: 'none'
					});
				} else {
					$('lightwindow_next').setStyle({
						display: 'block'
					});
					$('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current + 1].title;
				}
				
				if (! this.galleries[gallery[0]][gallery[1]][current - 1]) {
					$('lightwindow_previous').setStyle({
						display: 'none'
					});
				} else {
					$('lightwindow_previous').setStyle({
						display: 'block'
					});
					$('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current - 1].title;
				}
			}
			
			if (this._getParameter('lightwindow_iframe_embed')) {
				this.resizeTo.height = this.dimensions.viewport.height;
				this.resizeTo.width = this.dimensions.viewport.width;
			} else {
				this.resizeTo.height = this._getParameter('lightwindow_height');
				this.resizeTo.width = this._getParameter('lightwindow_width');
			}
			
			this._processWindow();
			
			break;
			
			case 'external':
			
			this._appendIframe('auto');
			
			this.resizeTo.height = this.dimensions.viewport.height;
			this.resizeTo.width = this.dimensions.viewport.width;
			
			this._processWindow();
			
			break;
			
			case 'page':
			
			var newAJAX = new Ajax.Request(
			this.contentToFetch, {
				method: 'get',
				parameters: '',
				onComplete: function (response) {
					$('lightwindow_contents').innerHTML += response.responseText;
					this.resizeTo.height = $('lightwindow_contents').scrollHeight +(this.options.contentOffset.height);
					this.resizeTo.width = $('lightwindow_contents').scrollWidth +(this.options.contentOffset.width);
					this._processWindow();
				}
				.bind(this)
			});
			
			break;
			
			case 'inline':
			
			var content = this.contentToFetch;
			if (content.indexOf('?') > - 1) {
				content = content.substring(0, content.indexOf('?'));
			}
			content = content.substring(content.indexOf('#') + 1);
			
			new Insertion.Top($('lightwindow_contents'), $(content).innerHTML);
			
			this.resizeTo.height = $('lightwindow_contents').scrollHeight +(this.options.contentOffset.height);
			this.resizeTo.width = $('lightwindow_contents').scrollWidth +(this.options.contentOffset.width);
			
			this._toggleTroubleElements('hidden', true);
			this._processWindow();
			
			break;
			
			default:
			throw ("Page Type could not be determined, please amend this lightwindow URL " + this.contentToFetch);
			break;
		}
	},
	//
	//  Resize the Window to fit the viewport if necessary
	//
	_resizeWindowToFit: function () {
		if (this.resizeTo.height + this.dimensions.cruft.height > this.dimensions.viewport.height) {
			var heightRatio = this.resizeTo.height / this.resizeTo.width;
			this.resizeTo.height = this.dimensions.viewport.height - this.dimensions.cruft.height -(2 * this.options.viewportPadding);
			// We only care about ratio's with this window type
			if (this.windowType == 'image' || (this.windowType == 'media' && ! this._getParameter('lightwindow_iframe_embed'))) {
				this.resizeTo.width = this.resizeTo.height / heightRatio;
				$('lightwindow_data_slide_inner').setStyle({
					width: this.resizeTo.width + 'px'
				});
			}
		}
		if (this.resizeTo.width + this.dimensions.cruft.width > this.dimensions.viewport.width) {
			var widthRatio = this.resizeTo.width / this.resizeTo.height;
			this.resizeTo.width = this.dimensions.viewport.width - 2 * this.dimensions.cruft.width -(2 * this.options.viewportPadding);
			// We only care about ratio's with this window type
			if (this.windowType == 'image' || (this.windowType == 'media' && ! this._getParameter('lightwindow_iframe_embed'))) {
				this.resizeTo.height = this.resizeTo.width / widthRatio;
				$('lightwindow_data_slide_inner').setStyle({
					height: this.resizeTo.height + 'px'
				});
			}
		}
	},
	//
	//  Set the Window to a preset size
	//
	_presetWindowSize: function () {
		if (this._getParameter('lightwindow_height')) {
			this.resizeTo.height = parseFloat(this._getParameter('lightwindow_height'));
		}
		if (this._getParameter('lightwindow_width')) {
			this.resizeTo.width = parseFloat(this._getParameter('lightwindow_width'));
		}
	},
	//
	//  Process the Window
	//
	_processWindow: function () {
		// Clean out our effects
		this.dimensions.dataEffects =[];
		
		// Set up the data-slide if we have caption information
		if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
			if (this.element.caption) {
				$('lightwindow_data_caption').innerHTML = this.element.caption;
				$('lightwindow_data_caption').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_caption').setStyle({
					display: 'none'
				});
			}
			if (this.element.author) {
				$('lightwindow_data_author').innerHTML = this.element.author;
				$('lightwindow_data_author_container').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_author_container').setStyle({
					display: 'none'
				});
			}
			if (this.activeGallery && this.options.showGalleryCount) {
				$('lightwindow_data_gallery_current').innerHTML = this.galleryLocation.current;
				$('lightwindow_data_gallery_total').innerHTML = this.galleryLocation.total;
				$('lightwindow_data_gallery_container').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_gallery_container').setStyle({
					display: 'none'
				});
			}
			
			$('lightwindow_data_slide_inner').setStyle({
				width: this.resizeTo.width + 'px',
				height: 'auto',
				visibility: 'visible',
				display: 'block'
			});
			$('lightwindow_data_slide').setStyle({
				height: $('lightwindow_data_slide').getHeight() + 'px',
				width: '1px',
				overflow: 'hidden',
				display: 'block'
			});
		} else {
			$('lightwindow_data_slide').setStyle({
				display: 'none',
				width: 'auto'
			});
			$('lightwindow_data_slide_inner').setStyle({
				display: 'none',
				visibility: 'hidden',
				width: this.resizeTo.width + 'px',
				height: '0px'
			});
		}
		
		if (this.element.title != 'null') {
			$('lightwindow_title_bar_title').innerHTML = this.element.title;
		} else {
			$('lightwindow_title_bar_title').innerHTML = '';
		}
		
		var originalContainerDimensions = {
			height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()
		};
		// Position the window
		$('lightwindow_container').setStyle({
			height: 'auto',
			// We need to set the width to a px not auto as opera has problems with it
			width: $('lightwindow_container').getWidth() + this.options.contentOffset.width -(this.windowActive? this.options.contentOffset.width: 0) + 'px'
		});
		var newContainerDimensions = {
			height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()
		};
		
		// We need to record the container dimension changes
		this.containerChange = {
			height: originalContainerDimensions.height - newContainerDimensions.height, width: originalContainerDimensions.width - newContainerDimensions.width
		};
		
		// Get out general dimensions
		this.dimensions.container = {
			height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()
		};
		this.dimensions.cruft = {
			height: this.dimensions.container.height - $('lightwindow_contents').getHeight() + this.options.contentOffset.height, width: this.dimensions.container.width - $('lightwindow_contents').getWidth() + this.options.contentOffset.width
		};
		
		// Set Sizes if we need too
		this._presetWindowSize();
		this._resizeWindowToFit();
		// Even if the window is preset we still don't want it to go outside of the viewport
		
		if (! this.windowActive) {
			// Position the window
			$('lightwindow_container').setStyle({
				left: -(this.dimensions.container.width / 2) + 'px',
				top: -(this.dimensions.container.height / 2) + 'px'
			});
		}
		$('lightwindow_container').setStyle({
			height: this.dimensions.container.height + 'px',
			width: this.dimensions.container.width + 'px'
		});
		
		// We are ready, lets show this puppy off!
		this._displayLightWindow('block', 'visible');
		this._animateLightWindow();
	},
	//
	//  Fire off our animation handler
	//
	_animateLightWindow: function () {
		if (this.options.animationHandler) {
			this.options.animationHandler().bind(this);
		} else {
			this._defaultAnimationHandler();
		}
	},
	//
	//  Fire off our transition handler
	//
	_handleNavigation: function (display) {
		if (this.options.navigationHandler) {
			this.options.navigationHandler().bind(this, display);
		} else {
			this._defaultDisplayNavigation(display);
		}
	},
	//
	//  Fire off our transition handler
	//
	_handleTransition: function () {
		if (this.options.transitionHandler) {
			this.options.transitionHandler().bind(this);
		} else {
			this._defaultTransitionHandler();
		}
	},
	//
	//  Handle the finish of the window animation
	//
	_handleFinalWindowAnimation: function (delay) {
		if (this.options.finalAnimationHandler) {
			this.options.finalAnimationHandler().bind(this, delay);
		} else {
			this._defaultfinalWindowAnimationHandler(delay);
		}
	},
	//
	//  Handle the gallery Animation
	//
	_handleGalleryAnimation: function (list) {
		if (this.options.galleryAnimationHandler) {
			this.options.galleryAnimationHandler().bind(this, list);
		} else {
			this._defaultGalleryAnimationHandler(list);
		}
	},
	//
	//  Display the navigation
	//
	_defaultDisplayNavigation: function (display) {
		if (display) {
			$('lightwindow_navigation').setStyle({
				display: 'block',
				height: $('lightwindow_contents').getHeight() + 'px',
				width: '100%',
				marginTop: this.options.dimensions.titleHeight + 'px'
			});
		} else {
			$('lightwindow_navigation').setStyle({
				display: 'none',
				height: 'auto',
				width: 'auto'
			});
		}
	},
	//
	//  This is the default animation handler for LightWindow
	//
	_defaultAnimationHandler: function () {
		// Now that we have figures out the cruft lets make the caption go away and add its effects
		if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
			$('lightwindow_data_slide').setStyle({
				display: 'none',
				width: 'auto'
			});
			this.dimensions.dataEffects.push(
			new Effect.SlideDown('lightwindow_data_slide', {
				sync: true
			}),
			new Effect.Appear('lightwindow_data_slide', {
				sync: true, from: 0.0, to: 1.0
			}));
		}
		
		// Set up the Title if we have one
		$('lightwindow_title_bar_inner').setStyle({
			height: '0px',
			marginTop: this.options.dimensions.titleHeight + 'px'
		});
		
		// We always want the title bar as well
		this.dimensions.dataEffects.push(
		new Effect.Morph('lightwindow_title_bar_inner', {
			sync: true, style: {
				height: this.options.dimensions.titleHeight + 'px', marginTop: '0px'
			}
		}),
		new Effect.Appear('lightwindow_title_bar_inner', {
			sync: true, from: 0.0, to: 1.0
		}));
		
		if (! this.options.hideGalleryTab) {
			this._handleGalleryAnimation(false);
			if ($('lightwindow_galleries_tab_container').getHeight() == 0) {
				this.dimensions.dataEffects.push(
				new Effect.Morph('lightwindow_galleries_tab_container', {
					sync: true, style: {
						height: '20px', marginTop: '0px'
					}
				}));
				$('lightwindow_galleries').setStyle({
					width: '0px'
				});
			}
		}
		
		var resized = false;
		var ratio = this.dimensions.container.width - $('lightwindow_contents').getWidth() + this.resizeTo.width + this.options.contentOffset.width;
		if (ratio != $('lightwindow_container').getWidth()) {
			new Effect.Parallel([
			new Effect.Scale('lightwindow_contents', 100 *(this.resizeTo.width / $('lightwindow_contents').getWidth()), {
				scaleFrom: 100 *($('lightwindow_contents').getWidth() /($('lightwindow_contents').getWidth() +(this.options.contentOffset.width))), sync: true, scaleY: false, scaleContent: false
			}),
			new Effect.Scale('lightwindow_container', 100 *(ratio /(this.dimensions.container.width)), {
				sync: true, scaleY: false, scaleFromCenter: true, scaleContent: false
			})], {
				duration: this.duration,
				delay: 0.25,
				queue: {
					position: 'end', scope: 'lightwindowAnimation'
				}
			});
		}
		
		ratio = this.dimensions.container.height - $('lightwindow_contents').getHeight() + this.resizeTo.height + this.options.contentOffset.height;
		if (ratio != $('lightwindow_container').getHeight()) {
			new Effect.Parallel([
			new Effect.Scale('lightwindow_contents', 100 *(this.resizeTo.height / $('lightwindow_contents').getHeight()), {
				scaleFrom: 100 *($('lightwindow_contents').getHeight() /($('lightwindow_contents').getHeight() +(this.options.contentOffset.height))), sync: true, scaleX: false, scaleContent: false
			}),
			new Effect.Scale('lightwindow_container', 100 *(ratio /(this.dimensions.container.height)), {
				sync: true, scaleX: false, scaleFromCenter: true, scaleContent: false
			})], {
				duration: this.duration,
				afterFinish: function () {
					if (this.dimensions.dataEffects.length > 0) {
						if (! this.options.hideGalleryTab) {
							$('lightwindow_galleries').setStyle({
								width: this.resizeTo.width + 'px'
							});
						}
						new Effect.Parallel(this.dimensions.dataEffects, {
							duration: this.duration,
							afterFinish: function () {
								this._finishWindow();
							}
							.bind(this),
							queue: {
								position: 'end', scope: 'lightwindowAnimation'
							}
						});
					}
				}
				.bind(this),
				queue: {
					position: 'end', scope: 'lightwindowAnimation'
				}
			});
			resized = true;
		}
		
		// We need to do our data effect since there was no resizing
		if (! resized && this.dimensions.dataEffects.length > 0) {
			new Effect.Parallel(this.dimensions.dataEffects, {
				duration: this.duration,
				beforeStart: function () {
					if (! this.options.hideGalleryTab) {
						$('lightwindow_galleries').setStyle({
							width: this.resizeTo.width + 'px'
						});
					}
					if (this.containerChange.height != 0 || this.containerChange.width != 0) {
						new Effect.MoveBy('lightwindow_container', this.containerChange.height, this.containerChange.width, {
							transition: Effect.Transitions.sinoidal
						});
					}
				}
				.bind(this),
				afterFinish: function () {
					this._finishWindow();
				}
				.bind(this),
				queue: {
					position: 'end', scope: 'lightwindowAnimation'
				}
			});
		}
	},
	//
	//  Finish up Window Animation
	//
	_defaultfinalWindowAnimationHandler: function (delay) {
		if (this.windowType == 'media' || this._getParameter('lightwindow_loading_animation')) {
			// Because of major flickering with the overlay we just hide it in this case
			Element.hide('lightwindow_loading');
			this._handleNavigation(this.activeGallery);
			this._setStatus(false);
		} else {
			Effect.Fade('lightwindow_loading', {
				duration: 0.75,
				delay: 1.0,
				afterFinish: function () {
					// Just in case we need some scroll goodness (this also avoids the swiss cheese effect)
					if (this.windowType != 'image' && this.windowType != 'media' && this.windowType != 'external') {
						$('lightwindow_contents').setStyle({
							overflow: 'auto'
						});
					}
					this._handleNavigation(this.activeGallery);
					this._defaultGalleryAnimationHandler();
					this._setStatus(false);
				}
				.bind(this),
				queue: {
					position: 'end', scope: 'lightwindowAnimation'
				}
			});
		}
	},
	//
	//  Handle the gallery Animation
	//
	_defaultGalleryAnimationHandler: function (list) {
		if (this.activeGallery) {
			$('lightwindow_galleries').setStyle({
				display: 'block',
				marginBottom: $('lightwindow_data_slide').getHeight() + this.options.contentOffset.height / 2 + 'px'
			});
			$('lightwindow_navigation').setStyle({
				height: $('lightwindow_contents').getHeight() - 20 + 'px'
			});
		} else {
			$('lightwindow_galleries').setStyle({
				display: 'none'
			});
			$('lightwindow_galleries_tab_container').setStyle({
				height: '0px',
				marginTop: '20px'
			});
			$('lightwindow_galleries_list').setStyle({
				height: '0px'
			});
			return false;
		}
		
		if (list) {
			if ($('lightwindow_galleries_list').getHeight() == 0) {
				var height = $('lightwindow_contents').getHeight() * 0.80;
				$('lightwindow_galleries_tab_span').className = 'down';
			} else {
				var height = 0;
				$('lightwindow_galleries_tab_span').className = 'up';
			}
			
			new Effect.Morph('lightwindow_galleries_list', {
				duration: this.duration,
				transition: Effect.Transitions.sinoidal,
				style: {
					height: height + 'px'
				},
				beforeStart: function () {
					$('lightwindow_galleries_list').setStyle({
						overflow: 'hidden'
					});
				},
				afterFinish: function () {
					$('lightwindow_galleries_list').setStyle({
						overflow: 'auto'
					});
				},
				queue: {
					position: 'end', scope: 'lightwindowAnimation'
				}
			});
		}
	},
	//
	//  Default Transition Handler
	//
	_defaultTransitionHandler: function () {
		// Clean out our effects
		this.dimensions.dataEffects =[];
		
		// Now that we have figures out the cruft lets make the caption go away and add its effects
		if ($('lightwindow_data_slide').getStyle('display') != 'none') {
			this.dimensions.dataEffects.push(
			new Effect.SlideUp('lightwindow_data_slide', {
				sync: true
			}),
			new Effect.Fade('lightwindow_data_slide', {
				sync: true, from: 1.0, to: 0.0
			}));
		}
		
		if (! this.options.hideGalleryTab) {
			if ($('lightwindow_galleries').getHeight() != 0 && ! this.options.hideGalleryTab) {
				this.dimensions.dataEffects.push(
				new Effect.Morph('lightwindow_galleries_tab_container', {
					sync: true, style: {
						height: '0px', marginTop: '20px'
					}
				}));
			}
			
			if ($('lightwindow_galleries_list').getHeight() != 0) {
				$('lightwindow_galleries_tab_span').className = 'up';
				this.dimensions.dataEffects.push(
				new Effect.Morph('lightwindow_galleries_list', {
					sync: true,
					style: {
						height: '0px'
					},
					transition: Effect.Transitions.sinoidal,
					beforeStart: function () {
						$('lightwindow_galleries_list').setStyle({
							overflow: 'hidden'
						});
					},
					afterFinish: function () {
						$('lightwindow_galleries_list').setStyle({
							overflow: 'auto'
						});
					}
				}));
			}
		}
		
		// We always want the title bar as well
		this.dimensions.dataEffects.push(
		new Effect.Morph('lightwindow_title_bar_inner', {
			sync: true, style: {
				height: '0px', marginTop: this.options.dimensions.titleHeight + 'px'
			}
		}),
		new Effect.Fade('lightwindow_title_bar_inner', {
			sync: true, from: 1.0, to: 0.0
		}));
		
		new Effect.Parallel(this.dimensions.dataEffects, {
			duration: this.duration,
			afterFinish: function () {
				this._loadWindow();
			}
			.bind(this),
			queue: {
				position: 'end', scope: 'lightwindowAnimation'
			}
		});
	},
	//
	//	Default Form handler for LightWindow
	//
	_defaultFormHandler: function (e) {
		var element = Event.element(e).parentNode;
		var parameterString = Form.serialize(this._getParameter('lightwindow_form', element.getAttribute('params')));
		if (this.options.formMethod == 'post') {
			var newAJAX = new Ajax.Request(element.href, {
				method: 'post',
				postBody: parameterString,
				onComplete: this.openWindow.bind(this, element)
			});
		} else if (this.options.formMethod == 'get') {
			var newAJAX = new Ajax.Request(element.href, {
				method: 'get',
				parameters: parameterString,
				onComplete: this.openWindow.bind(this, element)
			});
		}
	},
	//
	//  Wrap everything up
	//
	_finishWindow: function () {
		if (this.windowType == 'external') {
			// We set the externals source here because it allows for a much smoother animation
			$('lightwindow_iframe').setAttribute('src', this.element.href);
			this._handleFinalWindowAnimation(1);
		} else if (this.windowType == 'media') {
			
			var outerObject = document.createElement('object');
			outerObject.setAttribute('classid', this.options.classids[ this._fileExtension(this.contentToFetch)]);
			outerObject.setAttribute('codebase', this.options.codebases[ this._fileExtension(this.contentToFetch)]);
			outerObject.setAttribute('id', 'lightwindow_media_primary');
			outerObject.setAttribute('name', 'lightwindow_media_primary');
			outerObject.setAttribute('width', this.resizeTo.width);
			outerObject.setAttribute('height', this.resizeTo.height);
			outerObject = this._addParamToObject('movie', this.contentToFetch, outerObject);
			outerObject = this._addParamToObject('src', this.contentToFetch, outerObject);
			outerObject = this._addParamToObject('controller', 'true', outerObject);
			outerObject = this._addParamToObject('wmode', 'transparent', outerObject);
			outerObject = this._addParamToObject('cache', 'false', outerObject);
			outerObject = this._addParamToObject('quality', 'high', outerObject);
			
			if (! Prototype.Browser.IE) {
				var innerObject = document.createElement('object');
				innerObject.setAttribute('type', this.options.mimeTypes[ this._fileExtension(this.contentToFetch)]);
				innerObject.setAttribute('data', this.contentToFetch);
				innerObject.setAttribute('id', 'lightwindow_media_secondary');
				innerObject.setAttribute('name', 'lightwindow_media_secondary');
				innerObject.setAttribute('width', this.resizeTo.width);
				innerObject.setAttribute('height', this.resizeTo.height);
				innerObject = this._addParamToObject('controller', 'true', innerObject);
				innerObject = this._addParamToObject('wmode', 'transparent', innerObject);
				innerObject = this._addParamToObject('cache', 'false', innerObject);
				innerObject = this._addParamToObject('quality', 'high', innerObject);
				
				outerObject.appendChild(innerObject);
			}
			
			if (this._getParameter('lightwindow_iframe_embed')) {
				this._appendIframe('no');
				this._writeToIframe(this._convertToMarkup(outerObject, 'object'));
			} else {
				this._appendObject(outerObject, 'object', $('lightwindow_contents'));
			}
			
			this._handleFinalWindowAnimation(0);
		} else {
			this._handleFinalWindowAnimation(0);
		}
		
		// Initialize any actions
		this._setupActions();
	}
}

/*-----------------------------------------------------------------------------------------------*/

Event.observe(window, 'load', lightwindowInit, false);

//
//	Set up all of our links
//
var myLightWindow = null;
function lightwindowInit() {
	myLightWindow = new lightwindow();
	
	// The following was added to run code immediately
	// after this library loads and instantiates the
	// myLightWindow object.
	// ***********************
	// In the code on the main page we’ll need to create a
	// lightWindow_DoneLoading() function that catches
	// the the pseudo-event.
	// ***********************
	// Not elegant.
	// Tightly coupled.
	// But at least we check for the existence of
	// the lightWindow_DoneLoading() function before
	// we try calling it.
	if (('function' == typeof window.lightWindow_DoneLoading)) {
		lightWindow_DoneLoading();
	}
}
