我需要根据存储在元素.data()对象中的值来选择元素。至少,我想使用选择器选择顶级数据属性,可能是这样的:
.data()
$('a').data("category","music"); $('a:data(category=music)');
或者选择器可能是常规属性选择器格式:
$('a[category=music]');
或以属性格式,但带有说明符以指示它位于.data():
$('a[:category=music]');
我发现James Padolsey 的实现看起来很简单,但很好。该页面上显示的镜像方法上方的选择器格式。还有这个Sizzle 补丁。
出于某种原因,我记得不久前读过 jQuery 1.4 将支持对 jquery.data()对象中的值进行选择器。然而,现在我正在寻找它,我找不到它。也许这只是我看到的一个功能请求。是否有对此的支持,我只是没有看到它?
理想情况下,我想使用点符号支持 data() 中的子属性。像这样:
$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"}); $('a[:user.name.first=Tom]');
我还想支持多个数据选择器,其中只找到具有所有指定数据选择器的元素。常规的 jquery 多重选择器执行 OR 操作。例如,$('a.big, a.small')选择带有 class或) 的a标签。我正在寻找一个 AND,也许是这样的:big``small
$('a.big, a.small')
a
big``small
$('a').data("artist",{id: 3281, name: "Madonna"}); $('a').data("category","music"); $('a[:category=music && :artist.name=Madonna]');
最后,如果比较运算符和正则表达式功能可用于数据选择器,那就太好了。所以$(a[:artist.id>5000])才有可能。我意识到我可能可以使用filter().
$(a[:artist.id>5000])
filter()
有哪些解决方案可以做到这一点?詹姆斯的 Padolsey 是目前最好的解决方案吗?我关心的主要是性能,还有额外的特性,比如子属性点表示法和多个数据选择器。是否有其他实现支持这些东西或在某些方面更好?
我创建了一个新的data选择器,它应该使您能够执行嵌套查询和 AND 条件。用法:
data
$('a:data(category==music,artist.name==Madonna)');
模式是:
:data( {namespace} [{operator} {check}] )
“操作员”和“检查”是可选的。所以,如果你只有它,:data(a.b.c)它只会 检查.a.b.c
:data(a.b.c)
a.b.c
您可以在下面的代码中看到可用的运算符。其中包括~=允许正则表达式测试:
~=
$('a:data(category~=^mus..$,artist.name~=^M.+a$)');
我已经用一些变化对其进行了测试,它似乎工作得很好。我可能会很快将其添加为 Github 存储库(带有完整的测试套件),所以请留意!
编码:
(function(){ var matcher = /\s*(?:((?:(?:\\\.|[^.,])+\.?)+)\s*([!~><=]=|[><])\s*("|')?((?:\\\3|.)*?)\3|(.+?))\s*(?:,|$)/g; function resolve(element, data) { data = data.match(/(?:\\\.|[^.])+(?=\.|$)/g); var cur = jQuery.data(element)[data.shift()]; while (cur && data[0]) { cur = cur[data.shift()]; } return cur || undefined; } jQuery.expr[':'].data = function(el, i, match) { matcher.lastIndex = 0; var expr = match[3], m, check, val, allMatch = null, foundMatch = false; while (m = matcher.exec(expr)) { check = m[4]; val = resolve(el, m[1] || m[5]); switch (m[2]) { case '==': foundMatch = val == check; break; case '!=': foundMatch = val != check; break; case '<=': foundMatch = val <= check; break; case '>=': foundMatch = val >= check; break; case '~=': foundMatch = RegExp(check).test(val); break; case '>': foundMatch = val > check; break; case '<': foundMatch = val < check; break; default: if (m[5]) foundMatch = !!val; } allMatch = allMatch === null ? foundMatch : allMatch && foundMatch; } return allMatch; }; }());