Guest User

Untitled

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