在多个元素上启动jQuery插件。点击多次触发

时间:2013-05-09 14:01:37

标签: jquery triggers click toggle

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

/**
 * 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. 如果我点击第二个列表的更多/更少链接,点击会被触发3次。

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

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

  5. 这是jsfiddle,显示了我面临的问题。

    有人知道可能导致这种情况的原因吗?感谢。

2 个答案:

答案 0 :(得分:1)

将“{1}}添加到”更多“链接上的点击处理程序。这会将操作限制为仅preventDefault()函数:

toggleMoreLess()

答案 1 :(得分:0)

多次实例化插件,将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
    });