【问题标题】:Find closest previous element jQuery查找最近的前一个元素jQuery
【发布时间】:2011-10-24 12:05:27
【问题描述】:

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

如果我有这个 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。代码不应假定它确实如此。我不一定对周围的元素一无所知。

【问题讨论】:

  • 你想要层次结构中当前元素之前的“最近”元素吗?
  • 没有简单的方法。还有,你如何定义两个非兄弟节点之间的距离?

标签: jquery


【解决方案1】:

http://api.jquery.com/prev/

var link = $("#me").parent("div").prev("h3").find("b");
alert(link.text());

http://jsfiddle.net/gBwLq/

【讨论】:

    【解决方案2】:
    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:我刚刚更新了。我想这涵盖了你。您知道目标文本将在h3 span b 中吗?
    • 如果匹配节点是父节点的后代,此解决方案还将在文档中找到位于它之后的匹配节点。例如,说再见的跨度也将包含在结果中。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      不,没有“简单”的方法。你最好的办法是做一个循环,首先检查每个前一个兄弟节点,然后移动到父节点及其所有以前的兄弟节点。

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

      编辑:这也可能是一个插件。您可以将它与任何 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 没有改变的情况下才有效。例如,如果目标&lt;h3&gt; 包含在&lt;div&gt; 中,则接受的答案将失败。您可以在任何页面上查找任何元素,只需自定义选择器,它就会找到正确的元素。
      【解决方案5】:

      我知道这是旧的,但正在寻找同样的东西并最终想出了另一个相当简洁和简单的解决方案。这是我查找下一个或上一个元素的方法,考虑到遍历不是我们要查找的类型的元素:

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

      我不能 100% 确定 nextAll/prevAll 函数的集合返回的顺序,但在我的测试用例中,数组似乎在预期的方向上。如果有人可以澄清 jquery 的内部结构以确保可靠性,那可能会有所帮助。

      【讨论】:

      • 很棒的解决方案!可以单独使用,也可以与公认的答案结合使用,以获得更强大的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多