Quantcast
Channel: Code-Is-Art »Работа с DOM
Viewing all articles
Browse latest Browse all 5

Быстрый поиск DOM-элементов

$
0
0

js-core dom traversingВ новых браузерах для перемещения по DOM-дереву появилась возможность использовать интерфейс «Element Traversal», который позволяет искать элементы, исключая текстовые узлы так, как это происходит в Internet Explorer, при использовании стандартных firstChild, lastChild, nextSibling и previousSibling, что увеличивает скорость поиска элементов.

В браузерах, поддерживающих «Element Traversal», доступны новые методы:

  • firstElementChild — первый дочерний элементы;
  • lastElementChild — последний дочерний элементы;
  • nextElementSibling — следующий элементы;
  • previousElementSibling — предыдущий элементы;
  • childElementCount — количество дочерних элементов.

Эти методы работают с узлами, у которых 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;
};

Рассмотрим простой пример использования:

XHTML

<div id="test">
    text node
    <div>First</div>
    text node
    <div>Last</div>
    text node
</div>

JavaScript

var node = document.getElementById('test');
var text = firstChild(node).innerHTML;
alert(text); // → First

Аналогично будет выглядет функция 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

Назовем функции поиска следующего и предыдущего элемента «next» и «previous» соответственно:

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;
};

И рассмотрим их работу на простеньком примере:

XHTML

<div>
    text node
    <div id="first">First</div>
    text node
    <div id="last">Last</div>
    text node
</div>

JavaScript

var node = document.getElementById('first');
var text = next(node).innerHTML;
alert(text); // → Last
node = document.getElementById('last');
text = previous(node).innerHTML;
alert(text); // → First

Чтобы получить коллекцию дочерних узлов, среди которых могут содержаться, ненужные нам текстовые узлы, в интерфейсе 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;
};

Ну и конечно рассмотрим работу на примере:

XHTML

<div id="test">
    text node
    <div>First</div>
    text node
    <div>Last</div>
    text node
</div>

JavaScript

var node = document.getElementById('test');
var count = child(node).length;
alert(count); // → 2

Все эти методы, но в более функциональном виде, используются в новых версиях JavaScript фреймворка js-core. А так же, для поиска всех дочерних элементов по имени CSS-класса, атрибутам или просто по имени тега, когда это возможно, используется «Selectors API», что позволяет добиться хороших результатов в тестах на производительность.

Кстати, Microsoft как всегда «радует», в Internet Explorer 8 RC1 синтаксис методов querySelector и querySelectorAll ограничен версией CSS2 :-(

Еще подготовил более симпатичную страничку с примерами использования js-core, на которой можно посмотреть пошаговое выполнение некоторых операций.

В рамках акции «Обмен постовыми»:


Viewing all articles
Browse latest Browse all 5

Latest Images

Trending Articles





Latest Images