Расширяем Sizzle (псевдоселекторы)

Введение


Как известно, Джон Резиг (John Resig) создал абсолютно новый движок селекторов под названием Sizzle(selector[, context]).

Его можно использовать как отдельно от jQuery (всего 4Kb в формате min/gzip), так и вместе с ним.

Наряду с большой производительностью он обладает и хорошей расширяемостью, о которой я и хочу сейчас рассказать.

Псевдо-селекторы



Самый простой случай: напишем псевдо-селектор, который выбирает элементы, у которых свойство visibility = hidden.

Пример написан в предположении, что подключен Sizzle из jQuery.

<script type="text/javascript" src="/jslib/jquery.js"></script>
<div style="visibility:hidden;">test</div>
<script type="text/javascript">
(function(Sizzle)
{
  Sizzle.selectors.filters['vis-hidden'] = function(elem)
  {
    return elem.style.visibility == 'hidden';
  };
  // пробуем использовать.
  var elts = Sizzle(':vis-hidden');
  for (var i = 0; i < elts.length; i++)
  {
    var elt = elts[i];
    elt.innerHTML = 'Caught';
    elt.style.visibility = '';
  }
})(jQuery.find);
</script>
* This source code was highlighted with Source Code Highlighter.

_________
Текст подготовлен в ХабраРедакторе

Используем в jQuery



Селекторы Sizzle, естественно, прекрасно работают в jQuery:

<script src="/jslib/jquery.js"></script>
<div style="visibility:hidden;">test</div>
<script>
(function($)
{
  var Sizzle = $.find;

  Sizzle.selectors.filters['vis-hidden'] = function(elem)
  {
    return elem.style.visibility == 'hidden';
  };

  $(':vis-hidden').html('Caught').css('visibility', '');
})(jQuery);
</script>


* This source code was highlighted with Source Code Highlighter.


Селекторы и фильтры



Создание других вариантов селекторов и фильтров немного сложнее.
+22
7 марта 2009, 14:25
33
akzhan 15,8

комментарии (20)

+1
homm #
Что-то он не очень то быстрый. Он быстрее в новых браузерах, поддерживающих selector api, а в тех, что не поддерживает, он медленнее jQuery 1.2.6.
0
Octane #
В браузерах, поддерживающих Selectors API используется встроенный метод querySelectorAll, и Sizzle тут не играет никакой роли, даже снижает производительность конструкцией:
try {
    return makeArray( context.querySelectorAll(query), extra );
} catch(e){}

Которую пришлось ввести из-за того, что Internet Explorer 8 RC1 выдает сообщение об ошибке, при попытке использовать CSS3-селекторы, только непонятно для чего еще StaticDOMNodeList приводить к Array.
0
Octane #
Немного не так сформулировал :-) перефразирую:
Если поиск идет через Selectors API, используется встроенный метод querySelectorAll, и Sizzle тут не играет никакой роли...

И try {} catch(e) {} еще используется, чтобы в случае нестандартного селектора, продолжить поиск средствами Sizzle, т.е. поддержка браузером Selectors API тоже не будет играть никакой роли.
0
vflash #
при изменении DOM будет перестраиваться DOMNodeList.
0
Octane #
Хм… проверил, querySelectorAll в новых версиях Chrome и Safari стали возвращать просто NodeList, а Opera 10a и IE8RC1 так и возвращают по прежнему «StaticNodeList»
…the collection (being static) will not be updated when the element tree changes.

теперь понятно для чего все к Array приводить, похоже стандартов даже в новейших возможностях нам не увидеть :-)
–1
akzhan #
Последние билды Sizzle неплохи. Быстрее jQ1.2.6 точно :)
0
homm #
Я скачал отсюда и протестировал, там есть папка с тестами. Sizzle точно медленнее в опере 9.64 и ИЕ6 и быстрее в опере 10а. Я думаю не нужно говорить, что появилось в новой опере что заставило работать Sizzle быстрее.
0
Octane #
Когда вы смотрите тесты в Slick Speed, там нет не стандартных селекторов (потому что не все тестируемые библиотеки их поддерживают), все примеры соответствуют синтаксису CSS, а значит в браузерах Opera 10, Safari 3.2, Google Chrome 2, IE8, Firefox 3.1 вы смотрите не производительность движка селекторов Sizzle, YASS, Pappy или еще какого-то, а производительность браузера при работе со стандартным для него методом querySelectorAll, в который при возможности (когда селектор стандартный или соответствует синтаксису CSS2.1, как в IE8RC1) эти библиотеки просто передают параметры напрямую, т.е., если отбросить условия, в простейшем случае это выглядело бы так:
function Sizzle(selector) {
     var result;
     if(document.querySelectorAll) {
         result = document.querySelectorAll(selector);
     }
     else {
        // тут алгоритм поиска для браузеров,
        // не поддерживающих querySelectorAll
     }
     return result;
}
Поэтому не позволяйте себя запутать красивыми диаграмками, иллюстрирующими, как выросла производительность в новых браузерах. Реальную скорость движка можно увидеть только в старых браузер, либо в сравнение не стандартных селекторов, если такие есть в нескольких библиотеках.
0
homm #
Вы мне просто мозг взрываете своим уже третьим комментарием, полным технических подробностей и напрочь лишенных смысла.

> Реальную скорость движка можно увидеть только в старых браузер
Как будто я не тоже самое сказал в одну строчку своим первым комментарием.
0
Octane #
Звените :-) мне показалось, что вы не правильно понимаете, почему возрастает производительность в новых браузерах, и какое к этому отношение имеют библиотеки типа Sizzle.
0
akzhan #
Я проверял не на тестах, а на своём коде.

У меня достаточно специфичный код — например, львиная доля выборок идёт в контексте конкретного элемента, что играет свою роль.
+2
egorinsk #
Что за catched??? Caught может быть?
0
akzhan #
Писалось с бодуна :)
0
akzhan #
поменял на Caught. спасибо :)
–1
aps #
Я что-то не понимаю.
«In addition to the CSS 3 Selectors Sizzle supports the following additional selectors or conventions.
# :contains(TEXT): Finds all elements whose textual context contains the word ‘TEXT’ (case sensitive).
# :header: Finds all elements that are a header element (h1, h2, h3, h4, h5, h6).
# :parent: Finds all elements that contains another element.»

Это однозначно есть в обычном jquery без доп. библиотек. Часть других перечисленных на странице Sizzle тоже есть в самом jquery. Вообще с первого взгляда не нашел что-то радикально нового.

С функциями сложнее, но раздел Filtering тоже показался каким-то странным. У jquery есть родной метод filter. И как-то сложно придумать зачем его нужно наращивать чем-то еще.

0
Sannis #
Это новая ускоренная версия, вот и всё.
habrahabr.ru/blogs/javascript/38036/
0
akzhan #
Sizzle — это новый движок селекторов, который и используется в jQ 1.3.x.

Основное отличие от прошлого — Sizzle более расширяем и может использоваться отдеьно от jQ.

И, кстати, быстрее ветки jQ 1.2.x.
+1
akzhan #
Кстати, разработчики Prototype предполпгпют перейти на Sizzle в следующем мажорном релизе.
0
skorney #
Хотелось уточнить по поводу авторства. Здесь [http://github.com/jeresig/sizzle/tree/master] в файле LICENSE копирайт от J. Resig, а в самом файле (sizzle.js) другая строка «Copyright 2009, The Dojo Foundation»…
0
akzhan #
Джон решил перевести свой проект Sizzle под эгиду Dojo Foundation.

Сейчас он скорее maintainer проекта.

Это позволило использовать Sizzle в Dojo, кроме того, многие другие авторы задумались над встраиванием Sizzle.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.