/**
 * jQuery Lightbox
 * @author Warren Krewenki
 *
 * This package is distributed under the BSD license.
 * For full license information, see LICENSE.TXT
 *
 * Based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
 *
 *
 **/

(function($) {
	$.fn.lightBox = function(settings) {
		// Settings to configure the jQuery lightBox plugin how you like
		settings = jQuery.extend({
			// Configuration related to overlay
			overlayBgColor: 		'#000',		// (string) Background color to overlay; inform a hexadecimal value like: #RRGGBB. Where RR, GG, and BB are the hexadecimal values for the red, green, and blue values of the color.
			overlayOpacity:			0.8,		// (integer) Opacity value to overlay; inform: 0.X. Where X are number from 0 to 9
			// Configuration related to navigation
			fixedNavigation:		false,		// (boolean) Boolean that informs if the navigation (next and prev button) will be fixed or not in the interface.
			// Configuration related to images
			imageLoading:			'/images/lightbox-ico-loading.gif',		// (string) Path and the name of the loading icon
			imageBtnPrev:			'/images/lightbox-btn-prev.gif',			// (string) Path and the name of the prev button image
			imageBtnNext:			'/images/lightbox-btn-next.gif',			// (string) Path and the name of the next button image
			imageBtnClose:			'/images/lightbox-btn-close.gif',		// (string) Path and the name of the close btn
			imageBlank:				'/images/lightbox-blank.gif',			// (string) Path and the name of a blank image (one pixel)
			// Configuration related to container image box
			containerBorderSize:	10,			// (integer) If you adjust the padding in the CSS for the container, #lightbox-container-image-box, you will need to update this value
			containerResizeSpeed:	400,		// (integer) Specify the resize duration of container image. These number are miliseconds. 400 is default.
			// Configuration related to texts in caption. For example: Image 2 of 8. You can alter either "Image" and "of" texts.
			txtImage:				'Image',	// (string) Specify text "Image"
			txtOf:					'of',		// (string) Specify text "of"
			// Configuration related to keyboard navigation
			keyToClose:				'c',		// (string) (c = close) Letter to close the jQuery lightBox interface. Beyond this letter, the letter X and the SCAPE key is used to.
			keyToPrev:				'p',		// (string) (p = previous) Letter to show the previous image
			keyToNext:				'n',		// (string) (n = next) Letter to show the next image.
			// Don´t alter these variables in any way
			imageArray:				[],
			activeImage:			0
		},settings);
		// Caching the jQuery object with all elements matched
		var jQueryMatchedObj = this; // This, in this context, refer to jQuery object
		/**
		 * Initializing the plugin calling the start function
		 *
		 * @return boolean false
		 */
		function _initialize() {
			_start(this,jQueryMatchedObj); // This, in this context, refer to object (link) which the user have clicked
			return false; // Avoid the browser following the link
		}
		/**
		 * Start the jQuery lightBox plugin
		 *
		 * @param object objClicked The object (link) whick the user have clicked
		 * @param object jQueryMatchedObj The jQuery object with all elements matched
		 */
		function _start(objClicked,jQueryMatchedObj) {
			// Hime some elements to avoid conflict with overlay in IE. These elements appear above the overlay.
			$('embed, object, select').css({ 'visibility' : 'hidden' });
			// Call the function to create the markup structure; style some elements; assign events in some elements.
			_set_interface();
			// Unset total images in imageArray
			settings.imageArray.length = 0;
			// Unset image active information
			settings.activeImage = 0;
			// We have an image set? Or just an image? Let´s see it.
			if ( jQueryMatchedObj.length == 1 ) {
				settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));
			} else {
				// Add an Array (as many as we have), with href and title atributes, inside the Array that storage the images references		
				for ( var i = 0; i < jQueryMatchedObj.length; i++ ) {
					if(jQueryMatchedObj[i].getAttribute('rel')==objClicked.getAttribute('rel')) {
						settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));
					}
				}
			}
			while ( settings.imageArray[settings.activeImage][0] != objClicked.getAttribute('href') ) {
				settings.activeImage++;
			}
			// Call the function that prepares image exibition
			_set_image_to_view();
		}
		/**
		 * Create the jQuery lightBox plugin interface
		 *
		 * The HTML markup will be like that:
			<div id="jquery-overlay"></div>
			<div id="jquery-lightbox">
				<div id="lightbox-container-image-box">
					<div id="lightbox-container-image">
						<img src="../fotos/XX.jpg" id="lightbox-image">
						<div id="lightbox-nav">
							<a href="#" id="lightbox-nav-btnPrev"></a>
							<a href="#" id="lightbox-nav-btnNext"></a>
						</div>
						<div id="lightbox-loading">
							<a href="#" id="lightbox-loading-link">
								<img src="../images/lightbox-ico-loading.gif">
							</a>
						</div>
					</div>
				</div>
				<div id="lightbox-container-image-data-box">
					<div id="lightbox-container-image-data">
						<div id="lightbox-image-details">
							<span id="lightbox-image-details-caption"></span>
							<span id="lightbox-image-details-currentNumber"></span>
						</div>
						<div id="lightbox-secNav">
							<a href="#" id="lightbox-secNav-btnClose">
								<img src="../images/lightbox-btn-close.gif">
							</a>
						</div>
					</div>
				</div>
			</div>
		 *
		 */
		function _set_interface() {
			// Apply the HTML markup into body tag
			$('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + settings.imageLoading + '"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="' + settings.imageBtnClose + '"></a></div></div></div></div>');	
			// Get page sizes
			var arrPageSizes = ___getPageSize();
			// Style overlay and show it
			$('#jquery-overlay').css({
				backgroundColor:	settings.overlayBgColor,
				opacity:			settings.overlayOpacity,
				width:				arrPageSizes[0],
				height:				arrPageSizes[1]
			}).fadeIn();
			// Get page scroll
			var arrPageScroll = ___getPageScroll();
			// Calculate top and left offset for the jquery-lightbox div object and show it
			$('#jquery-lightbox').css({
				top:	arrPageScroll[1] + (arrPageSizes[3] / 10),
				left:	arrPageScroll[0]
			}).show();
			// Assigning click events in elements to close overlay
			$('#jquery-overlay,#jquery-lightbox').click(function() {
				_finish();									
			});
			// Assign the _finish function to lightbox-loading-link and lightbox-secNav-btnClose objects
			$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function() {
				_finish();
				return false;
			});
			// If window was resized, calculate the new overlay dimensions
			$(window).resize(function() {
				// Get page sizes
				var arrPageSizes = ___getPageSize();
				// Style overlay and show it
				$('#jquery-overlay').css({
					width:		arrPageSizes[0],
					height:		arrPageSizes[1]
				});
				// Get page scroll
				var arrPageScroll = ___getPageScroll();
				// Calculate top and left offset for the jquery-lightbox div object and show it
				$('#jquery-lightbox').css({
					top:	arrPageScroll[1] + (arrPageSizes[3] / 10),
					left:	arrPageScroll[0]
				});
			});
		}
		/**
		 * Prepares image exibition; doing a image´s preloader to calculate it´s size
		 *
		 */
		function _set_image_to_view() { // show the loading
			// Show the loading
			$('#lightbox-loading').show();
			if ( settings.fixedNavigation ) {
				$('#lightbox-image,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();
			} else {
				// Hide some elements
				$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();
			}
			// Image preload process
			var objImagePreloader = new Image();
			objImagePreloader.onload = function() {
				$('#lightbox-image').attr('src',settings.imageArray[settings.activeImage][0]);
				// Perfomance an effect in the image container resizing it
				_resize_container_image_box(objImagePreloader.width,objImagePreloader.height);
				//	clear onLoad, IE behaves irratically with animated gifs otherwise
				objImagePreloader.onload=function(){};
			};
			objImagePreloader.src = settings.imageArray[settings.activeImage][0];
		};
		/**
		 * Perfomance an effect in the image container resizing it
		 *
		 * @param integer intImageWidth The image´s width that will be showed
		 * @param integer intImageHeight The image´s height that will be showed
		 */
		function _resize_container_image_box(intImageWidth,intImageHeight) {
			// Get current width and height
			var intCurrentWidth = $('#lightbox-container-image-box').width();
			var intCurrentHeight = $('#lightbox-container-image-box').height();
			// Get the width and height of the selected image plus the padding
			var intWidth = (intImageWidth + (settings.containerBorderSize * 2)); // Plus the image´s width and the left and right padding value
			var intHeight = (intImageHeight + (settings.containerBorderSize * 2)); // Plus the image´s height and the left and right padding value
			// Diferences
			var intDiffW = intCurrentWidth - intWidth;
			var intDiffH = intCurrentHeight - intHeight;
			// Perfomance the effect
			$('#lightbox-container-image-box').animate({ width: intWidth, height: intHeight },settings.containerResizeSpeed,function() { _show_image(); });
			if ( ( intDiffW == 0 ) && ( intDiffH == 0 ) ) {
				if ( $.browser.msie ) {
					___pause(250);
				} else {
					___pause(100);	
				}
			} 
			$('#lightbox-container-image-data-box').css({ width: intImageWidth });
			$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ height: intImageHeight + (settings.containerBorderSize * 2) });
		};
		/**
		 * Show the prepared image
		 *
		 */
		function _show_image() {
			$('#lightbox-loading').hide();
			$('#lightbox-image').fadeIn(function() {
				_show_image_data();
				_set_navigation();
			});
			_preload_neighbor_images();
		};
		/**
		 * Show the image information
		 *
		 */
		function _show_image_data() {
			$('#lightbox-container-image-data-box').slideDown('fast');
			$('#lightbox-image-details-caption').hide();
			if ( settings.imageArray[settings.activeImage][1] ) {
				$('#lightbox-image-details-caption').html(settings.imageArray[settings.activeImage][1]).show();
			}
			// If we have a image set, display 'Image X of X'
			if ( settings.imageArray.length > 1 ) {
				$('#lightbox-image-details-currentNumber').html(settings.txtImage + ' ' + ( settings.activeImage + 1 ) + ' ' + settings.txtOf + ' ' + settings.imageArray.length).show();
			}		
		}
		/**
		 * Display the button navigations
		 *
		 */
		function _set_navigation() {
			$('#lightbox-nav').show();

			// Instead to define this configuration in CSS file, we define here. And it´s need to IE. Just.
			$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + settings.imageBlank + ') no-repeat' });
			
			// Show the prev button, if not the first image in set
			if ( settings.activeImage != 0 ) {
				if ( settings.fixedNavigation ) {
					$('#lightbox-nav-btnPrev').css({ 'background' : 'url(' + settings.imageBtnPrev + ') left 15% no-repeat' })
						.unbind()
						.bind('click',function() {
							settings.activeImage = settings.activeImage - 1;
							_set_image_to_view();
							return false;
						});
				} else {
					// Show the images button for Next buttons
					$('#lightbox-nav-btnPrev').unbind().hover(function() {
						$(this).css({ 'background' : 'url(' + settings.imageBtnPrev + ') left 15% no-repeat' });
					},function() {
						$(this).css({ 'background' : 'transparent url(' + settings.imageBlank + ') no-repeat' });
					}).show().bind('click',function() {
						settings.activeImage = settings.activeImage - 1;
						_set_image_to_view();
						return false;
					});
				}
			}
			
			// Show the next button, if not the last image in set
			if ( settings.activeImage != ( settings.imageArray.length -1 ) ) {
				if ( settings.fixedNavigation ) {
					$('#lightbox-nav-btnNext').css({ 'background' : 'url(' + settings.imageBtnNext + ') right 15% no-repeat' })
						.unbind()
						.bind('click',function() {
							settings.activeImage = settings.activeImage + 1;
							_set_image_to_view();
							return false;
						});
				} else {
					// Show the images button for Next buttons
					$('#lightbox-nav-btnNext').unbind().hover(function() {
						$(this).css({ 'background' : 'url(' + settings.imageBtnNext + ') right 15% no-repeat' });
					},function() {
						$(this).css({ 'background' : 'transparent url(' + settings.imageBlank + ') no-repeat' });
					}).show().bind('click',function() {
						settings.activeImage = settings.activeImage + 1;
						_set_image_to_view();
						return false;
					});
				}
			}
			// Enable keyboard navigation
			_enable_keyboard_navigation();
		}
		/**
		 * Enable a support to keyboard navigation
		 *
		 */
		function _enable_keyboard_navigation() {
			$(document).keydown(function(objEvent) {
				_keyboard_action(objEvent);
			});
		}
		/**
		 * Disable the support to keyboard navigation
		 *
		 */
		function _disable_keyboard_navigation() {
			$(document).unbind();
		}
		/**
		 * Perform the keyboard actions
		 *
		 */
		function _keyboard_action(objEvent) {
			// To ie
			if ( objEvent == null ) {
				keycode = event.keyCode;
				escapeKey = 27;
			// To Mozilla
			} else {
				keycode = objEvent.keyCode;
				escapeKey = objEvent.DOM_VK_ESCAPE;
			}
			// Get the key in lower case form
			key = String.fromCharCode(keycode).toLowerCase();
			// Verify the keys to close the ligthBox
			if ( ( key == settings.keyToClose ) || ( key == 'x' ) || ( keycode == escapeKey ) ) {
				_finish();
			}
			// Verify the key to show the previous image
			if ( ( key == settings.keyToPrev ) || ( keycode == 37 ) ) {
				// If we´re not showing the first image, call the previous
				if ( settings.activeImage != 0 ) {
					settings.activeImage = settings.activeImage - 1;
					_set_image_to_view();
					_disable_keyboard_navigation();
				}
			}
			// Verify the key to show the next image
			if ( ( key == settings.keyToNext ) || ( keycode == 39 ) ) {
				// If we´re not showing the last image, call the next
				if ( settings.activeImage != ( settings.imageArray.length - 1 ) ) {
					settings.activeImage = settings.activeImage + 1;
					_set_image_to_view();
					_disable_keyboard_navigation();
				}
			}
		}
		/**
		 * Preload prev and next images being showed
		 *
		 */
		function _preload_neighbor_images() {
			if ( (settings.imageArray.length -1) > settings.activeImage ) {
				objNext = new Image();
				objNext.src = settings.imageArray[settings.activeImage + 1][0];
			}
			if ( settings.activeImage > 0 ) {
				objPrev = new Image();
				objPrev.src = settings.imageArray[settings.activeImage -1][0];
			}
		}
		/**
		 * Remove jQuery lightBox plugin HTML markup
		 *
		 */
		function _finish() {
			$('#jquery-lightbox').remove();
			$('#jquery-overlay').fadeOut(function() { $('#jquery-overlay').remove(); });
			// Show some elements to avoid conflict with overlay in IE. These elements appear above the overlay.
			$('embed, object, select').css({ 'visibility' : 'visible' });
		}
		/**
		 / THIRD FUNCTION
		 * getPageSize() by quirksmode.com
		 *
		 * @return Array Return an array with page width, height and window width, height
		 */
		function ___getPageSize() {
			var xScroll, yScroll;
			if (window.innerHeight && window.scrollMaxY) {	
				xScroll = window.innerWidth + window.scrollMaxX;
				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
				if(document.documentElement.clientWidth){
					windowWidth = document.documentElement.clientWidth; 
				} else {
					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 = xScroll;		
			} else {
				pageWidth = windowWidth;
			}
			arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);
			return arrayPageSize;
		};
		/**
		 / THIRD FUNCTION
		 * getPageScroll() by quirksmode.com
		 *
		 * @return Array Return an array with x,y page scroll values.
		 */
		function ___getPageScroll() {
			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 arrayPageScroll;
		};
		 /**
		  * Stop the code execution from a escified time in milisecond
		  *
		  */
		 function ___pause(ms) {
			var date = new Date(); 
			curDate = null;
			do { var curDate = new Date(); }
			while ( curDate - date < ms);
		 };
		// Return the jQuery object for chaining. The unbind method is used to avoid click conflict when the plugin is called more than once
		return this.unbind('click').click(_initialize);
	};
	$.fn.lightbox = function(options) {
		// build main options
		var opts = $.extend({}, $.fn.lightbox.defaults, options);
        
		$(window).resize(resizeOverlayToFitWindow);

		return $(this).live("click",function(){
			// initialize the lightbox
			initialize();
			showLightbox(this);
			return false;
		});
		
		/*
		# Initialize the lightbox by creating our html and reading some image data
		# This method is called by the constructor after any click events trigger it
		# You will never call it by itself, to my knowledge.
		*/
		function initialize() {
			$('#overlay, #lightbox').remove();
			opts.inprogress = false;

			// if jsonData, build the imageArray from data provided in JSON format
			if (opts.jsonData && opts.jsonData.length > 0) {
				var parser = opts.jsonDataParser ? opts.jsonDataParser : $.fn.lightbox.parseJsonData;                
				opts.imageArray = [];
				opts.imageArray = parser(opts.jsonData);
			}
    
			var outerImage = '<div id="outerImageContainer"><div id="imageContainer"><iframe id="lightboxIframe"></iframe><img id="lightboxImage" /><div id="hoverNav"><a href="javascript://" title="' + opts.strings.prevLinkTitle + '" id="prevLink"></a><a href="javascript://" id="nextLink" title="' + opts.strings.nextLinkTitle + '"></a></div><div id="loading"><a href="javascript://" id="loadingLink"><img src="'+opts.fileLoadingImage+'"></a></div></div></div>';
			var imageData = '<div id="imageDataContainer" class="clearfix"><div id="imageData"><div id="imageDetails"><span id="caption"></span><span id="numberDisplay"></span></div><div id="bottomNav">';

			if (opts.displayHelp) {
				imageData += '<span id="helpDisplay">' + opts.strings.help + '</span>';
			}

			imageData += '<a href="javascript://" id="bottomNavClose" title="' + opts.strings.closeTitle + '"><img src="'+opts.fileBottomNavCloseImage+'"></a></div></div></div>';

			var string;

			if (opts.navbarOnTop) {
				string = '<div id="overlay"></div><div id="lightbox">' + imageData + outerImage + '</div>';
				$("body").append(string);
				$("#imageDataContainer").addClass('ontop');
			} else {
				string = '<div id="overlay"></div><div id="lightbox">' + outerImage + imageData + '</div>';
				$("body").append(string);
			}

			$("#overlay, #lightbox").click(function(){ end(); }).hide();
			$("#loadingLink, #bottomNavClose").click(function(){ end(); return false;});
			$('#outerImageContainer').width(opts.widthCurrent).height(opts.heightCurrent);
			$('#imageDataContainer').width(opts.widthCurrent);

			if (!opts.imageClickClose) {
				$("#lightboxImage").click(function(){ return false; });
				$("#hoverNav").click(function(){ return false; });
			}
			
			return true;
		};

		/*
		# Get the document and window width/heigh
		#
		# Examples
		#
		#	getPageSize()
		#	# => [1024,768,1024,768]
		#
		# Returns a numerically indexed array of document width/height and window width/height
		*/
		function getPageSize() {
			var jqueryPageSize = new Array($(document).width(),$(document).height(), $(window).width(), $(window).height());
			return jqueryPageSize;
		};
	    
		function getPageScroll() {
			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;
			}

			var arrayPageScroll = new Array(xScroll,yScroll);
			return arrayPageScroll;
		};

		/*
		# Pause execution for a length of time
		#
		# ms - Number of milliseconds to pause execution
		#
		# Examples
		#
		#	pause(500)
		#	# => true
		# This runs an ugly loop until the execution time has passed
		# It is a horrible, horrible method and I wish to dispense with it, maybe via timeouts or something.
		# Really, this thing is nasty.  I think it had a really bad childhood or something.  I mean, it is
		# incredibly cruel to your browser, and to my self esteem. I didn't want to write it. I didn't want to include
		# it in my library, what with it's sexy overlay and whatnot, but here it is 4 years later and this thing lives on.
		# Please don't upset it, i've been told it will eat your dreams.
		*/
		function pause(ms) {
			var date = new Date();
			var curDate = null;
			do{curDate = new Date();}
			while(curDate - date < ms);
		};
	    

		/*
		# Deploy the sexy overlay and display the lightbox
		#
		# imageObject - the jQuery object passed via the click event in the constructor
		#
		# Examples
		#
		#	showLightbox($('#CheesusCrust'))
		#
		# Returns a boolean true, because it's got nothing else to return. It should give visual feedback when run
		*/
		function showLightbox(imageObject) {
			/**
			* select, embed and object tags render over the lightbox in some browsers
			* Right now, the best way to fix it is to hide them, but that can trigger reloading of some flash content
			* I don't have a better fix for this right now, but I want ot leave this comment here so you and I both 
			* know that i'm aware of it, and I would love to fix it, if you have any suggestions.
			**/
			$("select, embed, object").hide();

			// Resize and display the sexy, sexy overlay.
			resizeOverlayToFitWindow();
			$("#overlay").hide().css({ opacity : opts.overlayOpacity }).fadeIn();
			imageNum = 0;

			// if data is not provided by jsonData parameter
			if (!opts.jsonData) {
				opts.imageArray = [];
				// if image is NOT part of a set..
				if ((!imageObject.rel || (imageObject.rel == '')) && !opts.allSet) {
					// add single image to Lightbox.imageArray
					opts.imageArray.push(new Array(imageObject.href, opts.displayTitle ? imageObject.title : ''));
				} else {
					// if image is part of a set..
					$("a").each(function() {
						if(this.href && (this.rel == imageObject.rel)) {
							opts.imageArray.push(new Array(this.href, opts.displayTitle ? this.title : ''));
						}
					});
				}
			}
	
			if (opts.imageArray.length > 1) {
				for (i = 0; i < opts.imageArray.length; i++) {
					for (j = opts.imageArray.length - 1; j > i; j--) {
						if (opts.imageArray[i][0] == opts.imageArray[j][0]) {
							opts.imageArray.splice(j, 1);
						}
					}
				}

				while (opts.imageArray[imageNum][0] != imageObject.href) { 
					imageNum++;
				}
			}

			// calculate top and left offset for the lightbox
			var arrayPageScroll = getPageScroll();
			var lightboxTop = arrayPageScroll[1] + ($(window).height() / 10);
			var lightboxLeft = arrayPageScroll[0];
			$('#lightbox').css({top: lightboxTop+'px', left: lightboxLeft+'px'}).show();

			if (!opts.slideNavBar) {
				$('#imageData').hide();
			}

			changeImage(imageNum);
		};
	    
		function changeImage(imageNum) {
			if (opts.inprogress == false) {
				opts.inprogress = true;

				// update global var
				opts.activeImage = imageNum;	

				// hide elements during transition
				$('#loading').show();
				$('#lightboxImage, #hoverNav, #prevLink, #nextLink').hide();

				// delay preloading image until navbar will slide up
				if (opts.slideNavBar) { 
					$('#imageDataContainer').hide();
					$('#imageData').hide();
				}
				doChangeImage();
			}
		};

		function doChangeImage() {
			imgPreloader = new Image();

			// once image is preloaded, resize image container
			imgPreloader.onload = function() {
				var newWidth = imgPreloader.width;
				var newHeight = imgPreloader.height;

				if (opts.scaleImages) {
					newWidth = parseInt(opts.xScale * newWidth);
					newHeight = parseInt(opts.yScale * newHeight);
				}

				if (opts.fitToScreen) {
					var arrayPageSize = getPageSize();
					var ratio;
					var initialPageWidth = arrayPageSize[2] - 2 * opts.borderSize;
					var initialPageHeight = arrayPageSize[3] - 200;

					var dI = initialPageWidth/initialPageHeight;
					var dP = imgPreloader.width/imgPreloader.height;

					if ((imgPreloader.height > initialPageHeight) || (imgPreloader.width > initialPageWidth)) {
						if (dI > dP) {
							newWidth = parseInt((initialPageHeight/imgPreloader.height) * imgPreloader.width);
							newHeight = initialPageHeight;
						} else {
							newHeight = parseInt((initialPageWidth/imgPreloader.width) * imgPreloader.height);
							newWidth = initialPageWidth;
						}
					}
				}

				$('#lightboxImage').
					attr('src', opts.imageArray[opts.activeImage][0]).
					width(newWidth).
					height(newHeight);

					resizeImageContainer(newWidth, newHeight);
				};

				imgPreloader.src = opts.imageArray[opts.activeImage][0];
			};

			function end() {
				disableKeyboardNav();
				$('#lightbox').hide();
				$('#overlay').fadeOut();
				$('select, object, embed').show();
			};

			function preloadNeighborImages() {
				if (opts.loopImages && opts.imageArray.length > 1) {
					preloadNextImage = new Image();
					preloadNextImage.src = opts.imageArray[(opts.activeImage == (opts.imageArray.length - 1)) ? 0 : opts.activeImage + 1][0];

					preloadPrevImage = new Image();
					preloadPrevImage.src = opts.imageArray[(opts.activeImage == 0) ? (opts.imageArray.length - 1) : opts.activeImage - 1][0];
				} else {
					if ((opts.imageArray.length - 1) > opts.activeImage) {
						preloadNextImage = new Image();
						preloadNextImage.src = opts.imageArray[opts.activeImage + 1][0];
					}
					if (opts.activeImage > 0) {
						preloadPrevImage = new Image();
						preloadPrevImage.src = opts.imageArray[opts.activeImage - 1][0];
					}
				}
			};

			function resizeImageContainer(imgWidth, imgHeight) {
				// get current width and height
				opts.widthCurrent = $("#outerImageContainer").outerWidth();
				opts.heightCurrent = $("#outerImageContainer").outerHeight();

				// get new width and height
				var widthNew = Math.max(350, imgWidth  + (opts.borderSize * 2));
				var heightNew = (imgHeight  + (opts.borderSize * 2));

				// calculate size difference between new and old image, and resize if necessary
				wDiff = opts.widthCurrent - widthNew;
				hDiff = opts.heightCurrent - heightNew;

				$('#imageDataContainer').animate({width: widthNew},opts.resizeSpeed,'linear');
				$('#outerImageContainer').animate({width: widthNew},opts.resizeSpeed,'linear', function() {
					$('#outerImageContainer').animate({height: heightNew},opts.resizeSpeed,'linear', function() {
						showImage();
					});
				});

				// if new and old image are same size and no scaling transition is necessary,
				// do a quick pause to prevent image flicker.
				if((hDiff == 0) && (wDiff == 0)) {
					if (jQuery.browser.msie) { 
						pause(250); 
					} else { 
						pause(100);
					}
				}

				$('#prevLink').height(imgHeight);
				$('#nextLink').height(imgHeight);
			};

			function showImage() {
				$('#loading').hide();
				$('#lightboxImage').fadeIn("fast");
				updateDetails();
				preloadNeighborImages();

				opts.inprogress = false;
			};

			function updateDetails() {
				$('#numberDisplay').html('');

				if (opts.imageArray[opts.activeImage][1]) {
					$('#caption').html(opts.imageArray[opts.activeImage][1]).show();
				}

				// if image is part of set display 'Image x of x'
				if (opts.imageArray.length > 1) {
					var nav_html;

					nav_html = opts.strings.image + (opts.activeImage + 1) + opts.strings.of + opts.imageArray.length;

					if (opts.displayDownloadLink) {
						nav_html += "<a href='" + opts.imageArray[opts.activeImage][0] + "'>" + opts.strings.download + "</a>";
					}				

					if (!opts.disableNavbarLinks) {
						// display previous / next text links
						if ((opts.activeImage) > 0 || opts.loopImages) {
							nav_html = '<a title="' + opts.strings.prevLinkTitle + '" href="#" id="prevLinkText">' + opts.strings.prevLinkText + "</a>" + nav_html;
						}

						if (((opts.activeImage + 1) < opts.imageArray.length) || opts.loopImages) {
							nav_html += '<a title="' + opts.strings.nextLinkTitle + '" href="#" id="nextLinkText">' + opts.strings.nextLinkText + "</a>";
						}
					}

					$('#numberDisplay').html(nav_html).show();
				}

				if (opts.slideNavBar) {
					$("#imageData").slideDown(opts.navBarSlideSpeed);
				} else {
					$("#imageData").show();
				}

				resizeOverlayToFitWindow();
				updateNav();
			};

			/*
			# Resize the sexy overlay to fit the constraints of your current viewing environment
			# 
			# This should now happen whenever a window is resized, so you should always see a full overlay
			*/
			function resizeOverlayToFitWindow(){
				$('#overlay').css({width: $(document).width(), height: $(document).height()});
				//  ^^^^^^^ <- sexy!
			};

			function updateNav() {
				if (opts.imageArray.length > 1) {
					$('#hoverNav').show();

					// if loopImages is true, always show next and prev image buttons 
					if(opts.loopImages) {
						$('#prevLink,#prevLinkText').show().click(function() {
							changeImage((opts.activeImage == 0) ? (opts.imageArray.length - 1) : opts.activeImage - 1); 
							return false;
						});

						$('#nextLink,#nextLinkText').show().click(function() {
							changeImage((opts.activeImage == (opts.imageArray.length - 1)) ? 0 : opts.activeImage + 1); 
							return false;
						});

					} else {
						// if not first image in set, display prev image button
						if(opts.activeImage != 0) {
							$('#prevLink,#prevLinkText').show().click(function() {
								changeImage(opts.activeImage - 1); 
								return false;
							});
						}

						// if not last image in set, display next image button
						if(opts.activeImage != (opts.imageArray.length - 1)) {
							$('#nextLink,#nextLinkText').show().click(function() {
								changeImage(opts.activeImage +1); 
								return false;
							});
						}
					}

					enableKeyboardNav();
				}
			};

			function keyboardAction(e) {
				var o = e.data.opts;
				var keycode = e.keyCode;
				var escapeKey = 27;

				var key = String.fromCharCode(keycode).toLowerCase();

				// close lightbox
				if ((key == 'x') || (key == 'o') || (key == 'c') || (keycode == escapeKey)) { 
					end();

					// display previous image	
				} else if ((key == 'p') || (keycode == 37)) {  
					if(o.loopImages) {
						disableKeyboardNav();
						changeImage((o.activeImage == 0) ? (o.imageArray.length - 1) : o.activeImage - 1);
					} else if (o.activeImage != 0) {
						disableKeyboardNav();
						changeImage(o.activeImage - 1);
					}

					// display next image
				} else if ((key == 'n') || (keycode == 39)) { 
					if (opts.loopImages) {
						disableKeyboardNav();
						changeImage((o.activeImage == (o.imageArray.length - 1)) ? 0 : o.activeImage + 1);
					} else if (o.activeImage != (o.imageArray.length - 1)) {
						disableKeyboardNav();
						changeImage(o.activeImage + 1);
					}
				}
			};

			function enableKeyboardNav() {
				$(document).bind('keydown', {opts: opts}, keyboardAction);
			};

			function disableKeyboardNav() {
				$(document).unbind('keydown');
			};	    
		};

		$.fn.lightbox.parseJsonData = function(data) {
			var imageArray = [];

			$.each(data, function() {
				imageArray.push(new Array(this.url, this.title));
			});

			return imageArray;
		};

		$.fn.lightbox.defaults = {
			allSet: false,
			fileLoadingImage: '/images/lightbox-ico-loading.gif',
			fileBottomNavCloseImage: '/images/lightbox-btn-close.gif',
			overlayOpacity: 0.6,
			borderSize: 10,
			imageArray: new Array,
			activeImage: null,
			inprogress: false,
			resizeSpeed: 350,
			widthCurrent: 250,
			heightCurrent: 250,
			scaleImages: false,
			xScale: 1,
			yScale: 1,
			displayTitle: true,
			navbarOnTop: false,
			displayDownloadLink: false,
			slideNavBar: false, 
			navBarSlideSpeed: 350,
			displayHelp: false,
			strings: {
				help: ' \u2190 / P - previous image\u00a0\u00a0\u00a0\u00a0\u2192 / N - next image\u00a0\u00a0\u00a0\u00a0ESC / X - çàêðûòü',
				prevLinkTitle: 'ëèñòàåì íàçàä',
				nextLinkTitle: 'ëèñòàåì äàëüøå',
				prevLinkText:  '&laquo; Íàçàä',
				nextLinkText:  'Äàëüøå &raquo;',
				closeTitle: 'Çàêðûòü',
				image: 'Ôîòîãðàôèÿ ',
				of: ' èç ',
				download: 'Ñêà÷àòü'
			},
			fitToScreen: true,		
			disableNavbarLinks: false,
			loopImages: false,
			imageClickClose: true,
			jsonData: null,
			jsonDataParser: null
		};	
})(jQuery);
