Обход всех элементов DOM


Содержание

»» В данной статье используется исходный код для примеров. Сохраните эту страницу для тестирования приведенных ниже примеров.

Выбранный набор элементов можно использовать в качестве отправной точки для перемещения к другим узлам DOM-дерева. При этом, по сути, один набор элементов используется для создания другого набора. Описанию и демонстрации применения методов jQuery, предназначенных для обхода структуры DOM, посвящены следующие разделы. В них рассматриваются различные типы отношений, которые могут существовать между содержащимися в документе элементами.

Каждый из описанных в последующих разделах методов возвращает объект jQuery. Этот объект может как содержать подходящие объекты, если таковые имеются, так и быть пустым в случае их отсутствия (свойство length таких объектов возвращает нулевое значение).

Перемещение вниз по дереву DOM

Процесс перемещения вниз по иерархической структуре DOM связан с выбором дочерних элементов (непосредственных потомков), а также всех остальных элементов, являющихся потомками элементов, содержащихся в объекте jQuery. Соответствующие методы jQuery и их краткое описание приведены в таблице ниже:

Методы, используемые для перемещения вниз по иерархической структуре DOM

Метод Описание
children() Выбирает дочерние элементы всех элементов, содержащихся в объекте jQuery
children(селектор) Выбирает все элементы, которые соответствуют указанному селектору и при этом являются непосредственными потомками элементов, содержащихся в объекте jQuery
contents() Возвращает дочерние элементы и текстовое содержимое всех элементов, содержащихся в объекте jQuery
find() Выбирает потомки элементов, содержащихся в объекте jQuery
find(селектор) Выбирает элементы, которые соответствуют указанному селектору и при этом являются потомками элементов, содержащихся в объекте jQuery
find(jQuery), find(HTMLElement),
find(HTMLElement[])
Выбирает пересечение множества непосредственных потомков элементов, содержащихся в объекте jQuery, и множества элементов, содержащихся в объекте аргумента

Метод children() выбирает лишь те элементы, которые являются непосредственными потомками (дочерними элементами) элементов, содержащихся в объекте jQuery, и может принимать селектор в качестве необязательного аргумента, обеспечивающего дополнительную фильтрацию элементов. Метод find() предназначен для выбора всех потомков, а не только дочерних элементов. Метод contents() наряду с дочерними элементами возвращает также текстовое содержимое.

Пример использования методов children() и find() приведен ниже:

В этом примере метод children() используется без селектора, тогда как метод find() используется с одним селектором. Подробная информация о выбранных элементах выводится на консоль вместе с указанием их количества:

Среди приятных особенностей методов children() и find() можно отметить отсутствие дублирования элементов в выбранном наборе. Это подтверждает пример, приведенный ниже:

В этом примере мы начинаем с того, что создаем объект jQuery, который содержит все элементы div с классом drow и все элементы div с классом dcell. Ключевым моментом здесь является то, что все элементы, принадлежащие классу dcell, одновременно являются элементами класса drow. Это означает, что мы имеем дело с двумя перекрывающимися множествами элементов-потомков, и в случае использования метода find() с селектором img это могло бы привести к дублированию элементов в результирующем наборе, поскольку элементы img являются потомками элементов div обоих классов. Однако jQuery выручает нас и самостоятельно заботится о том, чтобы среди возвращаемых элементов дублирование отсутствовало, что подтверждается результатами, выводимыми на консоль:

Перемещение вверх по дереву DOM

Перемещению вверх по DOM-дереву соответствует поиск родителей и предков элементов, содержащихся в объекте jQuery. Методы, используемые для таких перемещений, приведены в таблице ниже:

Методы, используемые для перемещения вверх по иерархической структуре DOM

Описание Метод
closest(селектор), closest(селектор, контекст) Выбор ближайшего предка, соответствующего указанному селектору, для каждого элемента, содержащегося в объекте jQuery
closest(jQuery), closest(HTMLElement) Выбор ближайшего предка для каждого элемента в объекте jQuery, совпадающего с одним из элементов, содержащихся в объекте аргумента
offsetParent() Нахождение ближайшего предка, значением CSS-свойства position которого является fixed, absolute или relative
parent(), parent(селектор) Выбор непосредственных предков для каждого элемента в объекте jQuery с возможностью их фильтрации с помощью селектора
parents(), parents(селектор) Выбор предков для каждого элемента в объекте jQuery с возможностью их фильтрации с помощью селектора
parentsUntil(селектор), parentsUntil(селектор, селектор) Выбор предков для каждого элемента в объекте jQuery до тех пор, пока не встретится элемент, соответствующий селектору. Результаты могут фильтроваться посредством второго селектора
parentsUntil(HTMLElement), parentsUntil(HTMLElement, селектор), parentsUntil(HTMLElement[]), parentsUntil(HTMLElement[], селектор) Выбирает предков для каждого элемента в объекте jQuery до тех пор, пока не встретится один из указанных элементов. Результаты могут фильтроваться посредством второго селектора

Выбор родительских элементов

Метод parent() позволяет выбрать родительский элемент для каждого из элементов, содержащихся в объекте jQuery. Если методу предоставляется селектор, то в результирующий набор будут включаться только те родительские элементы, которые соответствуют селектору. Пример использования метода parent() приведен ниже:

В этом сценарии сначала выбираются все элементы div, принадлежащие классу dcell, а затем вызывается метод parent(), выбирающий все родительские элементы. Здесь также демонстрируется использование метода parent() с селектором. Подробная информация о каждом выбранном родительском элементе выводится на консоль с использованием метода each:

Выбор предков

Метод parents() (обратите внимание на последнюю букву s в его названии) обеспечивает возможность выбора всех, а не только непосредственных предков (родителей) элементов, содержащихся в объекте jQuery. Как и в предыдущем случае, метод может принимать в качестве аргумента селектор для фильтрации результатов.

Пример использования метода parents() приведен ниже:

В этом примере метод parents() используется для выбора предков двух предварительно выбранных элементов img. Информация о каждом предке выводится на консоль:

Метод parentsUntil() является еще одной разновидностью методов, предназначенных для выбора предков элементов. Для каждого из элементов, содержащихся в объекте jQuery, метод parentsUntil() осуществляет перемещение вверх по иерархической структуре DOM, выбирая элементы-предки до тех пор, пока не встретится элемент, соответствующий селектору. Пример использования этого метода приведен ниже:

В этом примере процесс выбора предков для каждого элемента продолжается до тех пор, пока не встретится элемент form. На консоль выводится следующий результат:

Обратите внимание, что элементы, соответствующие селектору, исключаются из состава выбираемых предков. В данном случае это означает исключение элемента form. Набор предков можно подвергнуть дополнительной фильтрации, предоставив методу paraentsUntil() селектор в качестве второго аргумента, как показано в примере ниже:

В этом примере добавлен селектор, который фильтрует элементы, принадлежащие классу dcell. На консоль выводится следующий результат:

Выбор первого подходящего предка

Метод closest() позволяет выбирать первого из предков, соответствующих селектору, для каждого элемента в объекте jQuery. Пример использования этого метода приведен ниже:

В этом примере мы сначала выбираем элементы img в документе, а затем находим для каждого из них с помощью метода closest() ближайшего предка, который принадлежит классу drow.

Область выбора предков можно сузить, передав методу closest() объект HTMLElement() в качестве второго аргумента. Те предки, которые не являются контекстным объектом или его потомками, не включаются в выбранный набор. На консоль выводится следующий результат:

Методу closest() также можно передать в качестве аргумента объект jQuery, объект HTMLElement или массив объектов HTMLElement. В этом случае метод closest() будет продолжать процесс выбора предков для каждого из элементов, содержащихся в исходном объекте jQuery, до тех пор пока не встретится объект, переданный в качестве аргумента.

Метод offsetParent() представляет собой вариацию на тему метода closest() и предназначен для нахождения первого потомка, значение CSS-свойства position которого равно relative, absolute или fixed. Такие элементы называются , и их поиск может оказаться полезным при работе с анимацией. Пример использования этого метода приведен ниже:

В этой версии документа сначала с помощью CSS устанавливается значение свойства position элементов с атрибутом id равным row1 и row2. Далее в документе выбирается один из элементов img и с помощью метода offsetParent() находится ближайший позиционированный потомок выбранного элемента. После этого с помощью метода css() для свойства background-color выбранного элемента устанавливается значение lightgrey. Вид результирующей страницы в окне браузера представлен на рисунке:

Перемещение по дереву DOM в пределах одного иерархического уровня

Последняя разновидность перемещений по DOM-дереву, которую нам осталось рассмотреть, — это перемещение между узлами одного и того же уровня иерархии (между сестринскими узлами). Краткое описание предназначенных для этого методов jQuery приведено в таблице ниже:

Методы, используемые для перемещения между узлами DOM-дерева в пределах одного иерархического уровня

Метод Описание
next(), next(селектор) Выбирает сестринские элементы, непосредственно следующие за каждым из элементов, содержащихся в объекте jQuery. Имеется дополнительная возможность фильтрации результатов с использованием селектора
nextAll(), nextAll(селектор) Выбирает все последующие сестринские элементы для каждого из элементов, содержащихся в объекте jQuery. Имеется дополнительная возможность фильтрации результатов с использованием селектора
nextUntil(селектор), nextUntil(селектор, селектор), nextUntil(jQuery), nextUntil(jQuery, селектор), nextUntil(HTMLElement[]), nextUntil(HTMLElement[], селектор) Выбирает для каждого элемента последующие сестринские элементы вплоть до элемента (но не включая его), соответствующего селектору или содержащегося в объекте jQuery или массиве HTMLElement[]. Имеется дополнительная возможность фильтрации результатов с использованием селектора
prev(), prev(селектор) Выбирает сестринские элементы, непосредственно предшествующие каждому из элементов, содержащихся в объекте jQuery. Имеется дополнительная возможность фильтрации результатов с использованием селектора
prevAll(), prevAll(селектор) Выбирает все предшествующие сестринские элементы для каждого из элементов, содержащихся в объекте jQuery. Имеется дополнительная возможность фильтрации результатов с использованием селектора, передаваемого методу в качестве второго аргумента
prevUntil(селектор), prevUntil(селектор, селектор), prevUntil(jQuery), prevUntil(jQuery, селектор), prevUntil(HTMLElement[]), prevUntil(HTMLElement[], селектор) Выбирает для каждого элемента предшествующие сестринские элементы вплоть до элемента (но не включая его), соответствующего селектору или содержащегося в объекте jQuery или массиве HTMLElement[]. Имеется дополнительная возможность фильтрации результатов с использованием селектора, передаваемого методу в качестве второго аргумента
siblings(), siblings(селектор) Выбирает все сестринские элементы для каждого из элементов, содержащихся в объекте jQuery. Имеется дополнительная возможность фильтрации результатов с использованием селектора

Выбор всех сестринских элементов

Метод siblings() обеспечивает возможность выбора всех сестринских элементов для всех элементов, содержащихся в объекте jQuery. Пример использования этого метода приведен ниже:

В этом примере мы сначала выбираем два элемента img, затем находим их родительские элементы с помощью метода parent(), после чего выбираем сестринские элементы последних с помощью метода siblings(). При этом выбираются как предшествующие, так и последующие сестринские элементы и для свойства border каждого из них устанавливается определенное значение с помощью метода css(). Вид результирующей страницы в окне браузера представлен на рисунке:

Обратите внимание: выбираются лишь сестринские элементы, но не сами элементы. Разумеется, эта ситуация изменится, если один из элементов, содержащихся в объекте jQuery, является сестринским по отношению к другому, как показано в примере ниже:

В этом сценарии мы начинаем с выбора всех элементов div, являющихся дочерними по отношению к элементу rowl, а затем вызываем метод siblings(). Каждый из элементов в выбранном наборе является сестринским в отношении по крайней мере одного из других элементов, как показано на рисунке:

Выбор последующих и предшествующих сестринских элементов

Я не собираюсь подробно останавливаться на каждом из методов, предназначенных для выбора предшествующих и последующих сестринских элементов, поскольку все они работают аналогично любому другому методу, обеспечивающему перемещение между узлами DOM-дерева. Пример использования методов nextAll() и prevAll() приведен ниже:

В этом сценарии для родительского элемента изображения астры выбираются все последующие сестринские элементы, а для родительского элемента изображения примулы — все предыдущие сестринские элементы. Результат работы сценария представлен на рисунке:

обход дерева DOM

09.07.2012, 17:55

HTML DOM как с использованием Javascript создать узлы DOM
Доброго времени суток. хочу через Javascript по событию onclick добавить в html документ что то.

Написать скрипт, рекурсивно обходящий дерево DOM страницы dom.html, начиная от корня DOM
Написать скрипт на языке JavaScript, рекурсивно обходящий дерево DOM страницы dom.html, начиная от.

Обход дерева в глубину
Доброго времени суток. Ребята, подскажите, плиз, что я делаю не так. Есть дерево, неглубокое и.

Обход DOM дерева JavaScript
Добрый день, уважаемые. Есть сайт, на нем размещено n-ное количество DIV’ов (

Визуализация структуры DOM-дерева
Уважаемые знатоки подскажите решение по данному вопросу, нужно визуализировать DOM-дерева. Как.

Обход всех элементов DOM

Форум Приднестровской поддержки CMS XOOPS.

По ссылке вы можете скачать последнюю версию CMS XOOPS. А так же прочитать инструкции по установке XOOPS и модулей

По данным ссылкам можно скачать модули нашей разработки.

Модуль инструкций. Ознакомьтесь с установкой XOOPS. C начальными познаниями по HTML,CSS, JS, PHP и др.

Добро пожаловать на сайт поддержки XOOPS.

Приднестровская поддержка XOOPS

В jQuery обход элементов—это просмотр существующего дерева DOM-элементов. По сути, эта операция представляет собой разновидность фильтрации, которая выполняется после произведенного перед этим отбора элементов. Такая возможность чрезвычайно удобна для разработчиков, поскольку позволяет выполнить манипуляции с одной частью DOM-структуры, а затем перейти к другой ее части без повторного проведения процедуры поиска с помощью селекторов.

Данное средство значительно облегчает жизнь разработчикам, обеспечивая простой способ доступа к непосредственному окружению элемента, с которым в данный момент выполняются какие-либо манипуляции или который так или иначе используется в сценарии. Необходимость в этом может возникнуть в целом ряде других случаев, например когда в родительские элементы требуется добавить класс, позволяющий отслеживать их активность, или отключить все неактивные элементы формы.

Сравниваем инфраструктуры для разработки на JavaScript

Обзор инфраструктур для разработки на JavaScript

JavaScript — это объектно-ориентированный язык сценариев, который уже давно используется в разработке Web-приложений для создания выполняемых на клиенте сценариев. JavaScript позволяет Web-разработчикам программным образом работать с находящимися на Web-странице объектами, предоставляя платформу для манипулирования этими объектами на лету. Когда JavaScript только появился, он, как правило, использовался для реализации довольно тривиальной функциональности, такой как часы на Web-странице или прокрутка текста в строке состояния браузера. Другой типичной функциональностью были «наводящиеся ссылки», в которых изображение или цвет текста ссылки менялись при наведении курсора мыши. Однако в последнее время JavaScript эволюционировал и стал гораздо более полезным, а концепция асинхронного JavaScript в сочетании с XML — Ajax (Asynchronous JavaScript and XML) — вывела возможности реализации интерактивности Web-приложений на новый уровень. До Ajax любая обработка данных на сервере или операция с базой данных требовала обновления всей страницы целиком или отображения новой страницы. Такой подход не только был медленным и недружелюбным по отношению к пользователю, но и тратил впустую пропускную способность сетевого канала и ресурсы компьютера.

Ajax расшифровывается как Asynchronous JavaScript and XML, хотя сейчас запросы Ajax могут возвращать данные и в отличных от XML форматах, например, JSON (JavaScript Object Notation). Ajax позволяет из кода JavaScript асинхронно посылать HTTP-запросы на Web-сервер, а затем отображать его результат без обновления существующей страницы или отрисовки новой. Чтобы отразить изменения или данные, возвращенные в HTTP-ответе, изменяют лишь часть Web-страницы посредством манипуляций с моделью DOM (Document Object Model — объектная модель документа).

Илон Маск рекомендует:  Что такое код udm_free_res

Что такое инфраструктура JavaScript?

JavaScript сам по себе очень мощный язык, и, вообще говоря, на нем можно создавать приложения с насыщенным пользовательским интерфейсом без помощи дополнительных инфраструктур. Однако использовать JavaScript напрямую – работа не из легких. В первую очередь это связано со сложностями, возникающими при попытках обеспечить работу приложения в различных Web-браузерах. Как и в случае HTML и CSS, каждый браузер имеет свою собственную реализацию JavaScript, поэтому обеспечение кросс-браузерной совместимости приложения может стать настоящим кошмаром.

Инфраструктура или библиотека JavaScript представляет собой набор утилит и функций, которые существенно облегчают создание кода JavaScript, совместимого с множеством браузеров. Каждая библиотека активно тестируется на последних версиях многих современных Web-браузеров, поэтому вы, используя какую-либо из этих инфраструктур, можете быть уверены, что ваше приложение будет работать схожим образом на различных браузерах и платформах.

Помимо обеспечения кросс-браузерной совместимости, инфраструктуры JavaScript облегчают написание кода для извлечения, навигации и манипуляции с DOM-элементами. Они не только предоставляют простые функции для получения ссылок на элементы модели DOM, но и позволяют записывать цепочки вызовов функций обхода дерева DOM для поиска на любой глубине предков, потомков или братьев элемента. Наконец, инфраструктуры предоставляют ряд функций, облегчающих манипулирование этими объектами, позволяя изменять, добавлять или удалять непосредственно содержимое элементов, или манипулировать стилями CSS для изменения внешнего вида элемента.

Другой важной функциональностью инфраструктур JavaScript является улучшенная поддержка обработки событий. Кросс-браузерная обработка событий может оказаться кошмаром в связи с различными реализациями событий в разных браузерах, поэтому инфраструктуры JavaScript обычно оборачивают события браузера в набор функций, которые корректно работают в различных браузерах. Некоторые инфраструктуры также предоставляют набор стандартизованных кодов клавиш, которые представляют связанные с клавиатурой события (такие как нажатие клавиш Escape, Return, клавиш курсора и т.д.).

Вся эта функциональность очень важна, но, пожалуй, главным фактором недавнего роста популярности инфраструктур JavaScript стала поддержка Ajax. Как и другие аспекты JavaScript, технология Ajax в каждом Web-браузере реализована особенным образом, что делает утомительной работу по поддержке совместимости приложения с разными браузерами. Почти все инфраструктуры JavaScript включают в себя какую-либо библиотеку, поддерживающую Ajax, которая обычно предоставляет объекты для работы с запросами и ответами Ajax, вспомогательные функции для анализа ответов, обновления DOM-элементов и периодического опроса сервера.

Типичная функциональность инфраструктур JavaScript

Рассмотрим полезную функциональность, типичную для большинства инфраструктур JavaScript. Вот эта функциональность:

  • Селекторы
  • Обход дерева DOM
  • Манипуляция моделью DOM
  • Функции-утилиты
  • Обработка событий
  • Ajax

При рассмотрении функциональности я буду приводить примеры из одной или нескольких следующих инфраструктур JavaScript: Prototype, jQuery, YUI, ExtJS и MooTools. Хотя реализация и синтаксис разных инфраструктур различны, основные концепции остаются одинаковыми. Каждая инфраструктура предоставляет подробный справочник по API, к которому можно обращаться, чтобы понять, как использовать данную функциональность в той или иной библиотеке.

Селекторы

В большинстве имеющихся инфраструктур JavaScript реализована какая-либо форма селекторов — методов для быстрого выбора элементов. Селекторы значительно ускоряют процесс получения ссылки на нужный HTML-элемент. Они позволяют искать элементы по ID, имени класса, типу элемента или с помощью последовательности псевдоселекторов.

Например, с помощью обычного JavaScript можно выбрать DOM-элемент по ID с помощью следующего кода:

MooTools, как и некоторые другие инфраструктуры, предоставляет простой метод для выполнения этого действия. Помимо выбора нужного элемента, MooTools расширяет возможности элемента рядом дополнительных функций. Для обращения к элементу используется следующий синтаксис:

Показанная выше функция $ доступна в нескольких (но не всех) популярных инфраструктурах JavaScript. Библиотека Prototype, кроме этого, позволяет выбирать по ID несколько элементов, возвращая массив элементов. Как и в MooTools, возможности этих элементов расширяются рядом дополнительных функций Prototype. Для одновременного выбора нескольких элементов в Prototype используется следующий синтаксис:

В разделе Служебные функции вы узнаете о ряде предоставляемых инфраструктурами JavaScript функций, облегчающих итеративный обход коллекций объектов.

В предыдущих примерах поиск осуществлялся по ID конкретного элемента. Что делать, если мы хотим найти несколько элементов, например, все картинки или все строки таблицы с определенным именем CSS-класса? MooTools (и некоторые другие библиотеки) предоставляет для этого очень простой метод — функцию $$. Она работает по аналогии с функцией $, за исключением того, что вместо ID элемента она может принимать в качестве аргумента имя CSS-элемента, имя класса или псевдоселектор. Например, чтобы выбрать все изображения с Web-страницы с помощью MooTools, следует использовать следующий код:

Этот код возвращает массив элементов, представляющих все имеющиеся в документе изображения, для каждого из которых доступны служебные функции MooTools.

Выбор элементов по имени тега — это полезная функциональность, но что если мы хотим выбрать некое подмножество элементов по имени CSS-класса? Это тоже очень просто. В следующем примере MooTools выберет все строки таблицы с CSS-классом «odd». Это может быть полезно для реализации чередования цвета фона в строках таблицы:

На самом деле MooTools предлагает еще лучший способ реализации чередования фона строк. В предыдущем примере предполагалось, что каждая нечетная строка таблицы принадлежит к CSS классу с именем «odd». Следующий код не требует определения какого-либо CSS-класса для строк таблицы:

Здесь представлен пример псевдоселектора, который возвращает все объекты, удовлетворяющие спецификации, — в данном случае каждый нечетный элемент, являющийся потомком элемента tbody (тело таблицы). Вот еще несколько примеров псевдоселекторов MooTools:

  • checked — выбирает все помеченные элементы (например, все помеченные флажки)
  • enabled — выбирает все активные элементы
  • contains — выбирает все элементы, содержащие текст, переданный в селектор в качестве аргумента (например, contains(‘this text’) )

Как упоминалось ранее, не все инфраструктуры JavaScript используют функцию $ для выбора элементов модели DOM. В библиотеке YUI (Yahoo! User Interface) версии 3 для выбора элемента по ID используется следующий код (обратите внимание, что в YUI 3 перед ID элемента необходимо указывать символ #):

Аналогичным образом вместо использования функции $$ для извлечения элементов по имени тега или класса в YUI применяется функция Y.all :

ExtJS работает схожим образом. Для выбора элемента по ID в нем используется следующий синтаксис:

А для выбора элементов по имени тега или класса используется следующий синтаксис:

В следующем разделе мы увидим, как инфраструктуры JavaScript позволяют осуществлять обход дерева DOM, или, другими словами, находить элементы, являющиеся родственными (например, родителем, потомком или братом) определенному элементу. Также мы узнаем, как инфраструктуры позволяют манипулировать моделью DOM, чтобы изменять ее элементы.

Обход DOM-дерева

Поиск элемента по ID, типу элемента или имени CSS-класса — это очень полезная функциональность, но что если мы хотим найти элемент на основе его позиции в дереве DOM-модели? Например, мы хотим, имея определенный элемент, найти его родительский элемент, один из его потомков или же предыдущий или следующий элемент-брат. Рассмотрим пример разметки HTML, показанной в листинге 1.

Листинг 1. HTML таблица

В листинге 1 используются отступы для иллюстрации того, где в DOM-дереве находится каждый элемент. В этом примере элемент table является корневым элементом, у него имеется 2 потомка — элементы thead и tbody . Единственным потомком элемента thead является элемент tr , который в свою очередь имеет трех потомков — элементы th . Потомками элемента tbody являются два элемента tr , каждый из которых имеет в свою очередь трех потомков. Третий потомок в каждой из этих строк имеет еще двух потомков — теги a .

Как вы знаете, для простого выбора элемента по ID можно использовать функцию-селектор какой-либо инфраструктуры JavaScript. В данном примере у нас есть два элемента с атрибутами ID — это элементы tr (строки таблицы), ID которых равны row-001 и row-002 соответственно. Для выбора первого элемента tr с помощью Prototype можно было бы использовать следующий код:

В предыдущем разделе мы также узнали о том, что селекторы можно использовать для извлечения элементов на основе их типа или CSS-класса. В этом примере мы можем выбрать все элементы td , используя следующий синтаксис:

Проблема этого кода в том, что он возвращает абсолютно все элементы td из модели DOM. Но что делать, если мы хотим получить только элементы td , находящиеся в строке с ID равным row-001? Именно здесь на сцене появляются функции обхода DOM-дерева. Сначала давайте с помощью Prototype выберем всех потомков элемента tr с ID равным row-001:

Этот код возвращает массив потомков переменной theRow (в которую мы ранее поместили элемент с ID равным row-001).

Далее, предположим, мы хотим получить только первого потомка, т.е., в данном случае, элемент td с текстом «Joe Lennon». Для этого мы используем следующую инструкцию:

Не правда ли, просто? Данная инструкция эквивалентна следующему коду:

и также может быть записана в виде:

В JavaScript индексы начинаются с нуля, поэтому предыдущая инструкция указывает JavaScript выбрать первого потомка. Чтобы выбрать второго потомка (ячейку с адресом электронной почты — joe@joelennon.ie) можно использовать следующий код:

Также при обходе DOM-дерева можно использовать функции для перемещения по элементам-братьям. В нашем случае вторая ячейка является следующим братом по отношению к первой ячейке, поэтому можно использовать следующую инструкцию:

Эта функция работает точно так же как функция down() , поэтому, чтобы выбрать третью ячейку, следует использовать следующий код:

Помимо использования индексов для нахождения определенных узлов, Prototype также позволяет использовать синтаксис CSS-селекторов. Используя разметку из листинга 1, давайте найдем вторую ссылку (ссылку «Delete») для строки, содержащей подробную информацию о Jill Mac Sweeney:

В этом примере мы используем функцию $ для поиска элемента с ID равным row-002, и спускаемся вниз по дереву DOM до второго относительно нас элемента a .

Некоторые инфраструктуры также позволяют объединять функции обхода дерева в цепочки, т.е. соединять вместе несколько команд обхода. С помощью Prototype найти элемент из предыдущего примера можно и другим способом:

Рассмотрим следующий пример:

Как можно видеть, цепочки позволяют соединять вместе несколько инструкций обхода DOM-дерева. В действительности приведенный выше код просто выбирает элемент tr с ID row-001 , т.е. цепочка команд приводит нас обратно к тому элементу, с которого мы начинали!

Манипуляции с DOM-деревом

Ранее мы видели, как имеющиеся в инфраструктурах Javascript селекторы и функции обхода DOM-дерева облегчают выбор нужных элементов. Однако для того, чтобы изменять внешний вид или содержимое какого-либо элемента Web-страницы, нам нужно уметь манипулировать моделью DOM. Это может быть весьма непросто при использовании исключительно JavaScript, но, к счастью, большинство инфраструктур JavaScript предлагают ряд полезных функций, облегчающих этот труд.

Допустим, у нас есть элемент div с id равным the-box :

Поменять текст «Message goes here» с помощью jQuery можно следующим образом:

На самом деле браузер сумеет понять код и в случае если внутри этой функции использовать разметку HTML. Например:

В этом примере содержимое элемента div будет выглядеть в модели DOM следующим образом:

Конечно, иногда бывает необходимо использовать специальные символы, такие как знаки «больше» или «меньше». В таких случаях вместо указания специальных символов HTML, можно использовать имеющуюся в jQuery функцию text :


В результате обновленный div -элемент будет выглядеть так:

В предыдущих примерах мы заменяли существующее содержимое новым содержимым. Но что если мы хотим просто добавить что-то к существующему тексту? К счастью, в jQuery специально для этих целей предусмотрена функция append:

После этого вызова наш элемент div будет выглядеть так:

Можно добавлять содержимое не только в конец элемента, но и в его начало, перед существующими данными (функция prepend). Также jQuery предлагает функции для вставки содержимого за границы данного элемента, перед ним или после него. Кроме того, имеются функции для замены или очистки содержимого, удаления элементов из модели DOM, клонирования элементов и т.д.

Кроме функций для изменения модели DOM, в инфраструктурах JavaScript обычно имеется несколько функций для манипулирования стилями и CSS-классами элементов. Допустим, мы хотим подсвечивать строку таблицы при наведении на нее курсора мыши. Мы создаем специальный CSS-класс с именем hover и хотим динамически добавлять строке этот класс. В инфраструктуре YUI можно использовать следующий код для проверки того, имеет ли уже строка класс hover , удаляет его, если класс присутствует, и добавляет его, если класса нет:

Функции для манипулирования CSS встроены в большинство инфраструктур JavaScript.

Служебные функции

Большинство инфраструктур JavaScript поставляются в комплекте с огромным количеством служебных функций, облегчающих разработку приложений на JavaScript. Служебных функций слишком много для того, чтобы рассказать обо всех них в данной статье, поэтому мы рассмотрим одну из наиболее примечательных функций, типичных для большинства инфраструктур.

Если вы работали в JavaScript с массивами, возможно, вам приходилось использовать циклы for для обхода массива и получения значений его элементов. Например, рассмотрим код, представленный в листинге 2:

Листинг 2. Традиционный метод обхода массива в JavaScript

Код, приведенный в листинге 2, неплохой, но немного неуклюжий. В большинстве инфраструктур JavaScript имеется функция each , которая вызывает указанную функцию для каждого элемента массива. Например, используя MooTools, выполнить действие, указанное в листинге 2, можно следующим образом:

Листинг 3. Использование функции each в MooTools

Синтаксис работы с функцией each одинаков для Prototype и jQuery, но немного отличается в YUI и ExtJS. Однако при работе не с массивом, а со словарем или объектом в разных инфраструктурах используется различный синтаксис функции each. Например, в MooTools можно использовать следующий код:

Листинг 4. Использование функции each для обхода объекта с парами ключ-значение в MooTools

В Prototype это бы выглядело иначе:

Листинг 5. Использование функции each для обхода объекта с парами ключ-значение в Prototype

В каждой инфраструктуре имеется множество служебных функций, которые обычно подразделяют на функции по работе со строками, числами, массивами, словарями, датами и т.д. За более подробной информацией обращайтесь к руководству по API интересующей вас инфраструктуры.

Обработка событий

Во всех инфраструктурах JavaScript реализована кросс-браузерная поддержка обработки событий, которая поощряет переход от старомодной inline-обработки событий к более простому методу. Рассмотрим в листинге 6 пример работы с jQuery, в котором мы подсвечиваем элемент div на основе события hover.

Листинг 6. Обрабатываем в jQuery событие hover

hover — это особое событие, реализуемое в jQuery. Оно предоставляет две функции: первая вызывается при наступлении события onMouseOver , а вторая — при наступлении события onMouseOut . В модели DOM нет стандартного события hover (отражающего состояние, когда на объект наведена мышь), поэтому приходится определять две функции. Давайте рассмотрим более типичное событие, например click (см. листинг 7).

Листинг 7. Обрабатываем в jQuery событие click

Как видно, в этом примере событие принимает в виде аргумента только одну функцию-обработчик. Большинство событий JavaScript обрабатывается в jQuery именно таким образом. При использовании обработчиков jQuery контекстная переменная указывает на элемент, на котором произошло данное событие. Некоторые инфраструктуры работают иначе. Например, рассмотрим, как код, приведенный в листинге 7, будет выглядеть в Prototype.

Листинг 8. Обрабатываем в Prototype событие click

Во-первых, заметим, что здесь вместо функции click используется функция observe , которая принимает в качестве аргументов название события и ссылку на функцию. Также заметим, что функция принимает аргумент e . Это контекстная переменная, указывающая на элемент, на котором произошло данное событие. Чтобы увидеть ее в работе, давайте перепишем для Prototype код из листинга 6 (см. листинг 9).

Листинг 9. Обрабатываем в Prototype событие hover

В отличие от jQuery, где для получения контекстной переменной просто используется функция $, в Prototype нужно использовать функцию Event.element() . Также для обработки событий mouseover и mouseout нам пришлось использовать отдельные функции.

Вы могли заметить, что во всех примерах этой статьи мы создаем неименованные inline-функции. Это означает, что их нельзя повторно использовать. Пример обработки события hover в Prototype предоставляет нам возможность показать, как можно использовать вместо них именованные функции.

Илон Маск рекомендует:  Что такое код pg_num_rows
Листинг 10. Улучшенный пример обработки события hover в Prototype

Обратите внимание, что в этот раз мы просто определяем отдельную функцию, которая вызывается и при событии mouseover , и при mouseout . Эта функция определяет, имеется ли у элемента имя класса highlight, и в зависимости от результата либо удаляет, либо добавляет его. Обратите внимание, что аргумент e передается неявно. Другими словами, мы не передаем явно событие в качестве аргумента при вызове функции observe .

Одной из весомых причин использования инфраструктур JavaScript является стандартизованная кросс-браузерная обработка запросов Ajax. Запрос Ajax представляет собой асинхронный HTTP-запрос к сценарию на сервере, который возвращает ответ в таком формате, как XML, JSON, HTML или обычный текст. В большинстве инфраструктур JavaScript имеются объекты, представляющие запросы Ajax. Обычно у этих объектов есть метод для отправки запроса, принимающий ряд параметров. В число этих параметров, как правило, входит функция обратного вызова , которая вызывается при получении ответа от Web-сервера. Давайте посмотрим, как выглядят Ajax-запросы в ExtJS, MooTools и Prototype.

Давайте сначала взглянем на типичный Ajax-запрос в ExtJS (см. листинг 11).

Листинг 11. Ajax-запрос в ExtJS

Здесь метод request принимает единственный аргумент — объект с множеством полей, в числе которых url , params , method и success . Поле url содержит URL серверного сценария, который будет вызываться Ajax-запросом. Поле params само является объектом, состоящим из пар ключ/значение, которые будут переданы серверному сценарию в качестве параметров. Поле method может принимать одно из двух значений: GET или POST . По умолчанию его значение не определено, но оно будет считаться POST , если в запросе задано поле params . В последнем поле, success , задается функция, которая будет вызвана, когда Web-сервер вернет успешный результат. В данном примере предполагается, что серверный сценарий возвращает обычный текст и данная функция отображает этот текст в окне предупреждения.

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

Листинг 12. Ajax-запрос в MooTools

Как видно, в данном случае код MooTools очень похож на код ExtJS. Здесь вместо поля params параметры запроса передаются в поле data , а тип метода необходимо указывать в нижнем регистре. Также в MooTools поле, где указывается функция обратного вызова, называется onComplete , а не callback . Наконец, в MooTools, в отличие от ExtJS, необходимо посылать запрос с помощью функции send() объекта Request .

А сейчас давайте посмотрим, есть ли радикальные различия в работе с Ajax с помощью Prototype (см. листинг 13).

Листинг 13. Ajax-запрос в Prototype

Как видно, Prototype работает аналогичным образом, лишь с небольшими синтаксическими отличиями. Для начинающих поясним, что объект Request в Prototype принимает в своем конструкторе два параметра. Первым параметром является URL-адрес, по которому следует послать Ajax-запрос, а второй параметр — это объект с атрибутами запроса, похожий на объекты, которые мы видели в предыдущих примерах. Конечно же, поскольку здесь URL передается отдельным параметром, его нет среди атрибутов данного объекта. Также стоит заметить, что в отличие от MooTools в Prototype не нужно вызывать какой-либо метод, чтобы послать запрос, это делается неявно конструктором объекта Request .

Поддержка Ajax в большинстве инфраструктур JavaScript не ограничивается тем, что мы здесь рассмотрели. Среди прочих возможностей стоит отметить автоматическое обновление элемента при получении ответа, без необходимости определения специальных функций обратного вызова, таких как onSuccess . В некоторые библиотеки даже встроена функция автоматического дополнения, наподобие того, что можно наблюдать на странице поиска Google, когда при вводе текста предлагаются варианты типичных поисковых запросов.

В следующем разделе мы узнаем о пользовательских расширениях, предлагаемых Web-разработчикам инфраструктурами JavaScript.

Пользовательские расширения

До этого момента мы в данной статье рассматривали преимущества использования инфраструктур JavaScript с точки зрения разработки и того, как они облегчают кодирование интерактивных приложений. Однако большинство инфраструктур предлагают еще один привлекательный аспект: компоненты пользовательского интерфейса (UI) и легко подключаемые пользовательские расширения, самостоятельная разработка которых потребовала бы значительных усилий.

В этом разделе мы по отдельности изучим пользовательские расширения, предлагаемые следующими инфраструктурами: Prototype, jQuery, YUI, ExtJS и MooTools.

Prototype

Prototype — это одна из немногих инфраструктур JavaScript, в составе которых по умолчанию отсутствуют UI-компоненты или пользовательские расширения. Все они находятся в родственной библиотеке — script.aculo.us (ее последняя версия известна под именем Scripty2). Script.aculo.us добавляет в Prototype поддержку множества эффектов и разнообразного поведения. Среди этих эффектов можно отметить подсветку, изменения формы, складывание, покачивание, скольжение, вздутие и т.д.. Script.aculo.us также известна поддержкой функциональности drag-and-drop, а также слайдеров, редактирования «на месте» и автодополнения. В отличие от некоторых других инфраструктур Script.aculo.us не предоставляет стандартных тем, оставляя разработчикам все заботы по разработке дизайна всех элементов управления.

jQuery

В отличие от Prototype, в jQuery некоторые базовые пользовательские расширения включены в ядро библиотеки. Эти расширения похожи на некоторые из эффектов, имеющихся в script.aculo.us, например скольжение и затухание. Однако более сложные эффекты содержатся в отдельной библиотеке jQuery UI. Эта библиотека также поддерживает интерактивные возможности, такие как drag and drop, изменение размера элементов и сортировку. В отличие от script.aculo.us, библиотека jQuery UI также включает в себя набор виджетов и компонентов, существенно облегчающих разработку привлекательных пользовательских интерфейсов. На данный момент в ней имеются такие компоненты, как Accordion, Datepicker, Dialog, Progressbar, Slider и Tabs. Также jQuery UI предлагает большое количество готовых тем, в которые можно интегрировать виджеты и компоненты при разработке сайта или Web-приложения. На рисунке 1 показан пример Datepicker в теме Cupertino.

Рисунок 1. Виджет Datepicker библиотеки jQuery UI

В отличие от Prototype и jQuery, где нет доступных «из коробки» графических виджетов, в библиотеке Yahoo! User Interface library (YUI) их имеется множество. Помимо поддержки drag-and-drop и изменения размера элементов, 2-я версия YUI включает в себя элементы для управления автодополнением и календарем, вращающиеся по карусели компоненты, таблицы, диалоги, индикаторы прогресса, текстовые редакторы (или текстовые поля WYSIWYG), слайдеры, вкладки, деревья и многое другое. На момент написания этой статьи ни один из вышеупомянутых виджетов не был включен в 3-ю версию YUI. На рисунке 2 показан пример графического интерфейса, созданного с помощью данных компонентов.

Рисунок 2. Пример сложного приложения на основе YUI

ExtJS

Как и в YUI, в библиотеке ExtJS доступно «из коробки» множество компонентов, среди которых стоит особо отметить очень мощные средства для создания сеток элементов, поддерживающие редактирование «на месте», постраничный просмотр, фильтры, группировки, обобщенные представления, буферизацию и связывание с данными. Компоненты ExtJS выглядят очень профессионально и настраиваются посредством тем. Также в ExtJS имеются такие виджеты, как вкладки, таблицы, окна (диалоги), деревья, менеджеры разметки, дополнительные элементы управления на формах, панели инструментов и меню, drag-and-drop и direct remoting. Это лишь малая часть того, что может предложить ExtJS, поэтому если вы ищете обширный набор компонентов для разработки приложений с насыщенным пользовательским интерфейсом, обязательно посетите web-сайт ExtJS. На рисунке 3 показан пример разработанного с помощью ExtJS рабочего стола, иллюстрирующий, насколько богатая функциональность доступна в этой библиотеке.

Рисунок 3. Приложение «Рабочий стол», разработанное с помощью ExtJS

MooTools

Так же как Prototype и jQuery, MooTools не предоставляет «из коробки» виджеты и элементы управления. Как и в jQuery, в ядро библиотеки включен лишь ограниченный набор графических эффектов. Более сложные пользовательские расширения доступны в дополнительной библиотеке MooTools.More.js. В ней помимо графических расширений имеется ряд интересных надстроек над классами Array , Date , Hash и String , а также расширения класса Element . Говоря о графических расширениях MooTools.More.js, следует упомянуть поддержку drag-and-drop и некоторых других эффектов. Также в этом расширении имеются такие графические элементы управления, как accordion, сортируемые HTML-таблицы, элементы прокрутки, контекстные подсказки и spinner-ы, работающие с Ajax. Однако, как и в случае с script.aculo.us, разрабатывать их дизайн вам придется самостоятельно.

Сравнение инфраструктур

В таблице 1 представлено детальное сравнение функциональности пяти инфраструктур, которые мы обсуждали в данной статье.

Таблица 1. Сравнение функциональности инфраструктур
Prototype jQuery YUI ExtJS MooTools
Последняя версия 1.6.1 1.4.1 3.00 3.1 1.2.4
Лицензия MIT MIT & GPL BSD Коммерческая & GPL v3 MIT
Поддержка браузеров
Поддержка IE 6.0+ 6.0+ 6.0+ 6.0+ 6.0+
Поддержка Firefox 1.5+ 2.0+ 3.0+ 1.5+ 2.0+
Поддержка Safari 2.0.4+ 3.0+ 4.0+ 3.0+ 2.0+
Поддержка Opera 9.25+ 9.0+ 10.0+ 9.0+ 9.0+
Поддержка Chrome 1.0+ 1.0+ Неизвестно Неизвестно Неизвестно
Главная функциональность
Поддержка Ajax Есть Есть Есть Есть Есть
Манипуляция DOM-деревом Есть Есть Есть Есть Есть
Обход DOM-дерева Есть Есть Есть Есть Есть
Обработка событий Есть Есть Есть Есть Есть
JSON Есть Есть Есть Есть Есть
Селекторы Есть Есть Есть Есть Есть
Графические пользовательские расширения
Accordion Нет jQuery UI Нет Есть MooTools More
Анимация scriptaculous Есть Есть Есть Есть
Автодополнение scriptaculous Нет Есть Есть Нет
История браузера scriptaculous Нет Есть Есть Нет
Календарь Нет jQuery UI Есть Есть Нет
Таблицы Нет Нет Есть Есть Нет
Drag and Drop scriptaculous jQuery UI Есть Есть MooTools More
Сетки Нет Нет Есть Есть MooTools More
Индикатор прогресса Нет jQuery UI Есть Есть Нет
Изменение размера элементов Нет jQuery UI Есть Есть Нет
Сложный текстовый редактор Нет Нет Есть Есть Нет
Слайдеры scriptaculous jQuery UI Есть Есть MooTools More
Вкладки Нет jQuery UI Есть Есть Нет
Темы Нет jQuery UI Есть Есть MooTools More
Древовидные структуры Нет Нет Есть Есть Нет

Другие инфраструктуры

В целях краткости в данной статье мы рассмотрели только пять популярных инфраструктур разработки JavaScript. Это не обязательно означает, что эти инфраструктуры самые популярные, самые лучшие и предлагают наиболее богатую функциональность.

В числе других заслуживающих внимания инфраструктур JavaScript можно указать:

Заключение

В этой статье мы познакомились с концепцией инфраструктур JavaScript и узнали о преимуществах, которые инфраструктуры предоставляют при разработке Web-сайтов и Web-приложений. Мы рассмотрели некоторые типичные возможности, предоставляемые инфраструктурами, а также несколько примеров того, как эта функциональность реализуется в наиболее популярных библиотеках. Далее мы узнали о пользовательских расширениях, поставляемых либо в комплекте с инфраструктурой, либо в виде дополнительной библиотеки. В заключение мы подытожили сведения об этих инфраструктурах в таблице, чтобы можно было более наглядно сравнить их возможности. Вооружившись данной информацией, вы должны быть готовы к дальнейшему изучению этих инфраструктур и последующему принятию обоснованного решения о том, какая из них лучше подходит вам и вашей команде разработчиков.

Ресурсы для скачивания

Похожие темы

  • Ознакомьтесь с оригиналом статьи: «Compare JavaScript frameworks».(EN)
  • Познакомьтесь с инфраструктурой Dojo.
  • Прочитайте статью «Dojo concepts for Java developers» (developerWorks, октябрь 2008 г.), чтобы узнать, как сократить разрыв между кодом на Java и Dojo и быстро научиться использовать этот набор инструментов для разработки приложений.(EN)
  • Загрузите набор инструментов Dojo toolkit.(EN)
  • Прочтите статью «Call SOAP Web services with Ajax, Part 1: Build the Web services client» (developerWorks, октябрь 2005г.), чтобы узнать, как с помощью Ajax создать основанный на Web-браузере клиент SOAP Web-сервисов.(EN)
  • В статье «Overcome security threats for Ajax applications» (developerWorks, июнь 2007 г.) автор обсуждает угрозы безопасности, связанные с технологией Ajax и делится практическими рекомендациями, позволяющими их избегать.(EN)
  • В статье «Mastering Ajax, Part 1: Introduction to Ajax» (developerWorks, декабрь 2005 г.) рассказывается о том, как с помощью технологий HTML, JavaScript, DHTML и DOM сделать Web-разработку чрезвычайно эффективной и простой.
  • В статье «Simplify Ajax development with jQuery» (developerWorks, апрель 2007 г.) авторы рассматривают философию инфраструктуры jQuery, рассказывают о ее возможностях и функциях и показывают несколько типичных примеров работы с Ajax.(EN)
  • Слушайте интересные интервью и дискуссии разработчиков ПО в разделе подкастов developerWorks. (EN)
  • Загрузите инфраструктуру Prototype. (EN)
  • Загрузите jQuery.(EN)
  • Библиотека jQuery User Interface предоставляет построенный на основе Javascript уровень абстракции для низкоуровневых взаимодействий и анимации, сложных эффектов и высокоуровневых виджетов, поддерживающих темы.(EN)
  • Загрузите script.aculo.us.(EN)
  • Загрузите MooTools. (EN)
  • Загрузите и познакомьтесь с предоставляемой Yahoo! библиотекой YUI Library.(EN)
  • Загрузите ExtJS. (EN)
  • Разработайте свой следующий проект с помощью пробного ПО от IBM, которое можно загрузить непосредственно с сайта developerWorks или заказать на DVD.(EN)
  • Загрузите пробные версии продуктов IBM, чтобы получить практический опыт работы с инструментами разработки приложений и ПО промежуточного уровня от DB2, Lotus®, Rational®, Tivoli® и WebSphere®.(EN)

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

# 7 Добавление и удаление DOM элементов

В этом уроке мы с вами разберемся, как добавлять и удалять елементы. Это очень важные знания, так как очень много елементов на странице мы добавляем и удаляем с помощью javascript.

Итак сейчас у нас пустой body и давайте добавим туда контейнер, с которым будем работать.

Теперь в нашем javascript мы можем создать новый DOM елемент с помощью метода createElement.

В консоли браузера мы с вами видим этот пустой DOM елемент. И теперь, после того, как мы его создали мы можем вставить его в DOM. Для этого нам понадобится метод appendChild.

То есть мы нашли сначала наш елемент app, а потом добавили к нему как child елемент наш title.

Если мы посмотрим в браузер, то мы видим, что у нас появился новый пустой DOM елемент.

Но мы же хотим, чтобы наш елемент создавался с нужными нам классами. Для этого мы можем задать классы созданному елементу с помощью метода className.

Теперь в браузере у нас появился в DOM уже елемент с классом. Но теперь хотелось бы еще и добавить этому новому елементу текст. Мы можем использовать для этого метод innerHTML, который мы с вами уже изучали ранее.

Теперь мы в браузере видим, что у нас добавился новый DOM елемент с текстом и классом.

Но есть нюансы в том, как работает метод appendChild. Давайте сейчас добавим внутрь div app еще один div.

Если мы посмотрим в браузер, то у нас сначала вывелся content, а потом уже после него вывелся созданный елемент. Это происходит потом, что метод appendChild добавляет елемент в самый конец. Это значит, что этот елемент будет добавлен как последний дочерний елемент в родителе.

Что же нам сейчас делать? Ведь мы хотим вывести сначала title, а потом контент. В этом нам поможет метод .insertBefore. Он работает точно также, как и appendChild, но добавляет DOM елемент на позицию перед указанным елементом. То есть первым аргументом мы указываем елемент, который хотим вставить, а вторым перед каким дочерним елементом мы будем вставлять.

Так как мы хотим вставить перед первым дочерним елементом, то мы можем использовать метод .firstChild, чтобы найти первый дочерний елемент у app.

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

То есть мы вызываем на app removeChild, чтобы удалить дочерний елемент.

Есть также и более простой вариант записи, когда мы просто вызываем .remove на елементе.

Этот код отработает абсолютно одинаково.

Если у вас что-то не получается, либо возникли вопросы и комментарии, пишите их прямо под этим видео и я обязательно на них отвечу.

Техники работы с DOM: родительские, дочерние и соседние элементы

17 Декабря 2015

Сложные и тяжелые веб-приложения стали обычными в наши дни. Кроссбраузерные и простые в использовании библиотеки типа jQuery с их широким функционалом могут сильно помочь в манипулировании DOM на лету. Поэтому неудивительно, что многие разработчики использую подобные библиотеки чаще, чем работают с нативным DOM API, с которым было немало проблем. И хотя различия в браузерах по-прежнему остаются проблемой, DOM находится сейчас в лучшей форме, чем 5-6 лет назад, когда jQuery набирал популярность.

В этой статье я продемонстрирую возможности DOM по манипулированию HTML, сфокусировавшись на отношения родительских, дочерних и соседних элементов. В заключении я дам данные о поддержке этих возможностей в браузерах, но учитывайте, что библиотека типа jQuery по-прежнему остается хорошей опцией в силу наличия багов и непоследовательностей в реализации нативного функционала.

Подсчет дочерних узлов

Для демонстрации я буду использовать следующую разметку HTML, в течение статьи мы ее несколько раз изменим:

Если я хочу подсчитать, сколько элементов внутри

    , я могу сделать это двумя способами.

Как видите, результаты одинаковые, хотя техники используются разные. В первом случае я использую свойство children . Это свойство только для чтения, оно возвращает коллекцию элементов HTML, находящихся внутри запрашиваемого элемента; для подсчета их количества я использую свойство length этой коллекции.

Во втором примере я использую метод childElementCount , который мне кажется более аккуратным и потенциально более поддерживаемым способом (подробнее обсудим это позже, я не думаю, что у вас возникнут проблемы с пониманием того, что он делает).


Я мог бы попытаться использовать childNodes.length (вместо children.length ), но посмотрите на результат:

Он возвращает 13, потому что childNodes это коллекция всех узлов, включая пробелы — учитывайте это, если вам важна разница между дочерними узлами и дочерними узлами-элементами.

Проверка существования дочерних узлов

Для проверки наличия у элемента дочерних узлов я могу использовать метод hasChildNodes() . Метод возвращает логическое значение, сообщающие об их наличии или отсутствии:

Я знаю, что в моем списке есть дочерние узлы, но я могу изменить HTML так, чтобы их не было; теперь разметка выглядит так:

И вот результат нового запуска hasChildNodes() :

Метод по прежнему возвращает true . Хотя список не содержит никаких элементов, в нем есть пробел, являющийся валидным типом узла. Данный метод учитывает все узлы, не только узлы-элементы. Чтобы hasChildNodes() вернул false нам надо еще раз изменить разметку:

И теперь в консоль выводится ожидаемый результат:

Конечно, если я знаю, что могу столкнуться с пробелом, то сначала я проверю существование дочерних узлов, затем с помощью свойства nodeType определяю, есть ли среди них узлы-элементы.

Добавление и удаление дочерних элементов

Есть техника, которые можно использовать для добавления и удаления элементов из DOM. Наиболее известная из них основана на сочетании методов createElement() и appendChild() .

В данном случае я создаю

Но вместо вставки специально создаваемого элемента, я также могу использовать appendChild() и просто переместить существующий элемент. Предположим, у нас следующая разметка:

Я могу изменить место расположения списка с помощью следующего кода:

Итоговый DOM будет выглядеть следующим образом:

Обратите внимание, что весь список был удален со своего места (над параграфом) и затем вставлен после него перед закрывающим body . И хотя обычно метод appendChild() используется для добавления элементов созданных с помощью createElement() , он также может использоваться для перемещения существующих элементов.

Я также могу полностью удалить дочерний элемент из DOM с помощью removeChild() . Вот как удаляется наш список из предыдущего примера:

Теперь элемент удален. Метод removeChild() возвращает удаленный элемент и я могу его сохранить на случай, если он потребуется мне позже.

Таке существует метод ChildNode.remove() , относительно недавно добавленный в спецификацию:

Этот метод не возвращает удаленный объект и не работает в IE (только в Edge). И оба метода удаляют текстовые узлы точно так же, как и узлы-элементы.

Замена дочерних элементов

Я могу заменить существующий дочерний элемент новым, независимо от того, существует ли этот новый элемент или я создал его с нуля. Вот разметка:

Здесь я создал элемент, добавил текстовый узел с помощью createTextNode() и вставил его на страницу на место параграфа. Теперь на месте первоначального параграфа следующий HTML:

Как видите, метод replaceChild() принимает два аргумента: новый элемент и заменяемый им старый элемент.

Я также могу использовать это метод для перемещения существующего элемента. Взгляните на следующий HTML:

Я могу заменить третий параграф первым параграфом с помощью следующего кода:

Теперь сгенерированный DOM выглядит так:

Выборка конкретных дочерних элементов

Существует несколько разных способов выбора конкретного элемента. Как показано ранее, я могу начать с использования коллекции children или свойства childNodes . Но взглянем на другие варианты:

Свойства firstElementChild и lastElementChild делают именно то, чего от них можно ожидать по их названию: выбирают первый и последний дочерние элементы. Вернемся к нашей разметке:

Я могу выбрать первый и последний элементы с помощью этих свойств:

Я также могу использовать свойства previousElementSibling и nextElementSibling , если я хочу выбрать дочерние элементы, отличные от первого или последнего. Это делается сочетанием свойств firstElementChild и lastElementChild :

Также есть сходные свойства firstChild , lastChild , previousSibling , и nextSibling , но они учитывают все типы узлов, а не только элементы. Как правило, свойства, учитывающие только узлы-элементы полезнее тех, которые выбирают все узлы.

Вставка контента в DOM

Я уже рассматривал способы вставки элементов в DOM. Давайте перейдем к похожей теме и взглянем на новые возможности по вставке контента.

Во-первых, есть простой метод insertBefore() , он во многом похож на replaceChild() , принимает два аргумента и при этом работает как с новыми элементами, так и с существующими. Вот разметка:

Обратите внимание на параграф, я собираюсь сначала убрать его, а затем вставить перед списком, все одним махом:

В полученном HTML параграф будет перед списком и это еще один способ перенести элемент.

Как и replaceChild() , insertBefore() принимает два аргумента: добавляемый элемент и элемент, перед которым мы хотим его вставить.

Этот метод прост. Попробуем теперь более мощный способ вставки: метод insertAdjacentHTML() .

Этот код вставит определенную строку контента перед целевым элементом (в данном случае перед списком). Второй аргумент это строка с HTML, которую вы хотите вставить (это может быть и простой текст). Первый аргумент, это строка с одним из четырех возможных значений:

  • beforebegin – Вставляет строку перед указанным элементом.
  • afterbegin – Вставляет строку внутри указанного элемента перед первым дочерним элементом.
  • beforeend – Вставляет строку внутри указанного элемента после последнего дочернего элемента
  • afterend – Вставляет строку после указанного элемента

Чтобы было проще понять, как работает каждое из этих значений, взгляните на комментарии в сниппете разметки. Подразумевая, что #el div это целевой элемент, каждый комментарий показывает, где будет находится вставленный HTML.

Этот пример делает понятным, что делает каждое из этих значений.

Поддержка в браузерах

При обсуждении любых веб-технологий, их поддержка в браузерах всегда является важным фактором. Чтобы не ходить по граблям, ниже приводится список, что и как поддерживается:

Следующие возможности поддерживаются везде, включая старые версии IE:

Эти возможности поддерживаются в IE9+ и других современных браузерах:

И остается метод Node.remove(), который, как уже упоминалось, поддерживается Microsoft только начиная с браузера Edge.

В общем и целом, поддержка этих возможностей в браузерах превосходна. Конечно, остаются баги и проблемы с совместимостью, поэтому не забудьте тщательно протестировать все, если вы используете эти методы и свойства.

Заключение

В идеале, возможностей языка JavaScript и DOM API должно хватать для того, чтобы все делалось просто и кроссбраузерно. В итоге, мы к этому обязательно придем, но пока эти проблемы будут продолжать решаться с помощью инструментов типа jQuery.

Javascript:как перебрать все элементы DOM на странице?

Я пытаюсь зациклить все элементы на странице, поэтому я хочу проверить каждый элемент, который существует на этой странице для специального класса.

Итак, как сказать, что я хочу проверить каждый элемент?

9 ответов

вы можете пройти * to getElementsByTagName() так что он вернет все элементы на странице:

обратите внимание, что вы можете использовать querySelectorAll() , если он доступен (IE9+, CSS в IE8), чтобы просто найти элементы с определенным классом.

это, безусловно, ускорит вопросы для современных браузеров.

браузеры теперь поддерживают foreach на NodeList. Это означает, что вы можете напрямую цикла элементов вместо того, чтобы писать свой собственный цикл.

примечание по производительности — сделайте все возможное, чтобы охватить то, что вы ищете. Универсальный селектор может возвращать множество узлов, в зависимости от сложности страницы. Даже если вам нужно просмотреть все, что кто-то может увидеть, это означает, что вы можете использовать ‘body *’ как селектор, чтобы вырезать все head контента.

искал же. Ну, не совсем. Я только хотел перечислить все узлы DOM.

чтобы получить элементы с определенным классом, мы можем использовать функцию фильтра.

нашел решение на MDN

вот еще один пример того, как вы можете перебирать документ или элемент:

Как всегда лучшим решением является использование рекурсии:

В отличие от других предложений, это решение не требует создания массива для всех узлов, поэтому его больше света в памяти. Что более важно, он находит больше результатов. Я не уверен, каковы эти результаты, но при тестировании на chrome он находит около 50% больше узлов по сравнению с document.getElementsByTagName(«*»);

для тех, кто использует Jquery

UPDATE: EDIT

С момента моего последнего ответа я нашел более простое решение

Энди э. дал хороший ответ.

Я бы добавил, Если вы чувствуете, чтобы выбрать всех детей в каком-то специальном селекторе (это произошло со мной недавно), вы можете применить метод «getElementsByTagName()» на любом объекте DOM вы хотите.

например, мне нужно было просто разобрать «визуальную» часть веб-страницы, поэтому я просто сделал это

Это никогда не будет принимать во внимание головную часть.

DOM — Списки узлов

Объект NodeList — это список (набор) узлов, извлеченных из документа.

Объект NodeList — это почти то же самое, что объект HTMLCollection (см. предыдущую главу).

Некоторые (старые) браузеры возвращают объект NodeList вместо HTMLCollection при работе таких методов как, например, getElementsByClassName().

Во всех браузерах свойство childNodes возвращает объект NodeList.

В большинстве браузеров метод querySelectorAll() возвращает объект NodeList.

В следующем примере отбираются в документе все узлы

Доступ к элементам в объекте NodeList можно получить по номеру индекса.

Так, чтобы получить доступ ко второму узлу

Внимание! Индексация узлов начинается с 0.

Длина объекта NodeList

Свойство length определяет количество узлов в наборе NodeList:

    Создаем список всех элементов

  • Выводим на экран длину этого списка
  • Свойство length бывает полезно, когда необходимо в цикле обойти все узлы в списке NodeList.

    В следующем примере изменяется фоновый цвет всех элементов

    Разница между HTMLCollection и NodeList

    HTMLCollection — это набор HTML элементов (см. предыдущую главу).

    NodeList — это набор узлов документа.

    NodeList и HTMLCollection — во многом одно и то же.

    И объект HTMLCollection, и объект NodeList — похожие на массив списки (наборы) объектов.

    У обоих есть свойство length, которое определяет количество объектов в списке (наборе).

    Оба, как в массиве, предоставляют индекс (0, 1, 2, 3, 4, . ) для доступа к каждому объекту списка.

    Доступ к объектам списка HTMLCollection можно получить по их именам, id или номеру индекса.

    Доступ к объектам списка NodeList можно получить только по их номеру индекса.

    Только объект NodeList может содержать узлы атрибутов и текстовые узлы.

    Внимание! NodeList — это НЕ массив! Он может выглядеть как массив, но на самом деле им не является. Вы можете в цикле проходить по списку узлов и ссылаться на узлы как в массиве, но вы не можете использовать методы массива valueOf(), pop(), push() или join() со списком узлов.

    Информационные технологии, интернет, веб программирование, IT, Hi-Tech, …

    Проход По Узлам

    Здравствуйте, уважаемые читатели блога okITgo.ru! Сразу сделаю несколько пояснений относительно используемой в данной статье терминологии.

    Термин обход дерева здесь обозначает циклический перебор или перемещение по всем узлам дерева в цикле.

    Проход по узлам осуществляется посредством взаимоотношений между узлами (таких как отец, сын, следующий брат, предыдущий брат и т.п.).

    Обход Дерева Узлов

    Довольно часто позникает задача циклического обхода по всем узлам XML документа, например: когда Вы хотите извлечь значение каждого элемента.

    Это действие называется «Обходом дерева узлов»

    Пример ниже переберает в цикле все дочерние узлы и отображает их имена и значения:

    JavaScript — DOM: добавление и удаление узлов

    На этом уроке мы научимся создавать узлы-элементы ( createElement ) и текстовые узлы ( createTextNode ). А также рассмотрим методы, предназначенные для добавления узлов к дереву ( appendChild , insertBefore ) и для удаления узлов из дерева ( removeChild ).

    Добавление узлов к дереву

    Добавление нового узла к дереву обычно осуществляется в 2 этапа:

    1. Создать необходимый узел, используя один из следующих методов:
      • createElement() — создаёт элемент (узел) с указанным именем (тегом). Метод createElement(element) имеет один обязательный параметр ( element ) — это строка, содержащая имя создаваемого элемент (тега). Указывать имя элемента (тега) в параметре необходимо заглавными буквами. В качестве результата данный метод возвращает элемент, который был создан.
      • createTextNode() — создаёт текстовый узел с указанным текстом. Метод createTextNode(text) имеет один обязательный параметр ( text ) — это строка, содержащая текст текстового узла. В качестве результата данный метод возвращает текстовый узел, который был создан.
    2. Указать место в дереве, куда необходимо вставить узел. Для этого необходимо воспользоваться одним из следующих методов:
      • appendChild() — добавляет узел как последний дочерний узел элемента, для которого вызывается данный метод. Метод appendChild(node) имеет один обязательный параметр это узел ( node ), который Вы хотите добавить. В качестве результата данный метод возвращает добавленный узел.
      • insertBefore() — вставляет узел как дочерний узел элемента, для которого вызывается данный метод. Метод insertBefore(newNode,existingNode) имеет два параметра: newNode (обязательный) — узел, который Вы хотите добавить, existingNode (не обязательный) — это дочерний узел элемента перед которым, необходимо вставить узел. Если второй параметр ( existingNode ) не указать, то данный метод вставит его в конец, т.е. в качестве последнего дочернего узла элемента для которого вызывается данный метод. В качестве результата метод insertBefore() возвращает вставленный узел.

    Рассмотрим более сложный пример, в котором добавим к дереву узел LI , содержащий текстовый узел с текстом «Смартфон», в конец списка ul .

    Для этого необходимо выполнить следующее:

    1. Создать элемент (узел) LI .
    2. Создать текстовый узел, содержащий текст «Смартфон».
    3. Добавить созданный текстовый узел как последний дочерний узел только что созданному элементу LI
    4. Добавить недавно созданный узел LI как последний дочерний узел элемента ul

    Методы appendChild() и insertBefore() при работе с существующими узлами

    Работа с существующими узлами методами appendChild() и insertBefore() также осуществляется в 2 этапа:

    1. Получить существующий узел в дереве.
    2. Указать место, куда необходимо вставить узел, с помощью метода appendChild() или insertBefore() . При этом узел будет удалён из предыдущего места.

    Например, добавить существующий элемент li , содержащий текст “Планшет» в начало списка (при этом он будет удалён из предыдущего места):

    Задание

    • Имеется два списка в документе. Необходимо переместить элементы из второго списка в первый.
    • Создать список, текстовое поле и 2 кнопки. Написать код на языке JavaScript, который в зависимости от нажатой кнопки добавляет текст, находящийся в текстовом поле, в начало или в конец списка.

    Удаление узлов

    Удаление узла из дерева осуществляется в 2 этапа:

    1. Получить (найти) этот узел в дереве. Это действие обычно осуществляется одним из следующих методов: getElementById() , getElementsByClassName() , getElementsByTagName() , getElementsByName() , querySelector() или querySelectorAll() .
    2. Вызвать у родительского узла метод removeChild() , которому в качестве параметра необходимо передать узел, который мы хотим у него удалить.
      Метод removeChild() возвращает в качестве значения удалённый узел или null , если узел, который мы хотели удалить, не существовал.

    Например, удалить последний дочерний элемент у элемента, имеющего :

    Например, удалить все дочерние узлы у элемента, имеющего :

    Илон Маск рекомендует:  Жирность шрифта
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL