В новых браузерах для перемещения по DOM-дереву появилась возможность использовать интерфейс <Element Traversal>, который позволяет искать элементы, исключая текстовые узлы так, как это происходит в Internet Explorer, при использовании стандартных firstChild, lastChild, nextSibling и previousSibling, что увеличивает скорость поиска элементов.
Эти методы работают с узлами, у которых nodeType == 1, например, метод childElementCount показывает не сколько всего дочерних узлов, а количество дочерних элементов, т.е. узлов с nodeType == 1.
Все конечно хорошо и удобно, но нельзя забывать о огромной армии пользователей старых браузеров, поэтому напишем функции, которые позволят кросс-браузерно выполнять поиск дочерних элементов.
Для начала проверим, поддерживает ли браузер интерфейс "Element Traversal"?
var traversal = typeof document.createElement('div').childElementCount != 'undefined';
В итоге переменная traversal будет иметь значение true или false, опираясь на которое мы будем выбирать, какой из способов перемещения по DOM-дереву использовать.
Следующая функция будет искать первый дочерний элемент:
var firstChild = traversal ? function(node) { // для новых браузеров достаточно // воспользоваться встроенным методом return node.firstElementChild; } : function(node) { // для старых браузеров // находим первый дочерний узел node = node.firstChild; // ищем в цикле следующий узел, // пока не встретим элемент с nodeType == 1 while(node && node.nodeType != 1) node = node.nextSibling; // возвращаем результат return node; };
Рассмотрим простой пример использования:
<div id="test">
text node
<div>First</div>
text node
<div>Last</div>
text node
</div>
<script type="text/javascript"><!--
var node = document.getElementById('test');
var text = firstChild(node).innerHTML;
alert(text); // First
//--></script>
Аналогично будет выглядет функция lastChild:
var lastChild = traversal ? function(node) { return node.lastElementChild; } : function(node) { node = node.lastChild; while(node && node.nodeType != 1) node = node.previousSibling; return node; };Используем:
text = lastChild(node).innerHTML; alert(text); // LastНазовем функции поиска следующего и предыдущего элемента
var next = traversal ? function(node) { return node.nextElementSibling; } : function(node) { while(node = node.nextSibling) if(node.nodeType == 1) break; return node; }; var previous = traversal ? function(node) { return node.previousElementSibling; } : function(node) { while(node = node.previousSibling) if(node.nodeType == 1) break; return node; };
И рассмотрим их работу на простеньком примере:
<div> text node <div id="first">First</div> text node <div id="last">Last</div> text node </div> <script type="text/javascript"><!-- var text = next(node).innerHTML; alert(text); // Last node = document.getElementById('last'); text = previous(node).innerHTML; alert(text); // First //--></script>
Чтобы получить коллекцию дочерних узлов, среди которых могут содержаться, ненужные нам текстовые узлы, в интерфейсе DOM предусмотрен метод childNodes, но большинство браузеров поддерживает и более удобный метод children, который возвращает коллекцию, состоящую только из элементов.
Проверим, поддерживает ли браузер метод children?
var children = typeof document.createElement('div').children != 'undefined';
И напишем функцию поиска:
var child = children ? function(node) { return node.children; } : function(node) { var list = node.childNodes, length = list.length, i = -1, array = []; while(++i < length) if(list[i].nodeType == 1) array.push(list[i]); return array; };
Ну и конечно рассмотрим работу на примере:
<div id="test"> text node <div>First</div> text node <div>Last</div> text node </div> <script language=JavaScript><!-- var node = document.getElementById('test'); var count = child(node).length; alert(count); // 2 //--></script>
Все эти методы, но в более функциональном виде, используются в новых версиях JavaScript фреймворка js-core. А так же, для поиска всех дочерних элементов по имени CSS-класса, атрибутам или просто по имени тега, когда это возможно, используется "Selectors API", что позволяет добиться хороших результатов в тестах на производительность.
В Internet Explorer 8 RC1 синтаксис методов querySelector и querySelectorAll ограничен версией CSS2 :-(
© Copyright 2008-2018 by KDG