2013-05-09 72 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 
    });