Mercurial > repos > brasset_jensen > srnapipe
comparison lib/sRNAPipe/js/jquery.galleriffic.js @ 64:967512924317 draft
planemo upload for repository https://github.com/GReD-Clermont/sRNAPipe/ commit 410509088292be0687b8da3ea3bb75e72866a87d
| author | brasset_jensen |
|---|---|
| date | Mon, 28 Jan 2019 11:57:15 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 63:11708af40030 | 64:967512924317 |
|---|---|
| 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); |
