| 
0
 | 
     1 /**
 | 
| 
 | 
     2  * jQuery Galleriffic plugin
 | 
| 
 | 
     3  *
 | 
| 
 | 
     4  * Copyright (c) 2008 Trent Foley (http://trentacular.com)
 | 
| 
 | 
     5  * Licensed under the MIT License:
 | 
| 
 | 
     6  *   http://www.opensource.org/licenses/mit-license.php
 | 
| 
 | 
     7  *
 | 
| 
 | 
     8  * Much thanks to primary contributer Ponticlaro (http://www.ponticlaro.com)
 | 
| 
 | 
     9  */
 | 
| 
 | 
    10 ;(function($) {
 | 
| 
 | 
    11 	// Globally keep track of all images by their unique hash.  Each item is an image data object.
 | 
| 
 | 
    12 	var allImages = {};
 | 
| 
 | 
    13 	var imageCounter = 0;
 | 
| 
 | 
    14 
 | 
| 
 | 
    15 	// Galleriffic static class
 | 
| 
 | 
    16 	$.galleriffic = {
 | 
| 
 | 
    17 		version: '2.0.1',
 | 
| 
 | 
    18 
 | 
| 
 | 
    19 		// Strips invalid characters and any leading # characters
 | 
| 
 | 
    20 		normalizeHash: function(hash) {
 | 
| 
 | 
    21 			return hash.replace(/^.*#/, '').replace(/\?.*$/, '');
 | 
| 
 | 
    22 		},
 | 
| 
 | 
    23 
 | 
| 
 | 
    24 		getImage: function(hash) {
 | 
| 
 | 
    25 			if (!hash)
 | 
| 
 | 
    26 				return undefined;
 | 
| 
 | 
    27 
 | 
| 
 | 
    28 			hash = $.galleriffic.normalizeHash(hash);
 | 
| 
 | 
    29 			return allImages[hash];
 | 
| 
 | 
    30 		},
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 		// Global function that looks up an image by its hash and displays the image.
 | 
| 
 | 
    33 		// Returns false when an image is not found for the specified hash.
 | 
| 
 | 
    34 		// @param {String} hash This is the unique hash value assigned to an image.
 | 
| 
 | 
    35 		gotoImage: function(hash) {
 | 
| 
 | 
    36 			var imageData = $.galleriffic.getImage(hash);
 | 
| 
 | 
    37 			if (!imageData)
 | 
| 
 | 
    38 				return false;
 | 
| 
 | 
    39 
 | 
| 
 | 
    40 			var gallery = imageData.gallery;
 | 
| 
 | 
    41 			gallery.gotoImage(imageData);
 | 
| 
 | 
    42 			
 | 
| 
 | 
    43 			return true;
 | 
| 
 | 
    44 		},
 | 
| 
 | 
    45 
 | 
| 
 | 
    46 		// Removes an image from its respective gallery by its hash.
 | 
| 
 | 
    47 		// Returns false when an image is not found for the specified hash or the
 | 
| 
 | 
    48 		// specified owner gallery does match the located images gallery.
 | 
| 
 | 
    49 		// @param {String} hash This is the unique hash value assigned to an image.
 | 
| 
 | 
    50 		// @param {Object} ownerGallery (Optional) When supplied, the located images
 | 
| 
 | 
    51 		// gallery is verified to be the same as the specified owning gallery before
 | 
| 
 | 
    52 		// performing the remove operation.
 | 
| 
 | 
    53 		removeImageByHash: function(hash, ownerGallery) {
 | 
| 
 | 
    54 			var imageData = $.galleriffic.getImage(hash);
 | 
| 
 | 
    55 			if (!imageData)
 | 
| 
 | 
    56 				return false;
 | 
| 
 | 
    57 
 | 
| 
 | 
    58 			var gallery = imageData.gallery;
 | 
| 
 | 
    59 			if (ownerGallery && ownerGallery != gallery)
 | 
| 
 | 
    60 				return false;
 | 
| 
 | 
    61 
 | 
| 
 | 
    62 			return gallery.removeImageByIndex(imageData.index);
 | 
| 
 | 
    63 		}
 | 
| 
 | 
    64 	};
 | 
| 
 | 
    65 
 | 
| 
 | 
    66 	var defaults = {
 | 
| 
 | 
    67 		delay:                     3000,
 | 
| 
 | 
    68 		numThumbs:                 20,
 | 
| 
 | 
    69 		preloadAhead:              40, // Set to -1 to preload all images
 | 
| 
 | 
    70 		enableTopPager:            false,
 | 
| 
 | 
    71 		enableBottomPager:         true,
 | 
| 
 | 
    72 		maxPagesToShow:            7,
 | 
| 
 | 
    73 		imageContainerSel:         '',
 | 
| 
 | 
    74 		captionContainerSel:       '',
 | 
| 
 | 
    75 		controlsContainerSel:      '',
 | 
| 
 | 
    76 		loadingContainerSel:       '',
 | 
| 
 | 
    77 		renderSSControls:          true,
 | 
| 
 | 
    78 		renderNavControls:         true,
 | 
| 
 | 
    79 		playLinkText:              'Play',
 | 
| 
 | 
    80 		pauseLinkText:             'Pause',
 | 
| 
 | 
    81 		prevLinkText:              'Previous',
 | 
| 
 | 
    82 		nextLinkText:              'Next',
 | 
| 
 | 
    83 		nextPageLinkText:          'Next ›',
 | 
| 
 | 
    84 		prevPageLinkText:          '‹ Prev',
 | 
| 
 | 
    85 		enableHistory:             false,
 | 
| 
 | 
    86 		enableKeyboardNavigation:  true,
 | 
| 
 | 
    87 		autoStart:                 false,
 | 
| 
 | 
    88 		syncTransitions:           false,
 | 
| 
 | 
    89 		defaultTransitionDuration: 1000,
 | 
| 
 | 
    90 		onSlideChange:             undefined, // accepts a delegate like such: function(prevIndex, nextIndex) { ... }
 | 
| 
 | 
    91 		onTransitionOut:           undefined, // accepts a delegate like such: function(slide, caption, isSync, callback) { ... }
 | 
| 
 | 
    92 		onTransitionIn:            undefined, // accepts a delegate like such: function(slide, caption, isSync) { ... }
 | 
| 
 | 
    93 		onPageTransitionOut:       undefined, // accepts a delegate like such: function(callback) { ... }
 | 
| 
 | 
    94 		onPageTransitionIn:        undefined, // accepts a delegate like such: function() { ... }
 | 
| 
 | 
    95 		onImageAdded:              undefined, // accepts a delegate like such: function(imageData, $li) { ... }
 | 
| 
 | 
    96 		onImageRemoved:            undefined  // accepts a delegate like such: function(imageData, $li) { ... }
 | 
| 
 | 
    97 	};
 | 
| 
 | 
    98 
 | 
| 
 | 
    99 	// Primary Galleriffic initialization function that should be called on the thumbnail container.
 | 
| 
 | 
   100 	$.fn.galleriffic = function(settings) {
 | 
| 
 | 
   101 		//  Extend Gallery Object
 | 
| 
 | 
   102 		$.extend(this, {
 | 
| 
 | 
   103 			// Returns the version of the script
 | 
| 
 | 
   104 			version: $.galleriffic.version,
 | 
| 
 | 
   105 
 | 
| 
 | 
   106 			// Current state of the slideshow
 | 
| 
 | 
   107 			isSlideshowRunning: false,
 | 
| 
 | 
   108 			slideshowTimeout: undefined,
 | 
| 
 | 
   109 
 | 
| 
 | 
   110 			// This function is attached to the click event of generated hyperlinks within the gallery
 | 
| 
 | 
   111 			clickHandler: function(e, link) {
 | 
| 
 | 
   112 				this.pause();
 | 
| 
 | 
   113 
 | 
| 
 | 
   114 				if (!this.enableHistory) {
 | 
| 
 | 
   115 					// The href attribute holds the unique hash for an image
 | 
| 
 | 
   116 					var hash = $.galleriffic.normalizeHash($(link).attr('href'));
 | 
| 
 | 
   117 					$.galleriffic.gotoImage(hash);
 | 
| 
 | 
   118 					e.preventDefault();
 | 
| 
 | 
   119 				}
 | 
| 
 | 
   120 			},
 | 
| 
 | 
   121 
 | 
| 
 | 
   122 			// Appends an image to the end of the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
 | 
| 
 | 
   123 			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
 | 
| 
 | 
   124 			appendImage: function(listItem) {
 | 
| 
 | 
   125 				this.addImage(listItem, false, false);
 | 
| 
 | 
   126 				return this;
 | 
| 
 | 
   127 			},
 | 
| 
 | 
   128 
 | 
| 
 | 
   129 			// Inserts an image into the set of images.  Argument listItem can be either a jQuery DOM element or arbitrary html.
 | 
| 
 | 
   130 			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
 | 
| 
 | 
   131 			// @param {Integer} position The index within the gallery where the item shouold be added.
 | 
| 
 | 
   132 			insertImage: function(listItem, position) {
 | 
| 
 | 
   133 				this.addImage(listItem, false, true, position);
 | 
| 
 | 
   134 				return this;
 | 
| 
 | 
   135 			},
 | 
| 
 | 
   136 
 | 
| 
 | 
   137 			// Adds an image to the gallery and optionally inserts/appends it to the DOM (thumbExists)
 | 
| 
 | 
   138 			// @param listItem Either a jQuery object or a string of html of the list item that is to be added to the gallery.
 | 
| 
 | 
   139 			// @param {Boolean} thumbExists Specifies whether the thumbnail already exists in the DOM or if it needs to be added.
 | 
| 
 | 
   140 			// @param {Boolean} insert Specifies whether the the image is appended to the end or inserted into the gallery.
 | 
| 
 | 
   141 			// @param {Integer} position The index within the gallery where the item shouold be added.
 | 
| 
 | 
   142 			addImage: function(listItem, thumbExists, insert, position) {
 | 
| 
 | 
   143 				var $li = ( typeof listItem === "string" ) ? $(listItem) : listItem;				
 | 
| 
 | 
   144 				var $aThumb = $li.find('a.thumb');
 | 
| 
 | 
   145 				var slideUrl = $aThumb.attr('href');
 | 
| 
 | 
   146 				var title = $aThumb.attr('title');
 | 
| 
 | 
   147 				var $caption = $li.find('.caption').remove();
 | 
| 
 | 
   148 				var hash = $aThumb.attr('name');
 | 
| 
 | 
   149 
 | 
| 
 | 
   150 				// Increment the image counter
 | 
| 
 | 
   151 				imageCounter++;
 | 
| 
 | 
   152 
 | 
| 
 | 
   153 				// Autogenerate a hash value if none is present or if it is a duplicate
 | 
| 
 | 
   154 				if (!hash || allImages[''+hash]) {
 | 
| 
 | 
   155 					hash = imageCounter;
 | 
| 
 | 
   156 				}
 | 
| 
 | 
   157 
 | 
| 
 | 
   158 				// Set position to end when not specified
 | 
| 
 | 
   159 				if (!insert)
 | 
| 
 | 
   160 					position = this.data.length;
 | 
| 
 | 
   161 				
 | 
| 
 | 
   162 				var imageData = {
 | 
| 
 | 
   163 					title:title,
 | 
| 
 | 
   164 					slideUrl:slideUrl,
 | 
| 
 | 
   165 					caption:$caption,
 | 
| 
 | 
   166 					hash:hash,
 | 
| 
 | 
   167 					gallery:this,
 | 
| 
 | 
   168 					index:position
 | 
| 
 | 
   169 				};
 | 
| 
 | 
   170 
 | 
| 
 | 
   171 				// Add the imageData to this gallery's array of images
 | 
| 
 | 
   172 				if (insert) {
 | 
| 
 | 
   173 					this.data.splice(position, 0, imageData);
 | 
| 
 | 
   174 
 | 
| 
 | 
   175 					// Reset index value on all imageData objects
 | 
| 
 | 
   176 					this.updateIndices(position);
 | 
| 
 | 
   177 				}
 | 
| 
 | 
   178 				else {
 | 
| 
 | 
   179 					this.data.push(imageData);
 | 
| 
 | 
   180 				}
 | 
| 
 | 
   181 
 | 
| 
 | 
   182 				var gallery = this;
 | 
| 
 | 
   183 
 | 
| 
 | 
   184 				// Add the element to the DOM
 | 
| 
 | 
   185 				if (!thumbExists) {
 | 
| 
 | 
   186 					// Update thumbs passing in addition post transition out handler
 | 
| 
 | 
   187 					this.updateThumbs(function() {
 | 
| 
 | 
   188 						var $thumbsUl = gallery.find('ul.thumbs');
 | 
| 
 | 
   189 						if (insert)
 | 
| 
 | 
   190 							$thumbsUl.children(':eq('+position+')').before($li);
 | 
| 
 | 
   191 						else
 | 
| 
 | 
   192 							$thumbsUl.append($li);
 | 
| 
 | 
   193 						
 | 
| 
 | 
   194 						if (gallery.onImageAdded)
 | 
| 
 | 
   195 							gallery.onImageAdded(imageData, $li);
 | 
| 
 | 
   196 					});
 | 
| 
 | 
   197 				}
 | 
| 
 | 
   198 
 | 
| 
 | 
   199 				// Register the image globally
 | 
| 
 | 
   200 				allImages[''+hash] = imageData;
 | 
| 
 | 
   201 
 | 
| 
 | 
   202 				// Setup attributes and click handler
 | 
| 
 | 
   203 				$aThumb.attr('rel', 'history')
 | 
| 
 | 
   204 					.attr('href', '#'+hash)
 | 
| 
 | 
   205 					.removeAttr('name')
 | 
| 
 | 
   206 					.click(function(e) {
 | 
| 
 | 
   207 						gallery.clickHandler(e, this);
 | 
| 
 | 
   208 					});
 | 
| 
 | 
   209 
 | 
| 
 | 
   210 				return this;
 | 
| 
 | 
   211 			},
 | 
| 
 | 
   212 
 | 
| 
 | 
   213 			// Removes an image from the gallery based on its index.
 | 
| 
 | 
   214 			// Returns false when the index is out of range.
 | 
| 
 | 
   215 			removeImageByIndex: function(index) {
 | 
| 
 | 
   216 				if (index < 0 || index >= this.data.length)
 | 
| 
 | 
   217 					return false;
 | 
| 
 | 
   218 				
 | 
| 
 | 
   219 				var imageData = this.data[index];
 | 
| 
 | 
   220 				if (!imageData)
 | 
| 
 | 
   221 					return false;
 | 
| 
 | 
   222 				
 | 
| 
 | 
   223 				this.removeImage(imageData);
 | 
| 
 | 
   224 				
 | 
| 
 | 
   225 				return true;
 | 
| 
 | 
   226 			},
 | 
| 
 | 
   227 
 | 
| 
 | 
   228 			// Convenience method that simply calls the global removeImageByHash method.
 | 
| 
 | 
   229 			removeImageByHash: function(hash) {
 | 
| 
 | 
   230 				return $.galleriffic.removeImageByHash(hash, this);
 | 
| 
 | 
   231 			},
 | 
| 
 | 
   232 
 | 
| 
 | 
   233 			// Removes an image from the gallery.
 | 
| 
 | 
   234 			removeImage: function(imageData) {
 | 
| 
 | 
   235 				var index = imageData.index;
 | 
| 
 | 
   236 				
 | 
| 
 | 
   237 				// Remove the image from the gallery data array
 | 
| 
 | 
   238 				this.data.splice(index, 1);
 | 
| 
 | 
   239 				
 | 
| 
 | 
   240 				// Remove the global registration
 | 
| 
 | 
   241 				delete allImages[''+imageData.hash];
 | 
| 
 | 
   242 				
 | 
| 
 | 
   243 				// Remove the image's list item from the DOM
 | 
| 
 | 
   244 				this.updateThumbs(function() {
 | 
| 
 | 
   245 					var $li = gallery.find('ul.thumbs')
 | 
| 
 | 
   246 						.children(':eq('+index+')')
 | 
| 
 | 
   247 						.remove();
 | 
| 
 | 
   248 
 | 
| 
 | 
   249 					if (gallery.onImageRemoved)
 | 
| 
 | 
   250 						gallery.onImageRemoved(imageData, $li);
 | 
| 
 | 
   251 				});
 | 
| 
 | 
   252 
 | 
| 
 | 
   253 				// Update each image objects index value
 | 
| 
 | 
   254 				this.updateIndices(index);
 | 
| 
 | 
   255 
 | 
| 
 | 
   256 				return this;
 | 
| 
 | 
   257 			},
 | 
| 
 | 
   258 
 | 
| 
 | 
   259 			// Updates the index values of the each of the images in the gallery after the specified index
 | 
| 
 | 
   260 			updateIndices: function(startIndex) {
 | 
| 
 | 
   261 				for (i = startIndex; i < this.data.length; i++) {
 | 
| 
 | 
   262 					this.data[i].index = i;
 | 
| 
 | 
   263 				}
 | 
| 
 | 
   264 				
 | 
| 
 | 
   265 				return this;
 | 
| 
 | 
   266 			},
 | 
| 
 | 
   267 
 | 
| 
 | 
   268 			// Scraped the thumbnail container for thumbs and adds each to the gallery
 | 
| 
 | 
   269 			initializeThumbs: function() {
 | 
| 
 | 
   270 				this.data = [];
 | 
| 
 | 
   271 				var gallery = this;
 | 
| 
 | 
   272 
 | 
| 
 | 
   273 				this.find('ul.thumbs > li').each(function(i) {
 | 
| 
 | 
   274 					gallery.addImage($(this), true, false);
 | 
| 
 | 
   275 				});
 | 
| 
 | 
   276 
 | 
| 
 | 
   277 				return this;
 | 
| 
 | 
   278 			},
 | 
| 
 | 
   279 
 | 
| 
 | 
   280 			isPreloadComplete: false,
 | 
| 
 | 
   281 
 | 
| 
 | 
   282 			// Initalizes the image preloader
 | 
| 
 | 
   283 			preloadInit: function() {
 | 
| 
 | 
   284 				if (this.preloadAhead == 0) return this;
 | 
| 
 | 
   285 				
 | 
| 
 | 
   286 				this.preloadStartIndex = this.currentImage.index;
 | 
| 
 | 
   287 				var nextIndex = this.getNextIndex(this.preloadStartIndex);
 | 
| 
 | 
   288 				return this.preloadRecursive(this.preloadStartIndex, nextIndex);
 | 
| 
 | 
   289 			},
 | 
| 
 | 
   290 
 | 
| 
 | 
   291 			// Changes the location in the gallery the preloader should work
 | 
| 
 | 
   292 			// @param {Integer} index The index of the image where the preloader should restart at.
 | 
| 
 | 
   293 			preloadRelocate: function(index) {
 | 
| 
 | 
   294 				// By changing this startIndex, the current preload script will restart
 | 
| 
 | 
   295 				this.preloadStartIndex = index;
 | 
| 
 | 
   296 				return this;
 | 
| 
 | 
   297 			},
 | 
| 
 | 
   298 
 | 
| 
 | 
   299 			// Recursive function that performs the image preloading
 | 
| 
 | 
   300 			// @param {Integer} startIndex The index of the first image the current preloader started on.
 | 
| 
 | 
   301 			// @param {Integer} currentIndex The index of the current image to preload.
 | 
| 
 | 
   302 			preloadRecursive: function(startIndex, currentIndex) {
 | 
| 
 | 
   303 				// Check if startIndex has been relocated
 | 
| 
 | 
   304 				if (startIndex != this.preloadStartIndex) {
 | 
| 
 | 
   305 					var nextIndex = this.getNextIndex(this.preloadStartIndex);
 | 
| 
 | 
   306 					return this.preloadRecursive(this.preloadStartIndex, nextIndex);
 | 
| 
 | 
   307 				}
 | 
| 
 | 
   308 
 | 
| 
 | 
   309 				var gallery = this;
 | 
| 
 | 
   310 
 | 
| 
 | 
   311 				// Now check for preloadAhead count
 | 
| 
 | 
   312 				var preloadCount = currentIndex - startIndex;
 | 
| 
 | 
   313 				if (preloadCount < 0)
 | 
| 
 | 
   314 					preloadCount = this.data.length-1-startIndex+currentIndex;
 | 
| 
 | 
   315 				if (this.preloadAhead >= 0 && preloadCount > this.preloadAhead) {
 | 
| 
 | 
   316 					// Do this in order to keep checking for relocated start index
 | 
| 
 | 
   317 					setTimeout(function() { gallery.preloadRecursive(startIndex, currentIndex); }, 500);
 | 
| 
 | 
   318 					return this;
 | 
| 
 | 
   319 				}
 | 
| 
 | 
   320 
 | 
| 
 | 
   321 				var imageData = this.data[currentIndex];
 | 
| 
 | 
   322 				if (!imageData)
 | 
| 
 | 
   323 					return this;
 | 
| 
 | 
   324 
 | 
| 
 | 
   325 				// If already loaded, continue
 | 
| 
 | 
   326 				if (imageData.image)
 | 
| 
 | 
   327 					return this.preloadNext(startIndex, currentIndex); 
 | 
| 
 | 
   328 				
 | 
| 
 | 
   329 				// Preload the image
 | 
| 
 | 
   330 				var image = new Image();
 | 
| 
 | 
   331 				
 | 
| 
 | 
   332 				image.onload = function() {
 | 
| 
 | 
   333 					imageData.image = this;
 | 
| 
 | 
   334 					gallery.preloadNext(startIndex, currentIndex);
 | 
| 
 | 
   335 				};
 | 
| 
 | 
   336 
 | 
| 
 | 
   337 				image.alt = imageData.title;
 | 
| 
 | 
   338 				image.src = imageData.slideUrl;
 | 
| 
 | 
   339 
 | 
| 
 | 
   340 				return this;
 | 
| 
 | 
   341 			},
 | 
| 
 | 
   342 			
 | 
| 
 | 
   343 			// Called by preloadRecursive in order to preload the next image after the previous has loaded.
 | 
| 
 | 
   344 			// @param {Integer} startIndex The index of the first image the current preloader started on.
 | 
| 
 | 
   345 			// @param {Integer} currentIndex The index of the current image to preload.
 | 
| 
 | 
   346 			preloadNext: function(startIndex, currentIndex) {
 | 
| 
 | 
   347 				var nextIndex = this.getNextIndex(currentIndex);
 | 
| 
 | 
   348 				if (nextIndex == startIndex) {
 | 
| 
 | 
   349 					this.isPreloadComplete = true;
 | 
| 
 | 
   350 				} else {
 | 
| 
 | 
   351 					// Use setTimeout to free up thread
 | 
| 
 | 
   352 					var gallery = this;
 | 
| 
 | 
   353 					setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
 | 
| 
 | 
   354 				}
 | 
| 
 | 
   355 
 | 
| 
 | 
   356 				return this;
 | 
| 
 | 
   357 			},
 | 
| 
 | 
   358 
 | 
| 
 | 
   359 			// Safe way to get the next image index relative to the current image.
 | 
| 
 | 
   360 			// If the current image is the last, returns 0
 | 
| 
 | 
   361 			getNextIndex: function(index) {
 | 
| 
 | 
   362 				var nextIndex = index+1;
 | 
| 
 | 
   363 				if (nextIndex >= this.data.length)
 | 
| 
 | 
   364 					nextIndex = 0;
 | 
| 
 | 
   365 				return nextIndex;
 | 
| 
 | 
   366 			},
 | 
| 
 | 
   367 
 | 
| 
 | 
   368 			// Safe way to get the previous image index relative to the current image.
 | 
| 
 | 
   369 			// If the current image is the first, return the index of the last image in the gallery.
 | 
| 
 | 
   370 			getPrevIndex: function(index) {
 | 
| 
 | 
   371 				var prevIndex = index-1;
 | 
| 
 | 
   372 				if (prevIndex < 0)
 | 
| 
 | 
   373 					prevIndex = this.data.length-1;
 | 
| 
 | 
   374 				return prevIndex;
 | 
| 
 | 
   375 			},
 | 
| 
 | 
   376 
 | 
| 
 | 
   377 			// Pauses the slideshow
 | 
| 
 | 
   378 			pause: function() {
 | 
| 
 | 
   379 				this.isSlideshowRunning = false;
 | 
| 
 | 
   380 				if (this.slideshowTimeout) {
 | 
| 
 | 
   381 					clearTimeout(this.slideshowTimeout);
 | 
| 
 | 
   382 					this.slideshowTimeout = undefined;
 | 
| 
 | 
   383 				}
 | 
| 
 | 
   384 
 | 
| 
 | 
   385 				if (this.$controlsContainer) {
 | 
| 
 | 
   386 					this.$controlsContainer
 | 
| 
 | 
   387 						.find('div.ss-controls a').removeClass().addClass('play')
 | 
| 
 | 
   388 						.attr('title', this.playLinkText)
 | 
| 
 | 
   389 						.attr('href', '#play')
 | 
| 
 | 
   390 						.html(this.playLinkText);
 | 
| 
 | 
   391 				}
 | 
| 
 | 
   392 				
 | 
| 
 | 
   393 				return this;
 | 
| 
 | 
   394 			},
 | 
| 
 | 
   395 
 | 
| 
 | 
   396 			// Plays the slideshow
 | 
| 
 | 
   397 			play: function() {
 | 
| 
 | 
   398 				this.isSlideshowRunning = true;
 | 
| 
 | 
   399 
 | 
| 
 | 
   400 				if (this.$controlsContainer) {
 | 
| 
 | 
   401 					this.$controlsContainer
 | 
| 
 | 
   402 						.find('div.ss-controls a').removeClass().addClass('pause')
 | 
| 
 | 
   403 						.attr('title', this.pauseLinkText)
 | 
| 
 | 
   404 						.attr('href', '#pause')
 | 
| 
 | 
   405 						.html(this.pauseLinkText);
 | 
| 
 | 
   406 				}
 | 
| 
 | 
   407 
 | 
| 
 | 
   408 				if (!this.slideshowTimeout) {
 | 
| 
 | 
   409 					var gallery = this;
 | 
| 
 | 
   410 					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
 | 
| 
 | 
   411 				}
 | 
| 
 | 
   412 
 | 
| 
 | 
   413 				return this;
 | 
| 
 | 
   414 			},
 | 
| 
 | 
   415 
 | 
| 
 | 
   416 			// Toggles the state of the slideshow (playing/paused)
 | 
| 
 | 
   417 			toggleSlideshow: function() {
 | 
| 
 | 
   418 				if (this.isSlideshowRunning)
 | 
| 
 | 
   419 					this.pause();
 | 
| 
 | 
   420 				else
 | 
| 
 | 
   421 					this.play();
 | 
| 
 | 
   422 
 | 
| 
 | 
   423 				return this;
 | 
| 
 | 
   424 			},
 | 
| 
 | 
   425 
 | 
| 
 | 
   426 			// Advances the slideshow to the next image and delegates navigation to the
 | 
| 
 | 
   427 			// history plugin when history is enabled
 | 
| 
 | 
   428 			// enableHistory is true
 | 
| 
 | 
   429 			ssAdvance: function() {
 | 
| 
 | 
   430 				if (this.isSlideshowRunning)
 | 
| 
 | 
   431 					this.next(true);
 | 
| 
 | 
   432 
 | 
| 
 | 
   433 				return this;
 | 
| 
 | 
   434 			},
 | 
| 
 | 
   435 
 | 
| 
 | 
   436 			// Advances the gallery to the next image.
 | 
| 
 | 
   437 			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
 | 
| 
 | 
   438 			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.  
 | 
| 
 | 
   439 			next: function(dontPause, bypassHistory) {
 | 
| 
 | 
   440 				this.gotoIndex(this.getNextIndex(this.currentImage.index), dontPause, bypassHistory);
 | 
| 
 | 
   441 				return this;
 | 
| 
 | 
   442 			},
 | 
| 
 | 
   443 
 | 
| 
 | 
   444 			// Navigates to the previous image in the gallery.
 | 
| 
 | 
   445 			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
 | 
| 
 | 
   446 			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
 | 
| 
 | 
   447 			previous: function(dontPause, bypassHistory) {
 | 
| 
 | 
   448 				this.gotoIndex(this.getPrevIndex(this.currentImage.index), dontPause, bypassHistory);
 | 
| 
 | 
   449 				return this;
 | 
| 
 | 
   450 			},
 | 
| 
 | 
   451 
 | 
| 
 | 
   452 			// Navigates to the next page in the gallery.
 | 
| 
 | 
   453 			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
 | 
| 
 | 
   454 			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
 | 
| 
 | 
   455 			nextPage: function(dontPause, bypassHistory) {
 | 
| 
 | 
   456 				var page = this.getCurrentPage();
 | 
| 
 | 
   457 				var lastPage = this.getNumPages() - 1;
 | 
| 
 | 
   458 				if (page < lastPage) {
 | 
| 
 | 
   459 					var startIndex = page * this.numThumbs;
 | 
| 
 | 
   460 					var nextPage = startIndex + this.numThumbs;
 | 
| 
 | 
   461 					this.gotoIndex(nextPage, dontPause, bypassHistory);
 | 
| 
 | 
   462 				}
 | 
| 
 | 
   463 
 | 
| 
 | 
   464 				return this;
 | 
| 
 | 
   465 			},
 | 
| 
 | 
   466 
 | 
| 
 | 
   467 			// Navigates to the previous page in the gallery.
 | 
| 
 | 
   468 			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
 | 
| 
 | 
   469 			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
 | 
| 
 | 
   470 			previousPage: function(dontPause, bypassHistory) {
 | 
| 
 | 
   471 				var page = this.getCurrentPage();
 | 
| 
 | 
   472 				if (page > 0) {
 | 
| 
 | 
   473 					var startIndex = page * this.numThumbs;
 | 
| 
 | 
   474 					var prevPage = startIndex - this.numThumbs;				
 | 
| 
 | 
   475 					this.gotoIndex(prevPage, dontPause, bypassHistory);
 | 
| 
 | 
   476 				}
 | 
| 
 | 
   477 				
 | 
| 
 | 
   478 				return this;
 | 
| 
 | 
   479 			},
 | 
| 
 | 
   480 
 | 
| 
 | 
   481 			// Navigates to the image at the specified index in the gallery
 | 
| 
 | 
   482 			// @param {Integer} index The index of the image in the gallery to display.
 | 
| 
 | 
   483 			// @param {Boolean} dontPause Specifies whether to pause the slideshow.
 | 
| 
 | 
   484 			// @param {Boolean} bypassHistory Specifies whether to delegate navigation to the history plugin when history is enabled.
 | 
| 
 | 
   485 			gotoIndex: function(index, dontPause, bypassHistory) {
 | 
| 
 | 
   486 				if (!dontPause)
 | 
| 
 | 
   487 					this.pause();
 | 
| 
 | 
   488 				
 | 
| 
 | 
   489 				if (index < 0) index = 0;
 | 
| 
 | 
   490 				else if (index >= this.data.length) index = this.data.length-1;
 | 
| 
 | 
   491 				
 | 
| 
 | 
   492 				var imageData = this.data[index];
 | 
| 
 | 
   493 				
 | 
| 
 | 
   494 				if (!bypassHistory && this.enableHistory)
 | 
| 
 | 
   495 					$.historyLoad(String(imageData.hash));  // At the moment, historyLoad only accepts string arguments
 | 
| 
 | 
   496 				else
 | 
| 
 | 
   497 					this.gotoImage(imageData);
 | 
| 
 | 
   498 
 | 
| 
 | 
   499 				return this;
 | 
| 
 | 
   500 			},
 | 
| 
 | 
   501 
 | 
| 
 | 
   502 			// This function is garaunteed to be called anytime a gallery slide changes.
 | 
| 
 | 
   503 			// @param {Object} imageData An object holding the image metadata of the image to navigate to.
 | 
| 
 | 
   504 			gotoImage: function(imageData) {
 | 
| 
 | 
   505 				var index = imageData.index;
 | 
| 
 | 
   506 
 | 
| 
 | 
   507 				if (this.onSlideChange)
 | 
| 
 | 
   508 					this.onSlideChange(this.currentImage.index, index);
 | 
| 
 | 
   509 				
 | 
| 
 | 
   510 				this.currentImage = imageData;
 | 
| 
 | 
   511 				this.preloadRelocate(index);
 | 
| 
 | 
   512 				
 | 
| 
 | 
   513 				this.refresh();
 | 
| 
 | 
   514 				
 | 
| 
 | 
   515 				return this;
 | 
| 
 | 
   516 			},
 | 
| 
 | 
   517 
 | 
| 
 | 
   518 			// Returns the default transition duration value.  The value is halved when not
 | 
| 
 | 
   519 			// performing a synchronized transition.
 | 
| 
 | 
   520 			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
 | 
| 
 | 
   521 			getDefaultTransitionDuration: function(isSync) {
 | 
| 
 | 
   522 				if (isSync)
 | 
| 
 | 
   523 					return this.defaultTransitionDuration;
 | 
| 
 | 
   524 				return this.defaultTransitionDuration / 2;
 | 
| 
 | 
   525 			},
 | 
| 
 | 
   526 
 | 
| 
 | 
   527 			// Rebuilds the slideshow image and controls and performs transitions
 | 
| 
 | 
   528 			refresh: function() {
 | 
| 
 | 
   529 				var imageData = this.currentImage;
 | 
| 
 | 
   530 				if (!imageData)
 | 
| 
 | 
   531 					return this;
 | 
| 
 | 
   532 
 | 
| 
 | 
   533 				var index = imageData.index;
 | 
| 
 | 
   534 
 | 
| 
 | 
   535 				// Update Controls
 | 
| 
 | 
   536 				if (this.$controlsContainer) {
 | 
| 
 | 
   537 					this.$controlsContainer
 | 
| 
 | 
   538 						.find('div.nav-controls a.prev').attr('href', '#'+this.data[this.getPrevIndex(index)].hash).end()
 | 
| 
 | 
   539 						.find('div.nav-controls a.next').attr('href', '#'+this.data[this.getNextIndex(index)].hash);
 | 
| 
 | 
   540 				}
 | 
| 
 | 
   541 
 | 
| 
 | 
   542 				var previousSlide = this.$imageContainer.find('span.current').addClass('previous').removeClass('current');
 | 
| 
 | 
   543 				var previousCaption = 0;
 | 
| 
 | 
   544 
 | 
| 
 | 
   545 				if (this.$captionContainer) {
 | 
| 
 | 
   546 					previousCaption = this.$captionContainer.find('span.current').addClass('previous').removeClass('current');
 | 
| 
 | 
   547 				}
 | 
| 
 | 
   548 
 | 
| 
 | 
   549 				// Perform transitions simultaneously if syncTransitions is true and the next image is already preloaded
 | 
| 
 | 
   550 				var isSync = this.syncTransitions && imageData.image;
 | 
| 
 | 
   551 
 | 
| 
 | 
   552 				// Flag we are transitioning
 | 
| 
 | 
   553 				var isTransitioning = true;
 | 
| 
 | 
   554 				var gallery = this;
 | 
| 
 | 
   555 
 | 
| 
 | 
   556 				var transitionOutCallback = function() {
 | 
| 
 | 
   557 					// Flag that the transition has completed
 | 
| 
 | 
   558 					isTransitioning = false;
 | 
| 
 | 
   559 
 | 
| 
 | 
   560 					// Remove the old slide
 | 
| 
 | 
   561 					previousSlide.remove();
 | 
| 
 | 
   562 
 | 
| 
 | 
   563 					// Remove old caption
 | 
| 
 | 
   564 					if (previousCaption)
 | 
| 
 | 
   565 						previousCaption.remove();
 | 
| 
 | 
   566 
 | 
| 
 | 
   567 					if (!isSync) {
 | 
| 
 | 
   568 						if (imageData.image && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
 | 
| 
 | 
   569 							gallery.buildImage(imageData, isSync);
 | 
| 
 | 
   570 						} else {
 | 
| 
 | 
   571 							// Show loading container
 | 
| 
 | 
   572 							if (gallery.$loadingContainer) {
 | 
| 
 | 
   573 								gallery.$loadingContainer.show();
 | 
| 
 | 
   574 							}
 | 
| 
 | 
   575 						}
 | 
| 
 | 
   576 					}
 | 
| 
 | 
   577 				};
 | 
| 
 | 
   578 
 | 
| 
 | 
   579 				if (previousSlide.length == 0) {
 | 
| 
 | 
   580 					// For the first slide, the previous slide will be empty, so we will call the callback immediately
 | 
| 
 | 
   581 					transitionOutCallback();
 | 
| 
 | 
   582 				} else {
 | 
| 
 | 
   583 					if (this.onTransitionOut) {
 | 
| 
 | 
   584 						this.onTransitionOut(previousSlide, previousCaption, isSync, transitionOutCallback);
 | 
| 
 | 
   585 					} else {
 | 
| 
 | 
   586 						previousSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0, transitionOutCallback);
 | 
| 
 | 
   587 						if (previousCaption)
 | 
| 
 | 
   588 							previousCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0);
 | 
| 
 | 
   589 					}
 | 
| 
 | 
   590 				}
 | 
| 
 | 
   591 
 | 
| 
 | 
   592 				// Go ahead and begin transitioning in of next image
 | 
| 
 | 
   593 				if (isSync)
 | 
| 
 | 
   594 					this.buildImage(imageData, isSync);
 | 
| 
 | 
   595 
 | 
| 
 | 
   596 				if (!imageData.image) {
 | 
| 
 | 
   597 					var image = new Image();
 | 
| 
 | 
   598 					
 | 
| 
 | 
   599 					// Wire up mainImage onload event
 | 
| 
 | 
   600 					image.onload = function() {
 | 
| 
 | 
   601 						imageData.image = this;
 | 
| 
 | 
   602 
 | 
| 
 | 
   603 						// Only build image if the out transition has completed and we are still on the same image hash
 | 
| 
 | 
   604 						if (!isTransitioning && imageData.hash == gallery.data[gallery.currentImage.index].hash) {
 | 
| 
 | 
   605 							gallery.buildImage(imageData, isSync);
 | 
| 
 | 
   606 						}
 | 
| 
 | 
   607 					};
 | 
| 
 | 
   608 
 | 
| 
 | 
   609 					// set alt and src
 | 
| 
 | 
   610 					image.alt = imageData.title;
 | 
| 
 | 
   611 					image.src = imageData.slideUrl;
 | 
| 
 | 
   612 				}
 | 
| 
 | 
   613 
 | 
| 
 | 
   614 				// This causes the preloader (if still running) to relocate out from the currentIndex
 | 
| 
 | 
   615 				this.relocatePreload = true;
 | 
| 
 | 
   616 
 | 
| 
 | 
   617 				return this.syncThumbs();
 | 
| 
 | 
   618 			},
 | 
| 
 | 
   619 
 | 
| 
 | 
   620 			// Called by the refresh method after the previous image has been transitioned out or at the same time
 | 
| 
 | 
   621 			// as the out transition when performing a synchronous transition.
 | 
| 
 | 
   622 			// @param {Object} imageData An object holding the image metadata of the image to build.
 | 
| 
 | 
   623 			// @param {Boolean} isSync Specifies whether the transitions are synchronized.
 | 
| 
 | 
   624 			buildImage: function(imageData, isSync) {
 | 
| 
 | 
   625 				var gallery = this;
 | 
| 
 | 
   626 				var nextIndex = this.getNextIndex(imageData.index);
 | 
| 
 | 
   627 
 | 
| 
 | 
   628 				// Construct new hidden span for the image
 | 
| 
 | 
   629 				var newSlide = this.$imageContainer
 | 
| 
 | 
   630 					.append('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+imageData.title+'"> </a></span>')
 | 
| 
 | 
   631 					.find('span.current').css('opacity', '0');
 | 
| 
 | 
   632 				
 | 
| 
 | 
   633 				newSlide.find('a')
 | 
| 
 | 
   634 					.append(imageData.image)
 | 
| 
 | 
   635 					.click(function(e) {
 | 
| 
 | 
   636 						gallery.clickHandler(e, this);
 | 
| 
 | 
   637 					});
 | 
| 
 | 
   638 				
 | 
| 
 | 
   639 				var newCaption = 0;
 | 
| 
 | 
   640 				if (this.$captionContainer) {
 | 
| 
 | 
   641 					// Construct new hidden caption for the image
 | 
| 
 | 
   642 					newCaption = this.$captionContainer
 | 
| 
 | 
   643 						.append('<span class="image-caption current"></span>')
 | 
| 
 | 
   644 						.find('span.current').css('opacity', '0')
 | 
| 
 | 
   645 						.append(imageData.caption);
 | 
| 
 | 
   646 				}
 | 
| 
 | 
   647 
 | 
| 
 | 
   648 				// Hide the loading conatiner
 | 
| 
 | 
   649 				if (this.$loadingContainer) {
 | 
| 
 | 
   650 					this.$loadingContainer.hide();
 | 
| 
 | 
   651 				}
 | 
| 
 | 
   652 
 | 
| 
 | 
   653 				// Transition in the new image
 | 
| 
 | 
   654 				if (this.onTransitionIn) {
 | 
| 
 | 
   655 					this.onTransitionIn(newSlide, newCaption, isSync);
 | 
| 
 | 
   656 				} else {
 | 
| 
 | 
   657 					newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
 | 
| 
 | 
   658 					if (newCaption)
 | 
| 
 | 
   659 						newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
 | 
| 
 | 
   660 				}
 | 
| 
 | 
   661 				
 | 
| 
 | 
   662 				if (this.isSlideshowRunning) {
 | 
| 
 | 
   663 					if (this.slideshowTimeout)
 | 
| 
 | 
   664 						clearTimeout(this.slideshowTimeout);
 | 
| 
 | 
   665 
 | 
| 
 | 
   666 					this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
 | 
| 
 | 
   667 				}
 | 
| 
 | 
   668 
 | 
| 
 | 
   669 				return this;
 | 
| 
 | 
   670 			},
 | 
| 
 | 
   671 
 | 
| 
 | 
   672 			// Returns the current page index that should be shown for the currentImage
 | 
| 
 | 
   673 			getCurrentPage: function() {
 | 
| 
 | 
   674 				return Math.floor(this.currentImage.index / this.numThumbs);
 | 
| 
 | 
   675 			},
 | 
| 
 | 
   676 
 | 
| 
 | 
   677 			// Applies the selected class to the current image's corresponding thumbnail.
 | 
| 
 | 
   678 			// Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
 | 
| 
 | 
   679 			syncThumbs: function() {
 | 
| 
 | 
   680 				var page = this.getCurrentPage();
 | 
| 
 | 
   681 				if (page != this.displayedPage)
 | 
| 
 | 
   682 					this.updateThumbs();
 | 
| 
 | 
   683 
 | 
| 
 | 
   684 				// Remove existing selected class and add selected class to new thumb
 | 
| 
 | 
   685 				var $thumbs = this.find('ul.thumbs').children();
 | 
| 
 | 
   686 				$thumbs.filter('.selected').removeClass('selected');
 | 
| 
 | 
   687 				$thumbs.eq(this.currentImage.index).addClass('selected');
 | 
| 
 | 
   688 
 | 
| 
 | 
   689 				return this;
 | 
| 
 | 
   690 			},
 | 
| 
 | 
   691 
 | 
| 
 | 
   692 			// Performs transitions on the thumbnails container and updates the set of
 | 
| 
 | 
   693 			// thumbnails that are to be displayed and the navigation controls.
 | 
| 
 | 
   694 			// @param {Delegate} postTransitionOutHandler An optional delegate that is called after
 | 
| 
 | 
   695 			// the thumbnails container has transitioned out and before the thumbnails are rebuilt.
 | 
| 
 | 
   696 			updateThumbs: function(postTransitionOutHandler) {
 | 
| 
 | 
   697 				var gallery = this;
 | 
| 
 | 
   698 				var transitionOutCallback = function() {
 | 
| 
 | 
   699 					// Call the Post-transition Out Handler
 | 
| 
 | 
   700 					if (postTransitionOutHandler)
 | 
| 
 | 
   701 						postTransitionOutHandler();
 | 
| 
 | 
   702 					
 | 
| 
 | 
   703 					gallery.rebuildThumbs();
 | 
| 
 | 
   704 
 | 
| 
 | 
   705 					// Transition In the thumbsContainer
 | 
| 
 | 
   706 					if (gallery.onPageTransitionIn)
 | 
| 
 | 
   707 						gallery.onPageTransitionIn();
 | 
| 
 | 
   708 					else
 | 
| 
 | 
   709 						gallery.show();
 | 
| 
 | 
   710 				};
 | 
| 
 | 
   711 
 | 
| 
 | 
   712 				// Transition Out the thumbsContainer
 | 
| 
 | 
   713 				if (this.onPageTransitionOut) {
 | 
| 
 | 
   714 					this.onPageTransitionOut(transitionOutCallback);
 | 
| 
 | 
   715 				} else {
 | 
| 
 | 
   716 					this.hide();
 | 
| 
 | 
   717 					transitionOutCallback();
 | 
| 
 | 
   718 				}
 | 
| 
 | 
   719 
 | 
| 
 | 
   720 				return this;
 | 
| 
 | 
   721 			},
 | 
| 
 | 
   722 
 | 
| 
 | 
   723 			// Updates the set of thumbnails that are to be displayed and the navigation controls.
 | 
| 
 | 
   724 			rebuildThumbs: function() {
 | 
| 
 | 
   725 				var needsPagination = this.data.length > this.numThumbs;
 | 
| 
 | 
   726 
 | 
| 
 | 
   727 				// Rebuild top pager
 | 
| 
 | 
   728 				if (this.enableTopPager) {
 | 
| 
 | 
   729 					var $topPager = this.find('div.top');
 | 
| 
 | 
   730 					if ($topPager.length == 0)
 | 
| 
 | 
   731 						$topPager = this.prepend('<div class="top pagination"></div>').find('div.top');
 | 
| 
 | 
   732 					else
 | 
| 
 | 
   733 						$topPager.empty();
 | 
| 
 | 
   734 
 | 
| 
 | 
   735 					if (needsPagination)
 | 
| 
 | 
   736 						this.buildPager($topPager);
 | 
| 
 | 
   737 				}
 | 
| 
 | 
   738 
 | 
| 
 | 
   739 				// Rebuild bottom pager
 | 
| 
 | 
   740 				if (this.enableBottomPager) {
 | 
| 
 | 
   741 					var $bottomPager = this.find('div.bottom');
 | 
| 
 | 
   742 					if ($bottomPager.length == 0)
 | 
| 
 | 
   743 						$bottomPager = this.append('<div class="bottom pagination"></div>').find('div.bottom');
 | 
| 
 | 
   744 					else
 | 
| 
 | 
   745 						$bottomPager.empty();
 | 
| 
 | 
   746 
 | 
| 
 | 
   747 					if (needsPagination)
 | 
| 
 | 
   748 						this.buildPager($bottomPager);
 | 
| 
 | 
   749 				}
 | 
| 
 | 
   750 
 | 
| 
 | 
   751 				var page = this.getCurrentPage();
 | 
| 
 | 
   752 				var startIndex = page*this.numThumbs;
 | 
| 
 | 
   753 				var stopIndex = startIndex+this.numThumbs-1;
 | 
| 
 | 
   754 				if (stopIndex >= this.data.length)
 | 
| 
 | 
   755 					stopIndex = this.data.length-1;
 | 
| 
 | 
   756 
 | 
| 
 | 
   757 				// Show/Hide thumbs
 | 
| 
 | 
   758 				var $thumbsUl = this.find('ul.thumbs');
 | 
| 
 | 
   759 				$thumbsUl.find('li').each(function(i) {
 | 
| 
 | 
   760 					var $li = $(this);
 | 
| 
 | 
   761 					if (i >= startIndex && i <= stopIndex) {
 | 
| 
 | 
   762 						$li.show();
 | 
| 
 | 
   763 					} else {
 | 
| 
 | 
   764 						$li.hide();
 | 
| 
 | 
   765 					}
 | 
| 
 | 
   766 				});
 | 
| 
 | 
   767 
 | 
| 
 | 
   768 				this.displayedPage = page;
 | 
| 
 | 
   769 
 | 
| 
 | 
   770 				// Remove the noscript class from the thumbs container ul
 | 
| 
 | 
   771 				$thumbsUl.removeClass('noscript');
 | 
| 
 | 
   772 				
 | 
| 
 | 
   773 				return this;
 | 
| 
 | 
   774 			},
 | 
| 
 | 
   775 
 | 
| 
 | 
   776 			// Returns the total number of pages required to display all the thumbnails.
 | 
| 
 | 
   777 			getNumPages: function() {
 | 
| 
 | 
   778 				return Math.ceil(this.data.length/this.numThumbs);
 | 
| 
 | 
   779 			},
 | 
| 
 | 
   780 
 | 
| 
 | 
   781 			// Rebuilds the pager control in the specified matched element.
 | 
| 
 | 
   782 			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
 | 
| 
 | 
   783 			buildPager: function(pager) {
 | 
| 
 | 
   784 				var gallery = this;
 | 
| 
 | 
   785 				var numPages = this.getNumPages();
 | 
| 
 | 
   786 				var page = this.getCurrentPage();
 | 
| 
 | 
   787 				var startIndex = page * this.numThumbs;
 | 
| 
 | 
   788 				var pagesRemaining = this.maxPagesToShow - 1;
 | 
| 
 | 
   789 				
 | 
| 
 | 
   790 				var pageNum = page - Math.floor((this.maxPagesToShow - 1) / 2) + 1;
 | 
| 
 | 
   791 				if (pageNum > 0) {
 | 
| 
 | 
   792 					var remainingPageCount = numPages - pageNum;
 | 
| 
 | 
   793 					if (remainingPageCount < pagesRemaining) {
 | 
| 
 | 
   794 						pageNum = pageNum - (pagesRemaining - remainingPageCount);
 | 
| 
 | 
   795 					}
 | 
| 
 | 
   796 				}
 | 
| 
 | 
   797 
 | 
| 
 | 
   798 				if (pageNum < 0) {
 | 
| 
 | 
   799 					pageNum = 0;
 | 
| 
 | 
   800 				}
 | 
| 
 | 
   801 
 | 
| 
 | 
   802 				// Prev Page Link
 | 
| 
 | 
   803 				if (page > 0) {
 | 
| 
 | 
   804 					var prevPage = startIndex - this.numThumbs;
 | 
| 
 | 
   805 					pager.append('<a rel="history" href="#'+this.data[prevPage].hash+'" title="'+this.prevPageLinkText+'">'+this.prevPageLinkText+'</a>');
 | 
| 
 | 
   806 				}
 | 
| 
 | 
   807 
 | 
| 
 | 
   808 				// Create First Page link if needed
 | 
| 
 | 
   809 				if (pageNum > 0) {
 | 
| 
 | 
   810 					this.buildPageLink(pager, 0, numPages);
 | 
| 
 | 
   811 					if (pageNum > 1)
 | 
| 
 | 
   812 						pager.append('<span class="ellipsis">…</span>');
 | 
| 
 | 
   813 					
 | 
| 
 | 
   814 					pagesRemaining--;
 | 
| 
 | 
   815 				}
 | 
| 
 | 
   816 
 | 
| 
 | 
   817 				// Page Index Links
 | 
| 
 | 
   818 				while (pagesRemaining > 0) {
 | 
| 
 | 
   819 					this.buildPageLink(pager, pageNum, numPages);
 | 
| 
 | 
   820 					pagesRemaining--;
 | 
| 
 | 
   821 					pageNum++;
 | 
| 
 | 
   822 				}
 | 
| 
 | 
   823 
 | 
| 
 | 
   824 				// Create Last Page link if needed
 | 
| 
 | 
   825 				if (pageNum < numPages) {
 | 
| 
 | 
   826 					var lastPageNum = numPages - 1;
 | 
| 
 | 
   827 					if (pageNum < lastPageNum)
 | 
| 
 | 
   828 						pager.append('<span class="ellipsis">…</span>');
 | 
| 
 | 
   829 
 | 
| 
 | 
   830 					this.buildPageLink(pager, lastPageNum, numPages);
 | 
| 
 | 
   831 				}
 | 
| 
 | 
   832 
 | 
| 
 | 
   833 				// Next Page Link
 | 
| 
 | 
   834 				var nextPage = startIndex + this.numThumbs;
 | 
| 
 | 
   835 				if (nextPage < this.data.length) {
 | 
| 
 | 
   836 					pager.append('<a rel="history" href="#'+this.data[nextPage].hash+'" title="'+this.nextPageLinkText+'">'+this.nextPageLinkText+'</a>');
 | 
| 
 | 
   837 				}
 | 
| 
 | 
   838 
 | 
| 
 | 
   839 				pager.find('a').click(function(e) {
 | 
| 
 | 
   840 					gallery.clickHandler(e, this);
 | 
| 
 | 
   841 				});
 | 
| 
 | 
   842 
 | 
| 
 | 
   843 				return this;
 | 
| 
 | 
   844 			},
 | 
| 
 | 
   845 
 | 
| 
 | 
   846 			// Builds a single page link within a pager.  This function is called by buildPager
 | 
| 
 | 
   847 			// @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
 | 
| 
 | 
   848 			// @param {Integer} pageNum The page number of the page link to build.
 | 
| 
 | 
   849 			// @param {Integer} numPages The total number of pages required to display all thumbnails.
 | 
| 
 | 
   850 			buildPageLink: function(pager, pageNum, numPages) {
 | 
| 
 | 
   851 				var pageLabel = pageNum + 1;
 | 
| 
 | 
   852 				var currentPage = this.getCurrentPage();
 | 
| 
 | 
   853 				if (pageNum == currentPage)
 | 
| 
 | 
   854 					pager.append('<span class="current">'+pageLabel+'</span>');
 | 
| 
 | 
   855 				else if (pageNum < numPages) {
 | 
| 
 | 
   856 					var imageIndex = pageNum*this.numThumbs;
 | 
| 
 | 
   857 					pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageLabel+'">'+pageLabel+'</a>');
 | 
| 
 | 
   858 				}
 | 
| 
 | 
   859 				
 | 
| 
 | 
   860 				return this;
 | 
| 
 | 
   861 			}
 | 
| 
 | 
   862 		});
 | 
| 
 | 
   863 
 | 
| 
 | 
   864 		// Now initialize the gallery
 | 
| 
 | 
   865 		$.extend(this, defaults, settings);
 | 
| 
 | 
   866 		
 | 
| 
 | 
   867 		// Verify the history plugin is available
 | 
| 
 | 
   868 		if (this.enableHistory && !$.historyInit)
 | 
| 
 | 
   869 			this.enableHistory = false;
 | 
| 
 | 
   870 		
 | 
| 
 | 
   871 		// Select containers
 | 
| 
 | 
   872 		if (this.imageContainerSel) this.$imageContainer = $(this.imageContainerSel);
 | 
| 
 | 
   873 		if (this.captionContainerSel) this.$captionContainer = $(this.captionContainerSel);
 | 
| 
 | 
   874 		if (this.loadingContainerSel) this.$loadingContainer = $(this.loadingContainerSel);
 | 
| 
 | 
   875 
 | 
| 
 | 
   876 		// Initialize the thumbails
 | 
| 
 | 
   877 		this.initializeThumbs();
 | 
| 
 | 
   878 		
 | 
| 
 | 
   879 		if (this.maxPagesToShow < 3)
 | 
| 
 | 
   880 			this.maxPagesToShow = 3;
 | 
| 
 | 
   881 
 | 
| 
 | 
   882 		this.displayedPage = -1;
 | 
| 
 | 
   883 		this.currentImage = this.data[0];
 | 
| 
 | 
   884 		var gallery = this;
 | 
| 
 | 
   885 
 | 
| 
 | 
   886 		// Hide the loadingContainer
 | 
| 
 | 
   887 		if (this.$loadingContainer)
 | 
| 
 | 
   888 			this.$loadingContainer.hide();
 | 
| 
 | 
   889 
 | 
| 
 | 
   890 		// Setup controls
 | 
| 
 | 
   891 		if (this.controlsContainerSel) {
 | 
| 
 | 
   892 			this.$controlsContainer = $(this.controlsContainerSel).empty();
 | 
| 
 | 
   893 			
 | 
| 
 | 
   894 			if (this.renderSSControls) {
 | 
| 
 | 
   895 				if (this.autoStart) {
 | 
| 
 | 
   896 					this.$controlsContainer
 | 
| 
 | 
   897 						.append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.pauseLinkText+'">'+this.pauseLinkText+'</a></div>');
 | 
| 
 | 
   898 				} else {
 | 
| 
 | 
   899 					this.$controlsContainer
 | 
| 
 | 
   900 						.append('<div class="ss-controls"><a href="#play" class="play" title="'+this.playLinkText+'">'+this.playLinkText+'</a></div>');
 | 
| 
 | 
   901 				}
 | 
| 
 | 
   902 
 | 
| 
 | 
   903 				this.$controlsContainer.find('div.ss-controls a')
 | 
| 
 | 
   904 					.click(function(e) {
 | 
| 
 | 
   905 						gallery.toggleSlideshow();
 | 
| 
 | 
   906 						e.preventDefault();
 | 
| 
 | 
   907 						return false;
 | 
| 
 | 
   908 					});
 | 
| 
 | 
   909 			}
 | 
| 
 | 
   910 		
 | 
| 
 | 
   911 			if (this.renderNavControls) {
 | 
| 
 | 
   912 				this.$controlsContainer
 | 
| 
 | 
   913 					.append('<div class="nav-controls"><a class="prev" rel="history" title="'+this.prevLinkText+'">'+this.prevLinkText+'</a><a class="next" rel="history" title="'+this.nextLinkText+'">'+this.nextLinkText+'</a></div>')
 | 
| 
 | 
   914 					.find('div.nav-controls a')
 | 
| 
 | 
   915 					.click(function(e) {
 | 
| 
 | 
   916 						gallery.clickHandler(e, this);
 | 
| 
 | 
   917 					});
 | 
| 
 | 
   918 			}
 | 
| 
 | 
   919 		}
 | 
| 
 | 
   920 
 | 
| 
 | 
   921 		var initFirstImage = !this.enableHistory || !location.hash;
 | 
| 
 | 
   922 		if (this.enableHistory && location.hash) {
 | 
| 
 | 
   923 			var hash = $.galleriffic.normalizeHash(location.hash);
 | 
| 
 | 
   924 			var imageData = allImages[hash];
 | 
| 
 | 
   925 			if (!imageData)
 | 
| 
 | 
   926 				initFirstImage = true;
 | 
| 
 | 
   927 		}
 | 
| 
 | 
   928 
 | 
| 
 | 
   929 		// Setup gallery to show the first image
 | 
| 
 | 
   930 		if (initFirstImage)
 | 
| 
 | 
   931 			this.gotoIndex(0, false, true);
 | 
| 
 | 
   932 
 | 
| 
 | 
   933 		// Setup Keyboard Navigation
 | 
| 
 | 
   934 		if (this.enableKeyboardNavigation) {
 | 
| 
 | 
   935 			$(document).keydown(function(e) {
 | 
| 
 | 
   936 				var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
 | 
| 
 | 
   937 				switch(key) {
 | 
| 
 | 
   938 					case 32: // space
 | 
| 
 | 
   939 						gallery.next();
 | 
| 
 | 
   940 						e.preventDefault();
 | 
| 
 | 
   941 						break;
 | 
| 
 | 
   942 					case 33: // Page Up
 | 
| 
 | 
   943 						gallery.previousPage();
 | 
| 
 | 
   944 						e.preventDefault();
 | 
| 
 | 
   945 						break;
 | 
| 
 | 
   946 					case 34: // Page Down
 | 
| 
 | 
   947 						gallery.nextPage();
 | 
| 
 | 
   948 						e.preventDefault();
 | 
| 
 | 
   949 						break;
 | 
| 
 | 
   950 					case 35: // End
 | 
| 
 | 
   951 						gallery.gotoIndex(gallery.data.length-1);
 | 
| 
 | 
   952 						e.preventDefault();
 | 
| 
 | 
   953 						break;
 | 
| 
 | 
   954 					case 36: // Home
 | 
| 
 | 
   955 						gallery.gotoIndex(0);
 | 
| 
 | 
   956 						e.preventDefault();
 | 
| 
 | 
   957 						break;
 | 
| 
 | 
   958 					case 37: // left arrow
 | 
| 
 | 
   959 						gallery.previous();
 | 
| 
 | 
   960 						e.preventDefault();
 | 
| 
 | 
   961 						break;
 | 
| 
 | 
   962 					case 39: // right arrow
 | 
| 
 | 
   963 						gallery.next();
 | 
| 
 | 
   964 						e.preventDefault();
 | 
| 
 | 
   965 						break;
 | 
| 
 | 
   966 				}
 | 
| 
 | 
   967 			});
 | 
| 
 | 
   968 		}
 | 
| 
 | 
   969 
 | 
| 
 | 
   970 		// Auto start the slideshow
 | 
| 
 | 
   971 		if (this.autoStart)
 | 
| 
 | 
   972 			this.play();
 | 
| 
 | 
   973 
 | 
| 
 | 
   974 		// Kickoff Image Preloader after 1 second
 | 
| 
 | 
   975 		setTimeout(function() { gallery.preloadInit(); }, 1000);
 | 
| 
 | 
   976 
 | 
| 
 | 
   977 		return this;
 | 
| 
 | 
   978 	};
 | 
| 
 | 
   979 })(jQuery);
 |