/*
	ColorBox v1.2.9b - a full featured, light-weight, customizable lightbox based on jQuery 1.3
	(c) 2009 Jack Moore - www.colorpowered.com - jack@colorpowered.com
	Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/
(function (jQuery) {
	
	// ****************
	// COMMON VARIABLES
	// ****************
	
	//jQuery Object Variables
	var jQueryoverlay, jQuerycbox, jQuerywrap, jQuerycontent, jQuerytopBorder, jQueryleftBorder, jQueryrightBorder, jQuerybottomBorder, jQueryrelated, jQuerywindow, jQueryloaded, jQueryloadingOverlay, jQueryloadingGraphic, jQuerytitle, jQuerycurrent, jQueryslideshow, jQuerynext, jQueryprev, jQueryclose,
	
	//Variables
	publicMethod, interfaceHeight, interfaceWidth, loadedHeight, loadedWidth, maxWidth, maxHeight, element, index, settings, open, callback, colorbox = 'colorbox', hover = 'hover',

	//Functions
	prev, next, init, load, position, dimensions, slideshow, close,
	
	//Events
	cbox_open = 'cbox_open', cbox_load = 'cbox_load', cbox_complete = 'cbox_complete', cbox_close = 'cbox_close', cbox_closed = 'cbox_closed',

	// ColorBox Default Settings.	
	// See http://colorpowered.com/colorbox for details.

	defaults = {
		transition: 'fade',
		speed: 350,
		width: false,
		height: false,
		initialWidth: "100",
		initialHeight: "100",
		maxWidth: false,
		maxHeight: false,
		resize: true,
		inline: false,
		html: false,
		iframe: false,
		photo: false,
		href: false,
		title: false,
		rel: false,
		opacity: 0.3,
		preloading: true,
		current: "image {current} of {total}",
		previous: "previous",
		next: "next",
		close: "close",
		open: false,
		overlayClose: true,
		slideshow: false,
		slideshowAuto: true,
		slideshowSpeed: 2500,
		slideshowStart: "start slideshow",
		slideshowStop: "stop slideshow"
	};

	// ****************
	// HELPER FUNCTIONS
	// ****************
	
	// Set Navigation Keys
	function cbox_key(e) {
		if (e.keyCode === 37) {
			e.preventDefault();
			jQueryprev.click();
		} else if (e.keyCode === 39) {
			e.preventDefault();
			jQuerynext.click();
		}
	}

	// Convert % values to pixels
	function setSize(size, dimension) {
		dimension = dimension === 'x' ? document.documentElement.clientWidth : document.documentElement.clientHeight;
		return (typeof size === 'string') ? (size.match(/%/) ? (dimension / 100) * parseInt(size, 10) : parseInt(size, 10)) : size;
	}

	// Checks an href to see if it is a photo.
	// There is a force photo option for hrefs that cannot be matched by this regex.
	function isImage(url) {
		return settings.photo ? true : url.match(/\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?jQuery/i);
	}
	
	// Assigns functions results to their respective settings.  This allows functions to be used to set ColorBox options.
	function process() {
		for (var i in settings) {
			if (typeof(settings[i]) === 'function') {
			    settings[i] = settings[i].call(element);
			}
		}
	}

	jQuery.fn.colorbox = function (options, custom_callback) {
		
		if (this.length) {
			this.each(function () {
				var data = jQuery(this).data(colorbox) ? jQuery.extend({},
					jQuery(this).data(colorbox), options) : jQuery.extend({}, defaults, options);
				jQuery(this).data(colorbox, data).addClass("cboxelement");
			});
		} else {
			jQuery(this).data(colorbox, jQuery.extend({}, defaults, options));
		}
		
		jQuery(this).unbind("click.colorbox").bind("click.colorbox", function (event) {
			
			element = this;
			
			settings = jQuery(element).data(colorbox);
			
			process();//process settings functions
			
			jQuery().bind("keydown.cbox_close", function (e) {
				if (e.keyCode === 27) {
					e.preventDefault();
					jQueryclose.click();
				}
			});
			if (settings.overlayClose === true) {
				jQueryoverlay.css({"cursor": "pointer"}).one('click', close);
			}
			
			//remove the focus from the anchor to prevent accidentally calling
			//colorbox multiple times (by pressing the 'Enter' key
			//after colorbox has opened, but before the user has clicked on anything else)
			element.blur();
			
			callback = custom_callback || false;
			
			var rel = settings.rel || element.rel;
			
			if (rel && rel !== 'nofollow') {
				jQueryrelated = jQuery('.cboxelement').filter(function () {
					var relRelated = jQuery(this).data(colorbox).rel || this.rel;
					return (relRelated === rel);
				});
				index = jQueryrelated.index(element);
				
				if (index < 0) { //this checks direct calls to colorbox
					jQueryrelated = jQueryrelated.add(element);
					index = jQueryrelated.length - 1;
				}
			
			} else {
				jQueryrelated = jQuery(element);
				index = 0;
			}
			if (!open) {
				jQuery.event.trigger(cbox_open);
				jQueryclose.html(settings.close);
				jQueryoverlay.css({"opacity": settings.opacity}).show();
				open = true;
				position(setSize(settings.initialWidth, 'x'), setSize(settings.initialHeight, 'y'), 0);
				if (jQuery.browser.msie && jQuery.browser.version < 7) {
					jQuerywindow.bind("resize.cboxie6 scroll.cboxie6", function () {
						jQueryoverlay.css({width: jQuerywindow.width(), height: jQuerywindow.height(), top: jQuerywindow.scrollTop(), left: jQuerywindow.scrollLeft()});
					}).trigger('scroll.cboxie6');
				}
			}
			slideshow();
			load();
			
			event.preventDefault();
		});
		
		if (options && options.open) {
			jQuery(this).triggerHandler('click.colorbox');
		}
		
		return this;
	};
	

	// Initialize ColorBox: store common calculations, preload the interface graphics, append the html.
	// This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only
	// having to run once, instead of each time colorbox is opened.
	init = function () {				
		// jQuery object generator to save a bit of space
		function jQuerydiv(id) {
			return jQuery('<div id="cbox' + id + '"/>');
		}
		// Create & Append jQuery Objects
		jQuerywindow = jQuery(window);
		jQuerycbox = jQuery('<div id="colorbox"/>');
		jQueryoverlay = jQuerydiv("Overlay").hide();
		jQuerywrap = jQuerydiv("Wrapper");
		jQuerycontent = jQuerydiv("Content").append(
			jQueryloaded = jQuerydiv("LoadedContent").css({width: 0, height: 0}),
			jQueryloadingOverlay = jQuerydiv("LoadingOverlay"),
			jQueryloadingGraphic = jQuerydiv("LoadingGraphic"),
			jQuerytitle = jQuerydiv("Title"),
			jQuerycurrent = jQuerydiv("Current"),
			jQueryslideshow = jQuerydiv("Slideshow"),
			jQuerynext = jQuerydiv("Next"),
			jQueryprev = jQuerydiv("Previous"),
			jQueryclose = jQuerydiv("Close")
		);
		jQuerywrap.append( // The 3x3 Grid that makes up ColorBox
			jQuery('<div/>').append(
				jQuerydiv("TopLeft"),
				jQuerytopBorder = jQuerydiv("TopCenter"),
				jQuerydiv("TopRight")
			),
			jQuery('<div/>').append(
				jQueryleftBorder = jQuerydiv("MiddleLeft"),
				jQuerycontent,
				jQueryrightBorder = jQuerydiv("MiddleRight")
			),
			jQuery('<div/>').append(
				jQuerydiv("BottomLeft"),
				jQuerybottomBorder = jQuerydiv("BottomCenter"),
				jQuerydiv("BottomRight")
			)
		).children().children().css({'float': 'left'});
		jQuery('body').prepend(jQueryoverlay, jQuerycbox.append(jQuerywrap));
		
		if (jQuery.browser.msie && jQuery.browser.version < 7) {
			jQueryoverlay.css('position', 'absolute');
		}
		
		// Add rollover event to navigation elements
		jQuerycontent.children()
		.addClass(hover)
		.mouseover(function () { jQuery(this).addClass(hover); })
		.mouseout(function () { jQuery(this).removeClass(hover); })
		.hide();
		
		// Cache values needed for size calculations
		interfaceHeight = jQuerytopBorder.height() + jQuerybottomBorder.height() + jQuerycontent.outerHeight(true) - jQuerycontent.height();//Subtraction needed for IE6
		interfaceWidth = jQueryleftBorder.width() + jQueryrightBorder.width() + jQuerycontent.outerWidth(true) - jQuerycontent.width();
		loadedHeight = jQueryloaded.outerHeight(true);
		loadedWidth = jQueryloaded.outerWidth(true);
		
		// Setting padding to remove the need to do size conversions during the animation step.
		jQuerycbox.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
		
		// Setup button & key events.
		jQuerynext.click(next);
		jQueryprev.click(prev);
		jQueryclose.click(close);
		
		// Adding the 'hover' class allowed the browser to load the hover-state
		// background graphics.  The class can now can be removed.
		jQuerycontent.children().removeClass(hover);
	};

	position = function (mWidth, mHeight, speed, loadedCallback) {
		var winHeight = document.documentElement.clientHeight,
		posTop = winHeight / 2 - mHeight / 2,
		posLeft = document.documentElement.clientWidth / 2 - mWidth / 2,
		animate_speed;
		
		//keeps the box from expanding to an inaccessible area offscreen.
		if (mHeight > winHeight) { posTop -=(mHeight - winHeight); }
		if (posTop < 0) { posTop = 0; } 
		if (posLeft < 0) { posLeft = 0; }
		
		posTop += jQuerywindow.scrollTop();
		posLeft += jQuerywindow.scrollLeft();
		
		mWidth = mWidth - interfaceWidth;
		mHeight = mHeight - interfaceHeight;
		
		//setting the speed to 0 to reduce the delay between same-sized content.
		animate_speed = (jQuerycbox.width() === mWidth && jQuerycbox.height() === mHeight) ? 0 : speed;
		
		//this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
		//but it has to be shrank down around the size of div#colorbox when it's done.  If not,
		//it can invoke an obscure IE bug when using iframes.
		jQuerywrap[0].style.width = jQuerywrap[0].style.height = "9999px";
		
		function modalDimensions (that) {
			//loading overlay size has to be sure that IE6 uses the correct height.
			jQuerytopBorder[0].style.width = jQuerybottomBorder[0].style.width = jQuerycontent[0].style.width = that.style.width;
			jQueryloadingGraphic[0].style.height = jQueryloadingOverlay[0].style.height = jQuerycontent[0].style.height = jQueryleftBorder[0].style.height = jQueryrightBorder[0].style.height = that.style.height;
		}
		
		jQuerycbox.dequeue().animate({height:mHeight, width:mWidth, top:posTop, left:posLeft}, {duration: animate_speed,
			complete: function(){
				modalDimensions(this);
				
				//shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
				jQuerywrap[0].style.width = (mWidth+interfaceWidth) + "px";
				jQuerywrap[0].style.height = (mHeight+interfaceHeight) + "px";
				
				if (loadedCallback) {loadedCallback();}
			},
			step: function(){
				modalDimensions(this);
			}
		});
	};

	dimensions = function (object) {
		if(!open){ return; }
		
		jQuerywindow.unbind('resize.cbox_resize');
		
		var width, height, topMargin, prev, prevSrc, next, nextSrc, photo,
		speed = settings.transition==="none" ? 0 : settings.speed;
		
		jQueryloaded.remove();
		jQueryloaded = jQuery(object);
		
		function getWidth(){
			if(settings.width){
				width = maxWidth;
			} else {
				width = maxWidth && maxWidth < jQueryloaded.width() ? maxWidth : jQueryloaded.width();
			}
			return width;
		}
		function getHeight(){
			if(settings.height){
				height = maxHeight;
			} else {
				height = maxHeight && maxHeight < jQueryloaded.height() ? maxHeight : jQueryloaded.height();
			}
			return height;
		}
		
		jQueryloaded.hide().appendTo('body')
		.attr({id:'cboxLoadedContent'})
		.css({width:getWidth()})
		.css({height:getHeight()})//sets the height independently from the width in case the new width influences the value of height.
		.prependTo(jQuerycontent);
		
		
		// Hides 'select' form elements in IE6 because they would otherwise sit on top of the overlay.
		if (jQuery.browser.msie && jQuery.browser.version < 7) {
			jQuery('select:not(#colorbox select)').filter(function(){
				return jQuery(this).css('visibility') !== 'hidden';
			}).css({'visibility':'hidden'}).one(cbox_close, function(){
				jQuery(this).css({'visibility':'inherit'});
			});
		}
		
		photo = jQuery('#cboxPhoto')[0];
		if (photo && settings.height) {
			topMargin = (height - parseInt(photo.style.height, 10))/2;
			photo.style.marginTop = (topMargin > 0 ? topMargin : 0)+'px';
		}
		
		function setPosition (s) {
			var mWidth = width+loadedWidth+interfaceWidth,
			mHeight = height+loadedHeight+interfaceHeight;
			
			position(mWidth, mHeight, s, function(){
				if (!open) { return; }
				
				if (jQuery.browser.msie) {
					//This fadeIn helps the bicubic resampling to kick-in.
					if( photo ){jQueryloaded.fadeIn(100);}
					//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
					jQuerycbox.css('filter','');
				}
				
				jQuerycontent.children().show();
				
				//Waited until the iframe is added to the DOM & it is visible before setting the src.
				//This increases compatability with pages using DOM dependent JavaScript.
				jQuery('#cboxIframeTemp').after("<iframe id='cboxIframe' name='iframe_"+new Date().getTime()+"' frameborder=0 src='"+(settings.href || element.href)+"' />").remove();
				
				jQueryloadingOverlay.hide();
				jQueryloadingGraphic.hide();
				jQueryslideshow.hide();
				
				if (jQueryrelated.length>1) {
					jQuerycurrent.html(settings.current.replace(/\{current\}/, index+1).replace(/\{total\}/, jQueryrelated.length));
					jQuerynext.html(settings.next);
					jQueryprev.html(settings.previous);
					
					jQuery().unbind('keydown', cbox_key).bind('keydown', cbox_key);
					
					if(settings.slideshow){
						jQueryslideshow.show();
					}
				} else {
					jQuerycurrent.hide();
					jQuerynext.hide();
					jQueryprev.hide();
				}
				
				jQuerytitle.html(settings.title || element.title);
				
				jQuery.event.trigger(cbox_complete);
				
				if (callback) {
					callback.call(element);
				}
				
				if (settings.transition === 'fade'){
					jQuerycbox.fadeTo(speed, 1, function(){
						if(jQuery.browser.msie){jQuerycontent.css('filter','');}
					});
				}
				
				jQuerywindow.bind('resize.cbox_resize', function(){
					position(mWidth, mHeight, 0);
				});
			});
		}
		if (settings.transition === 'fade') {
			jQuerycbox.fadeTo(speed, 0, function(){setPosition(0);});
		} else {
			setPosition(speed);
		}
		
		// Preloads images within a rel group
		if (settings.preloading && jQueryrelated.length>1) {
			prev = index > 0 ? jQueryrelated[index-1] : jQueryrelated[jQueryrelated.length-1];
			next = index < jQueryrelated.length-1 ? jQueryrelated[index+1] : jQueryrelated[0];
			nextSrc = jQuery(next).data(colorbox).href || next.href;
			prevSrc = jQuery(prev).data(colorbox).href || prev.href;
			
			if(isImage(nextSrc)){
				jQuery('<img />').attr('src', nextSrc);
			}
			if(isImage(prevSrc)){
				jQuery('<img />').attr('src', prevSrc);
			}
		}
	};

	load = function () {
		var height, width, href, loadingElement;

		element = jQueryrelated[index];
		
		settings = jQuery(element).data(colorbox);
		
		//convert functions to static values
		process();

		jQuery.event.trigger(cbox_load);
		
		// Evaluate the height based on the optional height and width settings.
		height = settings.height ? setSize(settings.height, 'y') - loadedHeight - interfaceHeight : false;
		width = settings.width ? setSize(settings.width, 'x') - loadedWidth - interfaceWidth : false;
		
		href = settings.href || element.href;
		
		jQueryloadingOverlay.show();
		jQueryloadingGraphic.show();
		jQueryclose.show();
		
		//Re-evaluate the maximum dimensions based on the optional maxheight and maxwidth.
		if(settings.maxHeight){
			maxHeight = settings.maxHeight ? setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight : false;
			height = height && height < maxHeight ? height : maxHeight;
		}
		if(settings.maxWidth){
			maxWidth = settings.maxWidth ? setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth : false;
			width = width && width < maxWidth ? width : maxWidth;
		}
		
		maxHeight = height;
		maxWidth = width;
		
		if (settings.inline) {
			jQuery('<div id="cboxInlineTemp" />').hide().insertBefore(jQuery(href)[0]).bind(cbox_load+' '+cbox_close, function(){
				jQueryloaded.children().insertBefore(this);
				jQuery(this).remove();
			});
			dimensions(jQuery(href).wrapAll('<div/>').parent());
		} else if (settings.iframe) {
			dimensions(
				jQuery("<div><div id='cboxIframeTemp' /></div>")
			);//timestamp to prevent caching.
		} else if (settings.html) {
			dimensions(
				jQuery('<div/>').html(settings.html)
			);
		} else if (isImage(href)){
			loadingElement = new Image();
			loadingElement.onload = function(){
				loadingElement.onload = null;
				
				if((maxHeight || maxWidth) && settings.resize){
					var width = this.width,
					height = this.height,
					percent = 0,
					that = this,
					setResize = function(){
						height += height * percent;
						width += width * percent;
						that.height = height;
						that.width = width;	
					};
					
					if( maxWidth && width > maxWidth ){
						percent = (maxWidth - width) / width;
						setResize();
					}
					if( maxHeight && height > maxHeight ){
						percent = (maxHeight - height) / height;
						setResize();
					}
				}
				dimensions(jQuery("<div />").css({width:this.width, height:this.height}).append(jQuery(this).css({width:this.width, height:this.height, display:"block", margin:"auto", border:0}).attr('id', 'cboxPhoto')));
				if(jQueryrelated.length > 1){
					jQuery(this).css({cursor:'pointer'}).click(next);
				}
				if(jQuery.browser.msie && jQuery.browser.version == 7){
					this.style.msInterpolationMode='bicubic';
				}
			};
			loadingElement.src = href;
		} else {
			jQuery('<div />').load(href, function(data, textStatus){
				if(textStatus === "success"){
					dimensions(jQuery(this));
				} else {
					dimensions(jQuery("<p>Request unsuccessful.</p>"));
				}
			});
		}	
	};

	//navigates to the next page/image in a set.
	next = function () {
		index = index < jQueryrelated.length-1 ? index+1 : 0;
		load();
	};
	
	prev = function () {
		index = index > 0 ? index-1 : jQueryrelated.length-1;
		load();
	};

	slideshow = function () {
		var stop, timeOut, className = 'cboxSlideshow_';
		
		jQueryslideshow.bind(cbox_close, function(){
			clearTimeout(timeOut);
			jQueryslideshow.unbind();
		});
		
		function start(){
			jQueryslideshow
			.text(settings.slideshowStop)
			.bind(cbox_complete, function(){
				timeOut = setTimeout(next, settings.slideshowSpeed);
			})
			.bind(cbox_load, function(){
				clearTimeout(timeOut);	
			}).one("click", function(){
				stop();
				jQuery(this).removeClass(hover);
			});
			jQuerycbox.removeClass(className+"off").addClass(className+"on");
		}
		
		stop = function(){
			clearTimeout(timeOut);
			jQueryslideshow
			.text(settings.slideshowStart)
			.unbind(cbox_complete+' '+cbox_load)
			.one("click", function(){
				start();
				timeOut = setTimeout(next, settings.slideshowSpeed);
				jQuery(this).removeClass(hover);
			});
			jQuerycbox.removeClass(className+"on").addClass(className+"off");
		};
		
		if(settings.slideshow && jQueryrelated.length>1){
			if(settings.slideshowAuto){
				start();
			} else {
				stop();
			}
		}
	};

	//public function for closing colorbox.  To use this within an iframe use the following format: parent.jQuery.fn.colorbox.close();
	close = function () {
		jQuery.event.trigger(cbox_close);
		open = false;
		jQuery().unbind('keydown', cbox_key).unbind("keydown.cbox_close");
		jQuerywindow.unbind('resize.cbox_resize resize.cboxie6 scroll.cboxie6');
		jQueryoverlay.css({cursor:'auto'}).fadeOut('fast');
		
		jQuerycontent.children().hide();
		
		jQuerycbox
		.stop(true, false)
		.removeClass()
		.fadeOut('fast', function(){
			jQueryloaded.remove();
			jQuerycbox.css({'opacity':1});
			jQuery.event.trigger(cbox_closed);
		});
		
	};

	// Create Public Methods
	publicMethod = jQuery.fn.colorbox;
	publicMethod.init = init;
	publicMethod.next = next;
	publicMethod.prev = prev;
	publicMethod.close = close;
	publicMethod.load = load;
	publicMethod.position = position;
	publicMethod.dimensions = dimensions;
	publicMethod.element = function(){ return element; };
	publicMethod.settings = defaults;

	// Initializes ColorBox when the DOM has loaded
	jQuery(function () {
		init();
	});

}(jQuery));

