3

问题:给定一个特定的容器 dom 元素(窗口、div、fieldset 等),在该 DOM 元素中查找类 (.FormWidget) 的所有元素,递归搜索该容器的所有后代。包括但不查看内部具有匹配类 (.FormWidget) 的元素。元素可以嵌套到n层。

例如,给定这个 HTML:

<fieldset id="MyFieldset" class="FormWidget FieldSetMultiplier">
  <legend>My Legend</legend>

  <div>
    <label for="Field1">Field1</label>
    <input type="text" name="Field1" value="" id="Field1" class="BasicInput FormWidget">
  </div>

  <div id="SomeWidget" class="FormWidget">
    <label for="Field2">Field2</label>
    <div name="Field2" id="Field2" class="FormWidget RestrictedComboBox"></div>
    <input type="text">
  </div>
</fieldset>

<div>
    <label for="Field3">Field3</label>
    <input type="text" name="Field3" value="" id="Field3" class="BasicInput FormWidget">
</div>

示例 1:

让伪 Jquery 函数“.findButNotInside()”代表我正在寻找的功能。

$(document).findButNotInside('.FormWidget');

应该只返回#MyFieldset 和#Field3。从窗口开始,字段 1 和 2 以及 #SomeWidget 是 FormWidgets,但由于该函数不允许在其他 .FormWidgets 内部查找 FormWidgets,因此无法包含它们。.FormWidget 字段集中的任何内容都是禁止的。

示例 2:

$('#MyFieldset').findButNotInside('.FormWidget');

应该只返回#Field1and #SomeWidget。它应该寻找.FormWidget目标字段集内的 s #MyFieldset,但不应返回 #Field2,因为它不允许查看 .FormWidget(在本例中为 #SomeWidget)内部来查找其他 .FormWidget。

我认为这可以通过正确的函数和选择器来完成,但我不确定应该如何构造该选择器?

4

5 回答 5

5
$.fn.findButNotInside = function(selector) {
    var origElement = $(this);
    return origElement.find(selector).filter(function() {
        var nearestMatch = $(this).parent().closest(selector);
        return nearestMatch.length == 0 || origElement.find(nearestMatch).length == 0;
    });
};

小提琴。诀窍是检查nearestMatch实际是否在我们的搜索上下文中。

请注意,这无效:

$('window').findButNotInside('.FormWidget');

...因为没有<window>标签。你想要的是:

$(document).findButNotInside('.FormWidget');
于 2012-09-27T15:54:16.883 回答
1
$("container-selector").find(".class").not(".class .class");
于 2012-09-27T14:52:04.760 回答
0

此解决方案依赖于有关 HTML 结构的已知信息:

$('body .FormWidget').filter(function(){
    return $(this).parents('.FormWidget').length == 0;
}).css("border", "solid 3px red");​

$('#MyFieldset .FormWidget').filter(function(){
    return $(this).parents('.FormWidget').length == 1;
}).css("border", "solid 3px blue");

http://jsfiddle.net/dwgZu/

于 2012-09-27T15:02:51.447 回答
0

想不出更优雅的“jqueryish”解决方案。但是,这可以递归地完成。

http://jsfiddle.net/zzBMq/

function findIt($elements){

    $elements.children().each(function(i){
        var $this = $(this);

        if($this.is(".FormWidget")){
            // do something with the matched element
            $this.css("border","1px solid red");
        }else{
            // make the recursive call
            findIt($this);
        }
    });
}

findIt($("#MyFieldset"));

你显然可以把它变成一个插件。

于 2012-09-27T15:15:24.647 回答
0
(function($){
    $.fn.findButNotInside = function(selector){
        var _n,_o,elemArr=[];
        this.find('.FormWidget').each(function(){
            _o = _n;
            _n = $(this);
            try{
                if(_o&&_o.find(_n).length){
                    _n = _o;
                    if(elemArr.indexOf(_o)==-1) throw _o;
                }else throw _n;
            }catch(e){
                elemArr.push(e);
            }
        });
       return $().add(elemArr);
    }
})(jQuery);

小提琴:http: //jsfiddle.net/guerilla/p9fMX/

于 2012-09-27T15:48:07.590 回答