float,
ну так именно об этом и речь, главное скорость и достоверные результаты. Чем-то приходится жертвовать. Хотя что-то мне подсказывает, что совсем не сильно понизится производительность если в цикле будет 5 дополнительных if, я б даже сказал что практически совсем не понизится, будет регулярка такая TYPE|ID|CLASS|ATTR|PSEUDO|UNMATCHED, все виды простых селекторов могут быть описаны со всей грубостью и жестокостью, а если не один из них не подойдет под критерий, то мы увидим UNMATCHED, и просто смотрим, если этот карман содержит значение, кидаем ошибку. Ну на словах просто, на практике чуть больше проверок будет возможно.. |
poorking,
спасибо, я реально от подобных повисаний писал специально условие. Но как оказалось не дописал. То-есть нужно было еще в одном месте написать условие. Сейчас исправил версию, подправил регу. Дописал условие на проверку гнилых селекторов. |
насчет ковычек хотел сказать. Парсер работает по такому принципу:
допустим есть атрибут [blah*="test"] или такой [blah*='test'] или такой [blah*=test] в этом случае он его разобъет так: blah *= testесли же попадется такой как вы указали: [blah*='test\"] то он разобъет его так: blah *= 'test\"тоесть будет искать подстроку вместе с кавычками в атрибуте. |
Нашел оставленную на память регуляшку. Описание скобок:
( 1 - Запятая или комбинатор слева - ошибка если заполнено)? ( 2 - литерал ИД или КЛАССА (чтобы понимать для кого скобка 3) 3 - значение ИД или КЛАССА ИЛИ (4 - Пространство имен селектора ТИПА)? 5 - Значение селектора типа ИЛИ ( 6 - Пространство имен селектора атрибута )? 7 - имя атрибута (8 - тип сравнения значения аттрибута с переданной строкой 9 или 10 или 11 - значение аттрибута)? ИЛИ 12 - псевдокласс (13 - аргумент псевокласса)? ИЛИ 14 - ошибка ) ( 15 - запятая или комбинатор (если нет его, то далее будет сова прстой селектор) )? var GRINDER = /\s*([,>+~])?\s*(?:([#\.])(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)|(?:(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)?\|)?(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)|\[\s*(?:(-?(?:\\[\s\S]|[a-zA-Z_\u00C0-\uFFFF])(?:\\[\s\S]|[\-\w\u00C0-\uFFFF])*|\*)?\|)?(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)(?:\s*(\S|)=\s*(?:'((?:\\[\s\S]|[^'\n\r\f])*)'|"((?:\\[\s\S]|[^"\n\r\f])*)"|(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)))?\s*\]|:(-?(?:\\[\s\S]|[_a-zA-Z\u0080-\uFFFF])(?:\\[\s\S]|[\w\-\u0080-\uFFFF])*)(?:\(((?:'(?:\\[\s\S]|[^'\n\r\f])*'|"(?:\\[\s\S]|[^"\n\r\f])*"|\((?:\\[\s\S]|[^()])*\)|\\[\s\S]|[^()])*)\))?|([^,>+~\s]+))(?:\s*(?:$|([\s,>+~])\s*))?/g; Если это погонять в цикле, while ( m = GRINDER.exec(selectror) ) то из var selector = " NS|TYPE#ID.CLASS + :PSEUDO(ARG)[NS|ATTR='VAL'] " можно собрать что-то типа [ [ ["TYPE", "NS"], ["ID"], ["CLASS"] ], [ ["PSEUDO", "ARG"], ["ATTR", "=", "VAL", "NS"] ] ] Каждую итерацию по номеру заполненных скобок мы можем узнавать какого типа простой селектор и сразу брать его, уже разобранного на части. Когда появлялся m[15], я по содержимому, определял что будет дальше, следующая последовательность (комбинатор + последовательность простых) или вообще следующий одиночный селектор (если там запятая) Чтобы понимать в коде выборок к какому типу простого селектора относятся эти распарсенные куски, можно определить константы для разных типов и записывать значения например свойством массива (в котором кусочки простого селектора). Так же для оберток этих простых селекторов (последовательностей простых селекторов) и комбинаторов. Потом можно будет эти sequense сортировать, чтобы применять в том порядке в каком лучше. Ну это я так думаю, регулярное выражение писал давно, мне лень тестировать его производительность, но теоретически оно не шибко шустрое, 15 скобок, хотя я не исследовал производительность регекспов. За парсер, код которого к сожалению не сохранился, могу только одно сказать, что синтаксис селекторов полностью соответствовал спецификации и нельзя было передать не правильный селектор, 100% было бы SyntaxError |
Цитата:
|
а что начет таких селекторов?
NS|TYPE#ID.CLASS + :PSEUDO(ARG)[NS|ATTR='VAL'][NS|ATTR='VAL'][NS|ATTR='VAL'] несколько атрибутов подряд |
все будет ок, за одну итерацию находит один простой селектор
|
Цитата:
a[href=blah][rel=test]то есть найти элемент А с трибутом href который содержит blah и атрибутом rel который содержит test |
О раз уж ты в теме селекторов сейчас, можешь сказать достаточно ли такой регулярки, чтобы убрать ненужные слэши?
<prefix:tag-name class="class\name"> alert("prefix\\:tag-name.class\\\\name".replace(/\\([^\w\s])/g, "$1")) все что внутри кавычек в значениях атрибутов предварительно через escape заменено. |
Цитата:
|
Да, это можно определить и собирать распарсенные простые селекторы в кучки - последовательности, я сейчас шустро пишу примерно то , что раньше оборачивало эту регулярку и сразу ясно станет
|
Цитата:
a:not([href*=test]).test |
я убираю такой
string.replace(/\\([\s\S])/g, "$1"); |
Цитата:
prefix\:tag-name.class\\name {…} а второй слэш появляется из-за экранирования в JavaScript-строке |
Цитата:
prefix|tag-name.class\name |
Цитата:
alert(document.querySelectorAll("a:not([href*=test]).test")); Нативный qsa ест, значит так можно ) |
Цитата:
|
var hasQSA = (function() { var div = document.createElement('div'); div.innerHTML = "<p class='TEST'></p>"; if (!div.querySelectorAll || div.querySelectorAll(".TEST")|0) return 0; div = null; return 1; })(); alert(hasQSA); |
monolithed, а почему не прокатывает простая проверка наличия этого свойства в документе* ?
var hasQSA = "querySelector" in document; * при условии, что это свойство не добавили для "заглушки". |
melky,
Из Sizzle // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } |
Цитата:
На MDN нашёл баг на Safari, это он и есть ? Если она не поддерживает символы в верхнем регисте в режиме совместимости, почему бы не перевести строку селектора к нижнему регистру? .TEST или .test, в html разницы быть не должно. ЗЫ Если вам показалось, что я доказываю свою правоту, то это не так. (после марума может так казаться :)) Я хочу разобраться и понять. Цитата:
|
Цитата:
|
Цитата:
http://www.w3.org/TR/selectors/#casesens Возможно в этом, хотя я задумался и почти уже не знаю даже ASCII включает национальный алфавит, так что, выходит вы правы с мыслью о том, что можно привести селектор к нижнему регистру, надо потестить |
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
var hasQSA = (function() { var div = document.createElement('div'); div.innerHTML = "<p class='TEST'></p>"; if (!div.querySelectorAll || div.querySelectorAll(".TEST")|0) return 0; *!* div = null; */!* return 1; })(); alert(hasQSA); |
Цитата:
|
во время работы с селектором, обнаружил ошибку:
не искал по селекторам если они содержали слеш "\" Качаем новую версию, в первом топике. так же залил на github |
Цитата:
Если рассматривать эту библиотеку в качестве примера, то можно было-бы убрать контекст из второго аргумента. |
FINoM,
htc файлик подключи, там вешай сразу но ноде это свойство. Ещё document.createElement заменить надо, что бы перед возвращением вставляло ноду в документ. |
Цитата:
|
Цитата:
|
Понятно. А querySelectorAll и querySelector применяются на не вставленные в dom элементы?
|
Цитата:
|
добавил на гитхаб HTC файлы, если кому надо качайте.
|
Цитата:
|
Цитата:
|
Круть
|
ну а подключать примерно так:
<!--[if lt IE 9]> <style type="text/css"> * { behavior: url('qsa.min.htc'); } </style> <![endif]--> В ИЕ версии 8 расширяет встроенные селекторы до поддержки CSS3 селекторов. - |
Часовой пояс GMT +3, время: 07:51. |