Объектная модель dom. Выразительный JavaScript: Document Object Model (объектная модель документа). Когда HTML содержит ошибки разметки


Тема действительно сложная. Но, как говорится, не так страшен чёрт, как его малюют. Вот тут-то самый крепкий орешек достаётся мне: этакая сверхзадача «намалевать» по возможности удобоваримо, но и не совсем примитивно. Пока что все прочитанные мной материалы тяготеют либо к зауми, либо к примитиву.

Что такое DOM

Аббревиатура DOM расшифровывается как Document Object Model (объектная модель документа).

DOM - это программный интерфейс доступа к содержимому HTML, XHTML и XML-документов, то есть представление тэгов и атрибутов HTML, XHTML и XML, а также стилей CSS в виде объектов программирования. С этой моделью работает как JavaScript, так и другие языки web-программирования.

Немного истории

Существует 4 уровня DOM (0, 1, 2 и 3).

Уровень 0 (1996) включал в себя модели DOM , которые существовали до появления уровня 1. В основном это коллекции: document.images, document.forms, document.layers и document.all. Эти модели формально не являются спецификациями DOM , опубликованными W3C . Скорее они представляют информацию о том, что существовало до начала процесса стандартизации.

Уровень 1 (1997) включал также базовые функциональные возможности по обработке XML-документов: многочисленные способы работы с отдельными узлами, работа с инструкциями обработки XML и т.д.

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

В DOM уровня 2 (2002) было добавлено несколько новых возможностей.

Если в DOM уровня 1 отсутствовала поддержка пространств имён, то интерфейсы DOM уровня 2 содержат методы для управления пространствами имён, связанными с требованиями к составлению и обработке XML-документов.

Помимо этого, DOM уровня 2 поддерживает события.

Уровень 2 является текущим уровнем спецификаций DOM , однако W3C рекомендует и некоторые разделы спецификаций уровня 3.

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

Что означает «программный интерфейс»?

Английское слово interface можно перевести как «область контакта». Компьютер, грубо говоря, понимает только две вещи: пустой бит и заполненный бит. Язык, на котором «говорит» компьютер, можно представить как нескончаемую вереницу нулей и единиц, дающих бесконечное количество различных комбинаций.

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

Браузеры работают так же, как и другие компьютерные приложения. Они интерпретируют в «нули и единицы» коды HTML, XML, CSS, скрипты JavaScript, PHP, Perl и т.д. Для работы с этим многоязычием нужна общая платформа. Этой платформой и является DOM - спецификация, не зависящая от конкретного языка программирования или разметки. Это интерфейс, который можно использовать во многих популярных языках программирования, связанных с созданием web-страниц и способных понимать и интерпретировать объекты DOM .

DOM и браузеры

DOM и JavaScript

В JavaScript вершиной иерархической лестницы объектов DOM , своеобразным «проводником» в этот интерфейс служит объект document , а объекты DOM становятся его свойствами, свойствами его свойств и т.д. Их также называют узлами DOM .

Узлы DOM

В DOM уровня 2 есть 12 типов узлов. За каждым типом узла DOM закреплена константа с уникальным именем. Большинство узлов предназначено для работы с XML . В сборке HTML - JavaScript , которой мы занимаемся, можно использовать только 5 типов. Но и эта «верхушка айсберга» представляет собой весьма «развесистое дерево», которое не охватить за одно-два занятия.

Полный набор констант типов узлов, определённый в спецификации W3C DOM (голубым подсвечены узлы, доступные для HTML - JavaScript ):

Имя константы

Значение

Описание

Node.ELEMENT_NODE

Узел элемента (возвращает корневой элемент документа, для HTML-документов это элемент HTML)

Node.ATTRIBUTE_NODE

Узел атрибута (возвращает атрибут элемента XML- или HTML-документа)

Текстовый узел (#text)

Node.CDATA_SECTION_NODE

Узел секции CDATA (XML: альтернативный синтаксис для отображения символьных данных)

Node.ENTITY_REFERENCE_NODE

Node.ENTITY_NODE

Узел раздела

Node.PROCESSING_INSTRUCTION_NODE

Узел директивы XML

Node.COMMENT_NODE

Узел комментария

Node.DOCUMENT_NODE

Узел документа (основа доступа к содержанию документа и создания его составляющих)

Node.DOCUMENT_TYPE_NODE

Узел типа документа (возвращает тип данного документа, т.е. значение тэга DOCTYPE)

Node.DOCUMENT_FRAGMENT_NODE

Узел фрагмента документа (извлечение части дерева документа, создание нового фрагмента документа, вставка фрагмента в качестве дочернего элемента какого-либо узла и т.п.)

Node.NOTATION_NODE

Узел нотации*

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

Структура документа в модели DOM

Все объекты документа являются узлами DOM. Рассмотрим элементарный документ:

< title>DOM Заголовок

Текст абзаца

Вот схема его DOM-дерева:

Каждый узел может иметь дочерние узлы (на схеме к ним ведут стрелки). Объект document - основание дерева документа - тоже узел, но у него нет родительского узла и имеется ряд свойств и методов, отсутствующих у других узлов. Он имеет один дочерний узел: элемент .

У элемента два дочерних узла: и , для которых дочерними становятся все элементы, содержащиеся в них.

Внимание!

«Элемент» и «тэг» не синонимы. Тэг - это знак разметки: - это два разных тэга. А элемент - объект, помеченный этими тэгами:

Текст абзаца

.

Элементы , и

Содержат внутри себя текст . Это их дочерние текстовые узлы . У элемента есть также атрибут : align="center" . Узлы атрибутов - это тоже дочерние узлы элементов, которые их содержат.

При работе с узлами DOM-дерева используются их свойства и методы.

Некоторые свойства узлов

Маленькое вступление

Ещё раз повторю: когда мы обращаемся в скриптах к элементам страницы, то имеем дело не только с языком Javascript, но и с внедрённым в него интерфейсом DOM . Иногда необходимо отдавать себе в этом отчёт, иногда можно и забыть, «что говорим прозой».

Некоторыми свойствами и методами из объектной модели DOM мы уже таким образом пользовались. Поэтому временами я буду давать ссылки на предыдущие уроки.

В этом уроке мы не будем идти «академическим» путём, рассматривая все свойства всех узлов во всех браузерах. Для начала познакомимся с самыми практичными и «бесконфликтными» из них.

Именно поэтому не будем начинать, как принято, с «основных свойств»: nodeName и nodeValue .

tagName

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

Синтаксис

элемент .tagName

Пример

Тестируем свойство tagName

document.write (document.getElementById ("testTagName" ).tagName)

Результат

Тестируем свойство tagName

innerHTML

С этим свойством мы уже встречались (см. Урок 10). А теперь понимаем, откуда оно взялось: «из дома».

Даёт доступ к содержимому элемента. Задаёт не только текстовое содержание, но и все тэги HTML, находящиеся внутри элемента.

Это свойство не только для чтения, но и для изменения содержимого.

Примечание

В IE для ряда элементов innerHTML работает только для чтения: это все табличные элементы, за исключением и , а также и .

Например, мы создали пустую таблицу без элемента и хотим программно вставить его в через innerHTML :








IE выдаст «неизвестную ошибку выполнения», а остальные браузеры произведут вставку.

В то же время, если мы запросим существующее содержимое элемента , например, через alert(document.getElementById("id").innerHTML) , то в IE это сработает.

Синтаксис

элемент .innerHTML = "назначенный текст"

Пример




Абзац для вставки



// Эта функция читает текст и вставляет его в заданный абзац.
function testRead() {
document.getElementById ("target" ).innerHTML = document.getElementById ("testInnerHTML" ).innerHTML
}
// Эта функция изменяет текст заданного абзаца.
function testChange() {
document.getElementById ("target" ).innerHTML = "Перекрашиваем и меняем текст"
}
// Эта функция возвращает свойство в исходное положение.
function testReset() {
document.getElementById ("target" ).innerHTML = "Абзац для вставки"
}





Тестируем свойство innerHTML

Абзац для вставки


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

Как строится веб-страница?

Процесс преобразования исходного HTML-документа в отображаемую стилизованную и интерактивную страницу, называется “Critical Rendering Path”(“Критическим путем рендеринга”). Хотя этот процесс можно разбить на несколько этапов, как я описал это в статье «Понимание критического пути рендеринга », эти этапы можно условно сгруппировать в два этапа. В первом браузер анализирует документ, чтобы определить, что в конечном итоге будет отображаться на странице, а во второй браузер выполняет рендеринг.

Результатом первого этапа является то, что называется “render tree”(«дерево рендеринга»). Дерево рендеринга – это представление элементов HTML, которые будут отображаться на странице, и связанных с ними стилей. Чтобы построить это дерево, браузеру нужны две вещи:

  • CSSOM, представление стилей, связанных с элементами
  • DOM, представление элементов
  • Из чего состоит DOM?

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

    Структура объектов DOM представлена тем, что называется «деревом узлов». Оно так называется, потому что его можно рассматривать как дерево с одним родительским элементом, который разветвляется на несколько дочерних ветвей, каждая из которых может иметь листья. В этом случае родительский «элемент» – это корневой элемент, дочерние «ветви» – это вложенные элементы, а «листья» – это содержимое внутри элементов.

    Давайте рассмотрим этот HTML-документ в качестве примера:

    My first web page Hello, world!

    How are you?

    Этот документ может быть представлен в виде следующего дерева узлов:

    • html
      • head
        • title
          • My first web page
      • body
        • h1
          • Hello, world!
        • p
          • How are you?
    Чем DOM не является

    В приведенном выше примере кажется, что DOM является отображением 1: 1 исходного HTML-документа. Однако, как я уже говорил, есть различия. Чтобы полностью понять, что такое DOM, нам нужно взглянуть на то, чем он не является.

    DOM не является копией исходного HTML

    Хотя DOM создан из HTML-документа, он не всегда точно такой же. Есть два случая, в которых DOM может отличаться от исходного HTML.

    1. Когда HTML содержит ошибки разметки

    DOM – это интерфейс доступа к действительных (то есть уже отображаемым) элементам документа HTML. В процессе создания DOM, браузер сам может исправить некоторые ошибки в коде HTML.

    Рассмотрим в качестве примера этот HTML-документ:

    Hello, world!

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

    • html
      • head
      • body
        • Hello, world!
      2. Когда DOM модифицируется кодом Javascript

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

      Мы можем, например, создать дополнительные узлы для DOM, используя Javascript.

      Var newParagraph = document.createElement("p"); var paragraphContent = document.createTextNode("I"m new!"); newParagraph.appendChild(paragraphContent); document.body.appendChild(newParagraph);

      Этот код изменит DOM, но изменения не отобразятся в документе HTML .

      DOM – это не то, что вы видите в браузере (то есть, дерево рендеринга)

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

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

      Hello, world!

      How are you?

      DOM будет включать элемент

      • html
        • head
        • body
          • h1
            • Hello, world!
          • p
            • How are you?

      Однако дерево рендеринга и, следовательно, то, что видно в окне просмотра, не будет включено в этот элемент.

      • html
        • body
          • h1
            • Hello, world!
      DOM – это не то, что отображается в DevTools

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

      Лучший пример этого – псевдоэлементы CSS. Псевдоэлементы, созданные с использованием селекторов ::before и ::after , являются частью CSSOM и дерева рендеринга, но технически не являются частью DOM. Это связано с тем, что DOM создается только из исходного HTML-документа, не включая стили, примененные к элементу.

      Несмотря на то, что псевдоэлементы не являются частью DOM, они есть в нашем инспекторе элементов devtools.


      Резюме

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

    Модель DOM часто называют деревом DOM, поскольку она состоит из дерева объектов, называемых узлами. В вы узнали, что такое Document Object Model (DOM), как получить доступ к объекту document и изменить его свойства с помощью консоли, также мы разницу между исходным кодом HTML и DOM.

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

    Терминология HTML

    Понимание терминов HTML и JavaScript критически необходимо для работы с DOM. Давайте вкратце рассмотрим основные термины.

    Посмотрите на этот элемент HTML:

    Home

    В нем присутствует анкор, который является ссылкой на index.html.

    • a – тег
    • href – атрибут
    • html – значение атрибута
    • Home – текст.

    Все, что находится между открывающимся и закрывающимся тегами, составляет HTML-элемент.

    Вернемся к файлу index.html из предыдущего мануала:




    Learning the DOM


    Document Object Model

    Самый простой способ доступа к элементу с JavaScript – это атрибут id. Давайте добавим указанную выше ссылку в файл index.html с id=»nav».

    ...

    Document Object Model
    Home

    ...

    Загрузите (или обновите) страницу в окне браузера и посмотрите на DOM, чтобы убедиться, что код был обновлен.

    Затем используйте метод getElementById() для доступа ко всему элементу. В консоли введите следующее:

    document.getElementById("nav");
    Home

    Метод getElementById() извлечет весь элемент. Теперь вместо того, чтобы вводить этот объект и метод каждый раз, когда вам нужно получить доступ к ссылке nav, вы можете поместить элемент в переменную, чтобы с ним было проще работать.

    let navLink = document.getElementById("nav");

    Переменная navLink содержит анкор. Здесь можно легко изменять атрибуты и значения. Например, чтобы изменить место ссылки, измените атрибут href:

    navLink.href = "https://www.wikipedia.org";

    Также можно изменить текст, переназначив свойство textContent:

    navLink.textContent = "Navigate to Wikipedia";

    Теперь, просмотрев этот элемент в консоли или проверив тег Elements, вы увидите, как он обновился.

    navLink;
    Navigate to Wikipedia

    Изменения отобразятся и на фронт-энде.

    Обновление страницы вернет все исходные значения.

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

    Дерево и узлы DOM

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

  • Узел элемента
  • Текстовый узел
  • Узел комментария
  • Когда элемент HTML является элементом в DOM, он называется узлом элемента. Любой одиночный текст вне элемента является текстовым узлом, а комментарий HTML – узлом комментария. Помимо этих трех типов узлов, сам объект document – это узел документа, который является корневым узлом всех остальных узлов.

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

    Для примера создайте файл nodes.html. добавьте в него текстовый узел, а также узлы комментария и элемента.




    Learning About Nodes


    An element node

    A text node.

    Узел элемента html является родительским. head и body – дочерние узлы html. body содержит три дочерних узла, и все они находятся на одном уровне – тип узла не влияет на уровень вложения.

    Примечание : При работе с DOM, сгенерированным HTML, отступы исходного кода HTML создают много пустых текстовых узлов, которые не будут видны во вкладке DevTools Elements. Больше об этом по ссылке .

    Определение типа узла

    Каждый узел в документе имеет тип, доступ к которому осуществляется через свойство nodeType. В Mozilla Developer Network имеется обновленный список всех констант типов узлов. Ниже приведена таблица наиболее распространенных типов узлов.

    Во вкладке Elements в Developer Tools вы можете заметить, что всякий раз, когда вы нажимаете и выделяете любую строку в DOM, рядом с ней появляется значение == $0. Это очень удобный способ получить доступ к текущему активному элементу.

    В консоли node.html нажмите на первый элемент в body (h1).

    С помощью консоли узнайте тип выбранного узла с помощью свойства nodeType.

    $0.nodeType;
    1

    Выбрав элемент h1, вы увидите 1 как вывод, который относится к ELEMENT_NODE. Сделайте то же самое с другими узлами, и они вернут 3 и 8 соответственно.

    Зная, как получить доступ к элементу, вы можете увидеть тип узла, не выделяя элементы в DOM.

    document.body.nodeType;
    1

    В дополнение к nodeType вы также можете использовать свойство nodeValue, чтобы узнать значение текстового узла или узла комментария, а nodeName – для получения тега элемента.

    Изменение DOM с помощью событий

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

    Вернитесь в файл index.html и добавьте элемент button с id. Также нужно добавить ссылку на новый файл в новый js-каталог js/scripts.js.




    Learning the DOM


    Document Object Model
    Change Background Color


    Событие в JavaScript – это действие, которое выполняет пользователь. Пользователь наводит указатель мыши на элемент, нажимает на него или на определенную клавишу на клавиатуре – это все события. В этом конкретном случае кнопка должна выполнить действие, когда пользователь нажмет на нее. Для этого нужно добавить слушателя событий. Создайте файл scripts.js и сохраните его в новом каталоге js. В файле нужно определить элемент button и присвоить его переменной.

    Используя метод addEventListener(), кнопка будет прослушивать клики и выполнять свою функцию после клика.

    ...
    button.addEventListener("click", () => {
    // action will go here
    });

    Внутри функции нужно поместить код из предыдущего мануала, чтобы изменить цвет фона на fuchsia.

    ...

    Так выглядит скрипт:

    let button = document.getElementById("changeBackground");
    button.addEventListener("click", () => {
    document.body.style.backgroundColor = "fuchsia";
    });

    Сохраните и закройте файл. Обновите страницу index.html в браузере. Нажмите на новую кнопку, и цвет фона страницы изменится.

    Tags: ,

    innerHTML
    var text = element.innerHTML;
    element.innerHTML = "";
    Присвоение нового innerHTML осуществляет перезапись кода, даже если новое значение добавлено к текущему (+=). Скрипты, добавленные таким образом, не выполняются.

    outerHTML
    Содержит элемент целиком, изменить его невозможно. Технически при записи в это свойство создается новый элемент, который заменяет старый. Ссылки на старый элемент в переменных не изменяются.

    data
    textNode.data — содержимое текстовых узлов и комментариев

    textContent
    element.textContent — текст внутри элемента без тегов.
    Существует также нестандартное свойство innerText , имеющее с textContent много общего.

    Видимость элемента

    hidden
    element.hidden = true
    Атрибут hidden не поддерживается в IE11.

    Атрибуты

    Большинство стандартных атрибутов в DOM становятся свойствами объекта:
    element.id = "id"
    Для нестандартных атрибутов свойство не создается (undefined)

    Можно создавать собственные DOM-свойства:
    element.myData = {name:"John", lastName:"Smith"};
    и методы:
    element.myFunc = function(){alert this.nodeName};
    Это работает, потому что узлы DOM являются обычными JavaScript-объектами. Такие нестандартные свойства и методы не влияют на отображение тега и видны только в JavaScript.

    Доступ к атрибутам тегов:
    element.hasAttribute(name)
    element.getAttribute(name)
    element.setAttribute(name, value)
    element.removeAttribute(name)
    element.attributes — псевдомассив атрибутов.

    Атрибуты нечувствительны к регистру (html), а свойства чувствительны (javaScript).
    Значение атрибута — всегда строка.

    Атрибут: a.getAttribute("href") — отображает именно то, что в HTML
    Свойство: a.href — может отличать от значения атрибута
    Чаще всего свойство зависит от атрибута, но не наоборот. Изменение свойства не влияет на аттрибут.

    Работа с классами

    Атрибуту class соответствуют два свойства:
    className — строка
    classList — объект

    методы объекта classList:
    element.classList.contains("class") — проверка, содержит ли объект данный класс
    element.classList.add("class")
    element.classList.remove("class")
    element.classList.toggle("class")

    classList является псевдомассивом, его можно перебирать через цикл for .

    data-атрибуты

    Пользовательские data -атрибуты доступны не только как атрибуты, но и через свойство dataset
    data-about = "some value"
    element.dataset.about

    Порядок узлов

    parent.contains(child) — true или false
    проверяет, является ли узел child вложенным в parent

    nodeA.compareDocumentPosition(nodeB) — предоставляет информацию о содержании и относительном порядке элементов. Возвращаемое значение — побитовая маска:

    Добавление и удаление узлов

    var div = document.createElement("div")
    document.createTextNode("text")

    parent.appendChild(element) — элемент добавляется в конец родителя
    parent.insertBefore(element, nextSibling) — элемент добавляется перед nextSibling
    parent.insertBefore(element, parent.firstChild) — добавляется в начало
    parent.insertBefore(element, null) — сработает как appendChild
    Все методы вставки возвращают вставленный узел.
    При перемещении элемента не нужно его предварительно удалять со старого места, метода вставки делают это автоматически.

    element.insertAdjacentHTML(where, html) — вставка произвольного HTML-кода в любое место документа. Where указывает куда следует вставить html по отношению к element — beforeBegin, afterBegin, beforeEnd, afterEnd.
    element.insertAdjacentElement(where, newElement)
    element.insertAdjacentText(where, text)
    два последних метода не поддерживаются в Firefox

    node.append(...nodes) – вставляет nodes в конец node ,
    node.prepend(...nodes) – вставляет nodes в начало node ,
    node.after(...nodes) – вставляет nodes после узла node ,
    node.before(...nodes) – вставляет nodes перед узлом node ,
    node.replaceWith(...nodes) – вставляет nodes вместо node .
    здесь nodes — это узлы или строки, в любых количествах и сочетаниях, перечисленные через запятую.

    var fragment = document.createDocumentFragment() — имитация DOM-узла, который при вставке в документ исчезает, оставляя только своих потомков. В современных браузерах не рекомендуется.

    element.cloneNode(true) — глубокая копия элемента
    element.cloneNode(false) — копия без дочерних элементов

    parent.removeChild(element)
    parent.replaceChild(newElement, element)
    element.remove() — удаляет элемент напрямую, без ссылки на родителя.
    Методы возвращают удаленный узел

    В данном уроке мы разберем основы работы с событиями, атрибутами и 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 , а построить очень длинную цепочку .



    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: