查找最近的前一个元素jQuery

46

我想要类似于这个的东西,除了我想匹配的元素可能不是直接的兄弟元素。

比如,如果我有这样的HTML:

<h3>
    <span>
        <b>Whaddup?</b>
    </span>
</h3>
<h3>
    <span>
        <b>Hello</b>
    </span>
</h3>
<div>
    <div>
        <img />
    </div>
     <span id="me"></span>
</div>
<h3>
    <span>
        <b>Goodbye</b>
    </span>
</h3>

我想要能够做到这样:

var link = $("#me").closestPreviousElement("h3 span b");
console.log(link.text()); //"Hello"
有没有一种简单的方法可以使用jQuery来完成这个操作?
编辑:我应该更清楚地说明我的规格。$("#me")可能有一个父div,也可能没有。代码不应该假设它有。我并不一定知道周围元素的情况。

1
你想要在层次结构中当前元素之前的“最接近”的元素吗? - Felix Kling
在我看来,没有简单的方法。另外,你如何定义两个非兄弟节点之间的距离? - Robin
5个回答

65
var link = $("#me").closest(":has(h3 span b)").find('h3 span b');

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

这里使用closest()[docs]方法获取第一个祖先元素,该祖先元素包含嵌套的h3 span b元素,然后再使用.find()方法。

当然,你可能会有多个匹配项。


否则,你需要进行更直接的遍历。

var link = $("#me").closest("h3 + div").prev().find('span b');

编辑:这个适用于你更新后的HTML。

例子:http://jsfiddle.net/e27r8/2/


编辑:已更新以处理更新后的问题。

var link = $("#me").closest("h3 + *").prev().find('span b');

这使得.closest()的目标元素变得通用,即使没有父元素,它仍然可以工作。

例如:http://jsfiddle.net/e27r8/4/


抱歉,我应该一开始就更清楚地表达。 - Peter Olson
@Peter:我刚刚更新了。我认为这个已经涵盖了你的需求。你知道目标文本将在 h3 span b 中吗? - user113716
1
如果匹配的节点是父节点的后代,那么此解决方案还将找到在文档中它之后的匹配节点。例如,“Goodbye”所说的跨度也将包含在结果中。 - Ruan Mendes

14

10

我知道这已经过时了,但我一直在寻找同样的东西,并最终找到了另一种相当简洁和简单的解决方案。以下是我的查找下一个或前一个元素的方法,考虑到遍历不是我们正在查找的类型的元素:

var ClosestPrev = $( StartObject ).prevAll( '.selectorClass' ).first();
var ClosestNext = $( StartObject ).nextAll( '.selectorClass' ).first();

我不确定nextAll/prevAll函数返回的集合顺序是否正确,但在我的测试案例中,该数组的顺序似乎是符合预期的方向。如果有人能够澄清jquery内部的工作原理,可能会对可靠性提供有力的保证。


棒极了的解决方案!可以单独使用,也可以与被接受的答案结合使用以获得更强大的解决方案。 - Greggers

8

没有“简单”的方法。您最好的选择是首先检查每个前一个同级节点,然后移动到父节点和所有其前面的同级节点。

您需要将选择器分成两部分:第一部分用于检查当前节点是否可以成为选择器中的顶层节点,第二部分用于检查其后代是否匹配。

编辑: 这也可能成为插件。您可以将其与任何HTML中的任何选择器一起使用:

(function($) {
    $.fn.closestPrior = function(selector) {
        selector = selector.replace(/^\s+|\s+$/g, "");
        var combinator = selector.search(/[ +~>]|$/);
        var parent = selector.substr(0, combinator);
        var children = selector.substr(combinator);
        var el = this;
        var match = $();
        while (el.length && !match.length) {
            el = el.prev();
            if (!el.length) {
                var par = el.parent();
                // Don't use the parent - you've already checked all of the previous 
                // elements in this parent, move to its previous sibling, if any.
                while (par.length && !par.prev().length) {
                    par = par.parent();
                }
                el = par.prev();
                if (!el.length) {
                    break;
                }
            }
            if (el.is(parent) && el.find(children).length) {
                match = el.find(children).last();
            }
            else if (el.find(selector).length) {
                match = el.find(selector).last();
            }
        }
        return match;
    }
})(jQuery);

@Downvoter - 请评论一下。这段代码没有考虑HTML的问题。接受的答案只有在HTML不改变的情况下才能正常工作。例如,如果目标 <h3> 被包含在一个 <div> 中,接受的答案将会失败。你可以把我的代码放在任何页面上的任何元素上,并仅自定义选择器,它就能找到正确的元素。 - gilly3

1

var link = $("#me").closest(":has(h3 span b)").find('span b').text();

var link = $("#me").closest(":has(h3 span b)").find('span b').text();


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