jQuery查找下一个和上一个元素

18

我尝试找到当前元素的下一个或上一个元素。但是next()prev()函数只能在范围内使用,无法超越范围外。例如,这是我想要实现的:

<ul id="ul1">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>
    <ul id="ul2">
      <li>4</li>
      <li>
        <ul id="ul3">
          <li>5</li>
          <li>6</li>
        </ul>
      </li>
      <li>7</li>
      <li>8</li>
    </ul>
  </li>
  <li>9</li>
</ul>

如果当前元素是ul1,下一个元素是<li>1</li>,前一个元素为null。

如果当前元素是<li>1</li>,下一个元素是<li>2</li>,前一个元素为ul1

如果当前元素是<li>8</li>,下一个元素是<li>9</li>,前一个元素为<li>7</li>


如果当前元素是<li>3</li>?还有<li>4</li>吗? - ifaour
@ifaour - 不,父级元素是包含#ul2<li>元素。 - David Tang
3个回答

14

首先,这是一个非常棒的问题。感谢您的发布!

我用一个链接的jQuery语句完成了这个问题。唯一的问题是,如果在顶部的ul上运行previous(),你会得到body。我认为从技术上讲这是有道理的。然而,如果这不是期望的行为,请查看下面的我的更新。

用法: next("#ul3") 返回 <li>5</li>

接下来:

function next(selector) {
    var $element = $(selector);

    return $element
        .children(":eq(0)")
        .add($element.next())
        .add($element.parents().filter(function() {
            return $(this).next().length > 0;
        }).next()).first();
}

上一个:

function previous(selector) {
    var $element = $(selector);

    return $element
        .prev().find("*:last")   
        .add($element.parent())    
        .add($element.prev())
        .last();     
}

更新 如果你想限制前一个节点的上层节点,可以这样做:

function previous(selector, root) {
    var $element = $(selector);

    return $element
        .prev().find("*:last")   
        .add($element.parent())     
        .add($element.prev())
        .last().not($(root).parent());      
}

另一个更新:这里是一个jQuery插件,为方便起见:

http://jsfiddle.net/andrewwhitaker/n89dz/

(function($) {
    $.fn.domNext = function() {
        return this
            .children(":eq(0)")
            .add(this.next())
            .add(this.parents().filter(function() {
                return $(this).next().length > 0;
            }).next()).first();        
    };

    $.fn.domPrevious = function() {
        return this
            .prev().find("*:last")   
            .add(this.parent())     
            .add(this.prev())
            .last();         
    };
})(jQuery);

这里有一个更详细的例子:http://jsfiddle.net/andrewwhitaker/KzyAY/


它工作得很完美,我还在这里创建了一个片段http://jsfiddle.net/dqTkY/2/。谢谢。 - StoneHeart

5
非常有趣的问题!听起来你正在将HTML的递归结构展开,使其可以循环 - 我可以看到它会很方便。
您可以通过将.next()分解为以下情况来解决该问题:
  1. 元素具有子元素 -> next()是第一个子元素。
  2. 元素没有子元素,并且不是最后一个子元素 -> next()与jQuery的.next()相同
  3. 元素没有子元素,是最后一个子元素:
    1. 查找最近的不是最后一个子元素的父元素 -> next()是该父元素的下一个兄弟元素
    2. 如果不存在这样的父元素 -> next()null
代码如下(称其为flatNext以保留原始的jQuery .next行为):
$.fn.flatNext = function () {
   if (this.children().length) return this.children().eq(0);
   if (!this.is(":last-child")) return this.next();
   if (this.closest(":not(:last-child)").length)
       return this.closest(":not(:last-child)").next();
   return $([]); // Return empty jQuery object rather than null
};

而且$.fn.flatPrev应该跟随...


1
根据您的数据集,您可以像这样将整个内容展平(假设$.find是稳定的,我相信它是稳定的):
var eles = [];
$("#ul1").find("li").each(function (e) {
    eles.push(e);
});

ele[3]后面的下一个元素是ele[4],不论缩进级别。

示例 http://jsfiddle.net/xRpmL/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接