Продовжуємо заумні статті про jQuery, сьогодні розкажу про движку Sizzle та можливості його розширення.

Матеріали даної статті включені в підручник «jQuery для початківців». Підручник розповсюджується безкоштовно, і супроводжується інтерактивними прикладами.

Sizzle — движок Javascript для пошуку елементів по CSS селектору, був нерозлучний з jQuery, але з деяких пір так само поширюється як окрема бібліотека, і може використовуватися в тому ж Dojo Toolkit, або в вашому власному фреймворку

API для розширення фільтрів

Для початку наведу приклад фільтрів, які ви використовували, та не заглядали всередину:

$(“div:animated”); // пошук анімованих елементів
$(“div:hidden”); // пошук прихованих елементів div
$(“div:visible”); // пошук видимих елементів div (протилежний попередньому)

Чому я навів тільки ці фільтри? Все просто — вони не входять у Sizzle, і відносяться лише до jQuery, саме такі плагіни ми будемо тренуватися розробляти. Почнемо з коду, який нам допоможе розібратися з API:

(function($, window, undefined){
$.extend($.expr[‘:’], {
/**
* @param element DOM елемент
* @param i порядковий номер елемента
* @param match об’єкт матчинга регулярного виразу (шукайте PSEUDO в сорцах)
* @param масив elements всіх знайдених елементів DOM
*/
test: function(element, i, match, elements) {
return true; // елемент підходить нам
return false; // чи ні
}
})
})(jQuery, window);

Наведений код звичайно не дуже наочний, тому розширю його робочими прикладами:

test: function(element, i, match, elements) {
// ми можемо створювати перевірки на основі правил, які відносяться до елементу DOM
// нам потрібні лише параграфи – $(“p:test”)
if (element.tagName.toUpperCase() != ‘P’) return false;
// шукаємо по порядковому номеру
// $(“p:test(4)”)
if (parseInt(match[3]) == (i+1)) {
return true;
} else
// чет / непарне число
// $(“p:test(even)”) або(“p:test(odd)”)
if (match[3] == “even” && (i%2==0)) {
return true;
} else if (match[3] == “odd” && (i%2==1)) {
return true;
} else
// перший/останній
// $(“p:test(first)”) або(“p:test(last)”)
if (match[3] == “first” && (i==0)) {
return true;
} else if (match[3] == “last” && (i==(elements.length-1))) {
return true;
}
return false;
}

Приклади використання:

$(“p:test”);
$(“p:test(2)”);
// чет/непарне число
$(“p:test(odd)”);
$(“p:test(even)”);
// перший/останній
$(“p:test(first)”);
$(“p:test(last)”);

Ось таким не хитрим способом можна розширювати фільтри, якщо у вас є ще приклади можливих плагінів, прошу — коментуйте.

Приклад plugin а

Ну від тривіальних абстрактних завдань до чогось більш конкретного — є складна задачка: «виділити посилання в тексті залежно від типу: зовнішня, внутрішня, якір», ну і приклад тексту:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut lacinia quam
nec enim scelerisque porta. In ut lorem ipsum. Proin iaculis viverra rutrum. Maecenas quis
ante enim. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
Curae; Vestibulum luctus tristique feugiat. Morbi dictum est dolor,
at condimentum nisl. Ut id nunc augue, at luctus
enim. Phasellus urna nunc, aliquam sit amet rutrum ac, imperdiet in nunc. Cras mattis massa
et est sodales ac auctor mi sagittis. Fusce elementum ultrices nunc, eu scelerisque massa
sodales quis. Aliquam bibendum accumsan nibh ut blandit.

Praesent venenatis dictum ante, …

Aliquam erat volutpat. … Curabitur congue enim … Duis lectus tellus, gravida non commodo eu, dictum a tellus. Praesent a nibh vel nisl sodales tincidunt at ac leo.

Для вирішення найкраще підійшли б фільтри для селекторів:

$(“a:internal”);
$(“a:anchor”);
$(“a:external”);

Оскільки з коробки даний функціонал доступний, ми напишемо його самі, для цього нам знадобиться не так вже й багато:

$.extend($.expr[‘:’], {
/**
* Приклад визначення зовнішньої посилання
* інші фільтри знайдете на сторінці прикладів
*
* @param element нам знадобиться лише DOM Element
*/
external: function(element) {
// у посилання?
if (element.tagName.toUpperCase() != ‘A’) return false;
// є атрибут href
if (element.getAttribute(‘href’)) {
// відсікаємо непотрібне
if ((element.getAttribute(‘href’).indexOf(‘/’) === 0) // внутрішня посилання
|| (element.getAttribute(‘href’).indexOf(‘#’) === 0) // якір
|| (element.getAttribute(‘href’).indexOf(window.location.hostname) === 7) // наш домен http://…
|| (element.getAttribute(‘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”)

Матеріали

Тут все сумно — знайшов лише мізерну офіційну документацію, якщо є чим поділитись, ну ви зрозуміли…

Цикл статей

  • jQuery для початківців
  • jQuery для початківців. Частина 2. JavaScript Меню
  • jQuery для початківців. Частина 3. AJAX
  • jQuery для початківців. Частина 4. Селектори
  • jQuery для початківців. Частина 5. Ефекти
  • jQuery для початківців. Частина 6. Події
  • jQuery для початківців. Частина 7. Пишемо плагіни
  • jQuery для початківців. Частина 8. Розширюємо фільтри
  • jQuery для початківців. Частина 9. Пишемо плагіни анімації