Подтвердить что ты не робот

Получение объекта "match" в пользовательском селекторе фильтра в jQuery 1.8

Для справки, здесь статья о Создание настраиваемого селектора фильтров с помощью jQuery.


Введение:

Для тех, кто не знаком с специализированными селекторами фильтров jQuery, здесь приведено краткое описание того, что они собой представляют:

Если вам нужно использовать повторно filter, вы можете расширить селекторные выражения jQuerys, добавив свои собственные функции в объект jQuery.expr[':'].

Функция будет выполняться для каждого элемента текущей коллекции и должна возвращать значение true или false (например, filter). Три бита информации передаются этой функции:

  • Этот элемент

  • Индекс этого элемента среди всей коллекции

  • A match массив, возвращаемый из регулярного выражения соответствия, который содержит важную информацию для более сложных выражений.

Как только вы расширили jQuery.expr[':'], вы можете использовать его как фильтр в селекторе jQuery, подобно тому, как вы использовали бы любой из встроенных (:first, :last, :eq() и т.д.). )


Вот пример, где мы будем фильтровать для элементов, которым присвоено несколько классов:

jQuery.expr[':'].hasMultipleClasses = function(elem, index, match) {
    return elem.className.split(' ').length > 1;
};

$('div:hasMultipleClasses');

Здесь скрипка: http://jsfiddle.net/acTeJ/


В приведенном выше примере мы не использовали массив match, передаваемый нашей функции. Попробуйте более сложный пример. Здесь мы создадим фильтр для соответствия элементам с более высоким tabindex, чем указанное число:

jQuery.expr[':'].tabindexAbove = function(elem, index, match) {
    return +elem.getAttribute('tabindex') > match[3];
};

$('input:tabindexAbove(4)');

Здесь скрипка: http://jsfiddle.net/YCsCm/

Причина этого в том, что массив match является фактическим массивом, возвращаемым из регулярного выражения, которое использовалось для синтаксического анализа селектора. Итак, в нашем примере match будет следующим массивом:

[":tabIndexAbove(4)", "tabIndexAbove", "", "4"]

Как вы можете видеть, мы можем получить значение внутри круглых скобок, используя match[3].


Вопрос:

В jQuery 1.8, массив match больше не передается функции фильтра. Поскольку мы не имеем доступа к передаваемой информации, фильтр tabindexAbove больше не работает (единственная разница между этой скриптой и выше, заключается в том, что это использует более позднюю версию jQuery).

Итак, вот несколько моментов, которые я хотел бы уточнить:

  • Является ли это ожидаемым поведением? Документировано ли оно где-нибудь?

  • Это связано с тем, что Sizzle был обновлен (хотя в нем четко указано, что "старый API для Sizzle был не изменились в этом переписывании". Может быть, это то, что они подразумевают под "устранением ненужного Sizzle.filter" )?

  • Теперь, когда у нас нет доступа к массиву match, есть ли другой способ получить информацию, переданную в фильтр (в нашем случае 4)?

Я никогда не нашел в документах jQuery никакой документации о специальных селекторах фильтров, поэтому я не знаю, с чего начать поиск информации об этом.

4b9b3361

Ответ 1

jQuery добавила утилиту для создания пользовательских псевдосов в Sizzle. Это немного более подробный, но он гораздо читабельнее, чем использование match [3]. Это также имеет преимущество, заключающееся в том, чтобы быть более совершенным, так как вы можете избежать повторения утомительных вычислений каждый раз, когда элемент тестируется. Ответ, который уже был принят, является хорошим ответом, но позвольте мне добавить примечание, чтобы сказать, что вы можете использовать $.expr.createPseudo вместо того, чтобы самостоятельно устанавливать свойство sizzleFilter, что позволит сэкономить немного места.

jQuery.expr[':'].tabIndexAbove = $.expr.createPseudo(function( tabindex ) {
    return function(elem) {
        return +elem.getAttribute('tabindex') > tabindex;
    }
});

$('input:tabIndexAbove(4)').css('background', 'teal');

jsfiddle: http://jsfiddle.net/timmywil/YCsCm/7/

Все это описано в Sizzle github: https://github.com/jquery/sizzle/wiki/Sizzle-Documentation

Ответ 2

Посмотрев на источник jQuery 1.8 beta2 и раздел "Расширяемость" Новый Sizzle, вы должны установить fn.sizzleFilter в true, чтобы получить псевдо-аргумент и контекст. Если нет, вы просто получите все элементы в аргументах.

Вот код, который делает то же, что и ваш пример. Используйте параметр selector, переданный в функции, чтобы получить псевдо-аргумент.

Вот рабочий рабочий пример на jsfiddle.

Как упоминалось выше в блоге, вы даже можете предварительно скомпилировать и кешировать свой селектор.

var sizzle = jQuery.find;

var tabIndexAbove = function( selector, context, isXml ) {
    return function( elem ) {
        return elem.getAttribute("tabindex") > selector;
    };
};

/*
 fn.sizzleFilter is set to true to indicate that tabIndexAbove 
 is a function that will return a function for use by the compiler 
 and should be passed the pseudo argument, the context, and 
 whether or not the current context is xml. If this property is 
 not set, adding pseudos works similar to past versions of Sizzle
*/
tabIndexAbove.sizzleFilter = true;
sizzle.selectors.pseudos.tabIndexAbove = tabIndexAbove;

$('input:tabIndexAbove(4)').css('background', 'teal');

Просто обратите внимание, что если вы смотрите на источник, jQuery слегка изменил структуру, на которую указывает открытый интерфейс.

В jQuery 1.7.2:

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;

В jQuery 1.8b2:

jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.pseudos;