Атрибуты и свойства элементов в DOM
При построении страницы браузер берёт информацию об элементах из их атрибутов. Но, кроме того, все элементы страницы являются объектами со своими свойствами, которые также учитываются при отображении элементов. DOM-интерфейс позволяет работать и с атрибутами элементов и с их свойствами. При этом необходимо понимать разницу между ними, знать, что и где использовать.
Атрибуты элементов
В HTML-документах теги могут иметь определённые атрибуты с заданными значениями. Атрибуты могут влиять на отображение элемента на странице или изменять его назначение. Поэтому для манипулирования элементами страницы должна быть предоставлена возможность работы с атрибутами HTML-тегов.
DOM-интерфейс представляет набор методов для работы с атрибутами элементов.
element.hasAttribute(атрибут)- Проверяет наличие атрибута.
element.getAttribute(атрибут)- Возвращает строку со значением атрибута.
element.setAttribute(атрибут, значение)- Создаёт атрибут или присваивает ему новое значение.
element.removeAttribute(атрибут)- Удаляет атрибут.
Эти методы работают именно с HTML-атрибутами как они есть в документе. Фактически, они изменяют код страницы. Поэтому для них справедливо:
- Значения атрибутов - это всегда строки.
- Имя атрибута можно указывать в любом регистре, так как HTML не предъявляет требований к регистру символов в коде.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><a>Первый</a></p>
</body>
</html>
<script>
var anch = document.querySelector('a');
alert(anch.hasAttribute('href')); /* false */
anch.setAttribute('href', 'home.html');
alert(anch.getAttribute('href')); /* строка 'home.html' */
anch.removeAttribute('HREF');
alert(anch.hasAttribute('href')); /* false, атрибут удалился вне зависимости от регистра */
</script>
Свойства элементов
В DOM каждый элемент является объектом своего класса. При создании модели страницы для каждого элемента браузер создаёт определённые свойства. В них содержится информация о текущем состоянии данного элемента, которую можно изменить. Также, любому элементу можно присвоить совершенно любые свойства, как и для любого объекта в JavaScript.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p>Lorem ipsum dolor...</p>
</body>
</html>
<script>
var par = document.querySelector('p');
par.firstParagraph = true;
alert(par.firstParagraph); /* true */
</script>
В отличие от атрибутов:
- Значение свойства может быть любого типа.
- Имена свойств регистрозависимы.
Связь свойств с атрибутами
В DOM-интерфейсе понятия HTML-атрибутов и DOM-свойств элементов тесно связаны. При создании модели страницы для каждого элемента создаются одноимённые с атрибутами свойства и присваиваются им те же значения. Однако, это справедливо не для всех атрибутов, что приводит к некоторой путанице, но, чаще, это бывает полезно.
При выводе в окне браузера параметры элемента зависят именно от его свойств. Дальнейшее управление элементами на странице осуществляется изменением этих свойств. Поэтому в основном требуется работать со свойствами элементов, а не с артибутами. Атрибуты, обычно, используются для хранения информации.
Например, поле для ввода текста <input> имеет атрибут value. При построении документа создаётся элемент со свойством value, которое имеет значение, указанное в HTML-коде страницы. Текст для отображения в поле берётся именно из свойства value. Если пользователь вводит свой текст в поле, то свойство автоматически принимает новое текущее значение. При этом код страницы не меняется, поэтому первоначальное значение атрибута остаётся доступным.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><input type="text" value="Текст" autocomplete="off"></p>
</body>
</html>
<script>
var input = document.querySelector('input');
alert('Свойство: ' + input.value); /* 'Свойство: Текст' */
input.value = 'Новый текст'; /* изменили текст в поле */
alert('Свойство: ' + input.value + '\nАтрибут: ' + input.getAttribute('value')); /* Атрибут не изменился */
</script>
В примере видно, что изменение свойства value не отражается на значении атрибута value. Таким образом, сравнив значения атрибута и свойства, можно понять, был ли изменён текст в поле.
Для элементов создаются свойства не только из указанных в коде атрибутов, а вообще из всех доступных для данного элемента атрибутов, даже если их нет в коде. Сюда включены глобальные атрибуты и атрибуты событий
. Такие свойства принимают значения по умолчанию
.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><input name="field" value="data"></p>
</body>
</html>
<script>
var input = document.querySelector('input');
alert(input.hasAttribute('type')); /* false, атрибута type нет */
alert('type' in input); /* true, свойство type есть */
alert(input.type); /* text, значение по умолчанию */
</script>
При построении документа одноимённые атрибуты и свойства не всегда имеют одинаковое значение.
Самый распространённый пример - это атрибут href.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><a href="home.html">Домой</a></p>
</body>
</html>
<script>
var anch = document.querySelector('a');
alert(anch.getAttribute('href')); /* home.html */
alert(anch.href); /* http://web-gain.ru/home.html */
</script>
Свойство href всегда содержит полный (абсолютный) адрес ссылки. Это же касается и свойства src.
Для атрибута булевого
типа (hidden, autofocus, checked, disabled, multiple, readonly, required) создаётся одноимённое свойство также булевого
типа, то есть со значением true или false. Но в HTML-коде эти атрибуты вообще могут не иметь значений.
Если в HTML-коде будет указан нестандартный для конкретного элемента атрибут, то одноимённое свойство создано не будет.
И это логично, если атрибут не описан в стандарте, значит он не может повлиять на параметры элемента.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><a href="home.html" something="data">Домой</a></p>
</body>
</html>
<script>
var anch = document.querySelector('a');
alert(anch.hasAttribute('something')); /* true, атрибут something есть */
alert('something' in anch); /* false, свойства something нет */
</script>
Проблем с этой особенностью обычно не возникает, так как нестандартные атрибуты почти не используются (с ними страница не проходит валидацию).
Атрибуты data-
dataset
Для передачи информации в HTML введены атрибуты с префиксом data-. С такими атрибутами нужно работать через свойство dataset. Оно содержит список всех data-атрибутов элемента.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><input type="text" data-some-info="something"></p>
</body>
</html>
<script>
var input = document.querySelector('input');
alert(input.dataset.someInfo); /* something */
</script>
Атрибут class
className
Свойства с именем class не существует, так как это зарезервированное слово в JavaScript. Атрибуту class соответствует свойство className.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p class="first second"></p>
</body>
</html>
<script>
var par = document.querySelector('p');
alert(par.className); /* 'first second' */
</script>
Данное свойство удобно использовать, если элементу присвоен только один класс. Но если их несколько, то с этим свойством работать сложнее. Для таких случаев в DOM введено ещё одно свойство для работы с классами - classList.
classList
Свойство classList содержит список (псевдомассив) классов элемента. Для работы с этим массивом можно воспользоваться циклом или встроенными методами:
element.classList.add(класс)- Добавляет класс, если такой класс отсутствует.
element.classList.remove(класс)- Удаляет класс. Если такого класса нет, метод не выдаст ошибку.
element.classList.contains(класс)- Проверяет, имеется ли указанный класс.
element.classList.toggle(класс)- Добавляет класс, если его нет (и возвращает
true), или удаляет его, если он уже есть (и возвращаетfalse). element.classList.replace(старый_класс, новый_класс)- Заменяет указанный класс на новый.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p class="first second"></p>
</body>
</html>
<script>
var par = document.querySelector('p');
par.classList.remove('second');
par.classList.add('third');
alert(par.className); /* 'first third' */
par.classList.toggle('third');
alert(par.classList.contains('third')); /* false */
</script>
Атрибут style
style
Свойство style содержит объект-коллекцию всех CSS-свойств элемента. При этом значения имеют только те свойства, которые заданы атрибутом style. Значениями остальных свойств являются пустые строки.
Использование этого свойства очень удобно, так как CSS-свойства элемента, заданные с его помощью, имеют почти самый высокий приоритет (как и атрибут style).
Ещё одним достоинством является то, что с каждым CSS-свойством можно работать отдельно. Свойство style представляет объект, в котором каждому свойству соответствует определённый CSS-стиль.
Кроме того, свойству style можно присвоить стили в виде строки, как это делается с атрибутом style. Для этого используется доступное для записи свойство style.cssText. Однако, необходимо помнить, что присвоение нового значения свойству style.cssText полностью перезаписывает значение атрибута style.
<html>
<head>
<title>DOM интерфейс</title>
</head>
<body>
<p><input type="text" value="Текст" style="border: 5px solid red;"></p>
</body>
</html>
<script>
var input = document.querySelector('input');
alert(input.style.border); /* 5px solid red */
alert(input.style.borderWidth); /* 5px, отдельные свойства тоже присвоены */
input.style.cssText = 'color: red; font-size: 200%'; /* изменили атрибут style */
alert(input.style.color); /* red */
</script>
Свойство style очень полезно в случаях, когда нужно изменить какое-нибудь CSS-свойство элемента. Но оно не годится для получения значений применённых стилей. Так получается, потому что свойство style получает значения стилей из атрибута style, который используется редко (чаще всего CSS-стили выносятся в отдельный файл).
Чтобы получить значения всех CSS-свойств, применённых к элементу, необходимо воспользоваться методом window.getComputedStyle().
getComputedStyle()
Метод getComputedStyle() объекта window возвращает такой же объект, как и свойство style. Но в нём содержатся значения всех стилей, которые в данный момент применены к элементу (с учётом внешних файлов стилей и тега <style>).
window.getComputedStyle(элемент[, псевдоэлемент])
- элемент
- Исследуемый элемент (обязательно узел
элемент
, иначе выдаст ошибку). - псевдоэлемент
- Необязательный аргумент. Позволяет указать псевдоэлемент (
::after,::before,::first-letter,::first-line), чьи стили необходимо получить.
<html>
<head>
<title>DOM интерфейс</title>
<style>
p {
font-size: 20px;
}
p::first-letter {
font-size: 30px;
}
</style>
</head>
<body>
<p>Lorem ipsum dolor...</p>
</body>
</html>
<script>
var par = document.querySelector('p');
var style = window.getComputedStyle(par);
var style_pseudo = window.getComputedStyle(par, '::first-letter');
alert(style.fontSize); /* 20px */
alert(style_pseudo.fontSize); /* 30px */
</script>
Объект, получаемый данным методом, доступен только для чтения, поэтому с его помощью нельзя поменять стили у элемента. Для замены стилей нужно использовать свойство style элемента.