非贪婪的jquery选择器



我试图构建jQuery选择器,以"非贪婪"的方式匹配html元素类"widget",没有任何文档结构的假设。我的意思是:不匹配相同类的内部子元素,也不关心部件元素是否是直接子元素。

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

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

但是这样选择器就不能在小部件内容中再次找到"subwidgets"

例如,给定以下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

我的目标是实现一个简单的可嵌套的小部件系统,该系统基于应用于具有"widget"类的元素的小控制器S和data-xxx属性中的其他参数来选择实际的小部件控制器和参数。但是,小部件必须是ab

我对你的问题的理解与在座的其他人有些不同。在我看来,您想要的是从某个点遍历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");

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

>代表"First-level children"

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

$(".otherClass > .widget")

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

这应该比纯css选择器(如.otherClass > .widget)稍快。

仔细一想,也许这是一个解决方案

https://jsfiddle.net/xejtj9gw/

定义了一个函数

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

访问第一级Children.

所以选择器必须是

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

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

api.jquery.com文档

在内部,选择器上下文是用.find()方法实现的,所以$("span", this)等价于$(this)。查找("span").

所以要使用集合的索引,你要么需要这样做:

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/

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());
});
<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>

最新更新