2012-02-14 120 views
2

我想开发一个jQuery插件来显示自适应图像画廊。我使用.data()来存储图库中每张幻灯片的信息。jQuery插件数据混合与多个实例

当显示单个图库时,一切似乎都可以正常工作,但在尝试在单个页面上显示多个图库实例时会出现混淆。 A rough demo can be viewed here

这里是正在运行的代码:

(function($) { 
    $.Gallery = function(element, options) { 
     this.$el = $(element); 
     this._init(options); 
    }; 

    $.Gallery.defaults = { 
     showCarousel : true, 
    }; 

    $.Gallery.prototype = { 
     _init : function(options) { 
      var $this = $(this); 
      var instance = this; 

      // Get settings from stored instance 
      var settings = $this.data('settings'); 
      var slides = $this.data('slides'); 

      // Create or update the settings of the current gallery instance 
      if (typeof(settings) == 'undefined') { 
       settings = $.extend(true, {}, $.Gallery.defaults, options); 
      } 
      else { 
       settings = $.extend(true, {}, settings, options); 
      } 
      $this.data('settings', settings); 

      if (typeof(slides) === 'undefined') { 
       slides = []; 
      } 
      $this.data('slides', slides); 

      instance.updateCarousel(); 
     }, 

     addItems : function(newItems) { 
      var $this = $(this), 
       slides = $this.data('slides'); 

      for (var i=0; i<newItems.length; i++) { 
       slides.push(newItems[i]); 
      }; 
     }, 

     updateCarousel : function() { 
      var instance = this, 
       $this = $(this); 
       slides = $(instance).data('slides'); 

      var gallery = instance.$el.attr('id'); 

      /* Create carousel if it doesn't exist */ 
      if (instance.$el.children('.carousel').length == 0) { 
       $('<div class="carousel"><ul></ul></div>').appendTo(instance.$el); 
       var image = instance.$el.find('img'); 
      }; 

      var carouselList = instance.$el.find('.carousel > ul'), 
       slideCount = slides.length, 
       displayCount = carouselList.find('li').length; 


      if (displayCount < slideCount) { 
       for (var i=displayCount; i<slides.length; i++) {      
        slides[i].id = gallery + '-slide-' + i; 
        slide = $('<img>').attr({src : slides[i].thumb}).appendTo(carouselList).wrap(function() { 
         return '<li id="' + slides[i].id + '" />' 
        }); 

        slide.on({ 
         click : function() { 
          instance.slideTo($(this).parent().attr('id')); 
         }, 
        }); 
       }; 
      }; 
     }, 

     slideTo : function(slideID) { 
      var $this = $(this); 
      var slides = $this.data('slides'); 
      var image; 
      var $instance = $(this.$el); 

      $(slides).each(function() { 
       if (this.id == slideID){ 
        image = this.img; 
       }; 
      }); 

      $('<img/>').load(function() { 
       $instance.find('div.image').empty().append('<img src="' + image + '"/>'); 
      }).attr('src', image); 
     }, 
    }; 

    $.fn.gallery = function(options) { 

     args = Array.prototype.slice.call(arguments, 1); 

     this.each(function() { 
      var instance = $(this).data('gallery'); 

      if (typeof(options) === 'string') { 
       if (!instance) { 
        console.error('Methods cannot be called until jquery.responsiveGallery has been initialized.'); 
       } 
       else if (!$.isFunction(instance[options])) { 
        console.error('The method "' + options + '" does not exist in jquery.responsiveGallery.'); 
       } 
       else { 
        instance[options].apply(instance, args); 
       } 
      } 
      else { 
       if (!instance) { 
        $(this).data('gallery', new $.Gallery(this, options)); 
       } 
      } 
     }); 
     return this; 
    }; 

})(jQuery); 

$(window).load(function() { 
    $('#gallery2').gallery(); 
    $('#gallery3').gallery(); 

    $('#gallery2').gallery('addItems', [ 
     { 
      img: 'images/image2.jpg', 
      thumb: 'images/image2_thumb.jpg', 
      desc: 'Image of number 2' 
     }, 
     { 
      img: 'images/image3.jpg', 
      thumb: 'images/image3_thumb.jpg', 
      desc: 'Image of number 3' 
     }, 
     { 
      img: 'images/image4.jpg', 
      thumb: 'images/image4_thumb.jpg', 
      desc: 'Image of number 4' 
     }, 
     { 
      img: 'images/image5.jpg', 
      thumb: 'images/image5_thumb.jpg', 
      desc: 'Image of number 5' 
     } 
    ]); 

    $('.pGallery').gallery('addItems', [ 
     { 
      img: 'images/2.jpg', 
      thumb: 'images/2_thumb.jpg', 
      desc: 'Image of number 0' 
     }, 
     { 
      img: 'images/image1.jpg', 
      thumb: 'images/image1_thumb.jpg', 
      desc: 'The second image' 
     } 
    ]); 
    $('.pGallery').gallery('updateCarousel'); 
}); 

在它似乎与的适当的滑动结构创建两个画廊表面:

  • 库2
    • 库2滑动-0
    • gallery2-slide-1
    • gallery2-slide-2
    • 库2-滑动-3-
    • 库2-滑动-4-
    • 库2-滑动-5-
  • gallery3
    • gallery3滑动-0
    • gallery3滑动-1

但是,onclick动作不适用于Gallery2的最后两张幻灯片(这两张幻灯片都在两个画廊中重复)。一旦DOM的仔细检查,我可以看到,存储在库2数据的滑动时,具有以下的id:

  • 库2
    • 库2-滑动-0
    • 库2-滑动-1
    • 库2-滑动-2
    • 库2-滑动-3-
    • gallery3滑动-0
    • gallery3滑动-1

我不确定是什么导致混淆或如何解决,所以任何帮助将不胜感激。 谢谢

+0

我觉得你太复杂了。你为什么不尝试更简单的方法? – elclanrs 2012-02-14 18:02:59

+0

@elclanrs - 不知道你指的是复杂的。这个用例的简单解释是:在一个页面上有一个插件的多个实例,使用$ .data()来存储每个实例唯一的数据,从每个实例的$ .data()存储中获取唯一的数据。在示例代码中的某个点,来自一个实例的唯一数据被拉入另一个实例。我想知道为什么会发生这种情况,以及如何在用例的背景下纠正这种情况。 – raptureaid 2012-02-14 18:53:26

回答

0

你的问题是,调用$('.pGallery').gallery('addItems'...会导致相同的对象被添加到两个画廊的内部结构,当您拨打$('.pGallery').gallery('updateCarousel');存储在这些对象中的ID将被覆盖。

您需要在其中放置原始对象的副本。不要:

addItems : function(newItems) { 
    var $this = $(this), 
     slides = $this.data('slides'); 

    for (var i=0; i<newItems.length; i++) { 
     //slides.push(newItems[i]); 
     slides.push(jQuery.extend({}, newItems[i])); 
    }; 
}, 

随着jQuery.extend({}, oldObject)您可以执行shallow copy;

+0

谢谢,解决了这个问题,现在两个画廊都按预期工作。 – raptureaid 2012-02-14 19:14:33