Выборка DOM-элементов по имени класса || getElementsByClassName
Привет, привет, привет друзья!
Сегодня мы углубимся в тему получения DOM-элементов посредством выборки их из документа по нужному имени класса!
Так что пристегните ремни, полёт будет увлекательным
1. Самый простейший логический вариант – это применение встроенной функции getElementsByClassName:
1000 итераций данной функции в FireFox занимают примерно 13 миллисекунд.
Но вот не задача, этот метод не входит в спецификацию DOM level 2 ![]()
Но на данный момент ряд браузеров поддерживают этот метод, значит мы можем его применять!
2. Второй старинный метод – перебор все DOM-елементов документа и проверка на нужный класс. Эта функция выглядит примерно так:
// Если имя класса не передано - обрываем выполнение
if( !className )
return [];
var
// node - родитель - место поиска елементов
// Если node не передан, то им становится document
node = node || document,
// Берём все DOM-элементы узла
elements = node.getElementsByTagName( '*' ),
list = [],
expr = new RegExp( '(^|\\b)' + className + '(\\b|$)' );
if( elements.length == 0 )
return elements;
for( var i = 0, length = elements.length; i < length; i++ )
if( expr.test( elements[ i ].className ) )
list[ list.length ] = elements[ i ];
return list;
};
/*
** Пример использования
*/
var bull = getElementsByClassName( 'bull' );
alert( 'Буллитов используется в документе: ' + bull.length );
Конечно эта функция требует значительного времени исполнения.
1000 итераций данной функции в FireFox занимают примерно 400 миллисекунд.
3. Третий вариант – использование XPath.
Не буду сильно углубятся в теорию, небольшой обзор XPath вы можете увидеть здесь: http://www.quizful.net/post/xpath-in-javascript
Приведу пример моей функции выборки элементов с помощью XPath:
if( !className )
return [];
var
// node - родитель - место поиска елементов
// Если node не передан, то им становится document
node = node || document,
// Берём все DOM-элементы узла с помощью XPath
elements = document.evaluate(
// XPath селектор
"//*[contains(concat(' ',normalize-space(@class),' '),' " + className + " ')]",
node,
null,
XPathResult.ANY_TYPE,
null
),
list = [],
element = elements.iterateNext();
while( element ){
list[ list.length ] = element;
element = elements.iterateNext();
};
return list;
};
// Пример использования
var bull = getElementsByClassName( 'bull' );
alert( 'Буллитов используется в документе: ' + bull.length );
1000 итераций данной функции в FireFox занимают примерно 600 миллисекунд.
Это слишком долгий метод для нас и мы вынуждены от него отказаться в пользу второго самописного метода.
4. querySelectorAll – метод W3C CSS API Selectors. На данный момент приличное число браузеров поддерживают его. Метод принимает в качестве аргумента строку – CSS селектор и производит по нему выборку элементов. Очень быстрый метод! ![]()
Вот пример моей функции:
return !className && []
|| ( node || document ).querySelectorAll( '.' + className );
};
// Пример использования
var bull = getElementsByClassName( 'bull' );
alert( 'Буллитов используется в документе: ' + bull.length );
1000 итераций данной функции в FireFox занимают примерно 80 миллисекунд
Итак! На данный момент у нас есть 3 варианта получения элементов. Расположим их по скорости выполнения:
- Встроенный метод getElementsByClassName
- Метод W3C CSS API Selectors – querySelectorAll
- Самописная функция getElementsByClassName
Вариант с XPath мы отбрасываем, так как использование его не выгодно!
Такс, давайте теперь составим идеальную функцию, перебирающую возможные три варианта поиска и использующую оптимальный вариант:
* jvlGetClass - JavaScript-функция для выборки DOM-узлов по имени класса
* Версия 0.2
*
* Copyright (c) 2010 Александр Кузнецов aka Regent(http://vl.vg/)
* Подробности: http://vl.vg/18.01.2010/get-elements-by-class-name/
* Дата создания: 18.01.2010
*/
var getElementsByClassName = (
function(){
var d = window.document;
if( typeof d.getElementsByClassName == 'function' )
return function( className, node ){
return ( node || d ).getElementsByClassName( className );
};
else if( typeof d.querySelectorAll == 'function' )
return function( className, node ){
return ( node || d ).querySelectorAll( '.' + className );
};
else
return function( className, node ){
if( !className )
return [];
var
// node - родитель - место поиска елементов
// Если node не передан, то им становится document
// Берём все DOM-элементы узла
elements = ( node || document ).getElementsByTagName( '*' ),
list = [],
expr = new RegExp( '(^|\\b)' + className + '(\\b|$)' );
if( elements.length == 0 )
return elements;
for( var i = 0, length = elements.length; i < length; i++ )
if( expr.test( elements[ i ].className ) )
list[ list.length ] = elements[ i ];
return list;
};
}
)();
И в качестве подарка получите компактный минимизированный вариант
* jvlGetClass - JavaScript-функция для выборки DOM-узлов по имени класса
* Версия 0.2
*
* Copyright (c) 2010 Александр Кузнецов aka Regent(http://vl.vg/)
* Подробности: http://vl.vg/18.01.2010/get-elements-by-class-name/
* Дата создания: 18.01.2010
*/
var getElementsByClassName=(function(){var a=window.document;if(typeof a.getElementsByClassName=="function"){return function(b,c){return(c||a).getElementsByClassName(b)}}else{if(typeof a.querySelectorAll=="function"){return function(b,c){return(c||a).querySelectorAll("."+b)}}else{return function(c,e){if(!c){return[]}var e=e||document,g=e.getElementsByTagName("*"),f=[],h=new RegExp("(^|\\b)"+c+"(\\b|$)");if(g.length==0){return g}for(var b=0,d=g.length;b<d;b++){if(h.test(g[b].className)){f[f.length]=g[b]}}return f}}}})();
Спасибо! С уважением, Regent!
Либо скачать новый нормальный браузер
Комментарии(6)
getElementsByClassName использует самый минималистический поиск по запросам.
querySelectorAll - это уже CSS движок, можно сказать. Пока селектор разберётся, пока все фильтры пройдёт и т. д.
Это как бы размышление на тему )
P.S. Теги BB-кодов всегда вставляются в конце текста, не зависимо от положения фокуса и зоне выделения (((
В том то и дело, что querySelectorAll работает по своему алгоритму, если в него передать даже просто #id
Для простых селекторов я бы использовал то что уже есть, а для остальных то что они используют.