15 HTML-методов элементов, о которых вы, вероятно, никогда не слышали

От переводчика: Дэвид Гилбертсон (David Gilbertson) — известный автор, который пишет о веб- и криптовалютных технологиях. Он смог собрать большую аудиторию читателей, которым рассказывает о всяких хитростях и интересностях этих областей.

c0patjmeix9mr9ji7rrw_vjiz0y.jpeg

Небольшое вступление

Давайте обсудим разницу между HTML и DOM.

Например, возьмем элемент table из HTML. Вы можете использовать его в файле с расширением .html. В нем мы указываем набор атрибутов, которые определяют внешний вид и «поведение» страницы.
И это все, здесь нет ничего общего с JavaScript.

DOM — это то, что позволяет объединить ваш код JavaScript с HTML-элементами в документе, так что вы сможете взаимодействовать ними как с объектами.

Это модель «документ-в-объект».

Любой тип элементов в HTML имеет собственный «интерфейс» DOM, который определяет свойства и методы. Например, у table есть интерфейс, который называется HTMLTableElement.

Вы можете можете получить ссылку на определенный элемент, написав что-то вроде этого:

image

У вас есть доступ ко всем свойствам и методам, которые доступны для конкретного типа элемента. Например, вы можете получить доступ к свойствам value, использовав searchBox.value, или установить курсор в определенную позицию, воспользовавшись searchBox.focus ().

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

Но, к счастью, внимание к деталям и изучение спецификаций — моя сильная сторона. Поэтому все необходимое я сделал и о результатах пишу в этой статье.

Если вы хотите попробовать разобраться с DOM самостоятельно, стоит воспользоваться инструментами браузера для изучения некоторых элементов. Для этого нужно выбрать один из них в дереве элементов и набрать $0 в консоли. Это даст вам ссылку на элемент, который вы выбрали. Для того чтобы преобразовать его в объект, наберите dir ($0).

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

2e8669b2cc7abcecbee2b21a24a57d6e.jpg

Skillbox рекомендует: онлайн-курс Веб-разработчик
Напоминаем: Для всех читателей Хабра — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».

№1. Методы таблиц


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

const tableEl = document.querySelector('table');
 
const headerRow = tableEl.createTHead().insertRow();
headerRow.insertCell().textContent = 'Make';
headerRow.insertCell().textContent = 'Model';
headerRow.insertCell().textContent = 'Color';
 
const newRow = tableEl.insertRow();
newRow.insertCell().textContent = 'Yes';
newRow.insertCell().textContent = 'No';
newRow.insertCell().textContent = 'Thank you';


Здесь вы видите не только document.createElement (). Например, метод .insertRow () встроит tbody, если вы организуете вызов этого элемента прямо в дереве. Это ли не классно?

№2. scrollIntoView ()


Вы знаете, что если у вас есть #something в URL, то при загрузке страницы браузер проскроллит ее до элемента с этим ID?

Обычно это очень помогает, но не работает, если вы рендерите этот элемент после загрузки страницы. Для того чтобы воспользоваться возможностью, описанной выше, просто прописываете document.querySelector (document.location.hash).scrollIntoView ();

№3. hidden


Ну да, это вроде как не метод, но раз есть setter (метод задания свойства), то можно считать методом.

Как бы там ни было, вы когда-либо использовали myElement.style.display = 'none' для того, чтобы спрятать элемент? Если да, то не стоит этого делать.

Куда лучше воспользоваться myElement.hidden = true.

№4. toggle ()


Мы можем использовать этот метод для того, чтобы добавить или удалить класс элемента при помощи myElement.classList.toggle ('some-class').

И если вы когда-либо добавляли класс с использованием if, то подумайте: может, стоит попробовать что-то еще?

Например, можно просто использовать второй параметр для метода toggle. Нужно передать его методу переключения. Если это произойдет, ваш класс будет добавлен в элемент:

el.classList.toggle('some-orange-class', theme === 'orange');


Да, я понимаю, о чем вы сейчас думаете: это не то, что означает само слово «toogle». Те, кто стоит за Internet Explorer? с этим согласны и выражают свой протест, не используя второй параметр вообще.

Но давайте его вернем. Свободу параметрам!

№5. querySelector ()


Ну хорошо, вы определенно должны это знать, но я подозреваю, что примерно 17% читателей не в курсе, как можно использовать этот метод в связке с элементами.

Пример: myElement.querySelector ('.my-class') покажет соответствие элементов, у которых есть класс my-class и «потомков» myElement.

№6. closest


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

myElement.closest('article').querySelector('h1');


Начинаем с article и заканчиваем первым h1.

№7. getBoundingClientRect ()


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

{
  x: 604.875,
  y: 1312,
  width: 701.625,
  height: 31,
  top: 1312,
  right: 1306.5,
  bottom: 1343,
  left: 604.875
}


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

Не все браузеры возвращают все эти значения.

№8. matches ()


Я бы хотел проверить, принадлежит ли определенный элемент к определенному классу.

Максимальная сложность:

if (myElement.className.indexOf('some-class') > -1) {
  // do something
}
 
Немного лучше, но все равно не то:

if (myElement.className.includes('some-class')) {
  // do something
}


То, что нужно:

if (myElement.matches('.some-class')) {
  // do something
}


№9. insertAdjacentElement ()


Я обнаружил это сегодня! Это подобно appendChild (), но дает немного больше контроля в процессе добавления child.

parentEl.insertAdjacentElement ('beforeend', newEl) делает примерно то же, что и parentEl.appendChild (newEl), но вы можете указать beforebegin, afterbegin или afterend для помещения его в то место, которое указывают эти имена.

Сколько контроля!

№10. contains ()


Вы когда-нибудь хотели знать, есть ли элемент внутри другого? Я все время хочу это знать.

Например, если я обрабатываю клик мыши и хочу понять, происходил ли он внутри или снаружи (так что я могу закрыть его), я выполняю вот что:

const handleClick = e => {
  if (!modalEl.contains(e.target)) modalEl.hidden = true;
};


Здесь modal El — отсылка к модальному окну, а e.target — элемент, по которому кликают.

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

№11. getAttribute ()


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

Вы помните, что обычно свойства относятся к атрибутам?

Иногда это не так, например, когда href — атрибут элемента, например a href=»/animals/cat»>Cat

el.href не даст нам /animals/cat, как этого можно ожидать. Это потому, что элемент выполняет интерфейс HTMLHyperlinkElementUtils, который представляет собой связку вспомогательных свойств вроде protocol и hash, указывающих на объект ссылки.

Это одно из полезных свойств href, которое даст полный L, а не относительный URL в атрибуте.

Таким образом, вы должны использовать el.getAttribute ('href'), если вам нужна литеральная строка внутри атрибута href.

№12. dialog


У относительно нового элемента dialog есть два хороших метода и один идеальный. show () и close () делают именно то, что от них ожидают. И это хорошо, я полагаю.

Но showModal () выведет dialog поверх любых других элементов, размещенных на странице. Нет нужды в z-index, или ручном добавлении неяркого фона, или отслеживании нажатия кнопки Escape. Браузер знает, как работают модальные окна, и все сделает для вас. И это отлично.

№13. forEach ()


Иногда, когда вам нужна отсылка к списку элементов, вы можете использовать forEach ().

Но что, если вам нужно записать в лог все URL для всех ссылок страницы? Вы можете выполнить вот это и увидеть ошибку.

document.getElementsByTagName('a').forEach(el => {
    console.log(el.href);
});


Или выполнить вот что:

document.querySelectorAll('a').forEach(el => {
    console.log(el.href);
});


Дело в том, что getElementsByTagName и другие методы get… возвращают HTMLCollection, но querySelectorAll возвращает NodeList.

И интерфейс NodeList дает нам метод forEach () (наряду с ключами (), значениями () и entry ()).

Хорошие парни из ECMA дали нам Array.from (), который превратит все, что выглядит как массив, в сам массив.

Array.from(document.getElementsByTagName('a')).forEach(el => {
    console.log(el.href);
});


Бонус! Создавая массив, вы можете использовать map (), и filter (), и reduce () или любой другой метод. Например, возвращение массива внешних ссылок:

Array.from(document.querySelectorAll('a'))
  .map(el => el.origin)
  .filter(origin => origin !== document.origin)
.filter(Boolean);


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

№14. Forms


У form, как вы, скорее всего, уже знаете, есть метод submit (). Несколько менее вероятно, что вы знаете, что формы имеют метод reset () и могут сообщить значение Validity (), если вы используете проверку на своих элементах формы.

Вы также можете использовать свойство элементов формы с точечной нотацией для ссылки на элемент по его атрибуту name. Например, myFormEl.elements.email вернет элемент input name = «email» /, который принадлежит form («принадлежит» не обязательно означает, что он его «потомок»).

А вот сейчас я соврал. Дело в том, что elements не возвращает список элементов. Он возвращает список элементов управления (и, конечно же, это не массив).

Пример: если у вас есть три переключателя, каждый с тем же именем animal, то formEl.elements.animal даст вам ссылку на этот набор переключателей (1 элемент управления, 3 элемента).

И formEl.elements.animal.value вернет значение выбранного переключателя.

Это странный синтаксис, если подумать. Разбивайте его, ребята: formEl — это элемент, элементы — это HTMLFormControlsCollection, не-совсем-массив, где каждый элемент не обязательно является элементом HTML. Animal имеет несколько переключателей, объединенных только потому, что они имеют один и тот же атрибут имени (для этого есть интерфейс RadioNodeList), а значение просматривает атрибут value любого переключателя в коллекции.

№15. select ()


Метод .select () выберет весь текст в любом вводе, который вы вызываете.

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

Практические от Skillbox, которые помогут начинающему программисту стать востребованным специалистом:

© Habrahabr.ru