我编写了一个非常简单的jQuery插件来对客户端上的ul
或ol
元素进行切片,但是当我在多个元素上启动它时,我看到了非常奇怪的行为。该插件基本上隐藏了列表中的额外项目,只显示指定数量的项目。它会在列表中附加更多/更少的链接,以便用户可以切换项目。以下是插件的代码。
/**
* 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>
这是一个有点混乱的时候。我在这里看到的行为是:
如果我点击第一个列表的more/less
链接,点按次数会被触发4次,因此动画会上下滑动4次。
如果我点击第二个列表的更多/更少链接,点击会被触发3次。
如果我点击第三个列表的更多/更少链接,点击会被触发2次。
如果我点击第四个列表的更多/更少链接,它可以正常工作。 (即点击仅被触发一次)
这是jsfiddle,显示了我面临的问题。
有人知道可能导致这种情况的原因吗?感谢。
答案 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
});