找到最近的元素,而不是最接近

时间:2017-01-24 10:42:39

标签: javascript jquery

我的印象是closest()会给我最接近的匹配元素,但我错了,它会给我最近的祖先,parents()也是如此。那我怎样才能得到最近的元素?

e.g。我有2 div s,如下所示

<div id="clickme">
    Click me
</div>
<div class="findme" style="display:none">
    Find me
</div>

如果我想通过.findme引用#clickme该怎么办。

我可以执行$('#click').helpfullFunctionThatGivesNearestElement('.findme')之类的操作吗?

或者我是否需要像$('findme')那样扫描整个DOM?但是可以有100个.findme那么我怎样才能找到最接近特定元素的东西?

更新

.findme可以在DOM中的任何位置。

3 个答案:

答案 0 :(得分:2)

这是递归遍历DOM的方式。

我已经实现了函数 $.fn.nearest ,因为OP可以使用jQuery,因此可以使用$('clickme').nearest('.findme');

调用它

该方法将通过递归搜索找到多个元素**(如果它们与起始节点共享相同的距离),通过向各个方向(父,子,下一个和上一个)向前和向后看通过最近的选中元素。它还避免反复检查元素(即只检查多个子元素的父元素)。

如果您不需要检查特定方向,即childrenprev,您只需评论该部分。

在递归完成之前进行一些检查。当在DOM中找不到选择器时,返回一个空的jQuery元素,当只有一个元素被找到时,返回找到的元素。

我没有使用大型HTML测试它的效率,这完全取决于所需元素的位置,这与HTML结构的复杂性直接相关。但肯定它是指数级的,接近O(n³)或O(n⁴)。

试一试。

$.fn.nearest = function(selector) {
  var allFound = $(selector);

  if (!allFound.length) // selector not found in the dom
    return $([]);

  if (allFound.length == 1) // found one elem only
    return allFound;
  else
    return nearestRec($(this), selector);

  function nearestRec(elems, selector) {
    if (elems.length == 0)
      return this;

    var selector = selector;
    var newList = [],
      found = $([]);

    $(elems).each(function(i, e) {
      var options = e[1] || {};
      e = $($(e)[0]);

      // children
      if (!options.ignoreChildren)
        updateFound(e.children(), selector, newList, found, {
          ignoreParent: true
        });

      // next
      if (!options.ignoreNext)
        updateFound(e.next(), selector, newList, found, {
          ignoreParent: true,
          ignorePrev: true
        });

      // prev
      if (!options.ignorePrev)
        updateFound(e.prev(), selector, newList, found, {
          ignoreParent: true,
          ignoreNext: true
        });

      // parent
      if (!options.ignoreParent)
        updateFound(e.parent(), selector, newList, found, {
          ignoreChildren: true
        });
    });

    return found.length && found || nearestRec(newList, selector);

    function updateFound(e, selector, newList, found, options) {
      e.each(function() {
        var el = $(this);
        if (el.is(selector)) {
          found.push(el);
          return;
        }

        newList.push([el, options]);
      });
    }
  }
};


$(function() {
  // multiple elems found, traverse dom
  $(".clickme").nearest(".findme").each(function() {
    $(this).addClass("found");
  });
});
div {
  padding: 5px 3px 5px 10px;
  border: 1px solid #666;
  background-color: #fff;
  margin: 3px;
}
.found {
  background-color: red;
}
.clickme {
  background-color: #37a;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="findme">
  findme
  <div class="findme">
    findme
    <div>
      &nbsp;
      <div>
        &nbsp;
      </div>
      <div>
        &nbsp;
      </div>
      <div class="clickme">
        clickme
        <div>
          &nbsp;
        </div>
        <div>
          &nbsp;
          <div class="findme">
            findme
            <div class="findme">
              findme
            </div>
          </div>
          <div class="findme">
            findme
          </div>
        </div>
      </div>
      <div>
        &nbsp;
        <div class="findme">
          findme
        </div>
      </div>
      <div class="findme">
        findme
      </div>
    </div>

    <div class="findme">
      findme
      <div>
        &nbsp;
      </div>
      <div>
        &nbsp;
      </div>
      <div class="findme">
        findme
        <div class="findme">
          findme
        </div>
      </div>
      <div>
        &nbsp;
      </div>
      <div class="findme">
        findme
      </div>
    </div>
  </div>
</div>

答案 1 :(得分:0)

jquery插件:

 $('#clickme').nextElementInDom('.findme');

<强>用法:

android:descendantFocusability="blocksDescendants"

答案 2 :(得分:-1)

您可以尝试通过引用其封闭父级来定位元素,而不是遍历整个DOM树。

<div>
<div id="clickme" onclick="$(this).parent().find('.findme').show();">
    Click me
</div>
<div class="findme" style="display:none">
    Find me
</div>
</div>

但是,只有当您搜索的元素具有相同的祖先父级时,这才有效。