Объектная модель 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 работает только для чтения: это все табличные элементы, за исключением
Например, мы создали пустую таблицу без элемента
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, которые будут отображаться на странице, и связанных с ними стилей. Чтобы построить это дерево, браузеру нужны две вещи:
DOM – это объектное представление исходного HTML-документа. Он имеет некоторые различия, как мы увидим ниже, но по сути это попытка преобразовать структуру и содержание документа HTML в объектную модель, которая может использоваться различными программами.
Структура объектов DOM представлена тем, что называется «деревом узлов». Оно так называется, потому что его можно рассматривать как дерево с одним родительским элементом, который разветвляется на несколько дочерних ветвей, каждая из которых может иметь листья. В этом случае родительский «элемент» – это корневой элемент, дочерние «ветви» – это вложенные элементы, а «листья» – это содержимое внутри элементов.
Давайте рассмотрим этот HTML-документ в качестве примера:
My first web page Hello, world!
How are you?
Этот документ может быть представлен в виде следующего дерева узлов:
- html
- head
- title
- My first web page
- title
- body
- h1
- Hello, world!
- p
- How are you?
- h1
- head
В приведенном выше примере кажется, что 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!
Помимо того, что 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!
DOM будет включать элемент
- html
- head
- body
- h1
- Hello, world!
- p
- How are you?
- h1
Однако дерево рендеринга и, следовательно, то, что видно в окне просмотра, не будет включено в этот элемент.
- html
- body
- h1
- Hello, world!
- h1
- body
Это различие немного меньше, потому что инспектор элементов 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 , а построить очень длинную цепочку .