Advertisement
Guest User

jquery galleriffic.js

a guest
May 28th, 2012
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.                 if(isSync){
  629.                
  630.                     // Construct new hidden span for the image
  631.                     var newSlide = this.$imageContainer
  632.                         .append('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+imageData.title+'">&nbsp;</a></span>')
  633.                         .find('span.current').css('opacity', '0');
  634.                    
  635.                 }else{
  636.                
  637.                     //  *** photospace update - replace append with html to stop multiple images in fast clicks ***
  638.                     var newSlide = this.$imageContainer
  639.                         .html('<span class="image-wrapper current"><a class="advance-link" rel="history" href="#'+this.data[nextIndex].hash+'" title="'+imageData.title+'">&nbsp;</a></span>')
  640.                         .find('span.current').css('opacity', '0');
  641.  
  642.                 }
  643.                    
  644.                
  645.                 newSlide.find('a')
  646.                     .append(imageData.image)
  647.                     .click(function(e) {
  648.                         gallery.clickHandler(e, this);
  649.                     });
  650.                
  651.                 var newCaption = 0;
  652.                 if (this.$captionContainer) {
  653.                     // Construct new hidden caption for the image
  654.                     newCaption = this.$captionContainer
  655.                         .append('<span class="image-caption current"></span>')
  656.                         .find('span.current').css('opacity', '0')
  657.                         .append(imageData.caption);
  658.                 }
  659.  
  660.                 // Hide the loading conatiner
  661.                 if (this.$loadingContainer) {
  662.                     this.$loadingContainer.hide();
  663.                 }
  664.  
  665.                 // Transition in the new image
  666.                 if (this.onTransitionIn) {
  667.                     this.onTransitionIn(newSlide, newCaption, isSync);
  668.                 } else {
  669.                     newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
  670.                     if (newCaption)
  671.                         newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
  672.                 }
  673.                
  674.                 if (this.isSlideshowRunning) {
  675.                     if (this.slideshowTimeout)
  676.                         clearTimeout(this.slideshowTimeout);
  677.  
  678.                     this.slideshowTimeout = setTimeout(function() { gallery.ssAdvance(); }, this.delay);
  679.                 }
  680.  
  681.                 return this;
  682.             },
  683.  
  684.             // Returns the current page index that should be shown for the currentImage
  685.             getCurrentPage: function() {
  686.                 return Math.floor(this.currentImage.index / this.numThumbs);
  687.             },
  688.  
  689.             // Applies the selected class to the current image's corresponding thumbnail.
  690.             // Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
  691.             syncThumbs: function() {
  692.                 var page = this.getCurrentPage();
  693.                 if (page != this.displayedPage)
  694.                     this.updateThumbs();
  695.  
  696.                 // Remove existing selected class and add selected class to new thumb
  697.                 var $thumbs = this.find('ul.thumbs').children();
  698.                 $thumbs.filter('.selected').removeClass('selected');
  699.                 $thumbs.eq(this.currentImage.index).addClass('selected');
  700.  
  701.                 return this;
  702.             },
  703.  
  704.             // Performs transitions on the thumbnails container and updates the set of
  705.             // thumbnails that are to be displayed and the navigation controls.
  706.             // @param {Delegate} postTransitionOutHandler An optional delegate that is called after
  707.             // the thumbnails container has transitioned out and before the thumbnails are rebuilt.
  708.             updateThumbs: function(postTransitionOutHandler) {
  709.                 var gallery = this;
  710.                 var transitionOutCallback = function() {
  711.                     // Call the Post-transition Out Handler
  712.                     if (postTransitionOutHandler)
  713.                         postTransitionOutHandler();
  714.                    
  715.                     gallery.rebuildThumbs();
  716.  
  717.                     // Transition In the thumbsContainer
  718.                     if (gallery.onPageTransitionIn)
  719.                         gallery.onPageTransitionIn();
  720.                     else
  721.                         gallery.show();
  722.                 };
  723.  
  724.                 // Transition Out the thumbsContainer
  725.                 if (this.onPageTransitionOut) {
  726.                     this.onPageTransitionOut(transitionOutCallback);
  727.                 } else {
  728.                     this.hide();
  729.                     transitionOutCallback();
  730.                 }
  731.  
  732.                 return this;
  733.             },
  734.  
  735.             // Updates the set of thumbnails that are to be displayed and the navigation controls.
  736.             rebuildThumbs: function() {
  737.                 var needsPagination = this.data.length > this.numThumbs;
  738.  
  739.                 // Rebuild top pager
  740.                 if (this.enableTopPager) {
  741.                     var $topPager = this.find('div.top');
  742.                     if ($topPager.length == 0)
  743.                         $topPager = this.prepend('<div class="top pagination"></div>').find('div.top');
  744.                     else
  745.                         $topPager.empty();
  746.  
  747.                     if (needsPagination)
  748.                         this.buildPager($topPager);
  749.                 }
  750.  
  751.                 // Rebuild bottom pager
  752.                 if (this.enableBottomPager) {
  753.                     var $bottomPager = this.find('div.bottom');
  754.                     if ($bottomPager.length == 0)
  755.                         $bottomPager = this.append('<div class="bottom pagination"></div>').find('div.bottom');
  756.                     else
  757.                         $bottomPager.empty();
  758.  
  759.                     if (needsPagination)
  760.                         this.buildPager($bottomPager);
  761.                 }
  762.  
  763.                 var page = this.getCurrentPage();
  764.                 var startIndex = page*this.numThumbs;
  765.                 var stopIndex = startIndex+this.numThumbs-1;
  766.                 if (stopIndex >= this.data.length)
  767.                     stopIndex = this.data.length-1;
  768.  
  769.                 // Show/Hide thumbs
  770.                 var $thumbsUl = this.find('ul.thumbs');
  771.                 $thumbsUl.find('li').each(function(i) {
  772.                     var $li = $(this);
  773.                     if (i >= startIndex && i <= stopIndex) {
  774.                         $li.show();
  775.                     } else {
  776.                         $li.hide();
  777.                     }
  778.                 });
  779.  
  780.                 this.displayedPage = page;
  781.  
  782.                 // Remove the noscript class from the thumbs container ul
  783.                 $thumbsUl.removeClass('noscript');
  784.                
  785.                 return this;
  786.             },
  787.  
  788.             // Returns the total number of pages required to display all the thumbnails.
  789.             getNumPages: function() {
  790.                 return Math.ceil(this.data.length/this.numThumbs);
  791.             },
  792.  
  793.             // Rebuilds the pager control in the specified matched element.
  794.             // @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
  795.             buildPager: function(pager) {
  796.                 var gallery = this;
  797.                 var numPages = this.getNumPages();
  798.                 var page = this.getCurrentPage();
  799.                 var startIndex = page * this.numThumbs;
  800.                 var pagesRemaining = this.maxPagesToShow - 1;
  801.                
  802.                 var pageNum = page - Math.floor((this.maxPagesToShow - 1) / 2) + 1;
  803.                 if (pageNum > 0) {
  804.                     var remainingPageCount = numPages - pageNum;
  805.                     if (remainingPageCount < pagesRemaining) {
  806.                         pageNum = pageNum - (pagesRemaining - remainingPageCount);
  807.                     }
  808.                 }
  809.  
  810.                 if (pageNum < 0) {
  811.                     pageNum = 0;
  812.                 }
  813.  
  814.                 // Prev Page Link
  815.                 if (page > 0) {
  816.                     var prevPage = startIndex - this.numThumbs;
  817.                     pager.append('<a rel="history" class="pprev" href="#'+this.data[prevPage].hash+'" title="'+this.prevPageLinkText+'">'+this.prevPageLinkText+'</a>');
  818.                 }
  819.  
  820.                 // Create First Page link if needed
  821.                 if (pageNum > 0) {
  822.                     this.buildPageLink(pager, 0, numPages);
  823.                     if (pageNum > 1)
  824.                         pager.append('<span class="ellipsis">&hellip;</span>');
  825.                    
  826.                     pagesRemaining--;
  827.                 }
  828.  
  829.                 // Page Index Links
  830.                 while (pagesRemaining > 0) {
  831.                     this.buildPageLink(pager, pageNum, numPages);
  832.                     pagesRemaining--;
  833.                     pageNum++;
  834.                 }
  835.  
  836.                 // Create Last Page link if needed
  837.                 if (pageNum < numPages) {
  838.                     var lastPageNum = numPages - 1;
  839.                     if (pageNum < lastPageNum)
  840.                         pager.append('<span class="ellipsis">&hellip;</span>');
  841.  
  842.                     this.buildPageLink(pager, lastPageNum, numPages);
  843.                 }
  844.  
  845.                 // Next Page Link
  846.                 var nextPage = startIndex + this.numThumbs;
  847.                 if (nextPage < this.data.length) {
  848.                     pager.append('<a rel="history" class="pnext" href="#'+this.data[nextPage].hash+'" title="'+this.nextPageLinkText+'">'+this.nextPageLinkText+'</a>');
  849.                 }
  850.  
  851.                 pager.find('a').click(function(e) {
  852.                     gallery.clickHandler(e, this);
  853.                 });
  854.  
  855.                 return this;
  856.             },
  857.  
  858.             // Builds a single page link within a pager.  This function is called by buildPager
  859.             // @param {jQuery} pager A jQuery element set matching the particular pager to be rebuilt.
  860.             // @param {Integer} pageNum The page number of the page link to build.
  861.             // @param {Integer} numPages The total number of pages required to display all thumbnails.
  862.             buildPageLink: function(pager, pageNum, numPages) {
  863.                 var pageLabel = pageNum + 1;
  864.                 var currentPage = this.getCurrentPage();
  865.                 if (pageNum == currentPage)
  866.                     pager.append('<span class="current">'+pageLabel+'</span>');
  867.                 else if (pageNum < numPages) {
  868.                     var imageIndex = pageNum*this.numThumbs;
  869.                     pager.append('<a rel="history" href="#'+this.data[imageIndex].hash+'" title="'+pageLabel+'">'+pageLabel+'</a>');
  870.                 }
  871.                
  872.                 return this;
  873.             }
  874.         });
  875.  
  876.         // Now initialize the gallery
  877.         $.extend(this, defaults, settings);
  878.        
  879.         // Verify the history plugin is available
  880.         if (this.enableHistory && !$.historyInit)
  881.             this.enableHistory = false;
  882.        
  883.         // Select containers
  884.         if (this.imageContainerSel) this.$imageContainer = $(this.imageContainerSel);
  885.         if (this.captionContainerSel) this.$captionContainer = $(this.captionContainerSel);
  886.         if (this.loadingContainerSel) this.$loadingContainer = $(this.loadingContainerSel);
  887.  
  888.         // Initialize the thumbails
  889.         this.initializeThumbs();
  890.        
  891.         if (this.maxPagesToShow < 3)
  892.             this.maxPagesToShow = 3;
  893.  
  894.         this.displayedPage = -1;
  895.         this.currentImage = this.data[0];
  896.         var gallery = this;
  897.  
  898.         // Hide the loadingContainer
  899.         if (this.$loadingContainer)
  900.             this.$loadingContainer.hide();
  901.  
  902.         // Setup controls
  903.         if (this.controlsContainerSel) {
  904.             this.$controlsContainer = $(this.controlsContainerSel).empty();
  905.            
  906.             if (this.renderSSControls) {
  907.                 if (this.autoStart) {
  908.                     this.$controlsContainer
  909.                         .append('<div class="ss-controls"><a href="#pause" class="pause" title="'+this.pauseLinkText+'"><span>'+this.pauseLinkText+'</span></a></div>');
  910.                 } else {
  911.                     this.$controlsContainer
  912.                         .append('<div class="ss-controls"><a href="#play" class="play" title="'+this.playLinkText+'"><span>'+this.playLinkText+'</span></a></div>');
  913.                 }
  914.  
  915.                 this.$controlsContainer.find('div.ss-controls a')
  916.                     .click(function(e) {
  917.                         gallery.toggleSlideshow();
  918.                         e.preventDefault();
  919.                         return false;
  920.                     });
  921.             }
  922.        
  923.             if (this.renderNavControls) {
  924.                 this.$controlsContainer
  925.                     .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>')
  926.                     .find('div.nav-controls a')
  927.                     .click(function(e) {
  928.                         gallery.clickHandler(e, this);
  929.                     });
  930.             }
  931.         }
  932.  
  933.         var initFirstImage = !this.enableHistory || !location.hash;
  934.         if (this.enableHistory && location.hash) {
  935.             var hash = $.galleriffic.normalizeHash(location.hash);
  936.             var imageData = allImages[hash];
  937.             if (!imageData)
  938.                 initFirstImage = true;
  939.         }
  940.  
  941.         // Setup gallery to show the first image
  942.         if (initFirstImage)
  943.             this.gotoIndex(0, false, true);
  944.  
  945.         // Setup Keyboard Navigation
  946.         if (this.enableKeyboardNavigation) {
  947.             $(document).keydown(function(e) {
  948.                 var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
  949.                 switch(key) {
  950.                     case 32: // space
  951.                         gallery.next();
  952.                         //e.preventDefault(); *** photospace - don't break forms ***
  953.                         break;
  954.                     case 33: // Page Up
  955.                         gallery.previousPage();
  956.                         e.preventDefault();
  957.                         break;
  958.                     case 34: // Page Down
  959.                         gallery.nextPage();
  960.                         e.preventDefault();
  961.                         break;
  962.                     case 35: // End
  963.                         gallery.gotoIndex(gallery.data.length-1);
  964.                         e.preventDefault();
  965.                         break;
  966.                     case 36: // Home
  967.                         gallery.gotoIndex(0);
  968.                         e.preventDefault();
  969.                         break;
  970.                     case 37: // left arrow
  971.                         gallery.previous();
  972.  
  973.                         //e.preventDefault(); *** photospace - don't break forms ***
  974.                         break;
  975.                     case 39: // right arrow
  976.                         gallery.next();
  977.                         //e.preventDefault(); *** photospace - don't break forms ***
  978.                         break;
  979.                 }
  980.             });
  981.         }
  982.  
  983.         // Auto start the slideshow
  984.         if (this.autoStart)
  985.             this.play();
  986.  
  987.         // Kickoff Image Preloader after 1 second
  988.         setTimeout(function() { gallery.preloadInit(); }, 1000);
  989.  
  990.         return this;
  991.     };
  992. })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement