JavaScript чаще всего работает с уже существующими элементами страницы. При этом эти элементы как-то нужно выбрать. Методы, рассмотренные в данной статье, помогут вам это сделать. При работе с элементами страницы нужно соблюдать 2 условия:

  1. Размещать теги <script></script> вместе с нужным вам кодом после тех элементов html-страницы, которыми он (код) будет манипулировать. В идеале - перед закрывающимся тегом </body>, т.к. именно в нем размещается вся разметка. Если теги <script></script> размещены в блоке <head></head>, то нужно писать код в обработчике события window.onload = function(){} или
  2. Правильно находить элементы и перебирать их, т.к. в большинстве случаев у вас будет не один, а несколько элементов.
  3. Понимать, что коллекции элеметов отличаются от массивов

В этой статье мы рассмотрим такие методы для поиска элементов на странице:

  1. document.getElementById()
  2. document.querySelector()
  3. element.closest()
  4. element.matches()
  5. Метод contains()
  6. document.querySelectorAll()
  7. document.getElementsByClassName()
  8. document.getElementsByTagName()
  9. document.getElementsByName()

Методы для поиска одного элемента

Оба метода, рассмотренные ниже, возвращают ссылку на html-элемент, который соответствует вашему запросу.

Метод document.getElementById()

Метод document.getElementById('some_id') позволяет найти элемент по его id, который передается в скобках в качестве строкового параметра. Согласно спецификации HTML элемент с таким id на странице должен быть в единственном экземпляре. Если вы нарушили это правило, то HTML-CSS это пропустят,  отформатируют несколько элементов одинаково, а вот JavaScript найдет только первый такой элемент и отформатирует только его.

Например, у нас есть такая разметка и css-стили:

Как видно из примера, css-форматирование применилось ко всем 3-м блокам с id="someWrapper", хотя это и противоречит семантике.

Block 1 in someWrapper 1

Block 2 in someWrapper 2

Block 3 in someWrapper 3

Block 1 in someWrapper 1

Block 2 in someWrapper 2

Block 3 in someWrapper 3

Block 1 in someWrapper 1

Block 2 in someWrapper 2

Block 3 in someWrapper 3

Давайте напишем JS-код и применим его при клике на кнопке для нашего примера.

Щелкните на кнопку и посмотрите на внешний вид блоков выше.

JavaScript нашел самый верхний элемент по id="someWrapper" и изменил его фоновый цвет. Вторая строчка сработала даже без использования метода document.getElementById('someWrapper'), т.к. такой id является уникальным для данной страницы. Использовать такой подход к элементу с id="some-wrapper" (some-wrapper.style.fontStyle = 'italic') не получится, т.к. вы получите ошибку вида "Invalid left-hand side in assignment".

Такой подход был давно использован в Internet Explorer, а затем вошел в стандарт HTML 5. Связано такое поведение браузеров с тем, что id объекта становится глобальной переменной window["id"] и может быть вызвано в любом месте кода. С этой точки зрения можно обратиться к элементу с id="some-wrapper" как window["some-wrapper"] - и у вас все получится.

Минусом такого подхода является то, что использование глобальных переменных не приветствуется в JavaScript, т.к. возможна ситуация, когда такая переменная встретится в другом скрипте и будет являться функцией, например. Это может привести к ошибкам. Поэтому стоит все-так воспользоваться методом document.getElementById('some_id') во избежание таких ошибок и для совместимости с более старыми версиями браузеров.

Метод document.querySelector()

Метод document.querySelector('css-selector') позволяет найти первый элемент на странице, соответствующий css-селектору, переданному в качестве параметра. Из названия и характеристики этого метода понятно, что нужно ориентироваться во всем многообразии css-селекторов. Справедливости ради следует заметить, что его можно использовать и для поиска элемента по id или классу (это простые селекторы, которые должны быть известны каждому). В первом случае он будет заменой методу document.getElementById(), во втором - найдет первый элемент с указанным классом.

Рассмотрим пример:

Вот, что получим в результате:

  1. Элемент списка 1
  2. Элемент списка 2
  3. Элемент списка 3
  4. Элемент списка 4
  5. Элемент списка 5
  6. Элемент списка 6
  7. Элемент списка 7

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

Примечание: в JavaScript есть ряд объектов, к которым существует индивидуальное обращение:

  • document - главный элемент, из которого мы можем добраться до любых элементов;
  • document.documentElement - это корневой тег нашего документа, т.е. <html>
  • document.body - это основной тег, внутри которого находятся все остальные, с которыми мы потом работаем, т.е. <body>
  • document.head - тег заголовочной части нашего документа, т.е. <head> (есть во всех современных браузерах, кроме IE8 и ниже).

Метод element.closest()

Метод element.closest() предназначен для поиска ближайшего родительского элемента или данного элемента, который соответствует переданному в скобках селектору. Если такой элемент не найдется, вернется null.  Синтаксис:

Т.е. в скобках вы передаете селектор, который соответствует правилам записи селекторов в css.

Учтите, что вернуться может и ссылка на тот элемент, относительно которого мы выполняем поиск, если других соответствий не найдено или вы задали слишком общий селектор, например в виде селектора элемента (span, p, div и т.д.)

Чаще всего метод element.closest() применяется для поиска родительского элемента при обработке события на каком-либо вложенном элементе. Распространенный пример - удаление строки таблицы при оформлении заказа в интернет магазине. Код примера таков:

Обратите внимание, что для подсчета стоимости всех товаров в корзине в функции showPrice() мы использовали метод массивов reduce, предварительно преобразовав коллекцию элементов в массив методом Array.from().

Тестируем пример с корзиной:

Наименование Количество Цена, грн Удалить
Рюкзак школьный Rainbow Girl 1 269
Пенал Smart Power 4x4 1 99
Фломастеры BIC Visa 12 цветов 1 87
Набор шариковых ручек 4 шт BIC 1 32
Итого  

Метод element.matches("селектор")

Метод element.matches("css-селектор") возвращает true или false в зависимости от того, соответствует ли элемент указанному css-селектору. Селектор вы задаете по правилам css, то есть для выбора по id="my-test" задаем "#my-test", для поиска класса внутри списка "ul .my-class" аналогично тому, как это делали в методе querySelector().

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

Код будет таким:

Результат: 3-й элемент списка действительно стал красным:

  • Lorem ipsum dolor sit.
  • Quae quis, eveniet provident.
  • Possimus laudantium, soluta error?
  • Ea suscipit, provident quos!

Примечание: В некоторых браузерах данный метод имеет нестандартное название - matchesSelector().

Метод contains()

Метод Node.contains(element) проверяет содержит ли некий родительский узел Node вложенный в него element. Возвращает этот метод логическое значение true или false, которое указывает, является ли узел потомком данного узла, т. е. сам узел, один из его прямых потомков ( childNodes ), один из детей его детей и так далее.

В плане практического использования приведем такой пример: у нас есть 4 блока, в которых 2 содержат ссылку на внешний источник, а 2 обходятся без нее. Чтобы не портить внешний вид блока, мы проверяем, существует ли в нем ссылка с классом "descr" и добавляем к ней класс, задающий абсолютное позиционирование.

Кликните по кнопке "Проверить", чтобы увидеть разницу в форматировании.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius, libero.

More from site...

Architecto enim est neque ea atque modi quaerat. Nesciunt, doloremque.

Nemo praesentium ipsa maxime ducimus harum. Beatae corrupti ipsum quam?

Cupiditate rerum dolor officiis, dolores tempore debitis! Deserunt, sapiente, mollitia!

More from wikipedia...

Методы для поиска нескольких элементов

Как правило, на странице есть некоторое количество элементов с одинаковыми классами, названиями тегов (абзацы <p>, например, или <nav>) или последние ячейки в каждой строке таблицы. Манипулировать их css-свойствами желательно прежде всего с помощью стилей, но довольно часто нужно назначать css или обработчики событий динамически и сразу всем однотипным элементам.

Метод document.querySelectorAll()

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

Исключением для метода document.querySelectorAll() является метод forEach(), который поможет вам перебрать элементы коллекции и назначить нужные вам свойства или обработчики событий. Другие методы для поиска нескольких элементов не дают такой возможности, т.к. не имеют метода forEach(). Имейте в виду, что и для document.querySelectorAll() метод forEach() был добавлен относительно недавно, поэтому некоторые не слишком новые версии браузеров могут выдавать ошибку при его использовании.

В примере ниже мы применим метод  document.querySelectorAll() для назначения обработчика события клика, в котором добавим к каждому элементу набора css-свойство animation.

Давайте посмотрим на результат: все работает - по клику блоки исчезают за полсекунды.

Бжж
Бжж
Бжж
Бжж
Бжж

Примечание: метод querySelectorAll() можно применять, обращаясь не только ко всему документу (document), но и к какому-либо элементу, ссылку на который вы сохраняли ранее. В примере с удалением строки таблицы заказа с помощью метода element.closest(), была использована такая запись для поиска всех ячеек таблицы с ценой:

На самом деле дальше можно уже не читать, т.к метод document.querySelectorAll()  позволяет сделать любые выборки, которые вы можете использовать, как вам заблагорассудится. Все остальные методы являются на данный момент уже устаревшими в силу того, что область их действия значительно меньше, чем у document.querySelectorAll() . Однако вы можете использовать другие методы с целью поддержки устаревших браузеров или при необходимости работы только с определенными классами или тегами.

Метод document.getElementsByClassName()

Как следует из его названия, метод document.getElementsByClassName('className') возвращает HTML-коллекцию из элементов, имеющих в качестве атрибута переданный в скобках класс. Т.е. у него более узкий спектр выборки, чем у document.querySelectorAll(). Тем не менее, его можно использовать, если вам вполне достаточно выбрать именно элементы одного класса.

В примере ниже мы с помощью метода document.getElementsByClassName('className') выберем все абзацы с классом "example-edit" и сделаем их по событию клика редактируемыми за счет добавления атрибута contenteditable = "true". Кроме того, обработаем событие oninput, которое позволит нам подсчитать и вывести количество символов в каждом абзаце.

Обратите внимание, что здесь мы использовали цикл for(), т.к. метод forEach() для такой выборки применить не удастся.

Проверяем действие скрипта на живом примере:

Lorem ipsum dolor sit amet...

Perferendis adipisci voluptas ...

Quibusdam dolore cum aspernatur,...

Fugiat, a, esse. Laudantium ...

Ipsa ipsam aspernatur vel...

Minus maiores, dolor ne...

Метод document.getElementsByTagName()

Метод document.getElementsByTagName('tagName') предназначен для выбора элеметов по определенному тегу. То есть он дает нам доступ ко всем абзацам, input-ам или section на нашей html-странице.

Давайте посмотрим, сработает ли наш скрипт для строк таблицы:

Данные сотрудников
N п/п Ф.И.О. Должность Email Тел.
1 Кононов Иван Петрович Генеральный директор director@some-company.com (099) 223-44-55
2 Кондрашов Олег Николаевич Финансовый директор finansist@some-company.com (099) 224-44-56
3 Любочкина Ирина Сергеевна Главный бухгалтер glavbuh@some-company.com (099) 224-45-57
4 Смородинова Валентина Эдуардовна Начальник отдела кадров hr@some-company.com (099) 224-46-56
5 Веревкин Константин Степанович Главный менеджер top-manager@some-company.com (099) 224-48-67

Метод document.getElementsByName()

Метод document.getElementsByName('name') предполагает, что у элементов на странице должен быть атрибут name. Такой атрибут есть у элементов форм. Поскольку этот метод собирает элементы с указанным в скобках именем в коллекцию (псевдомассив), то чаще всего используют этот метод для радио-кнопок (переключателей) или флажков (чекбоксов), у которых имена могут быть одинаковыми. Это элементы вида <input type="radio"> или  <input type="checkbox">. Ко всем остальным элементам форм этот метод применять вряд ли имеет смысл, т.к. они, скорей всего, будут иметь уникальные имена.
Попробуйте изменить цвет фона этой статьи с помощью радио-переключателей в примере ниже.

Измените цвет фона статьи

Вот код, который позволяет это сделать:

В коде мы используем цикл for...of для перебора всех элементов типа radio.

Динамические и статические коллекции

Методы, которые были рассмотрены последними, а именно document.getElementsByName(), document.getElementsByTagName() и document.getElementsByClassName() хранят внутри себя динамические коллекции html-элементов, которые подразумевают, что количество элементов в них может увеличиваться, если элементы получаются путем клонирования, например, или уменьшаться, если элементы исчезают со страницы за счет удаления их методом remove() или removeChild(), или потому что меняют имя класса. В некоторых случаях это может вызвать ваше недоумение, т.к. элементы будут вести себя не так, как вы рассчитывали. Это можно назвать некоторым минусом. С другой стороны, такое поведение позволяет отследить количество постоянно меняющихся элементов, например, в списке задач. И это уже плюс.

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

Для ссылок, изображений и форм есть свои особые коллекции, которые можно использовать параллельно с другими методами, а именно:

  1. document.links - для всех ссылок на странице
  2. document.images - для изображений
  3. document.forms - для форм

При необходимости вы можете обращаться к ним, как к элементам массива, например, доступ к первой ссылке на странице будет выглядеть, как document.links[0], а ко второму изображению, как document.images[1]. Кроме того, к ним можно обращаться по id или по name, например, document.forms['myForm'].

Обратите внимание, что в конце наименования все эти коллекции имеют букву "s", т.е. подразумевается, что на странице может быть несколько ссылок, картинок и форм. И даже, если картинка, ссылка или форма одна, обратится к ней можно только через название коллекции с "s" в конце, например, document.images['pic1'] при наличии в html-разметке строки:

Пример использования коллекции document.links вы можете посмотреть в статье "Обработка события onkeyup" для сортировки списка контактов.

Использование методов массивов для html-коллекций

Как уже упоминалось ранее, html-коллекции - это псевдомассивы, которые имеют нумерованные индексы для каждого элемента, возвращают их количество в свойстве length, но при этом не позволяют перебирать массивы такими методами, как forEach(), map(), reduce(), filter() и т.д.

Тем не менее, мы можем изменить ситуацияю, превратив псевдомассив в массив.

Способ 1. Использование метода call()

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

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

Способ 2. Использование метода Array.from()

Метод Array.from() значительно более новый, чем call(), поддерживается только современными браузерами, но имеет простой и понятный синтаксис. Он преобразует псевдомассив в массив таким способом:

Способ 3. Использование оператора расширения

Оператор расширения, или spread-оператор, еще проще - вы помещаете нужный псевдомассив в квадратные скобки с троеточием и таким образом превращаете его в массив:

После такого преобразования вы можете пользоваться всеми методами массивов для html-коллекций.

Автор: Админ

4 комментария

  1. Доброго времени суток! Спасибо, автор. Очень рад, что нашел ваши статьи. Просто, доходчиво и понятно. А самое главное примеры жизненные. Спасибо! Удачи!

    • Спасибо за ваш комментарий. Хотелось сделать именно просто и доходчиво.

  2. Здравствуйте! Нашел ваш сайт. Очень хороший. Даже отличный. Спасибо Вам!

    • Спасибо! Очень приятно читать такие комментарии.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *