Добавление элемента на страницу




Послание № 10

Атрибуты и DOM-свойства

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

Например, если тег выглядит как <body id="page">, то у объекта будет свойство body.id = "page".

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

Если коротко – HTML-атрибуты и DOM-свойства обычно, но не всегда соответствуют друг другу, нужно понимать, что такое свойство и что такое атрибут, чтобы работать с ними правильно.

Атрибуты HTML

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

Значения атрибутов HTML-элементов доступны в виде свойств объектов HTMLElement, представляющих эти элементы. Кроме того, модель DOM определяет механизмы получения и изменения значений нестандартных HTML-атрибутов.

HTML-атрибуты как свойства объектов Element

Объекты HTMLElement, представляющие элементы HTML-документа, определяют свойства, доступные для чтения/записи, соответствующие HTML-атрибутам элементов.

Объект HTMLElement определяет свойства для поддержки универсальных HTTP-атрибутов, таких как id, title, lang и dir, и даже обработчики событий, такие как onclick.

Например, узнать URL-адрес изображения можно, обратившись к свойству src объекта HTMLEle­ment, представляющего элемент

var image = document.getElementById("myimage");

var imgurl = image.src; // Ат­ри­бут src оп­ре­де­ля­ет URL-ад­рес изо­бра­же­ния

Имена атрибутов в разметке HTML не чувствительны к регистру символов, в отличие от имен свойств в языке JavaScript. Чтобы преобразовать имя атрибута в имя свойства в языке JavaScript, его нужно записать символами в нижнем регистре. Однако, если имя атрибута состоит из более чем одного слова, первый символ каждого слова, кроме первого, записывается в верхнем регистре, например: defaultChecked и tabIndex.

Имена некоторых HTML-атрибутов совпадают с зарезервированными словами языка JavaScript. Имена свойств, соответствующих таким атрибутам, начинаются с приставки «html». Например, HTML-атрибуту for (элемента) в языке JavaScript соответствует свойство с именем htmlFor. Очень важный HTML-атрибут class, имя которого совпадает с зарезервированным (но не используемым) в языке JavaScript словом «class», является исключением из этого правила: в программном коде на языке JavaScript ему соответствует свойство className.

Обратите внимание, что основанный на свойствах прикладной интерфейс получения доступа к значениям атрибутов не позволяет удалять атрибуты из элементов.

Еще один способ работы с атрибутами

Доступ к атрибутам осуществляется при помощи стандартных методов:

· elem.hasAttribute(name) – проверяет наличие атрибута

· elem.getAttribute(name) – получает значение атрибута

· elem.setAttribute(name, value) – устанавливает атрибут

· elem.removeAttribute(name) – удаляет атрибут

Эти методы работают со значением, которое находится в HTML.

Классы в виде объекта: classList

Атрибут class – уникален. Ему соответствует аж целых два свойства!

Работать с классами как со строкой неудобно. Поэтому, кроме className, в современных браузерах есть свойство classList.

Свойство classList – это объект для работы с классами.

Методы classList:

· elem.classList.contains("class") – возвращает true/false, в зависимости от того, есть ли у элемента класс class.

· elem.classList.add/remove("class") – добавляет/удаляет класс class

· elem.classList.toggle("class") – если класса class нет, добавляет его, если есть – удаляет.

Кроме того, можно перебрать классы через for, так как classList – это псевдо-массив.

Например:

<body class="main page">

<script>

var classList = document.body.classList;

classList.remove('page'); // удалить класс

classList.add('post'); // добавить класс

for (var i = 0; i < classList.length; i++) { // перечислить классы

alert(classList[i]); // main, затем post

}

alert(document.body.className); // main post, тоже работает

</script>

</body>

Нестандартные атрибуты

У каждого элемента есть некоторый набор стандартных свойств, например для <a> это будут href, name, а для <img> это будут src, alt, и так далее.

Точный набор свойств описан в стандарте, обычно мы более-менее представляем, если пользуемся HTML, какие свойства могут быть, а какие – нет.

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

Как правило, это делается при помощи атрибутов с названиями, начинающимися на data-, например:

<div id="elem" data-about="Elephant" data-user-location="street">

По улице прошёлся слон. Весьма красив и толст был он.

</div>

<script>

alert(elem.getAttribute('data-about')); // Elephant

alert(elem.getAttribute('data-user-location')); // street

</script>

Стандарт HTML5 специально разрешает атрибуты data-* и резервирует их для пользовательских данных.

При этом во всех браузерах, кроме IE10-, к таким атрибутам можно обратиться не только как к атрибутам, но и как к свойствам, при помощи специального свойства dataset:

<div id="elem" data-about="Elephant" data-user-location="street">

По улице прошёлся слон. Весьма красив и толст был он.

</div>

<script>

alert(elem.dataset.about); // Elephant

alert(elem.dataset.userLocation); // street

</script>

Обратим внимание – название data-user-location трансформировалось в dataset.userLocation. Дефис превращается в большую букву.

 

Создание узлов

Создавать новые узлы Element можно с помощью метода createElement() объекта Document. Этому методу необходимо передать имя тега (имя не чувствительно к регистру символов при работе с HTML-документами).

Для создания текстовых узлов существует аналогичный метод — document.createTextNode("со­дер­жи­мое тек­сто­во­го уз­ла");

Еще один способ создания в документе новых узлов заключается в копировании существующих узлов. Каждый узел имеет метод cloneNode(), возвращающий новую копию узла. Если передать ему аргумент со значением true, он рекурсивно создаст копии всех потомков, но если передать false, то будет создана лишь поверхностная копия.

Добавление элемента на страницу

Чтобы DOM-узел был показан на странице, его необходимо вставить в document.

Для этого первым делом нужно решить, куда мы будем его вставлять. Предположим, что мы решили, что вставлять будем в некий элемент parentElem, например:

var parentElem = document.body.

Для вставки внутрь parentElem есть следующие методы:

· parentElem.appendChild(elem) Добавляет elem в конец дочерних элементов parentElem.

Следующий пример добавляет новый элемент в конец <ol>:

<ol id="list">

<li>0</li>

<li>1</li>

<li>2</li>

</ol>

<script>

var newLi = document.createElement('li');

newLi.innerHTML = 'Привет, мир!';

list.appendChild(newLi);

</script>

· parentElem.insertBefore(elem, nextSibling) Вставляет в коллекцию детей parentElem, перед элементом nextSibling.

Следующий код вставляет новый элемент перед вторым <li>:

<ol id="list">

<li>0</li>

<li>1</li>

<li>2</li>

</ol>

<script>

var newLi = document.createElement('li');

newLi.innerHTML = 'Привет, мир!';

list.insertBefore(newLi, list.children[1]);

</script>

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

list.insertBefore(newLi, list.firstChild);

У читателя, который посмотрит на этот код внимательно, наверняка возникнет вопрос: «А что, если list вообще пустой, в этом случае ведь list.firstChild = null, произойдёт ли вставка?»

Ответ – да, произойдёт.

Дело в том, что если вторым аргументом указать null, то insertBefore сработает как appendChild:

parentElem.insertBefore(elem, null);

// то же, что и:

parentElem.appendChild(elem)

Так что insertBefore универсален.

На заметку.

Все методы вставки возвращают вставленный узел.

Например, parentElem.appendChild(elem) возвращает elem.

Пример использования

Добавим сообщение в конец <body>:

<style>

.alert {

padding: 15px;

border: 1px solid #d6e9c6;

border-radius: 4px;

color: #3c763d;

background-color: #dff0d8;

}

</style>

<body>

<h3>Моя страница</h3>

</body>

 

<script>

var div = document.createElement('div');

div.className = "alert alert-success";

div.innerHTML = "<strong>Ура!</strong> Вы прочитали это важное сообщение.";

document.body.appendChild(div);

</script>

Удаление и замена узлов

Метод removeChild() удаляет элемент из дерева документа. Но будьте внимательны: этот метод вызывается не относительно узла, который должен быть удален, а (как следует из фрагмента «child» в его имени) относительно родителя удаляемого узла.

Этот метод вызывается относительно родителя и принимает в виде аргумента дочерний узел, который требуется удалить. Чтобы удалить узел n из документа, вызов метода должен осуществляться так: n.parentNode.removeChild(n);

Метод replaceChild() удаляет один дочерний узел и замещает его другим.

Этот метод должен вызываться относительно родительского узла. В первом аргументе он принимает новый узел, а во втором – замещаемый узел.

Например, ниже показано, как заменить узел n текстовой строкой:

n.parentNode.replaceChild(document.createTextNode("[ ИС­ПРАВ­ЛЕ­НО ]"), n);

Оба этих метода возвращают удаленный узел, то есть elem. Если нужно, его можно вставить в другое место DOM тут же или в будущем.

На заметку

Если вы хотите переместить элемент на новое место – не нужно его удалять со старого.

Все методы вставки автоматически удаляют вставляемый элемент со старого места.

Метод remove()

В современном стандарте есть также метод elem.remove(), который удаляет элемент напрямую, не требуя ссылки на родителя. Это зачастую удобнее, чем removeChild.

Он поддерживается во всех современных браузерах, кроме IE11-. Впрочем, легко подключить или даже сделать полифилл.

Итого

Методы для создания узлов:

· document.createElement(tag) – создает элемент;

· document.createTextNode(value) – создает текстовый узел;

· elem.cloneNode(deep) – клонирует элемент, если deep == true, то со всеми потомками, если false– без потомков.

Вставка и удаление узлов:

· parent.appendChild(elem) — вставляет последним элементом в родительский элемент;

· parent.insertBefore(elem, nextSibling) — вставляет в родительский элемент перед nextSibling;

· parent.removeChild(elem) — удаляет в родительском элементе указанный элемент (elem);

· parent.replaceChild(newElem, elem) удаляет один дочерний узел и замещает его другим.

Все эти методы возвращают elem.

DocumentFragment

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

Синтаксис для его создания:

var fragment = document.createDocumentFragment();

В него можно добавлять другие узлы.

fragment.appendChild(node);

Его можно клонировать:

fragment.cloneNode(true); // клонирование с подэлементами

 

Важно!

У DocumentFragment нет обычных свойств DOM-узлов, таких как innerHTML, tagName и т.п. Это не узел.

Его «Фишка» заключается в том, что когда DocumentFragment вставляется в DOM – то он исчезает, а вместо него вставляются его дети. Это свойство является уникальной особенностью DocumentFragment.

Например, если добавить в него много LI, и потом вызвать ul.appendChild(fragment), то фрагмент растворится, и в DOM вставятся именно LI, причём в том же порядке, в котором были во фрагменте.

Псевдокод:

// хотим вставить в список UL много LI

// делаем вспомогательный DocumentFragment

var fragment = document.createDocumentFragment();

for (цикл по li) {

fragment.appendChild(list[i]); // вставить каждый LI в DocumentFragment

}

ul.appendChild(fragment); // вместо фрагмента вставятся элементы списка

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

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-12-21 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: