确定嵌套 HTML 列表中的相邻 <li>

Determine adjacent <li> inside a nested HTML list

本文关键字:li 嵌套 HTML 列表      更新时间:2023-09-26

>我有一个嵌套列表。该列表中的一个元素包含一个名为"special"的类。此特定节点可以存在于嵌套列表中的任何位置。例如,

<ul id="mylist">
 <li>1</li>
 <li>2</li>
 <li>
    <ul>
        <li>3</li>
        <li class="special">4</li>
        <li>
           <ul>
              <li>5</li>
           </ul>
        </li>
    </ul>
 </li>
 <li>6</li>
</ul>

当我单击一个按钮时,我需要将两个类,说"向上"和"向下"应用于特殊节点上方和下方的节点。因此,在上述示例中,结果列表应如下所示:

<ul id="mylist">
 <li>1</li>
 <li>2</li>
 <li>
    <ul>
        <li class="up">3</li>
        <li class="special">4</li>
        <li>
           <ul>
              <li class="down">5</li>
           </ul>
        </li>
    </ul>
 </li>
 <li>6</li>
</ul>

如您所见,由于我的列表是一个嵌套列表,并且特殊的<li>节点可以存在于任何位置,因此"向上"和"向下"<li>可能也需要放置在其他<ul>中。

我的想法

  1. 我最初的想法是做 DOM 遍历,但很快就变得非常复杂。

  2. 接下来我想我会在我的列表中创建一个包含所有<li>的数组($("#mylist").find ("li")),然后找出这些<li>中哪些具有"特殊"类(hasClass("special")),一旦我知道"特殊"发生的数组索引,我将做 +1、-1 来获取下层和上层节点。但我不知道该怎么做。

您可以使用

.index()来确定哪个li具有.special。从那里,您可以使用您的想法#2:

var lis = $("#mylist").find ("li");
lis.eq(lis.index('.special')-1).addClass('up');
lis.eq(lis.index('.special')+1).addClass('down');

考虑到相邻在您的情况下具有特殊含义,我编写了一个考虑到该特殊定义的小插件。这能准确代表您要查找的内容吗?

$.fn.adjacent = function(options) {
  var df = $.extend({dir: 'up'}, options);
  return this.each(function() {
    var elem = df.dir === 'up' ? $(this).prev() : $(this).next();
    while( $('li', elem).length ) {
      elem = df.dir === 'up' ? $('li', elem).last() : $('li', elem).first();
    }
    elem.addClass(df.dir);
  });
};
$('button').on('click', function() {
    $('#mylist li.special')
    .adjacent()
    .adjacent({dir:'down'});
});
.up {
  border-bottom: 1px solid black;
  }
.down {
  border-top: 1px solid black;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="mylist">
 <li>1</li>
 <li>2</li>
 <li>
    <ul>
        <li>3</li>
        <li>
          <ul>
            <li>3.1</li>
            <li>3.2</li>
            <li>3.3</li>
          </ul>
        </li>
        <li class="special">4</li>
        <li>
           <ul>
              <li>
                <ul>
                  <li>4.1</li>
                </ul>
              </li>
              <li>5</li>
           </ul>
        </li>
    </ul>
 </li>
 <li>6</li>
</ul>
<button>Click</button>

你真正要问的是"如何在有序树图中获取包含前面和后面数字的节点?您只是在 HTML DOM 中分别将<ul><li>标签用作非终端节点和终端节点。解决方案是适当的树遍历。

function isBranch (node) {
    return node.is('ul');
}
function isList (node) {
    return node.is('li');
}
function getPrevious (node) {
    while (node.length && !node.previous().length) {
        node = node.parent();
    }
    while (isBranch(node) && !isLeaf(node)) {
        node = node.children().last();
    }
    return isLeaf(node) ? node : $();
}
function getNext (node) {
    while (node.length && !node.next().length) {
        node = node.parent();
    }
    while (isBranch(node) && !isLeaf(node)) {
        node = node.children().first();
    }
    return isLeaf(node) ? node : $();
}
function markPreviousAndNext (node) {
    getPrevious(node).addClass('up');
    getNext(node).addClass('down');
}
markPreviousAndNext($('#mylist .special'));

请花点时间,尝试更好地构建您的问题(及其标题),以便答案可以帮助未来的搜索者。我真的无法在短时间内想出一个真正合适的标题。