非贪婪 jquery 选择器
Non-greedy jquery selector
我正在尝试构建 jQuery 选择器以 html 元素与 class "widget" 以 "non-greedy" 方式且没有任何文档结构匹配假设。我的意思是:不匹配具有相同 class 的内部子元素,也不关心小部件元素是否是直接子元素。
我知道的唯一方法也是使用 .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>
假设我要构建的选择器存储在 selector 变量中,我希望这样:
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 属性中的其他参数来选择实际的小部件控制器和参数。但是,小部件必须是
le 在其 html 内容中展开其他子小部件。
使用$(".otherClass > .widget")
.
>
代表"First-level children".
转念一想 可以考虑这是一个解决方案
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]);
您需要使用直接子选择器:
$(".otherClass > .widget")
您可以使用 $('.otherClass').children('.widget')
,因为 children 仅匹配第一级。
这应该比像 .otherClass > .widget
.
这样的裸 css 选择器稍微快一点
如果您想按照您描述的方式进行限制,则需要使用直接后代选择器 或 jQuery children()
。 jQuery 上下文选择器默认情况下与 find()
相同,它将获得所有匹配的子元素:
Internally, selector context is implemented with the .find() method, so $( "span", this ) is equivalent to $( this ).find( "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>
我对你的问题的解释与这里的其他人有所不同。在我看来,您想要的是从某个点遍历 DOM,搜索 .widget
但不在具有 class 的任何元素下方递归。因此,如果您这样做:
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");
我正在尝试构建 jQuery 选择器以 html 元素与 class "widget" 以 "non-greedy" 方式且没有任何文档结构匹配假设。我的意思是:不匹配具有相同 class 的内部子元素,也不关心小部件元素是否是直接子元素。
我知道的唯一方法也是使用 .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>
假设我要构建的选择器存储在 selector 变量中,我希望这样:
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 属性中的其他参数来选择实际的小部件控制器和参数。但是,小部件必须是 le 在其 html 内容中展开其他子小部件。
使用$(".otherClass > .widget")
.
>
代表"First-level children".
转念一想 可以考虑这是一个解决方案
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]);
您需要使用直接子选择器:
$(".otherClass > .widget")
您可以使用 $('.otherClass').children('.widget')
,因为 children 仅匹配第一级。
这应该比像 .otherClass > .widget
.
如果您想按照您描述的方式进行限制,则需要使用直接后代选择器 或 jQuery children()
。 jQuery 上下文选择器默认情况下与 find()
相同,它将获得所有匹配的子元素:
Internally, selector context is implemented with the .find() method, so $( "span", this ) is equivalent to $( this ).find( "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>
我对你的问题的解释与这里的其他人有所不同。在我看来,您想要的是从某个点遍历 DOM,搜索 .widget
但不在具有 class 的任何元素下方递归。因此,如果您这样做:
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");