在拆分列表

时间:2015-11-27 08:43:21

标签: javascript jquery html

是否可以让.nextUntil()在拆分列表上工作,或者获得相同的功能?

所以我正在尝试为我的项目实现如此受欢迎的班次选择,并且由于它们在我的应用程序的列表中排序,我希望能够跨<ul>个边框进行选择。

我有以下DOM元素集:

<ul class="current">
  <li class="item">first</li>
  <li class="item clicked">second</li>
  <li class="item">third</li>
  <li class="item">fourth</li>
</ul>
<ul class="later">
  <li class="item">fifth</li>
  <li class="item selected">sixth</li>
  <li class="item">seventh</li>
</ul>

使用类似的东西:

$('li.clicked').nextUntil('li.selected');

我喜欢包含以下元素的列表

[ <li class="item">third</li>,
  <li class="item">fourth</li>,
  <li class="item">fifth</li> ]

然而,我得到的只是导致分割</ul>的元素。有没有办法做到这一点?我还尝试先使用$('.item')选择所有项目,然后使用.nextUntil(),但没有任何运气。

4 个答案:

答案 0 :(得分:2)

这是你在找什么?

$('li').slice($('li').index($('.clicked'))+1,$('li').index($('.selected')));

供参考

Jquery.Index

Jquery.Slice

修改

所以,如果你这样做

$('li')

你将获得所有元素'li'获得的数组:

[<li class=​"item">​first​</li>​, 
<li class=​"item clicked">​second​</li>​, 
<li class=​"item">​third​</li>​, 
<li class=​"item">​fourth​</li>​, 
<li class=​"item">​fifth​</li>​, 
<li class=​"item selected">​sixth​</li>​, 
<li class=​"item">​seventh​</li>​]

因为它是一个数组你可以切片他得到一个子数组你只需要两个位置,从哪里开始到这里完成。

//start
$('li').index($('.clicked'))+1 // +1 because you dont want to select him self
//end
$('li').index($('.selected'))

为了获得更好的性能,你应该在创建一个包含所有li的数组之前,这样就不会在'li'数组中搜索所有dom 3次

var array = $('li');
var subarray = array.slice(array.index($('.clicked'))+1,array.index($('.selected')));

答案 1 :(得分:2)

假设这些列表无法合并为一个,则无法使用nextUntil方法。这是因为jQuery如何执行遍历。根据文件,

  

获取每个元素的所有兄弟姐妹,但不包括由传递的选择器,DOM节点或jQuery对象匹配的元素。

fifth不是clicked元素的兄弟,而是元素父母兄弟的孩子。

我提出了两种可能的解决方案。

解决方案1:结合NEXT和PREV遍历

假设.clicked始终位于第一个列表中且.selected始终位于第二个列表中,则prevAll()nextAll()的组合应该可以解决问题。这假定订单是相同的。

var siblings = $("li.clicked").nextAll()

在元素本身之后获取当前元素的所有兄弟。

var distantSiblings = $("li.selected").prevAll();

在第一个元素之后但在第二个元素之前获取所有远程兄弟姐妹。

siblings.push(distantSiblings);

将它们组合成两个,然后遍历每个元素。

var siblings = $("li.clicked").nextAll()
var distantSiblings = $("li.selected").prevAll();

siblings.push(distantSiblings);

siblings.each(function() {
    $(this).addClass("blue");
});
.blue { color: blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="current">
  <li class="item">first</li>
  <li class="item clicked">second</li>
  <li class="item">third</li>
  <li class="item">fourth</li>
</ul>
<ul class="later">
  <li class="item">fifth</li>
  <li class="item selected">sixth</li>
  <li class="item">seventh</li>
</ul>

http://jsfiddle.net/r15z10o4/

注意:

您会注意到上面的代码有效,但它可能不是最佳解决方案。这仅适用于上述示例。可能还有一个不太冗长的解决方案。

解决方案2(查找所有列表项的索引)

另一个想法是找到所有项目的索引,并收集夹在这两个索引之间的元素。然后,您将需要使用“切片”选择器来获取它们之间的范围。

var items = $(".item");
var clicked = $(".clicked");
var selected = $(".selected");
var clickIndex = items.index(clicked);
var selectIndex = items.index(selected);

$("li").slice(clickIndex + 1, selectIndex).addClass("blue");

var clicked = $(".clicked");
var selected = $(".selected");

var clickIndex = $("li").index(clicked);
var selectIndex = $("li").index(selected);

$("li").slice(clickIndex+1, selectIndex).addClass("blue");
.blue { color: blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="current">
  <li class="item">first</li>
  <li class="item clicked">second</li>
  <li class="item">third</li>
  <li class="item">fourth</li>
</ul>
<ul class="later">
  <li class="item">fifth</li>
  <li class="item selected">sixth</li>
  <li class="item">seventh</li>
</ul>

答案 2 :(得分:0)

您可以通过一次选择所有这些项目并使用循环来手动完成。

考虑父元素,让我们说&#34;容器&#34;:

<div id="container">
  <ul class="current">
    <li class="item">first</li>
    <li class="item clicked">second</li>
    <li class="item">third</li>
    <li class="item">fourth</li>
  </ul>
  <ul class="later">
    <li class="item">fifth</li>
    <li class="item selected">sixth</li>
    <li class="item">seventh</li>
  </ul>
</div>

现在,您可以选择所有这些项目:

var $items = $("#container > ul > li.item"); // or simply $("#container .item");

迭代它们:

var $items = $(".item"), $result = $(), found = false;

for (var i = 0; i < $items.length; i++)
{
    $currentItem = $items.eq(i);

    if ($currentItem.is('.clicked')) {
        found = true;
        continue;
    }

    if ($currentItem.is('.selected'))
        break;

    if (found)
      $result = $result.add($currentItem);
}

console.log($result);

这是工作JSFiddle demo

答案 3 :(得分:0)

在任何情况下,您都需要定义li组。

我认为最简单的方法是创建一个函数来获取lis列表,你可以按照你想要的方式请求,然后过滤你感兴趣的el。

&#13;
&#13;
function elRange(elList, start, end){
  // we do not use indexOf directly as elList is likely to be a node list
  // and not an array.
  var startI = [].indexOf.call(elList, start);
  var endI = [].indexOf.call(elList, end);
  return [].slice.call(elList, startI, endI + 1);
}

// request the group of *ordered* elements that can be selected
var liList = document.querySelectorAll('ul.current > li, ul.later > li');
var selectionEnd = document.querySelector('.selected');

[].forEach.call(liList, function(li){
  li.addEventListener('click', function(){
    var selected = elRange(liList, li, selectionEnd);
    selected.forEach(function(el){
      el.classList.add('red');
    })
  });
});
&#13;
.selected {
  color: blue;
}
.red {
  color: red;
}
&#13;
<ul class="current">
  <li class="item">first</li>
  <li class="item">second</li>
  <li class="item">third</li>
  <li class="item">fourth</li>
</ul>
<ul class="later">
  <li class="item">fifth</li>
  <li class="item selected">sixth</li>
  <li class="item">seventh</li>
</ul>
&#13;
&#13;
&#13;