Добрый день. Меня зовут Чистяков Денис. И тема сегодняшней нашей лекции будет DOM. Я вам расскажу о том, что такое Document Object Model, для чего он нужен, и что с помощью него вы можете сделать. Итак, прежде всего, это программный интерфейс для работы с XML- и HTML-документами. Он позволяет обрабатывать любые элементы этого дерева, это могут быть атрибуты, элементы, свойства и многие другие. Простейшее DOM-дерево представляет собой вот такую обычную HTML страницу, с которой мы будем работать сегодня в течение всей нашей лекции. Она состоит из тега <head>, в котором находится метаописание, и тега <body>, внутри которого находится уже непосредственно тело документа. Именно с телом в течение всей лекции мы и будем работать. Итак, что нам позволяет сделать DOM. Он позволяет искать элементы, позволяет производить обход дерева, позволяет работать с атрибутами и свойствами узлов, а также добавлять, удалять их и обрабатывать на них события. Все начинается с поиска элементов, так же, как в фильме Люка Бессона «Пятый элемент» все герои бегали и искали знаменитый тайный пятый элемент, который при этом все время был у них под носом. Так и работа с DOM-деревом всегда начинается с поиска элементов. В любом случае нам нужно сначала найти что-то, какую-то часть нашего документа, а потом с ней поработать, изменить ее свойства, обработать на ней события. Как я уже говорил, в течение всей нашей сегодняшней лекции мы будем работать вот с этим небольшим элементом формы, который представлен у вас на экране, и все наши действия, весь поиск, все обработки событий всегда будут происходить именно с ним. И давайте начнем с самого классического метода поиска элемента, это метод getElementById, который возвращает нам элемент по его идентификатору. В данном случае мы ищем по идентификатору form и находим наш элемент формы. Объект, который возвращается нам, имеет класс HTMLFormElement. Метод getElementById всегда возвращает ровно один элемент, так как по спецификации элемент не может быть повторен с одинаковым идентификатором на странице. И в DOM-дереве всегда должен быть ровно один элемент с одним идентификатором. Как следствие, этот метод самый быстрый, так как мы можем очень легко найти элемент, так как его идентификатор не повторяется, и он хранится специальным образом. Следующий метод, который мы рассмотрим — это getElementByTagName. Как видно из его названия, он возвращает элементы с тем тегом, который указан в качестве параметра. В данном случае мы находим все элементы input и получаем input для ввода логина и input для ввода пароля. И этот метод всегда возвращает объект класса HTMLCollection. Этот метод достаточно устаревший и не очень удобный для применения, так как вам редко нужно находить все теги какого-то вида на странице. Скорее всего, у вас будет очень много лишнего и очень много мусора. И найденный результат вам придется каким-то образом фильтровать. На смену устаревшим методам для поиска были добавлены более современные, и прежде всего это метод querySelector, который позволяет искать внутри DOM-дерева элементы в зависимости от CSS-селектора. Другими словами, вы определяете CSS-селектор, который бы применил свойства CSS к какому-то набору DOM-элементов, который вы желали получить. И вы передаете этот селектор в качестве параметра. В данном случае мы ищем нашу форму по ее идентификатору. Здесь же мы ищем эту же самую форму, но уже по ее классу. Механизм поиска элементов по CSS-селектору очень гибкий, так как с помощью различных CSS правил и их комбинаций вы можете задавать очень сложные правила для поиска. Например, в данном случае мы находим все элементы, у которых есть атрибут name, значение которого — login. И находим наш input для ввода логина. Как вы, должно быть, обратили внимание, querySelector всегда возвращает один элемент, он всегда возвращает первый элемент из всех возможных, найденных внутри DOM-дерева. И если мы укажем, например, поиск по input и button, и под этот поиск бы подходило три элемента, в результате мы все равно получим первый. Для поиска множества элементов разработан метод querySelectorAll, который принимает точно также на вход CSS-селектор, но возвращает уже все DOM-элементы, которые этому селектору соответствуют. В данном случае мы ищем все input и все button на странице и получаем объект класса NodeList. HTMLCollection, про которую мы говорили в связи с методом getElementByTagName, и NodeList, про который мы говорили только что вместе с методом querySelectorAll, не являются массивами. Это важно понимать и важно помнить. Как следствие, у них нет методов для итерирования, таких как forEach, map, reduce или любых других методов работы с массивами. Эта ситуация достаточно неоднозначная и на Stack Overflow есть достаточно подробная большая статья и дискуссия по поводу того, правильное или неправильное это решение — делать их не массивами и не наделять их свойствами... методами массива. И вы можете прочитать ее по ссылке. Мнения там достаточно разные, но лично я согласен с Джоном Резигом, автором библиотеки jQuery, который считает, что это решение было ошибочным и мешает разработчикам, заставляет их делать одни и те же конструкции для того, чтобы просто проитерироваться по объектам. Итак, что же мы можем сделать для итерирования? Ведь всегда, когда мы получаем большую коллекцию элементов, нам нужно по ней пройтись, обработать на них свойства, навешать на них события и повзаимодействовать обычно не с одним, а сразу с несколькими элементами. Самый простой способ для итерирования по коллекциям, и HTMLCollection, и NodeList — это обычный цикл for. И тот и другой являются так называемыми array-like объектами, то есть подобиями массива. И у того и у другого есть свойство len, которое говорит о количестве элементов внутри коллекции. И к любому элементу внутри коллекции можно обратиться по индексу. Таким образом мы можем сделать цикл for от нулевого до − 1 от последнего элемента и пройтись по всем элементам коллекции в цикле. Возможно, но не очень удобно. Следующий вариант, на мой взгляд, чуть более изящный — это с помощью метода Array.prototype.slice преобразовать нашу коллекцию к настоящему массиву и уже воспользоваться всеми методами, которые есть у массива. Тоже неплохо, но не так современно. И последний вариант, который предоставляют нам современные браузеры — это метод Array.from, который на вход получает что-то, подобное массиву, и преобразует это в полноценный, настоящий массив. В нашем случае мы получаем массив с элементами и уже можем применить любые методы для работы с массивами к ним.