Как обратиться к элементу html через js
Перейти к содержимому

Как обратиться к элементу html через js

  • автор:

Searching: getElement*, querySelector*

DOM navigation properties are great when elements are close to each other. What if they are not? How to get an arbitrary element of the page?

There are additional searching methods for that.

document.getElementById or just id

If an element has the id attribute, we can get the element using the method document.getElementById(id) , no matter where it is.

Also, there’s a global variable named by id that references the element:

…That’s unless we declare a JavaScript variable with the same name, then it takes precedence:

This behavior is described in the specification, but it is supported mainly for compatibility.

The browser tries to help us by mixing namespaces of JS and DOM. That’s fine for simple scripts, inlined into HTML, but generally isn’t a good thing. There may be naming conflicts. Also, when one reads JS code and doesn’t have HTML in view, it’s not obvious where the variable comes from.

Here in the tutorial we use id to directly reference an element for brevity, when it’s obvious where the element comes from.

In real life document.getElementById is the preferred method.

The id must be unique. There can be only one element in the document with the given id .

If there are multiple elements with the same id , then the behavior of methods that use it is unpredictable, e.g. document.getElementById may return any of such elements at random. So please stick to the rule and keep id unique.

The method getElementById can be called only on document object. It looks for the given id in the whole document.

querySelectorAll

By far, the most versatile method, elem.querySelectorAll(css) returns all elements inside elem matching the given CSS selector.

Here we look for all <li> elements that are last children:

This method is indeed powerful, because any CSS selector can be used.

Pseudo-classes in the CSS selector like :hover and :active are also supported. For instance, document.querySelectorAll(‘:hover’) will return the collection with elements that the pointer is over now (in nesting order: from the outermost <html> to the most nested one).

querySelector

The call to elem.querySelector(css) returns the first element for the given CSS selector.

In other words, the result is the same as elem.querySelectorAll(css)[0] , but the latter is looking for all elements and picking one, while elem.querySelector just looks for one. So it’s faster and also shorter to write.

matches

Previous methods were searching the DOM.

The elem.matches(css) does not look for anything, it merely checks if elem matches the given CSS-selector. It returns true or false .

The method comes in handy when we are iterating over elements (like in an array or something) and trying to filter out those that interest us.

closest

Ancestors of an element are: parent, the parent of parent, its parent and so on. The ancestors together form the chain of parents from the element to the top.

The method elem.closest(css) looks for the nearest ancestor that matches the CSS-selector. The elem itself is also included in the search.

In other words, the method closest goes up from the element and checks each of parents. If it matches the selector, then the search stops, and the ancestor is returned.

getElementsBy*

There are also other methods to look for nodes by a tag, class, etc.

Today, they are mostly history, as querySelector is more powerful and shorter to write.

So here we cover them mainly for completeness, while you can still find them in the old scripts.

  • elem.getElementsByTagName(tag) looks for elements with the given tag and returns the collection of them. The tag parameter can also be a star "*" for “any tags”.
  • elem.getElementsByClassName(className) returns elements that have the given CSS class.
  • document.getElementsByName(name) returns elements with the given name attribute, document-wide. Very rarely used.

Let’s find all input tags inside the table:

Novice developers sometimes forget the letter "s" . That is, they try to call getElementByTagName instead of getElementsByTagName .

The "s" letter is absent in getElementById , because it returns a single element. But getElementsByTagName returns a collection of elements, so there’s "s" inside.

Another widespread novice mistake is to write:

That won’t work, because it takes a collection of inputs and assigns the value to it rather than to elements inside it.

We should either iterate over the collection or get an element by its index, and then assign, like this:

Looking for .article elements:

Live collections

All methods "getElementsBy*" return a live collection. Such collections always reflect the current state of the document and “auto-update” when it changes.

In the example below, there are two scripts.

  1. The first one creates a reference to the collection of <div> . As of now, its length is 1 .
  2. The second scripts runs after the browser meets one more <div> , so its length is 2 .

In contrast, querySelectorAll returns a static collection. It’s like a fixed array of elements.

If we use it instead, then both scripts output 1 :

Now we can easily see the difference. The static collection did not increase after the appearance of a new div in the document.

Summary

There are 6 main methods to search for nodes in DOM:

Method Searches by. Can call on an element? Live?
querySelector CSS-selector
querySelectorAll CSS-selector
getElementById id
getElementsByName name
getElementsByTagName tag or ‘*’
getElementsByClassName class

By far the most used are querySelector and querySelectorAll , but getElement(s)By* can be sporadically helpful or found in the old scripts.

  • There is elem.matches(css) to check if elem matches the given CSS selector.
  • There is elem.closest(css) to look for the nearest ancestor that matches the given CSS-selector. The elem itself is also checked.

And let’s mention one more method here to check for the child-parent relationship, as it’s sometimes useful:

How to get the <html> tag HTML with JavaScript / jQuery?

Using $(‘html’).html() I can get the HTML within the <html> tag ( <head> , <body> , etc.). But how can I get the actual HTML of the <html> tag (with attributes)?

Alternatively, is it possible to get the entire HTML of the page (including doctype, <html> , etc.) with jQuery (or plain old JavaScript)?

6 Answers 6

The simplest way to get the html element natively is:

UPDATE: To then grab the html element as a string you would do:

This is how to get the html DOM element purely with JS:

And if you want to use jQuery to get attributes from it.

In addition to some of the other answers, you could also access the HTML element via:

Then you could get the inner HTML content:

Doing so this way seems to be marginally faster. If you are just obtaining the HTML element, however, document.body.parentNode seems to be quite a bit faster.

After you have the HTML element, you can mess with the attributes with the getAttribute and setAttribute methods.

Шпаргалка по JS-методам для работы с DOM

image

JavaScript предоставляет множество методов для работы с Document Object Model или сокращенно DOM (объектной моделью документа): одни из них являются более полезными, чем другие; одни используются часто, другие почти никогда; одни являются относительно новыми, другие признаны устаревшими.

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

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

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

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

Вот как будет выглядеть наша начальная разметка:

У нас есть список ( ul ) с тремя элементами ( li ). Список и каждый элемент имеют идентификатор ( id ) и CSS-класс ( class ). id и class — это атрибуты элемента. Существует множество других атрибутов: одни из них являются глобальными, т.е. могут добавляться к любому элементу, другие — локальными, т.е. могут добавляться только к определенным элементам.

Мы часто будем выводить данные в консоль, поэтому создадим такую "утилиту":

Миксин NonElementParentNode

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

В чем разница между узлами (nodes) и элементами (elements)? Если кратко, то "узлы" — это более общее понятие, чем "элементы". Узел может быть представлен элементом, текстом, комментарием и т.д. Элемент — это узел, представленный разметкой (HTML-тегами (открывающим и закрывающим) или, соответственно, одним тегом).

У рассматриваемого миксина есть метод, наследуемый от объекта Document , с которого удобно начать разговор.

Небольшая оговорка: разумеется, мы могли бы создать список и элементы программным способом.

Для создания элементов используется метод createElement(tag) объекта Document :

Такой способ создания элементов называется императивным. Он является не очень удобным и слишком многословным: создаем родительский элемент, добавляет к нему атрибуты по одному, внедряем его в DOM , создаем первый дочерний элемент и т.д. Следует отметить, что существует и другой, более изысканный способ создания элементов — шаблонные или строковые литералы (template literals), но о них мы поговорим позже.

Одним из основных способов получения элемента (точнее, ссылки на элемент) является метод getElementById(id) объекта Document :

Почему идентификаторы должны быть уникальными в пределах приложения (страницы)? Потому что элемент с id становится значением одноименного свойства глобального объекта window :

Как мы знаем, при обращении к свойствам и методам window , слово window можно опускать, например, вместо window.localStorage можно писать просто localStorage . Следовательно, для доступа к элементу с id достаточно обратиться к соответствующему свойству window :

Обратите внимание, что это не работает в React и других фреймворках, абстрагирующих работу с DOM , например, с помощью Virtual DOM . Более того, там иногда невозможно обратиться к нативным свойствам и методам window без window .

Миксин ParentNode

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

  • children — потомки элемента

Такая структура называется коллекцией HTML и представляет собой массивоподобный объект (псевдомассив). Существует еще одна похожая структура — список узлов (NodeList ).

Массивоподобные объекты имеют свойство length с количеством потомков, метод forEach() ( NodeList ), позволяющий перебирать узлы (делать по ним итерацию). Такие объекты позволяют получать элементы по индексу, по названию ( HTMLCollection ) и т.д. Однако, у них отсутствуют методы настоящих массивов, такие как map() , filter() , reduce() и др., что делает работу с ними не очень удобной. Поэтому массивоподобные объекты рекомендуется преобразовывать в массивы с помощью метода Array.from() или spread-оператора:

  • firstElementChild — первый потомок — элемент
  • lastElementChild — последний потомок — элемент

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

Наша утилита принимает 4 аргумента: идентификатор, текст, название тега и CSS-класс. 2 аргумента (тег и класс) имеют значения по умолчанию. Функция возвращает готовый к работе элемент. Впоследствии, мы реализуем более универсальный вариант данной утилиты.

  • prepend(newNode) — добавляет элемент в начало списка
  • append(newNode) — добавляет элемент в конец списка

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

  • replaceChildren(nodes) — заменяет потомков новыми элементами

Наиболее универсальными способами получения ссылок на элементы являются методы querySelector(selector) и querySelectorAll(selector) . Причем, в отличие от getElementById() , они могут вызываться на любом родительском элементе, а не только на document . В качестве аргумента названным методам передается любой валидный CSS-селектор ( id , class , tag и т.д.):

Создадим универсальную утилиту для получения элементов:

Наша утилита принимает 3 аргумента: CSS-селектор, родительский элемент и индикатор количества элементов (один или все). 2 аргумента (предок и индикатор) имеют значения по умолчанию. Функция возвращает либо один, либо все элементы (в виде обычного массива), совпадающие с селектором, в зависимости от значения индикатора:

Миксин NonDocumentTypeChildNode

Данный миксин предназначен для обработки дочерних узлов, которые не являются документом, т.е. всех узлов, кроме document .

  • previousElementSibling — предыдущий элемент
  • nextElementSibling — следующий элемент

Миксин ChildNode

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

  • before(newNode) — вставляет новый элемент перед текущим
  • after(newNode) — вставляет новый элемент после текущего
  • replaceWith(newNode) — заменяет текущий элемент новым
  • remove() — удаляет текущий элемент

Интерфейс Node

Данный интерфейс предназначен для обработки узлов.

  • nodeType — тип узла
  • nodeName — название узла
  • baseURI — основной путь
  • parentNode — родительский узел
  • parentElement — родительский элемент
  • hasChildNodes() — возвращает true , если элемент имеет хотя бы одного потомка
  • childNodes — дочерние узлы
  • firstChild — первый потомок — узел
  • lastChild — последний потомок — узел
  • nextSibling — следующий узел
  • previousSibling — предыдущий узел
  • textContent — геттер/сеттер для извлечения/записи текста

Для извлечения/записи текста существует еще один (устаревший) геттер/сеттер — innerText .

  • cloneNode(deep) — копирует узел. Принимает логическое значение, определяющее характер копирования: поверхностное — копируется только сам узел, глубокое — копируется сам узел и все его потомки
  • isEqualNode(node) — сравнивает узлы
  • isSameNode(node) — определяет идентичность узлов
  • contains(node) — возвращает true , если элемент содержит указанный узел
  • insertBefore(newNode, existingNode) — добавляет новый узел ( newNode ) перед существующим ( existingNode )
  • appendChild(node) — добавляет узел в конец списка
  • replaceChild(newNode, existingNode) — заменяет существующий узел ( existingNode ) новым ( newNode ):
  • removeChild(node) — удаляет указанный дочерний узел

Интерфейс Document

Данный интерфейс предназначен для обработки объекта Document .

  • URL и documentURI — адрес документа
  • documentElement :
  • getElementsByTagName(tag) — возвращает все элементы с указанным тегом
  • getElementsByClassName(className) — возвращает все элементы с указанным CSS-классом
  • createDocumentFragment() — возвращает фрагмент документа:

Фрагменты позволяют избежать создания лишних элементов. Они часто используются при работе с разметкой, скрытой от пользователя с помощью тега template (метод cloneNode() возвращает DocumentFragment ).

createTextNode(data) — создает текст

createComment(data) — создает комментарий

importNode(existingNode, deep) — создает новый узел на основе существующего

  • createAttribute(attr) — создает указанный атрибут

Интерфейсы NodeIterator и TreeWalker

Интерфейсы NodeIterator и TreeWalker предназначены для обхода (traverse) деревьев узлов. Я не сталкивался с примерами их практического использования, поэтому ограничусь парочкой примеров:

Интерфейс Element

Данный интерфейс предназначен для обработки элементов.

  • localName и tagName — название тега
  • id — геттер/сеттер для идентификатора
  • className — геттер/сеттер для CSS-класса
  • classList — все CSS-классы элемента (объект DOMTokenList )

Работа с classList

  • classList.add(newClass) — добавляет новый класс к существующим
  • classList.remove(existingClass) — удаляет указанный класс
  • classList.toggle(className, force?) — удаляет существующий класс или добавляет новый. Если опциональный аргумент force имеет значение true , данный метод только добавляет новый класс при отсутствии, но не удаляет существующий класс (в этом случае toggle() === add() ). Если force имеет значение false , данный метод только удаляет существующий класс при наличии, но не добавляет отсутствующий класс (в этом случае toggle() === remove() )
  • classList.replace(existingClass, newClass) — заменяет существующий класс ( existingClass ) на новый ( newClass )
  • classList.contains(className) — возвращает true , если указанный класс обнаружен в списке классов элемента (данный метод идентичен className.includes(className) )

Работа с атрибутами

  • hasAttributes() — возвращает true , если у элемента имеются какие-либо атрибуты
  • getAttributesNames() — возвращает названия атрибутов элемента
  • getAttribute(attrName) — возвращает значение указанного атрибута
  • setAttribute(name, value) — добавляет указанные атрибут и его значение к элементу
  • removeAttribute(attrName) — удаляет указанный атрибут
  • hasAttribute(attrName) — возвращает true при наличии у элемента указанного атрибута
  • toggleAttribute(name, force) — добавляет новый атрибут при отсутствии или удаляет существующий атрибут. Аргумент force аналогичен одноименному атрибуту classList.toggle()

В использовании перечисленных методов для работы с атрибутами нет особой необходимости, поскольку многие атрибуты являются геттерами/сеттерами, т.е. позволяют извлекать/записывать значения напрямую. Единственным исключением является метод removeAttribute() , поскольку существуют атрибуты без значений: например, если кнопка имеет атрибут disabled , установка значения данного атрибута в false не приведет к снятию блокировки — для этого нужно полностью удалить атрибут disabled с помощью removeAttribute() .

Отдельного упоминания заслуживает атрибут data-* , где символ * означает любую строку. Он предназначен для определения пользовательских атрибутов. Например, в нашей начальной разметке для уникальной идентификации элементов используется атрибут id . Однако, это приводит к загрязнению глобального пространства имен, что чревато коллизиями между нашими переменными и, например, переменными используемой нами библиотеки — когда какой-либо объект библиотеки пытается записаться в свойство window , которое уже занято нашим id .

Вместо этого, мы могли бы использовать атрибут data-id и получать ссылки на элементы с помощью getEl(‘[data-id="id"]’) .

Название data-атрибута после символа — становится одноименным свойством объекта dataset . Например, значение атрибута data-id можно получить через свойство dataset.id .

  • closest(selectors) — возвращает первый родительский элемент, совпавший с селекторами
  • matches(selectors) — возвращает true , если элемент совпадает хотя бы с одним селектором

insertAdjacentElement(where, newElement) — универсальный метод для вставки новых элементов перед/в начало/в конец/после текущего элемента. Аргумент where определяет место вставки. Возможные значения:

  • beforebegin — перед открывающим тегом
  • afterbegin — после открывающего тега
  • beforeend — перед закрывающим тегом
  • afterend — после закрывающего тега

insertAdjacentText(where, data) — универсальный метод для вставки текста

Text — конструктор для создания текста

Comment — конструктор для создания комментария

Объект Document

  • location — объект с информацией о текущей локации документа

Свойства объекта location :

  • hash — хэш-часть URL (символ # и все, что следует за ним), например, #top
  • host — название хоста и порт, например, localhost:3000
  • hostname — название хоста, например, localhost
  • href — полный путь
  • origin — protocol + host
  • pathname — путь без протокола
  • port — порт, например, 3000
  • protocol — протокол, например, https
  • search — строка запроса (символ ? и все, что следует за ним), например, ?name=John&age=30

reload() — перезагружает текущую локацию

replace() — заменяет текущую локацию на новую

title — заголовок документа

head — метаданные документа

body — тело документа

images — псевдомассив ( HTMLCollection ), содержащий все изображения, имеющиеся в документе

  • links — псевдомассив, содержащий все ссылки, имеющиеся в документе
  • forms — псевдомассив, содержащий все формы, имеющиеся в документе

Следующие методы и свойство считаются устаревшими:

  • open() — открывает документ для записи. При этом документ полностью очищается
  • close() — закрывает документ для записи
  • write() — записывает данные (текст, разметку) в документ
  • writeln() — записывает данные в документ с переносом на новую строку
  • designMode — управление режимом редактирования документа. Возможные значения: on и off . Наберите document.designMode = ‘on’ в консоли DevTools и нажмите Enter . Вуаля, страница стала редактируемой: можно удалять/добавлять текст, перетаскивать изображения и т.д.
  • execCommand() — выполняет переданные команды. Со списоком доступных команд можно ознакомиться здесь. Раньше этот метод активно использовался для записи/извлечения данных из буфера обмена (команды copy и paste ). Сейчас для этого используются методы navigator.clipboard.writeText() , navigator.clipboard.readText() и др.

Миксин InnerHTML

Геттер/сеттер innerHTML позволяет извлекать/записывать разметку в элемент. Для подготовки разметки удобно пользоваться шаблонными литералами:

Расширения интерфейса Element

  • outerHTML — геттер/сеттер для извлечения/записи внешней разметки элемента: то, что возвращает innerHTML + разметка самого элемента
  • insertAdjacentHTML(where, string) — универсальный метод для вставки разметки в виде строки. Аргумент where аналогичен одноименному аргументу метода insertAdjacentElement()

Метод insertAdjacentHTML() в сочетании с шаблонными литералами и их продвинутой версией — тегированными шаблонными литералами (tagged template literals) предоставляет много интересных возможностей по манипулированию разметкой документа. По сути, данный метод представляет собой движок шаблонов (template engine) на стороне клиента, похожий на Pug , Handlebars и др. серверные движки. С его помощью (при участии History API ) можно, например, реализовать полноценное одностраничное приложение ( Single Page Application или сокращенно SPA ). Разумеется, для этого придется написать чуть больше кода, чем при использовании какого-либо фронтенд-фреймворка.

Вот несколько полезных ссылок, с которых можно начать изучение этих замечательных инструментов:

Иногда требуется создать элемент на основе шаблонной строки. Как это можно сделать? Вот соответствующая утилита:

Существует более экзотический способ создания элемента на основе шаблонной строки. Он предполагает использование конструктора DOMParser() :

Еще более экзотический, но при этом самый короткий способ предполагает использование расширения для объекта Range — метода createContextualFragment() :

В завершение, как и обещал, универсальная утилита для создания элементов:

Заключение

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

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

VDS от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

document.getElementById()

Возвращает ссылку на элемент по его идентификатору (ID (en-US) ); идентификатор является строкой, которая может быть использована для идентификации элемента; она может быть определена при помощи атрибута id в HTML или из скрипта.

Синтаксис

Параметры

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

Возвращаемое значение

ссылка на объект типа Element соответствующий указанному ID или null , если элемент с указанным ID не найден в документе.

Пример

Замечания

Начинающим следует знать, что верхний регистр в части имени метода ‘Id’ должен быть точным для корректного вызова функции; «getElementByID» будет не корректно, как бы естественно это ни казалось.

Если элементы с указанным id отсутствуют , функция вернёт null. Заметьте, что параметр id чувствителен к регистру, так document.getElementById(«Main») вернёт null вместо элемента <div > , потому что «M» и «m» различны для этого метода.

Элементы вне документа не ищутся getElementById() . При создании элемента и назначении ему ID, вам следует вставить элемент в дерево документа с помощью Node.insertBefore() или подобным методом, до того как вы сможете получить к нему доступ при помощи getElementById() :

Не-HTML документы. Релизация DOM должна содержать информацию, сообщающую о том, какие атрибуты являются идентификаторами. Атрибуты с именем «id» не являются идентификаторами только если это не указано в описании типа документа (DTD). Атрибут «id» определён в качестве идентификатора в общих случаях XHTML, XUL, и других. От реализаций, которые не знают, какой атрибут является идентификатором, ожидается возврат null.

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

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