Я должен выбрать элементы на основе значений, сохраненных в элементе .data()
объект. Как минимум я хотел бы выбрать свойства данных верхнего уровня с помощью селекторов, возможно, как это:
$('a').data("category","music");
$('a:data(category=music)');
Или возможно селектор был бы в регулярном формате селектора атрибута:
$('a[category=music]');
Или в формате атрибута, но со спецификатором для указания на это находится в .data()
:
$('a[:category=music]');
Я нашел, что реализация James Padolsey выглядит простой, все же хорошей. Селекторные форматы выше зеркальных методов, показанных на той странице. Существует также этот патч Шипения.
По некоторым причинам я вспоминаю чтение некоторое время назад, что jQuery 1.4 включал бы поддержку селекторов на значениях в jQuery .data()
объект. Однако теперь, когда я ищу его, я не могу найти его. Возможно, это был просто запрос новых функций, который я видел. Есть ли поддержка этого, и я просто не вижу его?
Идеально, я хотел бы поддерживать подсвойства в данных () использующий запись через точку. Как это:
$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');
Я также хотел бы поддерживать несколько селекторов данных, где только элементы со ВСЕМИ указанными селекторами данных найдены. Обычный jQuery несколько селектор делает ИЛИ операция. Например, $('a.big, a.small')
выбирает a
теги с любым классом big
или small
). Я ищу И, возможно, как это:
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
Наконец, было бы замечательно, если бы операторы сравнения и regex функции были доступны на селекторах данных. Так $(a[:artist.id>5000])
было бы возможно. Я понимаю, что мог, вероятно, сделать большую часть этого использования filter()
, но было бы хорошо иметь простой селекторный формат.
Какие решения доступны, чтобы сделать это? Действительно ли Padolsey Jame является лучшим решением в это время? Мое беспокойство, прежде всего, в отношении производительности, но также и в дополнительных функциях как запись через точку подсвойства и несколько селекторов данных. Есть ли другие реализации, которые поддерживают эти вещи или лучше в некотором роде?
Я создал новый селектор данных
, который должен позволить вам выполнять вложенные запросы и условия AND. Использование:
$('a:data(category==music,artist.name==Madonna)');
Шаблон:
:data( {namespace} [{operator} {check}] )
«оператор» и «проверка» необязательны. Итак, если у вас есть только : 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;
};
}());
Есть : data ()
плагин фильтра , который делает именно это:)
Некоторые примеры, основанные на вашем вопросе:
$('a:data("category=music")')
$('a:data("user.name.first=Tom")');
$('a:data("category=music"):data("artist.name=Madonna")');
//jQuery supports multiple of any selector to restrict further,
//just chain with no space in-between for this effect
Производительность не соответствует Это будет чрезвычайно здорово по сравнению с тем, что возможно , выбор из $ ._ cache
и захват соответствующих элементов, безусловно, самый быстрый, но гораздо более обходной и не очень » jQuery-ey "с точки зрения того, как вы работаете (обычно вы входите со стороны элемента). В общем, я не уверен, что это самый быстрый способ, поскольку процесс перехода от уникального идентификатора к элементу запутан сам по себе с точки зрения производительности.
Селектор сравнения, который вы упомянули, лучше всего использовать в .filter ()
, в плагине нет встроенной поддержки для этого, хотя вы можете добавить его без особых проблем.