/*

 * jQuery SuperBox! 0.9.2-dev

 * Copyright (c) 2009 Pierre Bertet (pierrebertet.net)

 * Licensed under the MIT (MIT-LICENSE.txt)

 *

 * TODO :

 * - Document.load if init is before </body> against IE crash.

 * - Animations

 * - Image / Gallery mode : display a legend

*/

;(function($) {

	

	// Local variables

	var $curLink, $overlay, $wrapper, $container, $superbox, $closeBtn, $loading, $nextprev, $nextBtn, $prevBtn, settings,

	

	// Default settings

	defaultSettings = {

		boxId: "superbox",

		boxClasses: "",

		overlayOpacity: .8,

		boxWidth: "600",

		boxHeight: "400",

		loadTxt: "Loading...",

		closeTxt: "Close",

		prevTxt: "Previous",

		nextTxt: "Next",

		beforeOpen: function(){},

		afterOpen: function(){}

	},

	

	galleryGroups = {},

	galleryMode = false,

	hideElts = $([]),

	isWaiting = false;

	

	// Init dispatcher

	$.superbox = function() {

		

		// Settings

		settings = $.extend({}, defaultSettings, $.superbox.settings);

		

		// If IE6, select elements to hide

		if ($.browser.msie && $.browser.version < 7) {

			hideElts = hideElts.add("select");

		}

		

		// Do not init SuperBox! twice

		if ($.superbox.mainInit !== true) {

			

			// Create base elements

			createElements();

			

			// Init global events (left / right, echap)

			initGlobalEvents();

			

			$.superbox.mainInit = true;

		}

		

		// Dispatch types

		dispatch();

	};

	

	// Dispatch types

	function dispatch() {

		

		// Match all superbox links

		$("a[rel^=superbox],area[rel^=superbox]").each(function() {

			

			// Optimisation

			var $this = $(this),

			relAttr = $this.attr("rel"),

			

			// Match first argument. Ex: superbox[gallery#my_id.my_class][my_gallery] > gallery#my_id.my_class

			firstArg = relAttr.match(/^superbox\[([^\]]+)\]/)[1],

			

			// Match type. Ex: superbox[gallery#my_id.my_class][my_gallery] > gallery

			type = firstArg.match(/^([^#\.]+)/)[1],

			

			// Match additionnal classes or IDs (#xxx.yyy.zzz)

			boxCurrentAttrs = firstArg.replace(type, "").match(/([#\.][^#\.\]]+)/g) || [],

			

			// Box ID and classes

			newBoxId = settings.boxId,

			newBoxClasses = settings.boxClasses;

			

			// Prevent multiple inits

			if ($this.data("superbox_init")) { return; }

			$this.data("superbox_init", true);

			

			// Additionnal rel settings

			this._relSettings = relAttr.replace("superbox["+ type + boxCurrentAttrs.join("") +"]", "");

			

			// Redefine settings

			$.each(boxCurrentAttrs, function(i, val) { // each class or id

				if (val.substr(0,1) == "#") {

					newBoxId = val.substr(1);

					

				} else if (val.substr(0,1) == ".") {

					newBoxClasses += " " + val.substr(1);

				}

			});

			

			// Call type method

			if (type.search(/^image|gallery|iframe|content|ajax$/) != -1) {

				$this.superbox(type, {boxId: newBoxId, boxClasses: newBoxClasses});

			}

		});

	};

	

	/*-- Superbox Method --*/

	$.fn.superbox = function(type, curSettings) {

		curSettings = $.extend({}, settings, curSettings);

		$.superbox[type](this, curSettings);

		

		this.click(function(e) {

			e.preventDefault();

			$curLink = this;

		});

	};

	

	/*-- Types --*/

	$.extend($.superbox, {

		

		// Wait... (loading)

		wait: function(callback) {

			

			isWaiting = true;

			

			prepareBox();

			

			// Loading anim

			initLoading(function() {

				

				// Execute callback after animation

				callback();

			});

		},

		

		// Custom SuperBox!

		open: function(content, curSettings) {

			

			curSettings = $.extend({}, settings, curSettings);

			

			// Launch load animation

			if (!isWaiting) {

				$.superbox.wait(function(){

					$.superbox.open(content, curSettings);

				});

				return;

			}

			

			// Specified dimensions

			$superbox.width( curSettings.boxWidth+"px" );

			$innerbox.height( curSettings.boxHeight+"px" );

			

			// Set Id and Classes

			$superbox.attr("id", curSettings.boxId).attr("class", curSettings.boxClasses);

			

			// Append content

			$(content).appendTo($innerbox);

			

			// Show box

			showBox(curSettings);

			

			// Stop waiting

			isWaiting = false;

		},

		

		// Close SuperBox!

		close: function() {

			

			hideBox();

			$overlay.fadeOut(300, function() {

				

				// Show hidden elements for IE6

				hideElts.show();

			});

			galleryMode = false;

		},

		

		// Image

		image: function($elt, curSettings, isGallery) {

			

			// On click event

			$elt.click(function() {

				

				galleryMode = !!isGallery;

				

				$.superbox.wait(function() {

					

					var relSettings = getRelSettings($elt.get(0)),

					dimensions = false;

					

					// Extra settings

					if (!!relSettings) {

						

						var relDimensions;

						

					 	if (galleryMode) {

							relDimensions = relSettings[1];

							

						} else {

							relDimensions = relSettings[0];

						}

						

						if (!!relDimensions) {

							dimensions = relDimensions.split("x");

						}

					}

					

					// Image

					var $curImg = $('<img src="'+ $elt.attr("href") +'" title="'+ ($elt.attr("title") || $elt.text()) +'" />');

					

					// On image load

					$curImg.load(function() {

						

						// Image box dimensions

						if (!!dimensions && dimensions[0] != "") {

							var boxWidth = dimensions[0] - 0;

						} else {

							// image width + $innerbox padding

							var boxWidth = $curImg.width() + ($innerbox.css("paddingLeft").slice(0,-2)-0) + ($innerbox.css("paddingRight").slice(0,-2)-0);

						}

						if (!!dimensions && dimensions[1] != "") {

							var boxHeight = dimensions[1] - 0;

						} else {

							var boxHeight = $curImg.height();

						}

						

						curSettings = $.extend({}, curSettings, {

							boxClasses: (galleryMode? "gallery " : "image ") + curSettings.boxClasses,

							boxWidth: boxWidth,

							boxHeight: boxHeight,

							beforeOpen: function() {

								if (galleryMode) {

									// "Prev / Next" buttons

									nextPrev($elt, relSettings[0]);

								}

							}

						});

						

						// Open SuperBox!

						$.superbox.open($curImg, curSettings);

					});

					

					// Append image to SuperBox! (to trigger loading)

					$curImg.appendTo($innerbox);

				});

				

			});

		},

		

		// Gallery

		gallery: function($elt, curSettings) {

			

			// Extra settings

			var extraSettings = getRelSettings($elt.get(0));

			

			// Create group

			if(!galleryGroups[extraSettings[0]]) {

				galleryGroups[extraSettings[0]] = [];

			}

			

			// Add element to current group

			galleryGroups[extraSettings[0]].push($elt);

			

			$elt.data("superboxGroupKey", galleryGroups[extraSettings[0]].length - 1);

			

			// Image Box

			$.superbox["image"]($elt, curSettings, true);

		},

		

		// iframe

		iframe: function($elt, curSettings) {

			

			// On click event

			$elt.click(function() {

				

				$.superbox.wait(function() {

					

					// Extra settings

					var extraSettings = getRelSettings($elt.get(0));

					

					// Dimensions

					var dims = false;

					if (extraSettings) {

						dims = extraSettings[0].split("x");

					}

					

					curSettings = $.extend({}, curSettings, {

						boxWidth: dims[0] || curSettings.boxWidth,

						boxHeight: dims[1] || curSettings.boxHeight,

						boxClasses: "iframe " + curSettings.boxClasses

					});

					

					// iframe element

					var $iframe = $('<iframe title="'+ $elt.text() +'" src="'+ $elt.attr("href") +'" name="'+ $elt.attr("href") +'" frameborder="0" scrolling="auto" width="'+ curSettings.boxWidth +'" height="'+ curSettings.boxHeight +'"></iframe>');

					

					// On iframe load

					$iframe.one("load", function() {

						

						// Open SuperBox!

						$.superbox.open($iframe, curSettings);

					});

					

					// Append iframe to SuperBox! (to trigger loading)

					$iframe.appendTo($innerbox);

				});

				

			});

		},

		

		// Content

		content: function($elt, curSettings) {

			

			// On click event

			$elt.click(function() {

				

				$.superbox.wait(function() {

					

					// Extra settings

					var extraSettings = getRelSettings($elt.get(0));

					

					// Dimensions

					var dims = false;

					if (extraSettings) {

						dims = extraSettings[0].split("x");

					}

					

					// Specific settings

					curSettings = $.extend({}, curSettings, {

						boxWidth: dims[0] || curSettings.boxWidth,

						boxHeight: dims[1] || curSettings.boxHeight,

						boxClasses: "content " + curSettings.boxClasses

					});

					

					// Open SuperBox!

					$.superbox.open($($elt.attr('href')).clone(), curSettings);

				});

				

			});

		},

		

		// Ajax

		ajax: function($elt, curSettings) {

			

			// On click event

			$elt.click(function() {

				

				$.superbox.wait(function() {

					

					// Extra settings

					var extraSettings = getRelSettings($elt.get(0));

					

					// Dimensions

					var dims = false;

					if (extraSettings && extraSettings[1]) {

						dims = extraSettings[1].split("x");

					}

					

					// Extend default dimension settings

					curSettings = $.extend({}, curSettings, {

						boxWidth: dims[0] || curSettings.boxWidth,

						boxHeight: dims[1] || curSettings.boxHeight,

						boxClasses: "ajax " + curSettings.boxClasses

					});

					

					// Get Ajax URL + ID

					var splitUrl = extraSettings[0].split("#");

					var ajaxUrl = splitUrl[0];

					var anchor = splitUrl[1] || false;

					

					$.get( ajaxUrl, function(data) {

						

						// Get a specific element (by ID)?

						if (anchor !== false) {

							data = $(data).find("#" + anchor);

						}

						

						// Open SuperBox!

						$.superbox.open(data, curSettings);

					});

				});

			});

		}

	});

	

	// Get extra settings in rel attribute

	function getRelSettings(elt) {

		return elt._relSettings.match(/([^\[\]]+)/g);

	};

	

	// Next / Previous

	function nextPrev($elt, group) {

		

		$nextprev.show();

		

		galleryMode = true;

		

		var nextKey = $elt.data("superboxGroupKey") + 1,

			prevKey = nextKey - 2;

		

		// Next

		if (galleryGroups[group][nextKey]) {

			$nextBtn.removeClass("disabled").unbind("click").bind("click", function() {

				galleryGroups[group][nextKey].click();

			});

			

		} else {

			$nextBtn.addClass("disabled").unbind("click");

		}

		

		// Prev

		if (galleryGroups[group][prevKey]) {

			$prevBtn.removeClass("disabled").unbind("click").bind("click", function() {

				galleryGroups[group][prevKey].click();

			});

			

		} else {

			$prevBtn.addClass("disabled").unbind("click");

		}

		

		// Keys shortcuts

		$(document)

			.unbind("keydown.superbox_np")

			.bind("keydown.superbox_np", function(e) {

				

				// Left/right arrows

				if (e.keyCode == 39) {

					$nextBtn.click();

				

				} else if (e.keyCode == 37) {

					$prevBtn.click();

				}

			});

	};

	

	// Hide Box

	function hideBox() {

		

		if (!!$curLink) {

			$curLink.focus();

		}

		

		$(document).unbind("keydown.spbx_close").unbind("keydown.superbox_np");

		$loading.hide();

		$nextprev.hide();

		$wrapper.hide().css({position: "fixed", top: 0});

		$innerbox.empty();

		$curLink = null;

	};

	

	// "Loading..."

	function initLoading(callback) {

		

		// Keys shortcuts

		$(document)

			.unbind("keydown.spbx_close")

			.bind("keydown.spbx_close",function(e) {

				

				// Escape

				if (e.keyCode == 27) {

					$.superbox.close();

				}

			});

		

		var loading = function() {

			

			// IE6

			if($.browser.msie && $.browser.version < 7) {

				$wrapper.css({position: "absolute", top:"50%"});

			}

			

			// Hide elements for IE6

			hideElts.hide();

			

			$loading.show();

			callback();

		};

		

		if (galleryMode) {

			$overlay.css("opacity", settings.overlayOpacity).show();

			loading();

		}

		else {

			$overlay.css("opacity", 0).show().fadeTo(100, settings.overlayOpacity, loading);

		}

	};

	

	// "Prepare" box : Show $superbox with top:-99999px;

	function prepareBox() {

		$wrapper.show();

		$innerbox.empty();

		$superbox.css({position: "absolute", top: "-99999px"});

	};

	

	// Display box

	function showBox(curSettings) {

		

		curSettings = $.extend({}, settings, curSettings);

		

		// Stop "Loading..."

		$loading.hide();

		

		// Show $superbox

		$superbox.css({position: "static", top: 0, opacity: 0});

		

		// IE6 and IE7

		if ($.browser.msie && $.browser.version < 8) {

			$superbox.css({position: "relative", top:"-50%"});

			

			// IE6

			if ($.browser.msie && $.browser.version < 7) {

				$wrapper.css({position: "absolute", top:"50%"});

			}

		}

		

		// Position absolute if image height > window height

		if ( $(window).height() < $wrapper.height() ) {

			$wrapper.css({position: "absolute", top: ($wrapper.offset().top + 10) + "px"});

		}

		

		curSettings.beforeOpen();

		

		$superbox.fadeTo(100, 1, function(){

			curSettings.afterOpen();

		}).focus();

	};

	

	// Create base elements (overlay, wrapper, box, loading)

	function createElements() {

		

		// Overlay (background)

		$overlay = $('<div id="superbox-overlay"/>').appendTo("body").hide();

		

		// Wrapper

		$wrapper = $('<div id="superbox-wrapper"/>').appendTo("body").hide();

		

		// Box container

		$container = $('<div id="superbox-container"/>').appendTo($wrapper);

		

		// Box

		$superbox = $('<div id="superbox" tabindex="0"/>').appendTo($container);

		

		// Inner box

		$innerbox = $('<div id="superbox-innerbox"/>').appendTo($superbox);

		

		// "Next / Previous"

		$nextprev = $('<p class="nextprev"/>').appendTo($superbox).hide();

		$prevBtn = $('<a class="prev" tabindex="0" role="button"><strong><span>'+ settings.prevTxt +'</span></strong></a>').appendTo($nextprev);

		$nextBtn = $('<a class="next" tabindex="0" role="button"><strong><span>'+ settings.nextTxt +'</span></strong></a>').appendTo($nextprev);

		

		// Add close button

		$closeBtn = $('<p class="close"><a tabindex="0" role="button"><strong><span>'+ settings.closeTxt +'</span></strong></a></p>').prependTo($superbox).find("a");

		

		// "Loading..."

		$loading = $('<p class="loading">'+ settings.loadTxt +'</p>').appendTo($container).hide();

	};

	

	// Init global events : close (echap), keyboard access (focus + enter)

	function initGlobalEvents() {

		

		// Hide on click

		$overlay.add($wrapper).add($closeBtn).click(function() {

			$.superbox.close();

		});

		

		// Remove "hide on click" on superbox

		$superbox.click(function(e) {

			e.stopPropagation();

		});

		

		// Opera already click on "focus + enter"

		if (!window.opera) {

			

			// Keyboard (focus + enter)

			$prevBtn.add($closeBtn).add($nextBtn).keypress(function(e) {

				if (e.keyCode === 13) {

					$(this).click();

				}

			});

		}

	}

	

})(jQuery);
