/* * jQuery Galleriffic plugin * * Copyright (c) 2008 Trent Foley (http://trentacular.com) * Licensed under the MIT License: *   http://www.opensource.org/licenses/mit-license.php * * Thanks to Taku Sano (Mikage Sawatari), whose history plugin I adapted to work with Galleriffic * Modified by Ghismo (ghismo.com) to disable the location rewrite  */;(function($) {// Write noscript styledocument.write("<style type='text/css'>.noscript{display:none}</style>");var ver = 'galleriffic-1.0';var galleryOffset = 0;var galleries = [];var allImages = [];	var historyCurrentHash;var historyBackStack;var historyForwardStack;var isFirst = false;var dontCheck = false;var isInitialized = false;function getHashFromString(hash) {if (!hash) return -1;hash = hash.replace(/^.*#/, '');if (isNaN(hash)) return -1;return (+hash);}function getHash() {var hash = location.hash;return getHashFromString(hash);}function registerGallery(gallery) {galleries.push(gallery);// update the global offset valuegalleryOffset += gallery.data.length;}function getGallery(hash) {for (i = 0; i < galleries.length; i++) {var gallery = galleries[i];if (hash < (gallery.data.length+gallery.offset))return gallery;}return 0;}function getIndex(gallery, hash) {return hash-gallery.offset;}function clickHandler(e, gallery, link) {gallery.pause();if (!gallery.settings.enableHistory) {var hash = getHashFromString(link.href);if (hash >= 0) {var index = getIndex(gallery, hash);if (index >= 0)gallery.goto(index);}e.preventDefault();}}function historyCallback() {// Using present location.hash always (seems to work, unlike the hash argument passed to this callback)var hash = getHash();if (hash < 0) return;var gallery = getGallery(hash);if (!gallery) return;var index = hash-gallery.offset;gallery.goto(index);}function historyInit() {if (isInitialized) return;isInitialized = true; var current_hash = location.hash; //(enableHistory) ? location.hash : currentIndexHash; // GhismohistoryCurrentHash = current_hash;if ($.browser.msie) {// To stop the callback firing twice during initilization if no hash presentif (historyCurrentHash == '') {historyCurrentHash = '#';}} else if ($.browser.safari) {// etablish back/forward stackshistoryBackStack = [];historyBackStack.length = history.length;historyForwardStack = [];isFirst = true;}setInterval(function() { historyCheck(); }, 100);}function historyAddHistory(hash) {// This makes the looping function do somethinghistoryBackStack.push(hash);historyForwardStack.length = 0; // clear forwardStack (true click occured)isFirst = true;}function historyCheck() {if ($.browser.safari) {if (!dontCheck) {var historyDelta = history.length - historyBackStack.length;if (historyDelta) { // back or forward button has been pushedisFirst = false;if (historyDelta < 0) { // back button has been pushed// move items to forward stackfor (var i = 0; i < Math.abs(historyDelta); i++) historyForwardStack.unshift(historyBackStack.pop());} else { // forward button has been pushed// move items to back stackfor (var i = 0; i < historyDelta; i++) historyBackStack.push(historyForwardStack.shift());}var cachedHash = historyBackStack[historyBackStack.length - 1];if (cachedHash != undefined) {historyCurrentHash = location.hash; // (enableHistory) ? location.hash : currentIndexHash; // GhismohistoryCallback();}} else if (historyBackStack[historyBackStack.length - 1] == undefined && !isFirst) {historyCallback();isFirst = true;}}} else {// otherwise, check for location.hashvar current_hash = location.hash; // (enableHistory) ? location.hash : currentIndexHash; // Ghismoif(current_hash != historyCurrentHash) {historyCurrentHash = current_hash;historyCallback();}}}var defaults = {delay:                  3000,numThumbs:              20,preloadAhead:           40, // Set to -1 to preload all imagesenableTopPager:         false,enableBottomPager:      true,imageContainerSel:      '',captionContainerSel:    '',controlsContainerSel:   '',loadingContainerSel:    '',renderSSControls:       true,renderNavControls:      true,playLinkText:           'Play',pauseLinkText:          'Pause',prevLinkText:           'Previous',nextLinkText:           'Next',nextPageLinkText:       'Next &rsaquo;',prevPageLinkText:       '&lsaquo; Prev',enableHistory:          false,autoStart:              false,onChange:               undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }onTransitionOut:        undefined, // accepts a delegate like such: function(callback) { ... }onTransitionIn:         undefined, // accepts a delegate like such: function() { ... }onPageTransitionOut:    undefined, // accepts a delegate like such: function(callback) { ... }onPageTransitionIn:     undefined  // accepts a delegate like such: function() { ... }};$.fn.galleriffic = function(thumbsContainerSel, settings) {//  Extend Gallery Object$.extend(this, {ver: function() {return ver;},initializeThumbs: function() {this.data = [];var gallery = this;this.$thumbsContainer.find('ul.thumbs > li').each(function(i) {var $li = $(this);var $aThumb = $li.find('a.thumb');var hash = gallery.offset+i;gallery.data.push({title:$aThumb.attr('title'),slideUrl:$aThumb.attr('href'),caption:$li.find('.caption').remove(),hash:hash});// Setup history$aThumb.attr('rel', 'history');$aThumb.attr('href', '#'+hash);$aThumb.click(function(e) {clickHandler(e, gallery, this);});});return this;},isPreloadComplete: false,preloadInit: function() {if (this.settings.preloadAhead == 0) return this;this.preloadStartIndex = this.currentIndex;var nextIndex = this.getNextIndex(this.preloadStartIndex);return this.preloadRecursive(this.preloadStartIndex, nextIndex);},preloadRelocate: function(index) {// By changing this startIndex, the current preload script will restartthis.preloadStartIndex = index;return this;},preloadRecursive: function(startIndex, currentIndex) {// Check if startIndex has been relocatedif (startIndex != this.preloadStartIndex) {var nextIndex = this.getNextIndex(this.preloadStartIndex);return this.preloadRecursive(this.preloadStartIndex, nextIndex);}var gallery = this;// Now check for preloadAhead countvar preloadCount = currentIndex - startIndex;if (preloadCount < 0)preloadCount = this.data.length-1-startIndex+currentIndex;if (this.settings.preloadAhead >= 0 && preloadCount > this.settings.preloadAhead) {// Do this in order to keep checking for relocated start indexsetTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);return this;}var imageData = this.data[currentIndex];if (!imageData)return this;// If already loaded, continueif (imageData.image)return this.preloadNext(startIndex, currentIndex); // Preload the imagevar image = new Image();image.onload = function() {imageData.image = this;gallery.preloadNext(startIndex, currentIndex);};image.title = "";//image.alt = imageData.alt;image.src = imageData.slideUrl;$(image).addClass('slideImage');return this;},preloadNext: function(startIndex, currentIndex) {var nextIndex = this.getNextIndex(currentIndex);if (nextIndex == startIndex) {this.isPreloadComplete = true;} else {// Use set timeout to free up threadvar gallery = this;setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);}return this;},getNextIndex: function(index) {var nextIndex = index+1;if (nextIndex >= this.data.length)nextIndex = 0;return nextIndex;},getPrevIndex: function(index) {var prevIndex = index-1;if (prevIndex < 0)prevIndex = this.data.length-1;return prevIndex;},pause: function() {if (this.interval)this.toggleSlideshow();return this;},play: function() {if (!this.interval)this.toggleSlideshow();return this;},toggleSlideshow: function() {if (this.interval) {clearInterval(this.interval);this.interval = 0;if (this.$controlsContainer) {this.$controlsContainer.find('div.ss-controls a').removeClass().addClass('play').attr('title', this.settings.playLinkText).attr('href', '#play').html(this.settings.playLinkText);}} else {this.ssAdvance();var gallery = this;this.interval = setInterval(function() {gallery.ssAdvance();}, this.settings.delay);if (this.$controlsContainer) {this.$controlsContainer.find('div.ss-controls a').removeClass().addClass('pause').attr('title', this.settings.pauseLinkText).attr('href', '#pause').html(this.settings.pauseLinkText);}}return this;},ssAdvance: function() {var nextIndex = this.getNextIndex(this.currentIndex);var nextHash = this.data[nextIndex].hash;// Seems to be working on both FF and Safariif (this.settings.enableHistory)location.href = '#'+nextHash;elsethis.goto(nextIndex);// IE we need to explicity call goto//if ($.browser.msie) {//	this.goto(nextIndex);//}return this;},goto: function(index) {if (index < 0) index = 0;else if (index >= this.data.length) index = this.data.length-1;if (this.settings.onChange)this.settings.onChange(this.currentIndex, index);this.currentIndex = index;this.preloadRelocate(index);return this.refresh();},refresh: function() {var imageData = this.data[this.currentIndex];if (!imageData)return this;// Flag we are transitioningvar isTransitioning = true;var gallery = this;var transitionOutCallback = function() {// Flag that the transition has completedisTransitioning = false;// Update Controlsif (gallery.$controlsContainer) {gallery.$controlsContainer.find('div.nav-controls a.prev').attr('href', '#'+gallery.data[gallery.getPrevIndex(gallery.currentIndex)].hash).end().find('div.nav-controls a.next').attr('href', '#'+gallery.data[gallery.getNextIndex(gallery.currentIndex)].hash);}var imageData = gallery.data[gallery.currentIndex];// Replace Captionif (gallery.$captionContainer) {gallery.$captionContainer.empty().append(imageData.caption);}if (imageData.image) {gallery.buildImage(imageData.image);} else {// Show loading containerif (gallery.$loadingContainer) {gallery.$loadingContainer.show();}}}if (this.settings.onTransitionOut) {this.settings.onTransitionOut(transitionOutCallback);} else {this.$transitionContainers.hide();transitionOutCallback();}if (!imageData.image) {var image = new Image();// Wire up mainImage onload eventimage.onload = function() {imageData.image = this;if (!isTransitioning) {gallery.buildImage(imageData.image);}};// set alt and srcimage.title = "";//image.alt = imageData.alt;image.src = imageData.slideUrl;$(image).addClass('slideImage');}// This causes the preloader (if still running) to relocate out from the currentIndexthis.relocatePreload = true;return this.syncThumbs();},buildImage: function(image) {if (this.$imageContainer) {this.$imageContainer.empty();var gallery = this;var nextIndex = this.getNextIndex(this.currentIndex);// Hide the loading conatinerif (this.$loadingContainer) {this.$loadingContainer.hide();}// Setup imagethis.$imageContainer.append('<span class="image-wrapper"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+image.alt+'"></a></span>').find('a').append(image).click(function(e) {clickHandler(e, gallery, this);});}if (this.settings.onTransitionIn)this.settings.onTransitionIn();elsethis.$transitionContainers.show();return this;},syncThumbs: function() {if (this.$thumbsContainer) {var page = Math.floor(this.currentIndex / this.settings.numThumbs);if (page != this.currentPage) {this.currentPage = page;this.updateThumbs();}// Remove existing selected class and add selected class to new thumbvar $thumbs = this.$thumbsContainer.find('ul.thumbs').children();$thumbs.filter('.selected').removeClass('selected');$thumbs.eq(this.currentIndex).addClass('selected');}return this;},updateThumbs: function() {var gallery = this;var transitionOutCallback = function() {gallery.rebuildThumbs();// Transition In the thumbsContainerif (gallery.settings.onPageTransitionIn)gallery.settings.onPageTransitionIn();elsegallery.$thumbsContainer.show();};// Transition Out the thumbsContainerif (this.settings.onPageTransitionOut) {this.settings.onPageTransitionOut(transitionOutCallback);} else {this.$thumbsContainer.hide();transitionOutCallback();}return this;},rebuildThumbs: function() {// Initialize currentPage to first pageif (this.currentPage < 0)this.currentPage = 0;var needsPagination = this.data.length > this.settings.numThumbs;// Rebuild top pagervar $topPager = this.$thumbsContainer.find('div.top');if ($topPager.length == 0)$topPager = this.$thumbsContainer.prepend('<div class="top pagination" id="top_pagination"></div>').find('div.top');if (needsPagination && this.settings.enableTopPager) {$topPager.empty();this.buildPager($topPager);}// Rebuild bottom pagerif (needsPagination && this.settings.enableBottomPager) {var $bottomPager = this.$thumbsContainer.find('div.bottom');if ($bottomPager.length == 0)$bottomPager = this.$thumbsContainer.append('<div class="bottom pagination" id="bottom_pagination"></div>').find('div.bottom');else$bottomPager.empty();this.buildPager($bottomPager);}var startIndex = this.currentPage*this.settings.numThumbs;var stopIndex = startIndex+this.settings.numThumbs-1;if (stopIndex >= this.data.length)stopIndex = this.data.length-1;// Show/Hide thumbsvar $thumbsUl = this.$thumbsContainer.find('ul.thumbs');$thumbsUl.find('li').each(function(i) {var $li = $(this);if (i >= startIndex && i <= stopIndex) {$li.show();} else {$li.hide();}});// Remove the noscript class from the thumbs container ul$thumbsUl.removeClass('noscript');return this;},buildPager: function(pager) {var gallery = this;var startIndex = this.currentPage*this.settings.numThumbs;// Prev Page Linkif (this.currentPage > 0) {var prevPage = startIndex - this.settings.numThumbs;pager.append('<a rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.settings.prevPageLinkText+'">'+this.settings.prevPageLinkText+'</a>');}// Page Index Linksfor (i=this.currentPage-3; i<=this.currentPage+3; i++) {var pageNum = i+1;if (i == this.currentPage)pager.append('<span class="current">'+pageNum+'</span>');else if (i>=0 && i<this.numPages) {var imageIndex = i*this.settings.numThumbs;pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageNum+'">'+pageNum+'</a>');}}// Next Page Linkvar nextPage = startIndex+this.settings.numThumbs;if (nextPage < this.data.length) {pager.append('<a rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.settings.nextPageLinkText+'">'+this.settings.nextPageLinkText+'</a>');}pager.find('a').click(function(e) {clickHandler(e, gallery, this);});return this;}});// Now initialize the gallerythis.settings = $.extend({}, defaults, settings);//enableHistory = this.settings.enableHistory; // Ghismoif (this.interval)clearInterval(this.interval);this.interval = 0;if (this.settings.imageContainerSel) this.$imageContainer = $(this.settings.imageContainerSel);if (this.settings.captionContainerSel) this.$captionContainer = $(this.settings.captionContainerSel);if (this.settings.loadingContainerSel) this.$loadingContainer = $(this.settings.loadingContainerSel);// Setup the jQuery object holding each container that will be transitionedthis.$transitionContainers = $([]);if (this.$imageContainer)this.$transitionContainers = this.$transitionContainers.add(this.$imageContainer);if (this.$captionContainer)this.$transitionContainers = this.$transitionContainers.add(this.$captionContainer);// Set the hash index offset for this gallerythis.offset = galleryOffset;this.$thumbsContainer = $(thumbsContainerSel);this.initializeThumbs();// Add this gallery to the global galleries arrayregisterGallery(this);this.numPages = Math.ceil(this.data.length/this.settings.numThumbs);this.currentPage = -1;this.currentIndex = 0;var gallery = this;// Hide the loadingContainerif (this.$loadingContainer)this.$loadingContainer.hide();// Setup controlsif (this.settings.controlsContainerSel) {this.$controlsContainer = $(this.settings.controlsContainerSel).empty();if (this.settings.renderSSControls) {if (this.settings.autoStart) {this.$controlsContainer.append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.settings.pauseLinkText+'">'+this.settings.pauseLinkText+'</a></div>');} else {this.$controlsContainer.append('<div class="ss-controls"><a href="#play" class="play" title="'+this.settings.playLinkText+'">'+this.settings.playLinkText+'</a></div>');}this.$controlsContainer.find('div.ss-controls a').click(function(e) {gallery.toggleSlideshow();e.preventDefault();return false;});}if (this.settings.renderNavControls) {var $navControls = this.$controlsContainer.append('<div class="nav-controls"><a class="prev" rel="history" title="'+this.settings.prevLinkText+'">'+this.settings.prevLinkText+'</a><a class="next" rel="history" title="'+this.settings.nextLinkText+'">'+this.settings.nextLinkText+'</a></div>').find('div.nav-controls a').click(function(e) {clickHandler(e, gallery, this);});}}// Initialize history only once when the first gallery on the page is initializedhistoryInit();// Build imagevar hash = getHash();var hashGallery = (hash >= 0) ? getGallery(hash) : 0;var gotoIndex = (hashGallery && this == hashGallery) ? (hash-this.offset) : 0;this.goto(gotoIndex);if (this.settings.autoStart) {setTimeout(function() { gallery.play(); }, this.settings.delay);}// Kickoff Image Preloader after 1 secondsetTimeout(function() { gallery.preloadInit(); }, 1000);return this;};})(jQuery);