Jquery:获取一个类的所有元素,这些元素不是具有相同类名的元素的后代?

时间:2012-09-27 14:45:00

标签: javascript jquery

问题:给定一个特定的容器dom元素(窗口,div,字段集等),在该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函数&#34; .findButNotInside()&#34;代表我正在寻找的功能。

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

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

示例2:

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

应仅返回#Field1#SomeWidget。应该查找目标字段集.FormWidget内的#MyFieldset,但不应返回#Field2,因为不允许查看.FormWidget(在本例中为#SomeWidget)内部找到其他.FormWidgets。

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

5 个答案:

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

Fiddle。诀窍是检查nearestMatch实际上是否在我们的搜索环境中。

请注意这个无效:

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

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

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

答案 1 :(得分:1)

$("container-selector").find(".class").not(".class .class");

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

答案 3 :(得分:0)

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

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"));

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

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