Методы объектов dom. Введение. Важные типы данных

Основным инструментом работы и динамических изменений на странице является DOM (Document Object Model) - объектная модель, используемая для XML/HTML-документов.

Согласно DOM-модели, документ является иерархией.
Каждый HTML-тег образует отдельный элемент-узел, каждый фрагмент текста - текстовый элемент, и т.п.

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

Простейший DOM

Построим, для начала, дерево DOM для следующего документа.

Заголовок Прекрасный документ

Самый внешний тег - , поэтому дерево начинает расти от него.

Внутри находятся два узла: и - они становятся дочерними узлами для .

Теги образуют узлы-элементы (element node). Текст представлен текстовыми узлами (text node). И то и другое - равноправные узлы дерева DOM.

Пример посложнее

Рассмотрим теперь более жизненную страничку:

О лосях Правда о лосях.

  • Лось - животное хитрое
  • .. И коварное
  • Корневым элементом иерархии является html . У него есть два потомка. Первый - head , второй - body . И так далее, каждый вложенный тег является потомком тега выше:

    На этом рисунке синим цветом обозначены элементы-узлы, черным - текстовые элементы.

    Дерево образовано за счет синих элементов-узлов - тегов HTML.

    А вот так выглядит дерево, если изобразить его прямо на HTML-страничке:

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

    Рассмотрим чуть более сложный документ.

    Документ Data

    • Осторожно
    • Информация
    Made in Russia

    Верхний тег - html , у него дети head и body , и так далее. Получается дерево тегов:

    Атрибуты

    В этом примере у узлов есть атрибуты: style , class , id . Вообще говоря, атрибуты тоже считаются узлами в DOM-модели, родителем которых является элемент DOM, у которого они указаны.

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

    Вообще-то это секрет, но DOCTYPE тоже является DOM-узлом, и находится в дереве DOM слева от HTML (на рисунке этот факт скрыт).

    P.S. Насчет секрета - конечно, шутка, но об этом и правда далеко не все знают. Сложно придумать, где такое знание может пригодиться...

    Нормализация в различных браузерах

    При разборе HTML Internet Explorer сразу создает нормализованный DOM, в котором не создаются узлы из пустого текста.

    Firefox - другого мнения, он создает DOM-элемент из каждого текстового фрагмента.
    Поэтому в Firefox дерево этого документа выглядит так:

    На рисунке для краткости текстовые узлы обозначены просто решеткой. У body вместо 3 появилось 7 детей.

    Opera тоже имеет чем похвастаться. Она может добавить лишний пустой элемент "просто от себя".

    Чтобы это увидеть - откройте документ . Он выдает число дочерних узлов document.body , включая текстовые узлы.

    У меня получается 3 для IE, 7 для Firefox и 8 (!?) для Opera.

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

    Возможности, которые дает DOM

    Зачем, кроме красивых рисунков, нужна иерархическая модель DOM?

    Очень просто:

    Каждый DOM-элемент является объектом и предоставляет свойства для манипуляции своим содержимым, для доступа к родителям и потомкам.

    Для манипуляций с DOM используется объект document .
    Используя document , можно получать нужный элемент дерева и менять его содержание.

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

    Var ol = document.getElementsByTagName("ol") var hiter = ol.removeChild(ol.firstChild) var kovaren = ol.removeChild(ol.firstChild) ol.appendChild(kovaren) ol.appendChild(hiter)

    Для примера работы такого скрипта - кликните на тексте на лосиной cтраничке

    В старых руководствах и скриптах можно встретить модификацию HTML-кода страницы напрямую вызовом document.write .

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

    Избегайте document.write.. Кроме случаев, когда вы действительно знаете, что делаете (а зачем тогда читаете самоучитель - вы и так гуру)

    Разберем подробнее способы доступа и свойства элементов DOM.

    Доступ к элементам

    Любой доступ и изменения DOM берут свое начало от объекта document .

    Начнем с вершины дерева.

    document.documentElement

    Самый верхний тег. В случае корректной HTML-страницы, это будет .

    document.body

    Тег , если есть в документе (обязан быть).

    Следующий пример при нажатии на кнопку выдаст текстовое представление объектов document.documentElement и document.body . Сама строка зависит от браузера, хотя объекты везде одни и те же.

    function go() { alert(document.documentElement) alert(document.body) }

    Типы DOM-элементов

    У каждого элемента в DOM-модели есть тип. Его номер хранится в атрибуте elem.nodeType

    Всего в DOM различают 12 типов элементов.

    Обычно используется только один: Node.ELEMENT_NODE , номер которого равен 1. Элементам этого типа соответствуют HTML-теги.

    Иногда полезен еще тип Node.TEXT_NODE , который равен 3. Это текстовые элементы.

    Остальные типы в javascript программировании не используются.

    Следующий пример при нажатии на кнопку выведет типы document.documentElement , а затем тип последнего потомка узла document.body . Им является текстовый узел.

    function go() { alert(document.documentElement.nodeType) alert(document.body.lastChild.nodeType) } Текст

    Пример

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

    ... Data

    • Осторожно
    • Информация
    Made in Russia

    Здесь показаны только элементы внутри body , т.к только они отображаются на странице. Для элементов типа 1 (теги) в скобочках указан соответствующий тег, для текстовых элементов (тип 3) - стоит просто цифра.

    Дочерние элементы
  • Все дочерние элементы, включая текстовые находятся в массиве childNodes .

    В следующем примере цикл перебирает всех детей document.body .

    For(var i=0; i BODY

    style

    Это свойство управляет стилем. Оно аналогично установке стиля в CSS.

    Например, можно установить element.style.width:

    Исходный код этой кнопки:

    Есть общее правило замены - если CSS-атрибут имеет дефисы, то для установки style нужно заменить их на верхний регистр букв.

    Например, для установки свойства z-index в 1000, нужно поставить:

    Element.style.zIndex = 1000

    innerHTML

    Когда-то это свойство поддерживалось только в IE. Теперь его поддерживают все современные браузеры.

    Оно содержит весь HTML-код внутри узла, и его можно менять.

    Свойство innerHTML применяется, в основном, для динамического изменения содержания страницы, например:

    Document.getElementById("footer").innerHTML = "Bye! "

    Пожалуй, innerHTML - одно из наиболее часто используемых свойств DOM-элемента.

    className

    Это свойство задает класс элемента. Оно полностью аналогично html-атрибуту "class".

    Elem.className = "newclass"

    onclick , onkeypress, onfocus ...

    И другие свойства, начинающиеся на "on...", хранят функции-обработчики соответствующих событий. Например, можно присвоить обработчик события onclick .

    Подробнее об этих свойствах и обработчиках событий - см.

    Работа с DOM-моделью

    Каждый объект Window имеет свойство document , ссылающееся на объект Document. Этот объект Document не является автономным объектом. Он является центральным объектом обширного API, известного как объектная модель документа (DOM), который определяет порядок доступа к содержимому документа.

    Обзор модели DOM

    Объектная модель документа (Document Object Model, DOM) - это фундаментальный прикладной программный интерфейс, обеспечивающий возможность работы с содержимым HTML и XML-документов. Прикладной программный интерфейс (API) модели DOM не особенно сложен, но в нем существует множество архитектурных особенностей, которые вы должны знать.

    Прежде всего, следует понимать, что вложенные элементы HTML или XML-документов представлены в виде дерева объектов DOM. Древовидное представление HTML-документа содержит узлы, представляющие элементы или теги, такие как и

    И узлы, представляющие строки текста. HTML-документ также может содержать узлы, представляющие HTML-комментарии. Рассмотрим следующий простой HTML-документ:

    Пример документа Это HTML-документ

    Пример простого текста.

    DOM-представление этого документа приводится на следующей диаграмме:

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

    Каждый прямоугольник на этой диаграмме является узлом документа, который представлен объектом Node . Обратите внимание, что на рисунке изображено три различных типа узлов. Корнем дерева является узел Document, который представляет документ целиком. Узлы, представляющие HTML-элементы, являются узлами типа Element, а узлы, представляющие текст, - узлами типа Text. Document, Element и Text - это подклассы класса Node. Document и Element являются двумя самыми важными классами в модели DOM.

    Тип Node и его подтипы образуют иерархию типов, изображенную на диаграмме ниже. Обратите внимание на формальные отличия между обобщенными типами Document и Element, и типами HTMLDocument и HTMLElement. Тип Document представляет HTML и XML-документ, а класс Element представляет элемент этого документа. Подклассы HTMLDocument и HTMLElement представляют конкретно HTML-документ и его элементы:

    На этой диаграмме следует также отметить наличие большого количества подтипов класса HTMLElement, представляющих конкретные типы HTML-элементов. Каждый из них определяет JavaScript-свойства, отражающие HTML-атрибуты конкретного элемента или группы элементов. Некоторые из этих специфических классов определяют дополнительные свойства или методы, которые не являются отражением синтаксиса языка разметки HTML.

    Выбор элементов документа

    Работа большинства клиентских программ на языке JavaScript так или иначе связана с манипулированием элементами документа. В ходе выполнения эти программы могут использовать глобальную переменную document, ссылающуюся на объект Document. Однако, чтобы выполнить какие-либо манипуляции с элементами документа, программа должна каким-то образом получить, или выбрать, объекты Element, ссылающиеся на эти элементы документа. Модель DOM определяет несколько способов выборки элементов. Выбрать элемент или элементы документа можно:

      по значению атрибута id;

      по значению атрибута name;

      по имени тега;

      по имени класса или классов CSS;

      по совпадению с определенным селектором CSS.

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

    Выбор элементов по значению атрибута id

    Все HTML-элементы имеют атрибуты id. Значение этого атрибута должно быть уникальным в пределах документа - никакие два элемента в одном и том же документе не должны иметь одинаковые значения атрибута id. Выбрать элемент по уникальному значению атрибута id можно с помощью метода getElementById() объекта Document:

    Var section1 = document.getElementById("section1");

    Это самый простой и самый распространенный способ выборки элементов. Если сценарию необходимо иметь возможность манипулировать каким-то определенным множеством элементов документа, присвойте значения атрибутам id этих элементов и используйте возможность их поиска по этим значениям.

    В версиях Internet Explorer ниже IE8 метод getElementById() выполняет поиск значений атрибутов id без учета регистра символов и, кроме того, возвращает элементы, в которых будет найдено совпадение со значением атрибута name.

    Выбор элементов по значению атрибута name

    HTML-атрибут name первоначально предназначался для присваивания имен элементам форм, и значение этого атрибута использовалось, когда выполнялась отправка данных формы на сервер. Подобно атрибуту id, атрибут name присваивает имя элементу. Однако, в отличие от id, значение атрибута name не обязано быть уникальным: одно и то же имя могут иметь сразу несколько элементов, что вполне обычно при использовании в формах радиокнопок и флажков. Кроме того, в отличие от id, атрибут name допускается указывать лишь в некоторых HTML-элементах, включая формы, элементы форм и элементы и .

    Выбрать HTML-элементы, опираясь на значения их атрибутов name, можно с помощью метода getElementsByName() объекта Document:

    Var radiobuttons = document.getElementsByName("favorite_color");

    Метод getElementsByName() определяется не классом Document, а классом HTMLDocument, поэтому он доступен только в HTML-документах и не доступен в XML-документах. Он возвращает объект NodeList , который ведет себя, как доступный только для чтения массив объектов Element.

    В IE метод getElementsByName() возвращает также элементы, значения атрибутов id которых совпадает с указанным значением. Чтобы обеспечить совместимость с разными версиями браузеров, необходимо внимательно подходить к выбору значений атрибутов и не использовать одни и те же строки в качестве значений атрибутов name и id.

    Выбор элементов по типу

    Метод getElementsByTagName() объекта Document позволяет выбрать все HTML или XML-элементы указанного типа (или по имени тега). Например, получить подобный массиву объект, доступный только для чтения, содержащий объекты Element всех элементов в документе, можно следующим образом:

    Var spans = document.getElementsByTagName("span");

    Подобно методу getElementsByName(), getElementsByTagName() возвращает объект NodeList. Элементы документа включаются в массив NodeList в том же порядке, в каком они следуют в документе, т.е. первый элемент

    В документе можно выбрать так:

    Var firstParagraph = document.getElementsByTagName("p");

    Имена HTML-тегов не чувствительны к регистру символов, и когда getElementsByTagName() применяется к HTML-документу, он выполняет сравнение с именем тега без учета регистра символов. Переменная spans, созданная выше, например, будет включать также все элементы , которые записаны как .

    Можно получить NodeList, содержащий все элементы документа, если передать методу getElementsByTagName() шаблонный символ «*».

    Кроме того, классом Element также определяет метод getElementsByTagName(). Он действует точно так же, как и версия метода в классе Document, но выбирает только элементы, являющиеся потомками для элемента, относительно которого вызывается метод. То есть отыскать все элементы внутри первого элемента

    Можно следующим образом:

    Var firstParagraph = document.getElementsByTagName("p"); var firstParagraphSpans = firstParagraph.getElementsByTagName("span");

    По историческим причинам класс HTMLDocument определяет специальные свойства для доступа к узлам определенных типов. Свойства images , forms и links , например, ссылаются на объекты, которые ведут себя как массивы, доступные только для чтения, содержащие элементы , и (но только те теги , которые имеют атрибут href). Эти свойства ссылаются на объекты HTMLCollection, которые во многом похожи на объекты NodeList, но дополнительно могут индексироваться значениями атрибутов id и name.

    Объект HTMLDocument также определяет свойства-синонимы embeds и plugins , являющиеся коллекциями HTMLCollection элементов . Свойство anchors является нестандартным, но с его помощью можно получить доступ к элементам , имеющим атрибут name, но не имеющим атрибут href. Свойство scripts определено стандартом HTML5 и является коллекцией HTMLCollection элементов .

    Кроме того, объект HTMLDocument определяет два свойства, каждое из которых ссылается не на коллекцию, а на единственный элемент. Свойство document.body представляет элемент HTML-документа, а свойство document.head - элемент . Эти свойства всегда определены в документе: даже если в исходном документе отсутствуют элементы и , браузер создаст их неявно. Свойство documentElement объекта Document ссылается на корневой элемент документа. В HTML-документах он всегда представляет элемент .

    Выбор элементов по классу CSS

    Значением HTML-атрибута class является список из нуля или более идентификаторов, разделенных пробелами. Он дает возможность определять множества связанных элементов документа: любые элементы, имеющие в атрибуте class один и тот же идентификатор, являются частью одного множества. Слово class зарезервировано в языке JavaScript, поэтому для хранения значения HTML-атрибута class в клиентском JavaScript используется свойство className.

    Обычно атрибут class используется вместе с каскадными таблицами стилей CSS, с целью применить общий стиль отображения ко всем членам множества. Однако кроме этого, стандарт HTML5 определяет метод getElementsByClassName() , позволяющий выбирать множества элементов документа на основе идентификаторов в их атрибутах class.

    Подобно методу getElementsByTagName(), метод getElementsByClassName() может вызываться и для HTML-документов, и для HTML-элементов, и возвращает «живой» объект NodeList, содержащий все потомки документа или элемента, соответствующие критерию поиска.

    Метод getElementsByClassName() принимает единственный строковый аргумент, но в самой строке может быть указано несколько идентификаторов, разделенных пробелами. Соответствующими будут считаться все элементы, атрибуты class которых содержат все указанные идентификаторы. Порядок следования идентификаторов не имеет значения. Обратите внимание, что и в атрибуте class, и в аргументе метода getElementsByClassName() идентификаторы классов разделяются пробелами, а не запятыми.

    Ниже приводится несколько примеров использования метода getElementsByClassName():

    // Отыскать все элементы с классом "warning" var warnings = document.getElementsByClassName("warning"); // Отыскать всех потомков элемента с идентификаторам "log" // с классами "error" и "fatal" var log = document.getElementById("log"); var fatal = log.getElementsByClassName("fatal error");

    Выбор элементов с использованием селекторов CSS

    Каскадные таблицы стилей CSS имеют очень мощные синтаксические конструкции, известные как селекторы, позволяющие описывать элементы или множества элементов документа. Наряду со стандартизацией селекторов CSS3 , другой стандарт консорциума W3C, известный как Selectors API , определяет методы JavaScript для получения элементов, соответствующих указанному селектору.

    Ключевым в этом API является метод querySelectorAll() объекта Document. Он принимает единственный строковый аргумент с селектором CSS и возвращает объект NodeList, представляющий все элементы документа, соответствующие селектору.

    В дополнение к методу querySelectorAll() объект документа также определяет метод querySelector() , подобный методу querySelectorAll(), - с тем отличием, что он возвращает только первый (в порядке следования в документе) соответствующий элемент или null, в случае отсутствия соответствующих элементов.

    Эти два метода также определяются классом Elements. Когда они вызываются относительно элемента, поиск соответствия заданному селектору выполняется во всем документе, а затем результат фильтруется так, чтобы в нем остались только потомки использованного элемента. Такой подход может показаться противоречащим здравому смыслу, так как он означает, что строка селектора может включать предков элемента, для которого выполняется сопоставление.

    Структура документа и навигация по документу

    После выбора элемента документа иногда бывает необходимо отыскать структурно связанные части документа (родитель, братья, дочерний элемент). Объект Document можно представить как дерево объектов Node. Тип Node определяет свойства, позволяющие перемещаться по такому дереву. Существует еще один прикладной интерфейс навигации по документу, как дерева объектов Element.

    Документы как деревья узлов

    Объект Document, его объекты Element и объекты Text, представляющие текстовые фрагменты в документе - все они являются объектами Node. Класс Node определяет следующие важные свойства:

    parentNode

    Родительский узел данного узла или null для узлов, не имеющих родителя, таких как Document.

    childNodes

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

    firstChild, lastChild

    Первый и последний дочерние узлы или null, если данный узел не имеет дочерних узлов.

    nextSibling, previousSibling

    Следующий и предыдущий братские узлы. Братскими называются два узла, имеющие одного и того же родителя. Порядок их следования соответствует порядку следования в документе. Эти свойства связывают узлы в двусвязный список.

    nodeType

    Тип данного узла. Узлы типа Document имеют значение 9 в этом свойстве. Узлы типа Element - значение 1. Текстовые узлы типа Text - значение 3. Узлы типа Comments - значение 8 и узлы типа DocumentFragment - значение 11.

    nodeValue

    Текстовое содержимое узлов Text и Comment.

    nodeName

    Имя тега элемента Element, в котором все символы преобразованы в верхний регистр.

    С помощью этих свойств класса Node можно сослаться на второй дочерний узел первого дочернего узла объекта Document, как показано ниже:

    Document.childNodes.childNodes == document.firstChild.firstChild.nextSibling

    Допустим, что рассматриваемый документ имеет следующий вид:

    TestHello World!

    Тогда вторым дочерним узлом первого дочернего узла будет элемент . В свойстве nodeType он содержит значение 1 и в свойстве nodeName - значение «BODY».

    Однако, обратите внимание, что этот прикладной интерфейс чрезвычайно чувствителен к изменениям в тексте документа. Например, если в этот документ добавить единственный перевод строки между тегами и , этот символ перевода строки станет первым дочерним узлом (текстовым узлом Text) первого дочернего узла, а вторым дочерним узлом станет элемент , а не .

    Документы как деревья элементов

    Когда основной интерес представляют сами элементы документа, а не текст в них (и пробельные символы между ними), гораздо удобнее использовать прикладной интерфейс, позволяющий интерпретировать документ как дерево объектов Element, игнорируя узлы Text и Comment, которые также являются частью документа.

    Первой частью этого прикладного интерфейса является свойство children объектов Element. Подобно свойству childNodes, его значением является объект NodeList. Однако, в отличие от свойства childNodes, список children содержит только объекты Element.

    Обратите внимание, что узлы Text и Comment не имеют дочерних узлов. Это означает, что описанное выше свойство Node.parentNode никогда не возвращает узлы типа Text или Comment. Значением свойства parentNode любого объекта Element всегда будет другой объект Element или корень дерева - объект Document или DocumentFragment.

    Второй частью прикладного интерфейса навигации по элементам документа являются свойства объекта Element, аналогичные свойствам доступа к дочерним и братским узлам объекта Node:

    firstElementChild, lastElementChild

    Похожи на свойства firstChild и lastChild, но возвращают дочерние элементы.

    nextElementSibling, previousElementSibling

    Похожи на свойства nextSibling и previousSibling, но возвращают братские элементы.

    childElementCount

    Количество дочерних элементов. Возвращает то же значение, что и свойство children.length.

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

    На этом уроке мы рассмотрим, что такое DOM, зачем он нужен, а также то, как он строится.

    Что такое DOM?

    Браузер, когда запрашивает страницу и получает в ответе от сервера её исходный HTML-код, должен сначала его разобрать. В процессе анализа и разбора HTML-кода браузер строит на основе него DOM-дерево .

    После выполнения этого действия и ряда других браузер приступает к отрисовке страницы. В этом процессе он, конечно, уже использует созданное им DOM-дерево , а не исходный HTML-код.

    DOM – это объектная модель документа, которую браузер создаёт в памяти компьютера на основании HTML-кода, полученного им от сервера.

    Если сказать по-простому, то HTML-код – это текст страницы, а DOM – это набор связанных объектов, созданных браузером при парсинге её текста.

    В Chrome исходный код страницы, который получает браузер, можно посмотреть во вкладке «Source» на панели «Инструменты веб-разработчика».


    В Chrome инструмента, с помощью которого можно было бы посмотреть созданное им DOM-дерево нет. Но есть представление этого DOM-дерева в виде HTML-кода, оно доступно на вкладке «Elements». С таким представлением DOM веб-разработчику, конечно, намного удобнее работать. Поэтому инструмента, который DOM представлял бы в виде древовидной структуры нет.


    Объекты в этой модели образуются практически из всего, что есть в HTML (тегов, текстового контента, комментариев и т.д.), включая при этом сам документ. Связи между этими объектами в модели формируются на основании того, как HTML-элементы расположены в коде относительно друг друга .

    При этом DOM документа после его формирования можно изменять . При изменении DOM браузер практически мгновенно перерисовывает изображение страницы. В результате у нас отрисовка страницы всегда соответствует DOM .

    Для чтения и изменения DOM программно браузер предоставляет нам DOM API или, другими словами, программный интерфейс. По-простому DOM API – это набор огромного количества различных объектов, их свойств и методов, которые мы можем использовать для чтения и изменения DOM .

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

    Зачем нам нужен DOM API? Он нам нужен для того, чтобы мы могли с помощью JavaScript изменять страницу на «лету», т.е. делать её динамической и интерактивной.

    DOM API предоставляет нам (разработчикам) огромное количество методов, с помощью которых мы можем менять всё что есть на странице, а также взаимодействовать с пользователем. Т.е. данный программный интерфейс позволяет нам создавать сложные интерфейсы, формы, выполнять обработку действий пользователей, добавлять и удалять различные элементы на странице, изменять их содержимое, свойства (атрибуты), и многое другое.

    Сейчас в вебе практически нет сайтов в сценариях которых отсутствовала бы работа с DOM.

    Из чего состоит HTML-код страницы?

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

    Исходный код веб-страницы состоит из тегов, атрибутов, комментариев и текста. Теги - это базовая синтаксическая конструкция HTML. Большинство из них являются парными. В этом случае один из них является открывающим, а другой – закрывающим. Одна такая пара тегов образует HTML-элемент. HTML-элементы могут иметь дополнительные параметры – атрибуты.

    В документе для создания определённой разметки одни элементы находятся внутри других. В результате HTML-документ можно представить как множество вложенных друг в друга HTML-элементов.

    В качестве примера рассмотрим следующий HTML код:

    Заголовок страницы Название статьи Раздел статьи

    Содержимое статьи

    В этом коде корневым элементом является html . В него вложены элементы head и body . Элемент head содержит title , а body – h1 и div . Элемент div в свою очередь содержит h2 и p .

    Теперь рассмотрим, как браузер на основании HTML-кода строит DOM-дерево.

    Как строится DOM-дерево документа?

    Как уже было описано выше браузер строит дерево на основе HTML-элементов и других сущностей исходного кода страницы. При выполнении этого процесса он учитывает вложенность элементов друг в друга.

    В результате браузер полученное DOM-дерево использует не только в своей работе, но также предоставляет нам API для удобной работы с ним через JavaScript.

    При строительстве DOM браузер создаёт из HTML-элементов, текста, комментариев и других сущностей этого языка объекты (узлы DOM-дерева).

    В большинстве случаев веб-разработчиков интересуют только объекты (узлы), образованные из HTML-элементов.

    При этом браузер не просто создаёт объекты из HTML-элементов, а также связывает их между собой определёнными связями в зависимости от того, как каждый из них относится к другому в коде.

    Элементы, которые находятся непосредственно в некотором элементе являются по отношению к нему детьми. А он для каждого из них является родителем. Кроме этого, все эти элементы по отношению друг к другу являются сиблингами (братьями).

    При этом в HTML любой элемент всегда имеет одного родителя (HTML-элемент, в котором он непосредственно расположен). В HTML у элемента не может быть несколько родителей. Исключение составляет только элемент html . У него нет родителя.

    Чтобы получить DOM-дерево так как его строит браузер, необходимо просто «выстроить» все элементы в зависимости от их отношения друг к другу.

    Создание DOM-дерева выполняется сверху вниз.

    При этом корнем DOM-дерева всегда является сам документ (узел document). Далее дерево строится в зависимости от структуры HTML кода.

    Например, HTML-код, который мы рассматривали выше будет иметь следующее DOM-дерево:


    В самом верху этого дерева находится узел document . Данный узел связан с html , он является его ребёнком. Узел html образован элементом html (...). Узлы head (...) и body (...) имеют родительскую связь с html . По отношению друг ту другу они являются сиблингами, т.к. имеют одного родителя. Узел head связан с title (lt;title>...), он является его ребёнком. Узлы h1 и div связаны с body , для них он является родителем. Узел div связан с h2 (...) и p (), они являются его детьми.

    Начинается дерево как было уже отмечено выше с объекта (узла) document . Он в свою очередь имеет один дочерний узел, образованный элементом html (...). Элементы head (...) и body (...) находятся в html и, следовательно, являются его детьми. Далее узел head является родительским для title (lt;title>...). Элементы h1 и div вложены в body , значит они являются его детьми. В div непосредственно расположены элементы h2 (...) и p (). Это значит, что узел div для каждого из них является родительским.

    Вот так просто строится DOM-дерево в браузере на основании HTML-кода.

    Зачем нужно знать, как строится DOM дерево? Во-первых, это понимание той среды, в которой вы хотите что-то изменять. Во-вторых, большинство действий при работе с DOM сводится к поиску (выбору) нужных элементов. Не зная как устроено DOM-дерево и связи между узлами найти какой-то определенный элемент в нём будет достаточно затруднительно.

    Задание

    На основе DOM-дерева, представленного на рисунке, создайте HTML-код.


    На этом уроке мы рассмотрим, что такое DOM, зачем он нужен, а также то, как он строится.

    Что такое DOM?

    Браузер, когда запрашивает страницу и получает в ответе от сервера её исходный HTML-код, должен сначала его разобрать. В процессе анализа и разбора HTML-кода браузер строит на основе него DOM-дерево .

    После выполнения этого действия и ряда других браузер приступает к отрисовке страницы. В этом процессе он, конечно, уже использует созданное им DOM-дерево , а не исходный HTML-код.

    DOM – это объектная модель документа, которую браузер создаёт в памяти компьютера на основании HTML-кода, полученного им от сервера.

    Если сказать по-простому, то HTML-код – это текст страницы, а DOM – это набор связанных объектов, созданных браузером при парсинге её текста.

    В Chrome исходный код страницы, который получает браузер, можно посмотреть во вкладке «Source» на панели «Инструменты веб-разработчика».


    В Chrome инструмента, с помощью которого можно было бы посмотреть созданное им DOM-дерево нет. Но есть представление этого DOM-дерева в виде HTML-кода, оно доступно на вкладке «Elements». С таким представлением DOM веб-разработчику, конечно, намного удобнее работать. Поэтому инструмента, который DOM представлял бы в виде древовидной структуры нет.


    Объекты в этой модели образуются практически из всего, что есть в HTML (тегов, текстового контента, комментариев и т.д.), включая при этом сам документ. Связи между этими объектами в модели формируются на основании того, как HTML-элементы расположены в коде относительно друг друга .

    При этом DOM документа после его формирования можно изменять . При изменении DOM браузер практически мгновенно перерисовывает изображение страницы. В результате у нас отрисовка страницы всегда соответствует DOM .

    Для чтения и изменения DOM программно браузер предоставляет нам DOM API или, другими словами, программный интерфейс. По-простому DOM API – это набор огромного количества различных объектов, их свойств и методов, которые мы можем использовать для чтения и изменения DOM .

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

    Зачем нам нужен DOM API? Он нам нужен для того, чтобы мы могли с помощью JavaScript изменять страницу на «лету», т.е. делать её динамической и интерактивной.

    DOM API предоставляет нам (разработчикам) огромное количество методов, с помощью которых мы можем менять всё что есть на странице, а также взаимодействовать с пользователем. Т.е. данный программный интерфейс позволяет нам создавать сложные интерфейсы, формы, выполнять обработку действий пользователей, добавлять и удалять различные элементы на странице, изменять их содержимое, свойства (атрибуты), и многое другое.

    Сейчас в вебе практически нет сайтов в сценариях которых отсутствовала бы работа с DOM.

    Из чего состоит HTML-код страницы?

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

    Исходный код веб-страницы состоит из тегов, атрибутов, комментариев и текста. Теги - это базовая синтаксическая конструкция HTML. Большинство из них являются парными. В этом случае один из них является открывающим, а другой – закрывающим. Одна такая пара тегов образует HTML-элемент. HTML-элементы могут иметь дополнительные параметры – атрибуты.

    В документе для создания определённой разметки одни элементы находятся внутри других. В результате HTML-документ можно представить как множество вложенных друг в друга HTML-элементов.

    В качестве примера рассмотрим следующий HTML код:

    Заголовок страницы Название статьи Раздел статьи

    Содержимое статьи

    В этом коде корневым элементом является html . В него вложены элементы head и body . Элемент head содержит title , а body – h1 и div . Элемент div в свою очередь содержит h2 и p .

    Теперь рассмотрим, как браузер на основании HTML-кода строит DOM-дерево.

    Как строится DOM-дерево документа?

    Как уже было описано выше браузер строит дерево на основе HTML-элементов и других сущностей исходного кода страницы. При выполнении этого процесса он учитывает вложенность элементов друг в друга.

    В результате браузер полученное DOM-дерево использует не только в своей работе, но также предоставляет нам API для удобной работы с ним через JavaScript.

    При строительстве DOM браузер создаёт из HTML-элементов, текста, комментариев и других сущностей этого языка объекты (узлы DOM-дерева).

    В большинстве случаев веб-разработчиков интересуют только объекты (узлы), образованные из HTML-элементов.

    При этом браузер не просто создаёт объекты из HTML-элементов, а также связывает их между собой определёнными связями в зависимости от того, как каждый из них относится к другому в коде.

    Элементы, которые находятся непосредственно в некотором элементе являются по отношению к нему детьми. А он для каждого из них является родителем. Кроме этого, все эти элементы по отношению друг к другу являются сиблингами (братьями).

    При этом в HTML любой элемент всегда имеет одного родителя (HTML-элемент, в котором он непосредственно расположен). В HTML у элемента не может быть несколько родителей. Исключение составляет только элемент html . У него нет родителя.

    Чтобы получить DOM-дерево так как его строит браузер, необходимо просто «выстроить» все элементы в зависимости от их отношения друг к другу.

    Создание DOM-дерева выполняется сверху вниз.

    При этом корнем DOM-дерева всегда является сам документ (узел document). Далее дерево строится в зависимости от структуры HTML кода.

    Например, HTML-код, который мы рассматривали выше будет иметь следующее DOM-дерево:


    В самом верху этого дерева находится узел document . Данный узел связан с html , он является его ребёнком. Узел html образован элементом html (...). Узлы head (...) и body (...) имеют родительскую связь с html . По отношению друг ту другу они являются сиблингами, т.к. имеют одного родителя. Узел head связан с title (lt;title>...), он является его ребёнком. Узлы h1 и div связаны с body , для них он является родителем. Узел div связан с h2 (...) и p (), они являются его детьми.

    Начинается дерево как было уже отмечено выше с объекта (узла) document . Он в свою очередь имеет один дочерний узел, образованный элементом html (...). Элементы head (...) и body (...) находятся в html и, следовательно, являются его детьми. Далее узел head является родительским для title (lt;title>...). Элементы h1 и div вложены в body , значит они являются его детьми. В div непосредственно расположены элементы h2 (...) и p (). Это значит, что узел div для каждого из них является родительским.

    Вот так просто строится DOM-дерево в браузере на основании HTML-кода.

    Зачем нужно знать, как строится DOM дерево? Во-первых, это понимание той среды, в которой вы хотите что-то изменять. Во-вторых, большинство действий при работе с DOM сводится к поиску (выбору) нужных элементов. Не зная как устроено DOM-дерево и связи между узлами найти какой-то определенный элемент в нём будет достаточно затруднительно.

    Задание

    На основе DOM-дерева, представленного на рисунке, создайте HTML-код.


    В данном уроке мы разберем основы работы с событиями, атрибутами и getElementById на языке JavaScript.

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

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

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

    В JavaScript существует несколько способов работы с событиями. Мы начнем с самого простого из них.

    Основы работы с событиями

    Самый простой способ задать реакцию элемента на определенное событие - указать ее с помощью атрибута для определенного тега. К примеру, событию "нажатие мышкой" соответствует атрибут onclick , событию "наведение мышкой" - атрибут onmouseover , а событию "уход курсора с элемента" - атрибут onmouseout .

    Значением атрибута с событием служит JavaScript код . В следующем примере по нажатию мышкой на кнопку выполнится функция alert :

    А сейчас по клику на элемент выполнится функция func :

    function func() { alert("!"); }

    Можно выполнить не одну функцию , а несколько:

    function func1() { alert("1"); } function func2() { alert("2"); }

    Обратите внимание на то, что если внутри атрибута вам нужны двойные кавычки (например, для строки) и внешние кавычки атрибута тоже двойные - onclick="alert("!")" - такой код не будет работать.

    С этим можно бороться несколькими способами: можно сменить внешние кавычки на одинарные onclick="alert("!")" , можно также заэкранировать внутренние кавычки обратным слешем onclick="alert(\"!\")" или же просто перенести JavaScript код из атрибута в функцию, а в атрибуте оставить только имя функции onclick="func()" .

    То же самое будет, если вы внешние кавычки атрибута ставите одинарными и для строки тоже используете одинарные: onclick="alert("!")" - тут также все решается аналогичными способами.

    Таблица атрибутов для событий Работа с getElementById

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

    Пусть у нас на странице есть тег с атрибутом id в значении test . Запишем ссылку на этот тег в переменную elem . Для этого мы должны воспользоваться методом getElementById , который получает элемент по его id .

    Эта запись произойдет по клику на кнопку, которой мы задали атрибут onclick . По нажатию на эту кнопку сработает функция func , которая найдет на HTML странице элемент с id равным test и запишет ссылку на него в переменную elem :

    Теперь в переменной elem у нас лежит ссылка на элемент с атрибутом id в значении test . Сама переменная elem является объектом .

    Этот объект и тег HTML страницы связаны друг с другом - мы можем поменять какие-либо свойства объекта elem и при этом увидим изменения на HTML странице, которые произойдут с полученным нами элементом.

    Давайте посмотрим, как это происходит на практике.

    Основы работы с атрибутами HTML через JavaScript

    Сейчас мы будем считывать и изменять атрибуты тегов. Пусть у нас опять даны инпут с id равным test и кнопка , по клику на которую будет запускаться функция func :

    Внутри функции func мы получим наш инпут по его id и запишем ссылку на него в переменную elem :

    function func() { var elem = document.getElementById("test"); }

    Давайте теперь выведем на экран содержимое атрибутов нашего инпута. Чтобы получить доступ, к примеру, к атрибуту value, следует написать следующее: elem.value , где elem - это переменная, в которую мы с помощью getElementById записали ссылку на наш элемент, а value - это атрибут тега, который нас интересует.

    Мы можем вывести содержимое атрибута через alert таким образом - alert(elem.value) - или записать в какую-нибудь переменную. Давайте проделаем это:

    function func() { var elem = document.getElementById("test"); alert(elem.value); //выведет "!" }

    Мы можем таким же образом считывать значения и других атрибутов, например так - elem.id - мы считаем значение атрибута id, а так - elem.type - значение атрибута type. Смотрите пример:

    function func() { var elem = document.getElementById("test"); alert(elem.value); //выведет "!" alert(elem.id); //выведет "test" alert(elem.type); //выведет "text" }

    Можно не только считывать значения атрибутов, но и изменять их. Чтобы, к примеру, поменять значение атрибута value , нужно просто присвоить его конструкции elem.value :

    function func() { var elem = document.getElementById("test"); elem.value = "www"; //присвоим новое значение атрибуту value }

    HTML код станет выглядеть так (значение атрибута value станет www):

    Ну, а теперь самое сложное - можно не вводить переменную elem , а строить цепочку из точек таким образом:

    function func() { alert(document.getElementById("test").value); //выведет "!" }

    Таким же образом (цепочкой) можно производить и перезапись атрибутов :

    function func() { document.getElementById("test").value = "www"; }

    Однако, в большинстве случаев введение переменной удобнее . Сравните два примера - сейчас я ввел переменную elem и могу считывать любое количество атрибутов, при этом getElementById вызывается только один раз :

    function func() { var elem = document.getElementById("test"); elem.value = "www"; elem.type = "submit"; }

    А сейчас я не ввожу новую переменную и поэтому мне приходится вызывать getElementById два раза:

    function func() { document.getElementById("test").value = "www"; document.getElementById("test").type = "submit"; }

    На мой взгляд, этот код стал сложнее , хотя и занимает на одну строчку меньше. Кроме того, если я захочу сменить значение id с test на, к примеру, www, мне придется делать это во многих местах, что не очень удобно.

    на браузер. Поиск элементов по странице, который делает метод getElementById , является довольно медленной операцией (и вообще любая работа с элементами страницы - это медленная операция - запомните это).

    В нашем случае, если мы каждый раз используем getElementById , то браузер каждый раз будет обрабатывать HTML страницу и искать элемент с заданным id несколько раз (не важно, что id одинаковые - браузер проделает все действия несколько раз), совершая бесполезные операции, которые могут замедлить работу браузера.

    Если же мы используем переменную elem - никакого поиска по странице не происходит (элемент уже найден и ссылка на него лежит в переменной elem ).

    Исключения: атрибуты class и for

    Вы уже научились работать с атрибутами через JavaScript и теперь пришло время рассказать вам о том, что не все так просто - при работе с атрибутами существует исключение - это атрибут class .

    Это слово является специальным в JavaScript и поэтому мы не можем просто написать elem.class , чтобы считать значение атрибута class . Вместо этого следует писать elem.className .

    В следующем примере на экран выводится значение атрибута class :

    function func() { var elem = document.getElementById("test"); alert(elem.className); }

    Кстати, есть и другие атрибуты, которые называются иначе, чем свойство. Например, атрибуту for () соответствует свойство с названием htmlFor .

    Работа с this

    Сейчас мы с вами будем работать со специальным объектом this , который указывает на текущий элемент (элемент в котором произошло событие). Причем указывает так, будто этот элемент уже получен методом getElementById .

    Давайте посмотрим как работать с this и в чем удобство такого подхода.

    Пусть у нас есть задача по нажатию на инпут вывести на экран содержимое его value.

    Пока вы умеете делать только такое решение:

    function func() { var elem = document.getElementById("test"); alert(elem.value); }

    В принципе, это решение хорошее, но представим теперь, что у нас есть много инпутов и по нажатию на каждый нам нужно выводить его value.

    В этом случае у нас получится что-то в таком роде:

    function func1() { var elem = document.getElementById("test1"); alert(elem.value); } function func2() { var elem = document.getElementById("test2"); alert(elem.value); } function func3() { var elem = document.getElementById("test3"); alert(elem.value); }

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

    Если у нас будет 10 инпутов - то придется сделать 10 функций, не удобно.

    Давайте упростим нашу задачу: будем передавать параметром функции id текущего элемента. И вместо большого количества функций все сведется к одной функции:

    function func(id) { var elem = document.getElementById(id); alert(elem.value); }

    Однако, такое решение все равно имеет недостаток - каждому элементу придется вводить разные id, что тоже несколько неудобно.

    Итак, давайте наконец рассмотрим вариант решения задачи через this .

    Сделаем так, что каждый инпут будет выводить свое содержимое по нажатию. Для этого параметром функции передадим объект this , вот так: func(this) .

    Наш this передается параметром функции и попадает в переменную elem . Этот elem ведет себя так, будто получен таким образом: var elem = document.getElementById(...) , но получать его таким образом не надо, там уже все готово и можно пользоваться. К примеру, elem.value указывает на value нашего инпута и так далее.

    Итак, вот самое просто решение нашей задачи:

    function func(elem) { alert(elem.value); }

    Основы работы с CSS

    В JavaScript работа с CSS свойствами происходит путем изменения значения атрибута style для элемента. К примеру, чтобы поменять цвет нужно построить следующую цепочку - elem.style.color - и присвоить ей нужное значение цвета:

    function func() { var elem = document.getElementById("test"); elem.style.color = "red"; }

    Можно также и не вводить переменную elem , а построить очень длинную цепочку .

    Windows