селектор данных jQuery

Я должен выбрать элементы на основе значений, сохраненных в элементе .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 является лучшим решением в это время? Мое беспокойство, прежде всего, в отношении производительности, но также и в дополнительных функциях как запись через точку подсвойства и несколько селекторов данных. Есть ли другие реализации, которые поддерживают эти вещи или лучше в некотором роде?

183
задан Tauren 23 May 2010 в 00:08
поделиться

2 ответа

Я создал новый селектор данных , который должен позволить вам выполнять вложенные запросы и условия 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;

    };

}());
102
ответ дан 23 November 2019 в 06:00
поделиться

Есть : 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 () , в плагине нет встроенной поддержки для этого, хотя вы можете добавить его без особых проблем.

11
ответ дан 23 November 2019 в 06:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: