4

是否有任何类似于最接近()的jQuery函数将返回父链之外的元素,横向遍历?例如,我想在 div 源上调用一个函数 foo() 来返回 div 目标。我知道我可以使用 parent() 和兄弟姐妹() 进行导航,但我需要一些通用的东西,可以根据需要向上、横向和向下移动?

var allsources = $('.source');

allsources.click(function()){
  $(this).closest('.target').hide();
});

<div class="row">
  <div>
     <div class="target" ></div>
  </div>
  <div>
    <div>
      <div class="source"></div>
    </div>
  </div>
</div>

<div class="row">
  <div>
     <div class="target" ></div>
  </div>
  <div>
    <div>
      <div class="source"></div>
    </div>
  </div>
</div>

编辑:

我对最接近的定义:你有一个元素来源。试着找到它。如果找到多于一个,则返回一个更少的节点箍向下/下一个/上一个。如果没有找到,请上一级,然后尝试再次找到。重复直到没有父母。

4

7 回答 7

7

如果最接近的是,您的意思是“尽可能少地向上移动,然后向下移动”,那么您可以这样做

$("#source")
  .closest(":has(.target)")
  .find(".target:first")  //make sure we only select one element in case of a tie

在您的情况下,最好直接指定共同父项:

$(this)
  .closest(".row")
  .find(".target")        //there's no tie here, no need to arbitrate
于 2012-11-30T09:17:23.993 回答
2

这是一个棘手的问题。如前所述,您如何在这种情况下定义最接近?假设你可以决定一些规则;例如:

向上移动:3pt
向下
移动:2pts 横向移动:1pts

然后认为具有最低点的项目是“最接近的”,那么编写一个插件就很容易了,命名为closestAll,它将递归遍历整个 dom 树以确定最接近的项目。

但是,查看您最近的编辑,对所述问题的一个(众多!)正确解决方案是:

var allsources = $('.source');

allsources.click(function(){
  $(this).parents('.row').find('.target').hide();
});

实时示例: http: //jsfiddle.net/zCvJM/(源 A 只隐藏目标 A,B 相同)

于 2012-11-30T09:19:15.660 回答
2

如果你确切地知道 dom 的结构和嵌套的级别,你有没有考虑使用 eq() 方法

$(this).parents().eq(1).prev().children(".target")
于 2012-11-30T09:49:10.707 回答
1

除了基本上查询整个DOM之外,我认为没有其他方法可以做到这一点:

$('#target')

因为如果您想向上和穿越(也不要介意向下),那么目标元素与子元素无关。如果您还想检查子元素的存在,则必须单独进行。

-编辑:

在阅读了关于想要找到最接近的元素(无论它是否是父元素)的评论后,我认为您将不得不编写一个自定义函数来一次爬回 dom 一个节点。我已经测试了以下内容并且可以正常工作:

标记

<div id="parent">
    <div id="child1">   
        <div id="source"></div>
    </div>
    <div id="child2">
        <div class="target" rel="right"></div>
    </div>
    <div id="child3">
        <div>
            <div class="target" rel="wrong"></div>
        </div>
    </div>
</div>

脚本

$(document).ready(function () {
    var tgt = findClosest($('#source'), '.target');
    if (tgt != undefined) {
        alert(tgt.attr('rel'));
    }
});


function findClosest(source, targetSel) {
    var crawledNodes = $();
    var target = null;

    // Go up
    source.parents().each(function () {
        console.log(crawledNodes.index($(this)));
        if (crawledNodes.index($(this)) == -1 && target == null) {
            crawledNodes.add($(this));
            target = findTarget($(this), targetSel);

            // Go across
            $(this).siblings().each(function () {
                console.log("Sibling");
                if (crawledNodes.index($(this)) == -1 && target == null) {
                    crawledNodes.add($(this));
                    target = findTarget($(this), targetSel);
                }
            });
        }
    });

    return target;
}

function findTarget(el, targetSel) {
    console.log(targetSel);
    var target = el.find(targetSel);
    if (target.size() > 0) {
        return target.eq(0);
    }
    else 
    {
        return null;
    }
}
于 2012-11-30T09:08:04.650 回答
1

如果我正确理解了规范,您的意思是类似于下面定义的最接近的函数:

var allsources = $(".source");

function closest($source,selector) {
    if($source == null) return  $([]);
    var $matchingChildren = $source.find(selector);
    if($matchingChildren.length != 0) return $($matchingChildren.get(0));
    else return closest($source.parent(), selector)
}

allsources.click(closest($(this),'.target').hide();});

您可以在http://jsfiddle.net/y2wJV/1/看到它的工作原理

您的定义要求在匹配子项中进行选择时,该函数必须返回一个更少的节点箍向下/下一个/上一个。这个要求没有得到满足,但是这个功能非常灵活,并且在您提供的示例的情况下似乎可以做您想做的事情。

于 2012-11-30T10:40:51.593 回答
0

我发现这段代码很简单,但不能解决平局问题(返回第一个)......

(function ($) {
  $.fn.findClosest = function (filter) {
    var $found = $(),
            $currentSet = this; // Current place

    while ($currentSet.length) {
        $found = $currentSet.find(filter);
        if ($found.length) break; // At least one match: break loop
        // Get all children of the current set
        $currentSet = $currentSet.parent();
    }
    return $found.first(); // Return first match of the collection
  };
})(jQuery);
于 2012-11-30T10:42:52.400 回答
0

我遇到了类似的问题,我有一个表我需要找到可能在当前 td 之外的下一个元素,所以我做了一个 jquery 函数:

    $.fn.nextAllLevels = function(sel) {
    if ($(this).nextAll(sel).length != 0) {
        return $(this).nextAll(sel).eq(0);
    } else if ($(this).nextAll(':has(' +  sel + ')').length != 0) {
        return $(this).nextAll(':has(' +  sel + ')').find(sel).eq(0);
    } else {
        return $(this).parent().nextAllLevels(sel);
    }

因此,要使用它,您只需调用

$('#current').nextAllLevels('.target');

为您提供在正向方向上最接近的元素,无论 in 是否在当前父级中。

于 2016-09-20T08:24:06.310 回答