2013-05-09 51 views
1

我已经编写了一个非常简单的jQuery插件,用于在客户端对ulol元素进行分片,但我在多个元素上启动时看到了非常奇怪的行为。该插件基本上隐藏了一个列表中的额外项目,只显示指定数量的项目。它将更多/更少链接添加到列表中,以便用户可以切换项目。以下是该插件的代码。在多个元素上启动一个jQuery插件。点击触发多次

/** 
* jQuery list slice v1.0 
* 
* Slices a list ('ul', 'ol') and shows a more/less link to either show more 
* or less 'li's respectively. 
* 
* @USAGE: 
*  For a list like the following: 
* 
*  <ul id="sample-list"> 
*   <li>Item 1</li> 
*   <li>Item 2</li> 
*   <li>Item 3</li> 
*  </ul> 
* 
*  Initiate the sliceList as follows: 
* 
*  $('ul.sample-list').listSlice({ 
*   default_items: 2, // Set Any other options here 
*  }); 
*/ 

(function($) { 
    $.fn.listSlice = function(options) { 
     // Merge or Override user defined options 
     options = $.extend({}, $.fn.listSlice.options, options); 

     var entity = $(this); 

     /** 
     * Slices the initiating list to show the number of default_items 
     * and append a more link to the list. 
     */ 
     function sliceList(){ 

      entity.find('li').addClass('listSliceItem'); 

      // Make sure we do not count items in ignore_list 
      ignore_list = options.ignore_list.split(','); 
      $.each(ignore_list, function() { 
       var class_name = '.' + $.trim(this); 
       var id_name = '#' + $.trim(this); 

       var obj = entity.find(class_name); 
       obj.removeClass('listSliceItem'); 
       if (!(obj.is('li'))) { 
        obj.closest('li').removeClass('listSliceItem'); 
       } 

       var obj = entity.find(id_name); 
       obj.removeClass('listSliceItem'); 
       if (!(obj.is('li'))) { 
        obj.closest('li').removeClass('listSliceItem'); 
       } 
      }); 

      $.each(entity, function() { 
       var current_entity = $(this); 
       var should_apply = true; 
       if((current_entity.find('li.listSliceItem').length) <= (
         options.default_items)) { 
        should_apply = false; 
       } 

       // Make sure we apply more/less only to lists that have 
       // enough 'li' elements. 
       if(should_apply) { 
       current_entity.find('li.listSliceItem' + 
          ':gt(' + (options.default_items - 1).toString() + 
          ')').hide(); 
       current_entity.append('<' + options.link_container + 
           ' class="' + options.link_container_class + '">' + 
           '<a href="#!" class="listSliceMore ' + 
           options.link_class + '">' + options.more_text + '</a>'); 
       } 
      }); 

     } 

     /** 
     * uses the slideToggle method to toggle between showing more or less 
     * list items in the initiated list. 
     */ 
     function toggleMoreLess(btn){ 
      var dad = btn.parent().parent(); 
      dad.find('li.listSliceItem' + 
        ':gt(' + (options.default_items - 1).toString() + 
        ')').slideToggle(options.animation_time); 
      btn.text(btn.text() == options.more_text ? options.less_text : options.more_text); 
     } 

     /** 
     * Initiate the sliceList method and more link click method. 
     */ 
     sliceList(); 
     $('a.listSliceMore').click(function() { 
      toggleMoreLess($(this)); 
      return false; // Cancel Default Anchor Action. 
          // This prevents appending '#!' to the end of the url 
     }); 
    } 

    // Default options 
    $.fn.listSlice.options = { 

     // Default number of items to be displayed (Accepts Integer only). 
     default_items: 5, 

     // More Anchor link's label when hiding items (Accepts Strings only). 
     more_text: 'More', 

     // More Anchor link's label when showing all items (Accepts Strings only). 
     less_text: 'Less', 

     // Class names to be applied to the More link (Accepts Strings only). 
     link_class: 'more link', 

     // Class names to be applied to the More link's container (Accepts Strings only). 
     link_container_class: 'more', 

     // An element that wraps the more link. (Accepts Strings only) 
     link_container: 'li', 

     // Amount of time in miliseconds the show/hide animation should run.(Accepts Integer and Strings) 
     animation_time: 500, 

     // Ignore 'li' items to be counted as the part of list which have following classes 
     // or id's. A comma separated list of classes or id's or both. (Accepts Strings Only) 
     ignore_list: 'ignore, no-include, all', 
    } 

})(jQuery); 

现在,这是场景。说我有HTML格式如下:

<div id ="one"> 
    <ul class="item_list"> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
    </ul> 
</div> 

<div id ="two"> 
    <ul class="item_list"> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
    </ul> 
</div> 

<div id ="three"> 
    <ul class="item_list"> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
    </ul> 
</div> 

<div id ="four"> 
    <ul class="item_list"> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
     <li> Sample Item </li> 
    </ul> 
</div> 

,我开始我的插件如下:

<script type="text/javascript"> 
    $('.item_list').listSlice(); 
</script> 

它工作绝对没问题。但是,假设我想为上述四个元素设置不同的选项,我将它们分开绑定,如下所示。

<script type="text/javascript"> 
    $('div#one .item_list').listSlice({ 
     some_option: some_value, 
    }); 
    $('div#two .item_list').listSlice({ 
     some_option: some_value, 
    }); 
    $('div#three .item_list').listSlice({ 
     some_option: some_value, 
    }); 
    $('div#four .item_list').listSlice({ 
     some_option: some_value, 
    }); 
</script> 

这是当它变得有点混乱。我在这里看到的行为是:

  1. 如果我点击more/less链接,第一个列表中,单击被触发4次,做动画上下滑动的4倍。

  2. 如果我点击更多/更少链接的第二个列表,Click会触发3次。

  3. 如果我点击第三个列表的更多/更少链接,Click会触发2次。

  4. 如果我点击更多/更少链接的第四个列表,它工作正常。 (即点击只触发一次)

这是一个jsfiddle显示我面对的问题。

有没有人有一个想法可能导致这种情况?谢谢。

回答

1

preventDefault()添加到您的更多链接上的点击处理程序。这将限制行动,只是toggleMoreLess()功能:

$('a.listSliceMore').click(function() { 
     toggleMoreLess($(this)); 
     e.preventDefault(); 
     return false; // Cancel Default Anchor Action. 
         // This prevents appending '#!' to the end of the url 
    }); 
+0

试过,但没有帮助。此外,使用'return false'确实会阻止默认操作,所以我不认为这是问题所在。问题在于,由于某种原因,listSlice()方法在第一个列表上被实例化了4次,在第二个列表中被实例化了3次,等等。 – Amyth 2013-05-10 04:41:35

+0

添加preventDefault为我工作:http://jsfiddle.net/6K6sB/ – mccannf 2013-05-10 08:53:51

+0

哎呀,是的,它的确如此!上次我检查时应该是缓存问题。谢谢。 – Amyth 2013-05-10 09:09:04

0

实例化插件1倍以上,结合时代的插件被实例化的click事件a.listSliceMore元素数量。我通过确保我解除之前的单击事件来解决它。

$('a.listSliceMore').unbind('click').click(function() { 
     toggleMoreLess($(this)); 
     return false; // Cancel Default Anchor Action. 
         // This prevents appending '#!' to the end of the url 
    }); 
相关问题