JavaScript чаще всего работает с уже существующими элементами страницы. При этом эти элементы как-то нужно выбрать. Методы, рассмотренные в данной статье, помогут вам это сделать. При работе с элементами страницы нужно соблюдать 2 условия:
- Размещать теги
<script></script>
вместе с нужным вам кодом после тех элементов html-страницы, которыми он (код) будет манипулировать. В идеале - перед закрывающимся тегом</body>
, т.к. именно в нем размещается вся разметка. Если теги<script></script>
размещены в блоке<head></head>
, то нужно писать код в обработчике событияwindow.onload = function(){}
или
123document.addEventListener("DOMContentLoaded",function(event) { console.log("DOM структура загружена");}); - Правильно находить элементы и перебирать их, т.к. в большинстве случаев у вас будет не один, а несколько элементов.
- Понимать, что коллекции элеметов отличаются от массивов
В этой статье мы рассмотрим такие методы для поиска элементов на странице:
- document.getElementById()
- document.querySelector()
- element.closest()
- element.matches()
- Метод contains()
- document.querySelectorAll()
- document.getElementsByClassName()
- document.getElementsByTagName()
- document.getElementsByName()
Методы для поиска одного элемента
Оба метода, рассмотренные ниже, возвращают ссылку на html-элемент, который соответствует вашему запросу.
Метод document.getElementById()
Метод document.getElementById('some_id')
позволяет найти элемент по его id, который передается в скобках в качестве строкового параметра. Согласно спецификации HTML элемент с таким id на странице должен быть в единственном экземпляре. Если вы нарушили это правило, то HTML-CSS это пропустят, отформатируют несколько элементов одинаково, а вот JavaScript найдет только первый такой элемент и отформатирует только его.
Например, у нас есть такая разметка и css-стили:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <style> #someWrapper { display: flex; justify-content: space-between; text-align: center; } .some-block { border: 2px dotted blue; padding: 10px; flex: 0 0 28%; margin-bottom: 10px; } </style> <div id="someWrapper"> <div class="some-block"> <h2>Block 1 in someWrapper 1</h2> </div> <div class="some-block"> <h2>Block 2 in someWrapper 2</h2> </div> <div class="some-block"> <h2>Block 3 in someWrapper 3</h2> </div> </div> <div id="someWrapper"> <div class="some-block"> <h2>Block 1 in someWrapper 1</h2> </div> ... </div> <div id="someWrapper"> <div class="some-block"> <h2>Block 1 in someWrapper 1</h2> </div> ... </div> |
Как видно из примера, 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-код и применим его при клике на кнопке для нашего примера.
1 2 3 4 | const some=document.getElementById('someWrapper'); some.style.backgroundColor = '#cde'; //если обратиться просто по id, тоже сработает someWrapper.style.fontStyle = 'italic'; |
Щелкните на кнопку и посмотрите на внешний вид блоков выше.
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <ol id="testOl"> <li class='li-item'>Элемент списка <strong>1</strong></li> <li class='li-item'>Элемент списка <strong>2</strong></li> <li class='li-item'>Элемент списка <strong>3</strong></li> <li class='li-item'>Элемент списка <strong>4</strong></li> <li class='li-item'>Элемент списка <strong>5</strong></li> <li class='li-item'>Элемент списка <strong>6</strong></li> <li class='li-item'>Элемент списка <strong>7</strong></li> </ol> <script> const liItem = document.querySelector('.li-item'), liLast = document.querySelector('#testOl li:last-child'), strongElem = document.querySelector('#testOl .li-item:nth-child(3) strong'); console.log(liLast); liItem.style.cssText = 'line-height: 2; background-color:#8af2ce;' liLast.style.cssText = 'list-style-type:upper-roman; font-weight: bold'; strongElem.style.color = 'red'; </script> |
Вот, что получим в результате:
- Элемент списка 1
- Элемент списка 2
- Элемент списка 3
- Элемент списка 4
- Элемент списка 5
- Элемент списка 6
- Элемент списка 7
На самом деле все достаточно предсказуемо, если проанализировать, какие именно селекторы мы передали этому методу. Для демонстрации изменений были использованы свойства, позволяющие изменять стилевые свойства из JavaScript.
Примечание: в JavaScript есть ряд объектов, к которым существует индивидуальное обращение:
document
- главный элемент, из которого мы можем добраться до любых элементов;document.documentElement
- это корневой тег нашего документа, т.е.<html>
document.body
- это основной тег, внутри которого находятся все остальные, с которыми мы потом работаем, т.е.<body>
document.head
- тег заголовочной части нашего документа, т.е.<head>
(есть во всех современных браузерах, кроме IE8 и ниже).
Метод element.closest()
Метод element.closest() предназначен для поиска ближайшего родительского элемента или данного элемента, который соответствует переданному в скобках селектору. Если такой элемент не найдется, вернется null
. Синтаксис:
1 2 3 4 | //элемент с классом row, который находится внутри элемента с id wrap let parent = element.closest('#wrap .row'); //или div, у которого есть атрибут data-description let div = element.closest('div[data-description]'); |
Т.е. в скобках вы передаете селектор, который соответствует правилам записи селекторов в css.
Учтите, что вернуться может и ссылка на тот элемент, относительно которого мы выполняем поиск, если других соответствий не найдено или вы задали слишком общий селектор, например в виде селектора элемента (span, p, div и т.д.)
Чаще всего метод element.closest() применяется для поиска родительского элемента при обработке события на каком-либо вложенном элементе. Распространенный пример - удаление строки таблицы при оформлении заказа в интернет магазине. Код примера таков:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <table id="basket"> <thead> <tr> <th>Наименование</th> <th>Количество</th> <th>Цена, грн</th> <th>Удалить</th> </tr> </thead> <tbody> <tr> <td>Рюкзак школьный Rainbow Girl</td> <td>1</td> <td>269</td> <td><span class="trash"></span></td> </tr> <tr> <td>Пенал Smart Power 4x4 </td> <td>1</td> <td>99</td> <td><span class="trash"></span></td> </tr> <tr> <td>Фломастеры BIC Visa 12 цветов</td> <td>1</td> <td>87</td> <td><span class="trash"></span></td> </tr> <tr> <td>Набор шариковых ручек 4 шт BIC</td> <td>1</td> <td>32</td> <td><span class="trash"></span></td> </tr> <tr> <td>Итого</td> <td colspan="2" id="itogo"></td> <th> </th> </tr> </tbody> </table> <script> let trash = document.querySelectorAll('#basket .trash'), basket = document.getElementById('basket');; trash.forEach(del => del.onclick = function() { if (confirm("Вы уверены?")) this.closest('tr').remove(); showPrice(); }); function showPrice() { let priceTd = basket.querySelectorAll('td:nth-child(3)'); priceTd = Array.from(priceTd); let summa = 0; summa = priceTd.reduce((res, el) => summa += +el.textContent, 0); itogo.textContent = summa; } showPrice(); </script> |
Обратите внимание, что для подсчета стоимости всех товаров в корзине в функции 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, но, предположим, что номер элемента мы получаем от пользователя динамически.
Код будет таким:
1 2 3 4 5 6 7 8 9 10 11 12 | <ul> <li>Lorem ipsum dolor sit.</li> <li>Quae quis, eveniet provident.</li> <li>Possimus laudantium, soluta error?</li> <li>Ea suscipit, provident quos!</li> </ul> <script> let li = document.querySelectorAll('li'); for(item of li){ if(item.matches('li:nth-child(3)')) item.style.color = 'red'; } </script> |
Результат: 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" и добавляем к ней класс, задающий абсолютное позиционирование.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <style> .test-block { display: inline-block; vertical-align: top; width: 180px; height: 110px; padding: 16px; padding-top: 22px; margin-right: 10px; border: 2px dotted #ccc; background-color: #898989; position: relative; color: #fff; } .descr { text-decoration: none; color: inherit; display: block; text-align: center; padding: 7px; background-color: rgba(255, 255, 255, 0.5); } .above { width: 100%; position: absolute; top: 0; left: 0; } </style> <div class="test"> <div class="test-block"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius, libero.</p> <a class="descr" href="#">More from site...</a> </div> <div class="test-block"> <p>Architecto enim est neque ea atque modi quaerat. Nesciunt, doloremque.</p> </div> <div class="test-block"> <p>Nemo praesentium ipsa maxime ducimus harum. Beatae corrupti ipsum quam?</p> </div> <div class="test-block"> <p>Cupiditate rerum dolor officiis, dolores tempore debitis! Deserunt, sapiente, mollitia!</p> <a class="descr" href="#">More from wikipedia...</a> </div> <button type="button" class="button" id="testBlocks">Проверить</button> <script> var btn = document.getElementById('testBlocks'); btn.onclick = function(){ let blocks = document.querySelectorAll('.test-block'); for(elem of blocks){ let descr = elem.querySelector('.descr'); if(elem.contains(descr)) descr.classList.add('above') } this.hidden=true; } </script> </div> |
Кликните по кнопке "Проверить", чтобы увидеть разницу в форматировании.
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
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <style> @keyframes fade{ 99% {opacity: 0;} 100% {visibility: hidden;} } .bee { background-image: repeating-linear-gradient(#000 0,#000 8px, #ff0 10px, #ff0 21px); width: 70px; height: 70px; display: inline-block; margin: 10px; border: 2px solid #000; border-radius: 50%; line-height: 70px; text-align: center; cursor: pointer; } </style> <div id="example-query"> <div class="bee"><strong>Бжж</strong></div> <div class="bee"><strong>Бжж</strong></div> <div class="bee"><strong>Бжж</strong></div> <div class="bee"><strong>Бжж</strong></div> <div class="bee"><strong>Бжж</strong></div> </div> <script> let beeCollection = document.querySelectorAll('#example-query .bee'); beeCollection.forEach(item => item.addEventListener('click', function(){ item.style.animation = "fade .5s ease-out forwards" }) ); </script> </body> |
Давайте посмотрим на результат: все работает - по клику блоки исчезают за полсекунды.
Примечание: метод querySelectorAll()
можно применять, обращаясь не только ко всему документу (document
), но и к какому-либо элементу, ссылку на который вы сохраняли ранее. В примере с удалением строки таблицы заказа с помощью метода element.closest(), была использована такая запись для поиска всех ячеек таблицы с ценой:
1 | let priceTd = basket.querySelectorAll('td:nth-child(3)'); |
На самом деле дальше можно уже не читать, т.к метод document.querySelectorAll()
позволяет сделать любые выборки, которые вы можете использовать, как вам заблагорассудится. Все остальные методы являются на данный момент уже устаревшими в силу того, что область их действия значительно меньше, чем у document.querySelectorAll()
. Однако вы можете использовать другие методы с целью поддержки устаревших браузеров или при необходимости работы только с определенными классами или тегами.
Метод document.getElementsByClassName()
Как следует из его названия, метод document.getElementsByClassName('className') возвращает HTML-коллекцию из элементов, имеющих в качестве атрибута переданный в скобках класс. Т.е. у него более узкий спектр выборки, чем у document.querySelectorAll()
. Тем не менее, его можно использовать, если вам вполне достаточно выбрать именно элементы одного класса.
В примере ниже мы с помощью метода document.getElementsByClassName('className')
выберем все абзацы с классом "example-edit"
и сделаем их по событию клика редактируемыми за счет добавления атрибута contenteditable = "true"
. Кроме того, обработаем событие oninput
, которое позволит нам подсчитать и вывести количество символов в каждом абзаце.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <style> .example-edit { padding: 5px; } </style> <div id="example-class"> <p class="example-edit">Lorem ipsum dolor sit amet...</p> <p class="example-edit">Perferendis adipisci voluptas ...</p> <p class="example-edit">Quibusdam dolore cum aspernatur,...</p> <p class="example-edit">Fugiat, a, esse. Laudantium ...</p> <p class="example-edit">Ipsa ipsam aspernatur vel...</p> <p class="example-edit">Minus maiores, dolor ne...</p> </div> <script> let pEdit = document.getElementsByClassName('example-edit'); console.log(pEdit); for (let i = 0, len = pEdit.length; i < len; i++) { pEdit[i].insertAdjacentHTML('beforeEnd', ' <input type="text" value="' + pEdit[i].textContent.length + ' символов" readonly>'); pEdit[i].onclick = function() { this.contentEditable = "true"; this.style.border = '1px solid #cde'; } pEdit[i].oninput = function() { let input = this.lastElementChild; if(input.tagName != 'INPUT') input = this.lastElementChild.lastElementChild; input.value = this.textContent.length + ' символов'; } } </script> |
Обратите внимание, что здесь мы использовали цикл 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-странице.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | <style> .select {background-color: #ffdc68; } #testTable tr {cursor: pointer} </style> <table id="testTable" class="unselectable"> <caption>Данные сотрудников</caption> <tr> <th>N п/п</th> <th>Ф.И.О.</th> <th>Должность</th> <th>Email</th> <th>Тел.</th> </tr> <tr> <td>1</td> <td>Кононов Иван Петрович</td> <td>Генеральный директор</td> <td>director@some-company.com</td> <td>(099) 223-44-55</td> </tr> <tr> <td>2</td> <td>Кондрашов Олег Николаевич</td> <td>Финансовый директор</td> <td>finansist@some-company.com</td> <td>(099) 224-44-56</td> </tr> <tr> <td>3</td> <td>Любочкина Ирина Сергеевна</td> <td>Главный бухгалтер</td> <td>glavbuh@some-company.com</td> <td>(099) 224-45-57</td> </tr> <tr> <td>4</td> <td>Смородинова Валентина Эдуардовна</td> <td>Начальник отдела кадров</td> <td>hr@some-company.com</td> <td>(099) 224-46-56</td> </tr> <tr> <td>5</td> <td>Веревкин Константин Степанович</td> <td>Главный менеджер</td> <td>top-manager@some-company.com</td> <td>(099) 224-48-67</td> </tr> </table> </table> <script> let tr = testTable.getElementsByTagName('tr'); tr = [].slice.call(tr); tr.forEach((item, index) => { if (index>0) item.onclick = function(evt){ this.classList.toggle('select'); } }) </script> |
Давайте посмотрим, сработает ли наш скрипт для строк таблицы:
N п/п | Ф.И.О. | Должность | Тел. | |
---|---|---|---|---|
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">
. Ко всем остальным элементам форм этот метод применять вряд ли имеет смысл, т.к. они, скорей всего, будут иметь уникальные имена.
Попробуйте изменить цвет фона этой статьи с помощью радио-переключателей в примере ниже.
Вот код, который позволяет это сделать:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <fieldset class="test control"> <legend>Измените цвет фона статьи</legend> <label><input type="radio" name="color-control" value="white" checked=""> белый</label> <label><input type="radio" name="color-control" value="beige"> бежевый</label> <label><input type="radio" name="color-control" value="#cde"> светло-голубой</label> <label><input type="radio" name="color-control" value="#ccc"> серый</label> </fieldset> <script> let colorRadio = document.getElementsByName('color-control'), article = document.querySelector('article'); for(let one of colorRadio){ one.onclick = function(){ article.style.backgroundColor = this.value; } } </script> |
В коде мы используем цикл for...of
для перебора всех элементов типа radio.
Динамические и статические коллекции
Методы, которые были рассмотрены последними, а именно document.getElementsByName()
, document.getElementsByTagName()
и document.getElementsByClassName()
хранят внутри себя динамические коллекции html-элементов, которые подразумевают, что количество элементов в них может увеличиваться, если элементы получаются путем клонирования, например, или уменьшаться, если элементы исчезают со страницы за счет удаления их методом remove()
или removeChild()
, или потому что меняют имя класса. В некоторых случаях это может вызвать ваше недоумение, т.к. элементы будут вести себя не так, как вы рассчитывали. Это можно назвать некоторым минусом. С другой стороны, такое поведение позволяет отследить количество постоянно меняющихся элементов, например, в списке задач. И это уже плюс.
Метод document.querySelectorAll()
хранит выборку из некоторого количества узлов DOM-дерева, которые были на странице на момент вызова этого метода. Поэтому вновь созданные элементы, соответствующие указанному в нем селектору, в эту коллекцию не попадут, а удаленные все еще будут числиться, как существуюшие. Поэтому данную выборку можно считать статической. Поскольку в большинстве случаев нас устраивает такое положение дел, т.к. элементы на странице не так уж часто добавляются или удаляются, а сам метод позволяет выбрать любые элементы, соответствующие нужному вам селектору - и по классу, и по имени тега, и по атрибуту name
, и еще по куче разных вариантов, - то статические коллекции будут отличным вариантом для обработки событий, например.
Коллекции ссылок, изображений и форм
Для ссылок, изображений и форм есть свои особые коллекции, которые можно использовать параллельно с другими методами, а именно:
document.links
- для всех ссылок на страницеdocument.images
- для изображенийdocument.forms
- для форм
При необходимости вы можете обращаться к ним, как к элементам массива, например, доступ к первой ссылке на странице будет выглядеть, как document.links[0]
, а ко второму изображению, как document.images[1]
. Кроме того, к ним можно обращаться по id или по name, например, document.forms['myForm']
.
Обратите внимание, что в конце наименования все эти коллекции имеют букву "s", т.е. подразумевается, что на странице может быть несколько ссылок, картинок и форм. И даже, если картинка, ссылка или форма одна, обратится к ней можно только через название коллекции с "s" в конце, например, document.images['pic1']
при наличии в html-разметке строки:
1 | <img src="img/mypic.jpg" id="pic1" alt="Picture"> |
Пример использования коллекции document.links вы можете посмотреть в статье "Обработка события onkeyup" для сортировки списка контактов.
Использование методов массивов для html-коллекций
Как уже упоминалось ранее, html-коллекции - это псевдомассивы, которые имеют нумерованные индексы для каждого элемента, возвращают их количество в свойстве length, но при этом не позволяют перебирать массивы такими методами, как forEach()
, map()
, reduce()
, filter()
и т.д.
Тем не менее, мы можем изменить ситуацияю, превратив псевдомассив в массив.
Способ 1. Использование метода call()
Метод call() позволяет вызвать любой из методов массива и передать ему в качестве аргумента нашу коллекцию. Мы уже использовали этот подход для строк таблицы.
1 2 3 4 5 6 7 8 9 | let tr = testTable.getElementsByTagName('tr'); console.log(tr instanceof Array); //false tr = [].slice.call(tr); // или несколько длиннее //tr = Array.prototype.slice.call(tr); console.log(tr instanceof Array); //true |
Можно попробовать получить номер (индекс) каждой ячейки td
в строке tr
таблицы (поместите этот код для проверки в функцию, вызываемую по onclick
):
1 | let indexTD = Array.prototype.indexOf.call(this.children, evt.target); |
Способ 2. Использование метода Array.from()
Метод Array.from() значительно более новый, чем call()
, поддерживается только современными браузерами, но имеет простой и понятный синтаксис. Он преобразует псевдомассив в массив таким способом:
1 2 3 4 5 | let pars = document.getElementsByClassName('example-edit'); console.log(pars instanceof Array); //false pars = Array.from(pars); console.log(pars instanceof Array); //true |
Способ 3. Использование оператора расширения
Оператор расширения, или spread-оператор, еще проще - вы помещаете нужный псевдомассив в квадратные скобки с троеточием и таким образом превращаете его в массив:
1 2 3 | let liElems = document.getElementsByTagName('li'); [...liItems].forEach(item => item.addEventListener('click', myFunc)) |
После такого преобразования вы можете пользоваться всеми методами массивов для html-коллекций.
Доброго времени суток! Спасибо, автор. Очень рад, что нашел ваши статьи. Просто, доходчиво и понятно. А самое главное примеры жизненные. Спасибо! Удачи!
Спасибо за ваш комментарий. Хотелось сделать именно просто и доходчиво.
Здравствуйте! Нашел ваш сайт. Очень хороший. Даже отличный. Спасибо Вам!
Спасибо! Очень приятно читать такие комментарии.