Sizzle
Когда я рассказывал о Sizzle, то решил вас не грузить возможностями по расширению библиотеки, и вот время настало… В Sizzle можно расширять много чего:
Sizzle.selectors.match
Sizzle.selectors.find
Sizzle.selectors.filter
Sizzle.selectors.attrHandle
Sizzle.selectors.pseudos
Но браться мы будем лишь за расширение псевдо-селекторов, наподобие:
$("div:animated"); // поиск анимированных элементов
$("div:hidden"); // поиск скрытых элементов div
$("div:visible"); // поиск видимых элементов div
Почему я привел только эти фильтры? Всё просто — только они не входят в Sizzle и относятся лишь к jQuery, именно такие плагины мы будем тренироваться разрабатывать. Начнем с кода фильтра «:visible»:
// пример для расширения Sizzle внутри jQuery
// для расширения самого Sizzle нужен чуть-чуть другой код
jQuery.expr.pseudos.visible = function( elem ) {
// проверяем ширину и высоту каждого элемента в выборке
return !!( elem.offsetWidth || elem.offsetHeight);
};
Выглядит данный код несложно, но, пожалуй, я-таки дам каркас для нового фильтра и добавлю чуть-чуть пояснений:
$.extend($.expr.pseudos, {
/**
* @param element DOM-элемент
* @param i порядковый номер элемента
* @param match объект матчинга регулярного выражения
* @param elements массив всех найденных DOM-элементов
*/
test: function(element, i, match, elements) {
/* тут будет наш код, и он будет решать, кто виноват */
return true || false; // выносим вердикт
}
})
Ну, теперь попробуем решить следующую задачку:
— Необходимо выделить ссылку в тексте в зависимости от её типа: внешняя, внутренняя или якорь.
Для решения лучше всего подошли бы фильтры для селекторов следующего вида:
$("a:internal");
$("a:anchor");
$("a:external");
Поскольку «из коробки» данный функционал не доступен, мы напишем его сами. Для этого нам понадобится не так уж и много (пример лишь для последнего «:external», рабочий код на странице sizzle.filter.html):
$.extend($.expr.pseudos, {
// определения внешней ссылки
// нам понадобится лишь DOM-Element
external: function(element) {
// а у нас ссылка?
if (element.tagName.toUpperCase() != 'A') return false;
// есть ли атрибут href
if (element.getAttribute('href')) {
var href = element.getAttribute('href');
// отсекаем ненужное
if ((href.indexOf('/') === 0) // внутренняя ссылка
|| (href.indexOf('#') === 0) // якорь
|| (href.indexOf(window.location.hostname) === 7) // наш домен по http://
|| (href.indexOf(window.location.hostname) === 8) // или https://
) {
return false; // мимо
} else {
return true; // да, мы нашли внешние ссылки
}
} else {
return false;
}
}
});
ВСЕГДА используйте фильтр вместе с HTML-тегом, который ищете:
$("tag:filter")
Это один из пунктов оптимизации работы с фильтрами jQuery, иначе ваш фильтр будет обрабатывать все DOM-элементы на странице, а это может очень сильно сказаться на производительности. Если же у вас несколько тегов, то пишите уж лучше так — «$("tag1:filter, tag2:filter, tag3:filter")», или, ещё лучше, через вызов метода «.filter()».
- Sizzle Documentation — скудненькая официальная документация