非贪婪的jquery选择器

时间:2015-05-18 13:46:23

标签: jquery jquery-selectors

我正在尝试构建jQuery选择器,以便将html元素与类" widget"相匹配。在"非贪婪的"方式,没有任何文件结构假设。我的意思是:没有匹配内部子元素与同一个类,而不关心小部件元素是否是直接的儿子。

我知道的唯一方法是使用.not()选择器,如:

$(".widget").not(".widget .widget");

但是这样选择器无法再找到"子小部件"内部小部件内容。

例如,给出这个html:

<div class="otherClass">
    <h1>Some title</h1>
    <p>Some text...</h1>
    <div class="widget" id="w100">
        <div>
            <h2>Some intermediate level...</h2>
            <div class="widget" id="w110">
                <h2>Some title</h2>
                <div class="widget" id="w111">
                    ...
                </div>
                <div class="widget" id="w112">
                    ...
                </div>
            </div>
        </div>
        <div class="widget" id="w120">
            <h2>Some title</h2>
            <div class="widget" id="w121">
                ...
            </div>
            <div class="widget" id="w122">
                ...
            </div>
        </div>
    </div>
</div>

假设我尝试构建的选择器存储在选择器变量中,我希望如此:

var s0 = $(selector); // Matches div#w100 but not inner elements with "widget" class".
var s1 = $(selector, s0); // Matches div#w110 and div#w120
var s21 = $(selector, s1[0]); // Matches div#w111 and div#112
var s22 = $(selector, s1[1]); // Matches div#w121 and div#122

我的目标是实现一个简单的可嵌套窗口小部件系统,该系统基于应用于具有&#34;小部件&#34;的元素的小型控制器。 CLAS s和data-xxx属性中的其他参数来选择实际的小部件控制器和参数。但是,小部件必须是ab le在其html内容中展开其他子小部件。

6 个答案:

答案 0 :(得分:2)

我在这里解释你的问题与其他人有所不同。在我看来,你想要的是从某个点遍历DOM,搜索.widget但不在该类的任何元素下面递归。因此,如果你这样做:

var tops = $( /* some selector here*/ );

你想要顶级小部件,如果你这样做了:

var next = $(tops[0]).find( /* some selector here*/ );

你想要第二级小部件位于第一级顶级小部件之下,等等。

有一个插件可以执行此操作:

https://github.com/jstnjns/jquery-nearest

我冒昧地在这里张贴代码:

(function() {

  $.fn.nearest = function(selector) {
    var $found = $(),
        checkChildren = function(filter) {
          var $children = this.children()
              $collection = $();

          $children.each(function() {
            var $matches = $(this).filter(filter),
                $fails = $(this).not(filter);

            if($matches.length) { $found = $found.add($matches); }

            if($fails.length) { checkChildren.call($fails, filter); }
          });
        };

    checkChildren.call(this, selector);

    return $found;
  }

}());

你会像这样使用它:

var tops = $(document).nearest(".widget");
var next = $(tops[0]).nearest(".widget");

答案 1 :(得分:0)

使用$(".otherClass > .widget")

>代表&#34;一级儿童&#34;。

答案 2 :(得分:0)

第二个想法可能会认为这是一个解决方案

https://jsfiddle.net/xejtj9gw/

基本上定义了一个函数

function $Flevel(selector,parent)
{
    var sol=$(parent).children(selector);
   return sol;  
}

访问一级儿童。

所以选择器需要

var selector='div.widget';
var s0 = $Flevel(selector,'.otherClass');
var s1 = $Flevel(selector, s0); 
var s21 = $Flevel(selector, s1[0]); 
var s22 = $Flevel(selector, s1[1]);

答案 3 :(得分:0)

您需要使用直接子选择器:

$(".otherClass > .widget")

答案 4 :(得分:0)

您可以使用$('.otherClass').children('.widget'),因为children仅匹配第一级。

这应该比像.otherClass > .widget这样的裸css选择器稍快一些。

答案 5 :(得分:0)

如果您想以您描述的方式进行限制,则需要使用直接后代选择器 jQuery children()。默认情况下,jQuery上下文选择器与find()的行为相同,它将获得所有匹配的子元素:

api.jquery.com docs

  

在内部,选择器上下文是使用.find()方法实现的,所以$(&#34; span&#34;,this)相当于$(this).find(&#34; span&#34;)

因此,要使用集合的索引,您需要执行以下操作:

selector = '.otherClass > .widget';
var s0 = $(selector);
var s1 = $(s0).children('.widget');
var s22 = $(s1[0]).children('.widget');

或将直接后代与nth-child()对象结合使用:

var selector = {};
selector.s0 = '.otherClass > .widget';
selector.s1 = selector + ' > .widget';
selector.s22 = s1 + ':nth-child(0) > .widget';

var s22 = $(selector.s22);

我可能正在使用像前者这样的选择器。这是一个有效的例子:

https://jsfiddle.net/udev4gzv/6/

&#13;
&#13;
selector = '.otherClass > .widget';

var s0 = $(selector); // Matches div#w100 but not inner elements with "widget" class".
var s1 = $(s0).children('.widget'); // Matches div#w110 and div#w120
var s21 = $(s1[0]).children('.widget'); // Matches div#w111 and div#112
var s22 = $(s1[1]).children('.widget'); // Matches div#w121 and div#122

$(document).ready(function(){
    $('#s0').html('s0 matches: ' + s0.map(function() { return this.id; }).get());
    $('#s1').html('s1 matches: ' + s1.map(function() { return this.id; }).get());
    $('#s21').html('s21 matches: ' + s21.map(function() { return this.id; }).get());
    $('#s22').html('s22 matches: ' + s22.map(function() { return this.id; }).get());
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="otherClass">
    <h1>Some title</h1>
    <p>Some text...</p>
    <div class="widget" id="w100">
        <div class="widget" id="w110">
            <h2>Some title</h2>
            <div class="widget" id="w111">
               ...
            </div>
            <div class="widget" id="w112">
                ...
            </div>
        </div>
        <div class="widget" id="w120">
            <h2>Some title</h2>
            <div class="widget" id="w121">
                ...
            </div>
            <div class="widget" id="w122">
                ...
            </div>
        </div>
    </div>
</div>
<br />
<h3>results:</h3>
<div id="s0"></div>
<div id="s1"></div>
<div id="s21"></div>
<div id="s22"></div>
&#13;
&#13;
&#13;