类似于最接近的jQuery函数将返回父链之外的元素

时间:2012-11-30 09:03:43

标签: javascript jquery

是否有任何类似于nearest()的jQuery函数会返回父链外的元素,横向移动?例如,我想在div源上调用一个函数foo()来返回div目标。我知道我可以使用parent()和siblings()进行导航,但是我需要一些通用的东西,可以根据需要,向上,向侧面和向下进行多个级别?

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>

编辑:

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

7 个答案:

答案 0 :(得分:5)

如果,最近,你的意思是“尽可能少地往前走”,那么你可以做到

$("#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

答案 1 :(得分:2)

这是一个棘手的问题。正如已经评论过的,在这种情况下如何定义最接近的?假设你可以决定一些规则;例如:

遍历:3pt
横穿:2分
横向移动:1pts

然后将具有最低点的项目视为“最接近”,然后创建一个名为closestAll的名称的插件就足够了,它会对整个dom树进行递归遍历。确定最近的项目。

然而,看看你最近的编辑,一个(很多!)正确的解决问题的方法是:

var allsources = $('.source');

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

实例:http://jsfiddle.net/zCvJM/(来源A仅隐藏目标A,B代表相同)

答案 2 :(得分:2)

如果您确切知道dom的结构和嵌套级别,您是否考虑使用eq()方法

$(this).parents().eq(1).prev().children(".target")

答案 3 :(得分: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;
    }
}

答案 4 :(得分: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/

看到它正常工作

您的定义要求在匹配的子项中进行选择时,该函数必须返回一个较少的节点向下/ next / prev。这个要求还没有达到,但是这个功能非常灵活,似乎就你所提供的例子做了你想做的事。

答案 5 :(得分: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);

答案 6 :(得分: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是否在当前的父级中。