Элемент DOM - это узел, который объявлен с использованием тега в HTML-документе (например, <html>, <head>,<body> и т.д.). Далее, в синтаксисе методов, обозначается как Element или element. Все остальные узлы обозначаются в синтаксисе методов как Node или node.
Создание узлов DOM
Метод document.createElement(tagName) создает в документе:
- HTML элемент, указанный в tagName, или
- HTMLUnknownElement, если tagName не распознается.
Синтаксис:
1 |
let element = document.createElement (tagName [, param]); |
где
- tagName - строка, определяющая тип создаваемого элемента, при этом NodeName создаваемого элемента инициализируется значением tagName;
- param (необязательный) - объект ElementCreationOptions, содержащий одно свойство с именем is, значение которого является именем тега настраиваемого элемента, ранее определенного с помощью customElements.define().
Не используйте полные имена (например, «html: a») с этим методом.
Возвращаемое значение:
- новый HTMLElement, если документ является HTMLDocument;
- новый элемент.
Особенности метода document.createElement():
- при вызове HTML-документа createElement() перед созданием элемента преобразует tagName в нижний регистр;
- в Firefox, Opera и Chrome createElement(null) работает аналогично createElement("null").
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="div_1"> <p>Paragraph_1</p> <p>Paragraph_2</p> <p>Paragraph_3</p> <p><span>SPAN</span></p> </div> <div id="div_2"> <ul> <li>Список_1</li> <li>Список_2</li> </ul> </div> <!-- это комментарий --> <div></div> </body> </html> <script> document.body.onload = addElement; // вызов функции addElement при загрузке body function addElement() { // Создаём новый элемент div и добавляем в него тег <H1> let newDiv = document.createElement("div"); newDiv.insertAdjacentHTML("afterbegin", "<h1>Привет!</h1>"); // Добавляем созданный элемент в дерево DOM let myDiv = document.getElementById("div_2"); myDiv.before(newDiv); // или так document.body.insertBefore(newDiv, myDiv); } </script> |
Метод Document.createTextNode() создаёт новый текстовый узел. Этот метод можно использовать для экранирования символов HTML.
Синтаксис:
1 |
let text = document.createTextNode(data); |
где
- text - это текстовый узел;
- data - это строка с данными, которые будут помещены в текстовый узел.
Метод Node.cloneNode() возвращает дубликат узла, из которого этот метод был вызван.
Синтаксис:
1 |
let dubNode = node.cloneNode(deep); |
где
- node - узел, который будет клонирован;
- dubNode - новый узел, который будет клоном node;
- deep (необязательный) - true, если должны быть клонированы все дочерние узлы (включая текстовые узлы), или false - будет клонирован только узел node.
Особенности метода cloneNode():
- Клонирование узлов копирует все их атрибуты и их значения, в том числе собственных (в линию) обработчиков.
- Клонирование узлов не копирует обработчики событий, добавленные с использованием addEventListener() или те, что назначены через свойства элемента (т.е. так: node.onclick = fn).
- Дубликат узла, возвращённого cloneNode():
- не является частью документа, пока не будет добавлен в другой узел, который является частью документа, с использованием Node.appendChild() или другого метода;
- не имеет родителя, пока не будет добавлен к другому узлу.
- Для пустых узлов (т.е., например, <img> или <input> элементов) не имеет значения установлен ли deep как true или false.
- cloneNode() может привести к дублированию идентификаторов элементов в документе. Если исходный узел имеет идентификатор и клон размещён в том же документе, идентификатор должен быть изменён, для того чтобы быть уникальным. Имя атрибута также может нуждаться в изменении, в зависимости от будущего имени дубликата.
Копии, сделанные с помощью cloneNode() , не будут автоматически синхронизироваться.
Чтобы клонировать узел для добавления к другому документу вместо Node.cloneNode() используйте Document.importNode().
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="div_1"> <p>Paragraph_1</p> <p>Paragraph_2</p> <p>Paragraph_3</p> </div> <div id="div_2"> <ul> <li>Список_1</li> <li>Список_2</li> </ul> </div> <!-- это комментарий --> <div></div> </body> </html> <button onclick="cloneMyDiv();">Клонировать div_2!</button> <script> function cloneMyDiv() { let cloneDiv = document.getElementById("div_2"); // получили клонируемый элемент let newDiv = cloneDiv.cloneNode(true); // клонируем cloneDiv.insertAdjacentElement("afterbegin", newDiv); // вставляем клонированный элемент в заданную позицию } </script> |
Нахождение заданного узла
Метод node.hasChildNodes() возвращает Boolean значение, показывающее имеет ли текущий узел node дочерние узлы или нет.
Синтаксис:
1 |
node.hasChildNodes() |
Свойство только для чтения Node.nodeName возвращает имя текущего узла в виде строки.
Возвращаемое значение для различных типов узлов
Синтаксис:
1 |
let str = node.nodeName; |
где nodeName - это имя текущего узла node.
Пример:
1 2 3 4 5 6 7 |
<div id="d">Hello, world!</div> <input type="text" id="t" /> <script> let myDiv = document.getElementById("d"); // <div id="d">Hello, world!</div> let text_field = document.getElementById("t"); // <input type="text" id="t"> text_field.value = myDiv.nodeName; // DIV </script> |
В XHTML (или любых других форматов XML), значение text_field будет прочитано как div (в нижнем регистре). Свойства nodeName и tagName возвращают имена элементов HTML в DOM, помеченном как HTML документ, в верхнем регистре (подробнее...).
Свойство tagName можно было бы использовать вместо nodeName, однако для текстового узла:
- nodeName возвращает #text ,
- tagName возвращает undefined.
1 2 3 4 5 6 7 |
<div id="d">Hello, world!</div> <input type="text" id="t" /> <script> let myDiv = document.getElementById("d"); // <div id="d">Hello, world!</div> let text_field = document.getElementById("t"); // <input type="text" id="t"> text_field.value = myDiv.nodeName; // DIV </script> |
Свойство parentNode возвращает:
- родителя определённого элемента DOM дерева;
- null - если узел не имеет родителя;
- null - если элемент только был создан и ещё не добавлен в DOM-дерево.
Синтаксис:
1 |
let parentNode = node.parentNode |
где
- parentNode - ссылка на родительский узел текущего элемента (родитель элемента имеет тип Element, Document или DocumentFragment).
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<html> <body> <div id="ID"> <p id="foo">Это 1-й дочерний элемент узла div</p> <li id="LI">Это 2-й дочерний элемент узла div</li> </div> <!-- <input type="text" id="textDel" /> --> </body> </html> <script> let myNode = document.getElementById("foo"); console.log(myNode.parentNode); // <div id="ID"> ... </div> (родительский узел для "foo") </script> |
Доступный для чтения атрибут Node.childNodes возвращает живую (динамическую) коллекцию (NodeList) дочерних узлов (не потомков!) узла Node, включая элементы, текст и комментарии.
Синтаксис:
1 |
let ndList = node.childNodes; |
где node.childNodes - упорядоченная коллекция объектов элементов (тип этого списка - NodeList), которые являются дочерними для элемента node. Если у элемента node нет дочерних, то node.childNodes пуст.
Несмотря на то, что NodeList не является массивом (Array), его можно перебрать при помощи метода forEach(). NodeList также можно конвертировать в Array при помощи метода Array.from().
Пример ниже последовательно выведет дочерних элементов document.body:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<html> <body> <div>Начало</div> <ul> <li>Список_1</li> <li>Список_2</li> </ul> <div>Конец</div> ...HTML-код 1... <script> console.log(document.body.childNodes); // NodeList(8) [text, div, text, ul, text, div, text, script] for (let i = 0; i < document.body.childNodes.length; i++) { console.log(document.body.childNodes[i]); } </script> ...HTML-код 2... </body> </html> |
Если запустить пример выше, то последним будет выведен элемент <script>, несмотря на то, что в документе есть ещё «...HTML-код 2...». На момент выполнения скрипта браузер ещё до элемента «...HTML-код 2...» не дошёл, поэтому скрипт его не выведет.
Свойство Element.children, доступное только для чтения, возвращает живую (динамическую) коллекцию (HTMLCollection), которая содержит все дочерние элементы узла Element.
Если элемент не имеет дочерних элементов, дочерние элементы представляют собой пустой список длиной 0.
Element.children включает только узлы элементов. Чтобы получить все дочерние узлы, включая узлы, не являющиеся элементами, например узлы текста и комментариев, используйте Node.childNodes.
Синтаксис:
1 |
collection = node.children; |
где
- collection - упорядоченная коллекция (HTMLCollection) элементов DOM, которые являются дочерними элементами узла node.
Вы можете получить доступ к отдельным дочерним узлам в коллекции, используя метод item() в коллекции или используя скобочную нотацию в стиле массива JavaScript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<body> <div>Начало</div> <ul> <li>Список_1</li> <li>Список_2</li> </ul> </body> <script> let myElchildren = document.body.children; console.log(myElchildren); // HTMLCollection(4) [div, ul, script] console.log(myElchildren[0]); // <div>Начало</div> (доступ как к элементу псевдомассива) console.log(myElchildren.item(1)); // <ul> ... </ul> (доступ через item()) </script> |
Подробнее о селекторах читайте CSS-селекторы
Метод Document.querySelector() возвращает:
- первый элемент (Element) документа, который соответствует указанному в аргументе селектору или группе селекторов;
- null - если совпадений не найдено.
Сопоставление аргумента с узлами DOM выполняется с использованием последовательного обхода всех узлов документа в глубину, начиная с первого элемента в разметке документа.
Синтаксис:
1 |
element = document.querySelector(selectors); |
где
- element - ссылка на объект типа Element, являющийся первым элементом DOM, который соответствует указанному в аргументе селектору (группе селекторов) selectors;
- selectors - строка DOMString, содержащая один или более селекторов для сопоставления (если не является допустимой строкой селектора CSS, то генерируется исключение SYNTAX_ERR).
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<html> <body> <ul class="UL"> <li class="book Book_1">Book_1</li> <li class="book Book_2">Book_2</li> <li class="book Book_3">Book_3</li> </ul> <ul class="UL"> <li class="Car_1">Car_1</li> <li class="Car_2">Car_2</li> <li class="Car_3">Car_3</li> </ul> </body> </html> <script> let myBookQS = document.querySelector(".UL"); console.log(myBookQS); // <ul class="UL"> ... "book Book..." ... </ul> console.log(myBookQS.children); // HTMLCollection(3) [li.book.book_1, li.book.book_2, li.book.book_3] (живая коллекция) </script> |
Ещё пример:
1 2 3 4 |
// в переменную dropMenu передан элемент let dropMenu = document.querySelector(".dropdown-item") dropMenu.querySelector(".dropdown-menu") |
Если вам нужен список всех элементов, соответствующих указанным селекторам, используйте метод querySelectorAll():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<html> <body> <ul class="UL"> <li class="book Book_1">Book_1</li> <li class="book Book_2">Book_2</li> <li class="book Book_3">Book_3</li> </ul> <ul class="UL"> <li class="Car_1">Car_1</li> <li class="Car_2">Car_2</li> <li class="Car_3">Car_3</li> </ul> </body> </html> <script> let myBookQS_All = document.querySelectorAll(".UL"); console.log(myBookQS_All); // NodeList(2) [ul.ul, ul.ul] console.log(myBookQS_All[1]); // <ul class="UL"> "Car_..." </ul> (неживая коллекция) myBookQS_All[1].remove(); // удаляем второй элемент коллекции NodeList console.log(myBookQS_All); // NodeList(2) [ul.ul, ul.ul] (коллекция не изменилась) </script> |
Символы, которые не являются частью стандартного синтаксиса CSS должны быть экранированы символом обратной косой черты. Поскольку JavaScript также использует экранирование символом обратной косой черты, будьте особенно внимательны при написании строковых литералов с использованием этих символов (подробнее...).
Псевдо-элементы CSS никогда не вернут никаких элементов, как указано в API селекторов.
Метод Document.querySelectorAll() возвращает статическую (неживую) коллекцию (NodeList), содержащую все найденные элементы документа, которые соответствуют указанному в аргументе метода селектору.
Синтаксис:
1 |
elementList = document.querySelectorAll(selectors); |
где
- elementList - статический (non-live) NodeList, содержащий все элементы в пределах документа, которые соответствуют как минимум одному из указанных селекторов selectors, или пустой NodeList в случае отсутствия совпадений указанному в аргументе селектору (группе селекторов) selectors;
- selectors - строка DOMString, содержащая один или более селекторов для сопоставления (если не является допустимой строкой селектора CSS, то генерируется исключение SYNTAX_ERR); несколько селекторов разделяются запятыми.
Символы, которые не являются частью стандартного синтаксиса CSS должны быть экранированы символом обратной косой черты. Поскольку JavaScript также использует экранирование символом обратной косой черты, будьте особенно внимательны при написании строковых литералов с использованием этих символов (подробнее...).
Если в строке selectors содержатся CSS псевдоэлементы, то возвращаемый список будет всегда пуст.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<html> <body> <ul class="UL_1"> <li class="book Book_1"> Book_1 <ul><li><p class="ID">Это параграф</p></li></ul> </li> <li class="book Book_2">Book_2</li> <li class="book Book_3">Book_3</li> </ul> <ul class="UL_2"> <li class="Car_1">Car_1</li> <li class="Car_2">Car_2</li> <li class="Car_3">Car_3</li> </ul> </body> </html> <script> let myBookQS_All = document.querySelectorAll(".UL_2, .UL_1, .ID"); console.log(myBookQS_All); // NodeList(3) [ul.ul_1, p.id, ul.ul_2] (неживая коллекция) console.log(myBookQS_All[1]); // <p class="ID">Это параграф</p> myBookQS_All[1].remove(); // удаляем второй элемент коллекции NodeList console.log(myBookQS_All); // NodeList(3) [ul.ul_1, p.id, ul.ul_2] (коллекция не изменилась) </script> |
Метод Element.closest() возвращает:
- соответствующий заданному в параметре CSS-селектору:
- сам элемент DOM или
- ближайший родительский элемент;
- null, если таковых элементов вообще нет.
Синтаксис:
let elt = element.closest(selector);
где
- selector - строка DOMString, содержащая CSS-селектор (например, "#id", ".class", "div");
- elt - элемент DOM (Element), либо null.
Примеры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <article> <div id="block" title="Я - блок 1"> <p id="p1"><a href="#">Some link P</p></a></p> <p id="p2"><a href="http://site.ru">Site link P</a></p> <div id="p3" title="Я - блок 2"> <div class="span"> <div id="too"><a href="#">Some link</a></div> </div> </div> </div> </article> </body> </html> <script> let res = document.querySelector("#too"); // элемент,c которого начинается поиск (с идентификатором id="too") let result = res.closest("div"); // сам блок <div id="too"></div> (подходит под тег "div") result = res.closest(".span"); // возвращает <div id="span"> ... </div> (с class="span") result = res.closest("#p3[title]"); // возвращает <div id="block" title="Я - блок 2"> ... </div> result = res.closest("#block"); // возвращает <div id="block" title="Я - блок 1"> ... </div> console.log(result); </script> |
Метод Element.matches() возвращает:
- true, если элемент соответствует указанному в параметре метода CSS-селектору;
- false, если элемент не соответствует указанному в параметре метода CSS-селектору;.
В некоторых браузерах метод имеет нестандартное название - matchesSelector().
Синтаксис:
let elt= element.matches(selector);
где
- selector - строка DOMString, содержащая CSS-селектор (например, "#id", ".class", "div");
- elt - элемент DOM (Element), либо null.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="one">Первый div</div> <div class="someClass" id="two">Второй div</div> </body> </html> <script> var coll = document.querySelectorAll("div"); for (var i = 0, len = coll.length; i < len; i++) { if (coll[i].matches(".someClass")) { // вернет true для div с class="someClass" console.log("Второй div с идентификатором id: " + coll[i].id); } else { coll[i].remove(); // удаляет из DOM } } </script> |
Или тот же результат с помощью метода forEach():
1 2 3 4 5 6 7 8 9 10 |
<script> var coll = document.querySelectorAll("div"); coll.forEach((element) => { if (element.matches(".someClass")) { // вернет true для div с class="someClass" console.log("Второй div с идентификатором id: " + element.id); } else { element.remove(); // удаляет из DOM } }); </script> |
Метод Node.contains() возвращает Boolean значение, указывающее является ли узел, переданный в параметр метода, потомком узла Node, на котором этот метод вызывается.
Синтаксис:
node.contains(otherNode);
где
- node - узел, который проверяется на качество "родительский" по отношению к otherNode;
- otherNode - узел, который проверяется на качество "дочерний" по отношению к node.
Пример функции, которая проверяет, находится ли элемент в теле страницы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="block" title="Я - блок 1"> <p><a href="#">Some link</a></p> <p><a href="http://site.ru">Site link</a></p> <div title="Я - блок 2"><div id="too"></div></div> </div> </body> </html> <script> function isInPage(ndParent = "body", ndChild) { ndParent = document.querySelector(ndParent); ndChild = document.querySelector(ndChild); return ndParent.contains(ndChild); } let result = isInPage("body"); // false result = isInPage("body", "span"); // false result = isInPage("body", "p"); // true result = isInPage(); // false console.log(result); </script> |
Сравнительная таблица методов поиска элементов:
Метод | Критерий поиска | Поиск внутри элемента | Возвращение "живой" коллекции |
querySelector | CSS-selector | да | нет (возвращает первое совпадение) |
querySelectorAll | CSS-selector | да | нет (NodeList) |
getElementById | id | нет | нет |
getElementsByName | name | нет | да |
getElementsByTagName | тэг или '*' | да | да |
getElementsByClassName | class | да | да |
Работа только с узлами-элементами
Учитывают только узлы-элементы:
- children – коллекция (HTMLCollection) элементов DOM, которые являются дочерними элементами узла;
- firstElementChild, lastElementChild – первый и последний дочерний элемент;
- previousElementSibling, nextElementSibling – соседи-элементы;
- parentElement – родитель-элемент.
1 2 |
console.log( document.documentElement.parentNode ); // document console.log( document.documentElement.parentElement ); // null |
Причина в том, что родителем корневого узла document.documentElement (<html>) является document. Но document – это не узел-элемент, так что parentNode его вернёт, а parentElement - нет.
Добавление и замена узлов и элементов в DOM
Метод Node.appendChild()
Метод Node.appendChild() добавляет узел в конец списка дочерних элементов указанного родительского узла.
Если узел является элементом, целесообразнее использовать методы Element.append() и Element.prepend(), которые, в отличие от Node.appendChild(), поддерживают несколько аргументов и добавление строк.
Синтаксис:
1 |
let aChild = node.appendChild(child); |
где
- node - родительский элемент node, в который вставляется child;
- child - элемент, который вставляется в конец node.
Возвращаемое значение:
- дочерний элемент (aChild);
- если child - это DocumentFragment, то возвращается пустой DocumentFragment.
Особенности appendChild():
- Если дочерний элемент child является ссылкой на существующий узел в документе, то функция appendChild() перемещает его из текущей позиции в новую позицию (нет необходимости удалять узел из родительского узла перед добавлением его к какому-либо другому узлу). Поэтому, если у узла уже есть родитель, он сначала удаляется, а затем добавляется в новую позицию.
- Если дочерний элемент child является DocumentFragment, то все содержимое DocumentFragment перемещается в дочерний список указанного родительского узла.
Цепочка методов с appendChild() может работать не так, как ожидалось:
1 2 3 4 5 6 7 8 |
// так не работает result = document .createElement("block") .appendChild(document.createElement("b")); // <b></b> // так работает result = document.createElement("block"); // <block></block> result.appendChild(document.createElement("b")); // <block><b></b></block> |
Метод Element.append() вставляет узлы после последнего дочернего элемента узла (Element.prepend() - перед первым дочерним элементом узла), заменяя строки в узлах эквивалентными текстовыми узлами (т.е. обеспечивают безопасную вставку HTML).
Отличия Element.append() и Element.prepend() от метода Node.appendChild():
- позволяют вставлять строки с текстом, в то время как Node.appendChild() работает только с узлами;
- ничего не возвращают, в то время как Node.appendChild() возвращает вставленный узел;
- позволяют вставить сразу несколько узлов или строк текста, в то время как Node.appendChild() умеет вставлять по одной сущности за раз.
Синтаксис:
1 2 3 |
element.append(...nodesOrDOMStrings); element.prepend(...nodesOrDOMStrings); |
где
- nodesOrDOMStrings - один или несколько узлов или строк с текстом, которые необходимо вставить.
Пример:
1 2 3 4 5 6 7 |
result = document.createElement("block"); result.append(document.createElement("b")); // <block><b></b></block> result.append("Здесь будет тег <b>"); // <block><b></b>"Здесь будет тег <b>"</block> (добавляем в конец, после <b></b>) result = document.createElement("block"); result.prepend(document.createElement("b")); // <block><b></b></block> result.prepend("Здесь будет тег <b>"); // <block>"Здесь будет тег <b>"<b></b></block> (добавляем в начало, перед <b></b>) |
Цепочка методов с Element.append() или Element.prepend() может работать не так, как ожидалось.
Метод Node.before() вставляет узлы, переданные в аргумент, непосредственно перед узлом Node (Node.after() - после узла Node), заменяя строки в узлах эквивалентными текстовыми узлами.
Синтаксис:
1 2 3 |
node.before(...nodesOrDOMStrings); node.after(...nodesOrDOMStrings); |
где
- nodesOrDOMStrings - один или несколько узлов или строк с текстом, которые необходимо вставить.
Методы Node.before() и Node.after() ничего не возвращают.
Цепочка методов с Node.before() и Node.after() может работать не так, как ожидалось (т.к. методы ничего не возвращают):
1 2 |
document.body.after(document.createElement("div")) // (вставит <div></div> - ожидаемо) document.body.after(document.createElement("div").after("Новый текст")) // (вставит "undefined" без <div></div>) |
Метод node.replaceWith() – заменяет узел node узлами, переданными в аргументы, при этом строки в узлах заменяются эквивалентными узлами текста.
Синтаксис:
1 |
node.replaceWith(...nodesOrDOMStrings); |
где
- nodesOrDOMStrings - один или несколько узлов или строк с текстом, которые заменяют узел node.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Работа с DOM</title> </head> <body> <h2>Работа с DOM</h2> <div id="div_1"> <b></b> </div> <div id="div_2"></div> </body> </html> <script> let result; result = document.querySelector("div").childNodes[0]; // #text // Вставит <div></div>"textNew" вместо узла #text после открывающего тега <div id="div_1"> перед тегом <b></b> result.replaceWith(document.createElement("div"), "textNew"); result = document.querySelector("div").childNodes[0]; // <div></div> </script> |
Метод node.replaceWith() ничего не возвращает.
Для выполнения добавления в DOM списка узлов используется добавление узлов DOM в массив, а далее массив деструктурируется и его элементы поочередно добавляются в DOM с помощью методов:
- node.append(...nodes or strings) – добавляет узлы или строки в конец node;
- node.prepend(...nodes or strings) – вставляет узлы или строки в начало node;
- node.before(...nodes or strings) – вставляет узлы или строки до node;
- node.after(...nodes or strings) – вставляет узлы или строки после node.
Добавление в DOM списка узлов:
1 2 3 4 5 6 7 8 9 10 11 |
function getListNoFrag() { let result = []; for (let i = 1; i <= 3; i++) { let li = document.createElement("li"); li.append(i); result.push(li); } return result; // [li, li, li] } ul.append(...getListNoFrag()); |
DocumentFragment является специальным DOM-узлом, который служит объектом-обёрткой для передачи списка узлов и, при этом, не является частью основного дерева DOM. Это позволяет добавить в него другие узлы, а затем вставить его содержимое в основное дерево DOM.
DocumentFragment — это контейнер, который может содержать произвольное количество элементов DOM.
DocumentFragment обычно используются для создания фрагмента документа, добавления в него новых элементов или узлов, а затем присоединения внутреннего содержимого этого фрагмента к основному дереву.
В основное дерево объект-обёртка (DocumentFragment) не добавляется, а заменяется внутренним содержимым (собственными дочерними элементами).
Использование DocumentFragment может снижать производительность, поэтому перед тем как решать, использовать ли DocumentFragment, необходим профайлинг.
Создание нового пустого DocumentFragment:
1 2 3 |
let myFragment = new DocumentFragment(); // узел #document-fragment // или let myFragment = document.createDocumentFragment(); // узел #document-fragment |
где
- myFragment - ссылка на пустой объект DocumentFragment.
Добавление в DOM списка узлов с помощью DocumentFragment:
1 2 3 4 5 6 7 8 9 10 11 |
function getListWithFrag() { let fragment = new DocumentFragment(); for (let i = 1; i <= 3; i++) { let li = document.createElement("li"); li.append(`Это <li> ${i}`); fragment.append(li); } return fragment; // #document-fragment } ul.append(getListWithFrag()); |
Существует одно место, где можно встретить DocumentFragment, не создавая его через JS. Это — свойство content элемента <template>.
HTML-элемент шаблона контента <template> — это механизм для отложенного создания клиентского контента, который не отображается во время загрузки страницы, но может быть инициализирован при помощи JavaScript. Его можно представить себе как фрагмент контента страницы, сохранённый для последующего использования в документе. Парсер хотя и обрабатывает содержимое элемента <template> во время загрузки страницы, он делает это, только чтобы убедиться в валидности содержимого, само содержимое при этом не отображается (то, что находится внутри этого тега, не становится частью активного DOM-дерева, в частности, его нельзя найти с помощью querySelector()).
Элементы, созданные из HTML-кода, находящегося внутри тега <template>, не становятся ему дочерними. Вместо этого JavaScript может получить к ним доступ через свойство content, которое является DocumentFragment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <h2>Мои примеры</h2> </head> <body> <template> <div id="div_template"> <li>Привет</li> <li>Мир</li> </div></template> </body> </html> <script> let template = document.querySelector("template"); console.log(template.innerHTML); // <div id="div_template"> ... </div> console.log(template.content); // # document-fragment ( с содержимым <div id="div_template"> ... </div> ) |
Добавление элементам классов, атрибутов и CSS-стилей (их удаление и проверка наличия)
Как правило, существует два способа задания стилей для элемента:
- cоздать класс в CSS как <div class="..."> и использовать его;
- определять стили непосредственно в атрибуте style как <div style="...">.
JavaScript может менять и классы, и свойство style, однако определение и изменение классов – предпочтительный вариант по сравнению с изменением style.
Использование style является приемлемым, если мы вычисляем координаты элемента и хотим установить их из JavaScript, например:
1 2 3 4 |
let top = /* вычисление во время работы скрипта */; let left = /* вычисление во время работы скрипта */; elem.style.left = left; // например, '333px' elem.style.top = top; // например, '555px' |
В остальных случаях целесообразно описывать в CSS и добавлять в класс - это более гибкое и лёгкое в поддержке решение.
Добавление классов
Классы (class) применяют тогда, когда необходимо определить стиль для индивидуального элемента веб-страницы или задать разные стили для одного тега. При использовании совместно с тегами синтаксис для классов будет следующий:
1 2 3 4 |
tag.className { property_1: value; property_2: value; } |
где
- tag - тег, к которому применяется class;
- className - пользовательское имя класса class (имена классов должны начинаться с латинского символа и могут содержать в себе символ дефиса (-) и подчеркивания (_), использование кириллицы в именах классов недопустимо).
Чтобы указать в коде HTML, что тег используется с определённым классом, к тегу добавляется атрибут class="className":
1 2 |
<div class="myClass" id="div_2"></div> document.getElementById("div_2").className // 'myClass' |
Добавление одного класса с помощью свойства className:
Присваивание какого-либо значения свойству className элемента полностью заменяет всю строку классов:
1 2 3 4 5 6 7 |
<div class="myClass foo bar" id="div_2"></div> <script> document.getElementById("div_2").className; // 'myClass foo bar' document.getElementById("div_2").className = "newMyClass"; document.getElementById("div_2").className; // 'newMyClass' (замена всей строки) </script> |
Добавление (удаление) выбранного класса из нескольких с помощью объекта (псевдомассива) classList:
Методы объекта classList:
- elem.classList.add("class") – добавить класс;
- elem.classList.remove("class") – удалить класс;
- elem.classList.toggle("class") – добавить класс, если его нет, иначе - удалить;
- elem.classList.contains("class") – проверка наличия класса (возвращает true/false).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<!DOCTYPE html> <html lang="en"> <head> <h2>Мои примеры</h2> </head> <body> <div id="div_1"> <li>Привет</li> <li>Мир</li> </div> <ul id="ul"></ul> </body> </html> <script> let myElement = document.getElementById("div_1"); myElement.classList.add("foo"); // <div id="div_1" class="foo"> ... </div> myElement.classList.add("bar"); // <div id="div_1" class="foo bar"> ... </div> myElement.classList.remove("bar"); // <div id="div_1" class="foo"> ... </div> myElement.classList.toggle("baz"); // <div id="div_1" class="foo baz"> ... </div> console.log(myElement.classList); // DOMTokenList(2) ['foo', 'baz', value: 'foo baz'] // полная замена строки классов myElement.classList.value = "baz" // <div id="div_1" class="baz"> ... </div> </script> |
Объект classList является перебираемым, поэтому можно перечислить все классы элемента при помощи цикла for..of.
В CSS селекторы атрибутов позволяют установить стиль для конкретных элементов DOM по присутствию определённого атрибута тега или его значения.
У каждого элемента есть некоторый набор стандартных атрибутов (свойств), описанных в стандарте HTML именно для этого элемента (тега), например для <a> это будут href, name, а для <img> это будут src, alt, и т.д. Итак:
- атрибуты – это код (строки) HTML;
- свойство – это поле DOM-объекта.
Для нестандартных атрибутов DOM свойство узла как объекта DOM не создаётся.
1 2 3 4 5 6 7 8 9 |
<h2 id="myMeta" lang="ru" myAttr="myAttr">Заголовок H2</h2> <script> let myAttr = document.getElementById("myMeta"); console.log(myAttr); // <h2 id="myMeta" lang="ru" myattr="myAttr">Заголовок H2</h2> myMeta.id; // myMeta myAttr.lang; // ru myAttr.myAttr; // undefined (нестандартный атрибут) </script> |
Доступ к атрибутам осуществляется при помощи методов:
- работающих со значением, которое находится в HTML:
- elem.hasAttribute(nameAttr) – проверяет наличие атрибута;
- elem.getAttribute(nameAttr) – получает значение атрибута;
- elem.setAttribute(nameAttr, value) – устанавливает атрибут;
- elem.removeAttribute(nameAttr) – удаляет атрибут;
- свойства elem.attributes, которое содержит объект NamedNodeMap{}.
В отличие от свойств, атрибуты:
- всегда являются строками;
- их имя нечувствительно к регистру (это HTML);
- видны в innerHTML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<h2 id="myMeta" lang="ru" myAttr="myAttr">Заголовок H2</h2> <script> let myAttr = document.getElementById("myMeta"); console.log(myAttr); // <h2 id="myMeta" lang="ru" myattr="myAttr">Заголовок H2</h2> myAttr.hasAttribute("LANG"); // true (нечувствителен к регистру) myAttr.hasAttribute("myAttr"); // true myAttr.getAttribute("myAttr"); // 'myAttr' (получаем значение нестандартного атрибута) myAttr.setAttribute("myAttr", "newMyAttr"); // (изменим значение атрибута myAttr) myAttr.getAttribute("myAttr"); // 'newMyAttr' myAttr.removeAttribute("myAttr"); console.log(myAttr); // <h2 id="myMeta" lang="ru">Заголовок H2</h2> </script> |
Методы getAttibute(), setAttribute() и removeAttribute() сразу же меняют HTML-атрибуты элемента (в отличие от DOM-свойств), что вызовет браузерную перерисовку (вы сможете увидеть все изменения, изучив элемент с помощью инструментов разработчика в браузере). Такие перерисовки не только требуют больше ресурсов, чем установка DOM-свойств, но и могут привести к непредвиденным ошибкам. Как правило, их используют для элементов, у которых нет соответствующих DOM-свойств, например, colspan, или для HTML-свойств при наследовании.
Свойство элемента element.style – это объект, поля которого соответствуют тому, что написано в атрибуте style, например:
1 2 3 4 5 6 7 8 9 10 11 |
// Установка style в HTML <h2 id="myMeta" lang="ru" myAttr="myAttr" style="font-size: 20px"> Заголовок H2 </h2> // Определение style через свойство element.style <script> let myAttr = document.getElementById("myMeta"); console.log(myAttr.style.fontSize); // 20px (получаем значение) myAttr.style.fontSize = "40px"; // (можно задать новое значение) </script> |
Для обращения к свойству из нескольких слов используется camelCase, например:
- font-size => elem.style.fontSize;
- background-color => elem.style.backgroundColor;
- border-left-width => elem.style.borderLeftWidth.
Стили с браузерным префиксом, например, -moz-border-radius, -webkit-border-radius преобразуются по тому же принципу, при этом дефис обозначается через заглавную букву, например:
- button.style.MozBorderRadius = '5px';
- button.style.WebkitBorderRadius = '5px'.
Сброс стилей:
- element.style = "none" или
- element.style = "".
1 2 3 4 5 6 7 8 9 10 11 12 |
<h2 id="myMeta" lang="ru" myAttr="myAttr" style="font-size: 20px"> <script> let myAttr = document.getElementById("myMeta"); console.log(myAttr); // <h2 id="myMeta" lang="ru" myAttr="myAttr" style="font-size: 20px"> myAttr.style = "none"; console.log(myAttr); // <h2 id="myMeta" lang="ru" myAttr="myAttr" style> // или myAttr.style = ""; console.log(myAttr); // <h2 id="myMeta" lang="ru" myAttr="myAttr" style> </script> |
Если установить в element.style пустую строку "", то браузер применит CSS-классы и встроенные стили, как если бы свойства element.style вообще не было.
Установка нескольких стилей в одной строке (свойство style.cssText и метод setAttribute() ):
1 |
myAttr.style.cssText = "font-size: 40px; background-color: red"; |
Это свойство редко используется, потому что такое присваивание удаляет все существующие стили: оно не добавляет, а заменяет их. Его можно использовать, например, для новых элементов.
То же самое можно сделать установкой атрибута методом setAttribute():
1 |
myAttr.setAttribute("style", "font-size: 40px; background-color: yellow"); |
Навигация по узлам внутри родительского узла
Свойство только для чтения Node.firstChild возвращает:
- первый потомок узла в древе или
- null, если узел является бездетным.
Если узел это документ, он возвращает первый узел в списке своих прямых дочерних элементов.
Синтаксис:
1 |
let childNode = node.firstChild; |
где childNode - это ссылка на первый потомок узла node, если таковой имеется, в противном случае - null.
Примеры (обратите внимание на обработку пробелов как текстовых узлов):
1 2 3 4 5 6 7 8 |
<!-- Пробел между <p> и <span> отсутствует --> <p id="myNode"><span>My span</span></p> <script type="text/javascript"> let result = document.getElementById("myNode"); console.log(result.firstChild); // <span>My span</span> console.log(result.firstChild.nodeName); // SPAN (имя узла в виде строки) </script> |
1 2 3 4 5 6 7 8 9 10 |
<!-- Пробел между <p> и <span> --> <p id="myNode"> <span>My span</span> </p> <script type="text/javascript"> let result = document.getElementById("myNode"); console.log(result.firstChild); // #text console.log(result.firstChild.nodeName); // #text </script> |
Любое пустое пространство между узлами (в т.ч. единичный пробел, разрыв строки, отступ и т. д.) является причиной вставки узла #text.
Если эти пробелы удаляются из источника, узлы #text не вставляются и элемент span становится первым потомком абзаца <p id="myNode">.
Свойства nodeName и tagName возвращают имена элементов HTML в DOM, помеченном как HTML документ, в верхнем регистре (подробнее...).
Свойство lastChild возвращает последнего потомка в узле.
1 |
let last_child = node.lastChild |
Возвращаемый элемент last_child является последним потомком узла node. Если в опрашиваемом узле node нет дочерних элементов, node.lastChild возвращает null .
Если у тега есть дочерние узлы, условие ниже всегда верно:
1 2 |
node.childNodes[0] === node.firstChild node.childNodes[node.childNodes.length - 1] === node.lastChild |
Свойство Node.nextSibling используется только для чтения и возвращает:
- узел, непосредственно следующий за данным узлом в списке childNodes его родительского элемента, или
- null, если данный узел последний в этом списке.
Свойство Node.previousSibling используется только для чтения и возвращает:
- узел, предшествующий указанному в родительском элементе childNodes, или
- null, если указанный узел первый в своём родителе.
Синтаксис:
1 2 |
nextNode = node.nextSibling previousNode = node.previousSibling; |
Браузеры, основанные на Gecko, вставляют текстовые узлы в документ для представления пробелов в разметке. Поэтому узел, полученный, например, при использовании Node.firstChild или Node.previousSibling может относиться к пробелу, а не к тому элементу, который вы хотели бы получить.
Работа с HTML или XML разметкой элементов DOM
Свойство Element.innerHTML получает или задает разметку HTML или XML, содержащуюся в элементе Element.
Установка значения innerHTML позволяет легко заменить существующее содержимое элемента новым содержимым, что создает угрозу безопасности, если вставляемая строка может содержать потенциально вредоносное содержимое.
При вставке данных, предоставленных пользователем, всегда используйте:
- вместо Element.innerHTML метод Element.SetHTML() (экспериментальный метод), чтобы дезинфицировать контент перед его вставкой в DOM;
- Node.textContent при вставке простого текста, поскольку он вставляет его как необработанный текст, а не анализирует его как HTML.
Чтобы вставить HTML в документ, а не заменять содержимое элемента, используйте метод insertAdjacentHTML().
Предупреждение (https://developer.mozilla.org): если ваш проект будет проходить проверку безопасности в любой форме, использование innerHTML, скорее всего, приведет к отклонению вашего кода. Например, если вы используете innerHTML в расширении браузера и отправляете расширение на addons.mozilla.org, оно может быть отклонено в процессе проверки.
Синтаксис:
1 2 |
const oldContent = element.innerHTML; element.innerHTML = newContent; |
где
oldContent - строка DOMString, содержащая HTML-сериализацию потомков элемента.
Установка значения innerHTML удаляет обработчики событий и все потомки элемента и заменяет их узлами, созданными путем синтаксического анализа HTML, указанного в строке newContent.
Если была сделана попытка установить значение innerHTML с помощью строки, которая не является правильно сформированным HTML, то вызывается исключение SyntaxError DOMException.
Свойство innerHTML можно использовать для проверки текущего источника HTML страницы, включая любые изменения, которые были внесены с момента первоначальной загрузки страницы. Чтение innerHTML заставляет пользовательский агент сериализовать HTML или XML-фрагмент, состоящий из потомков элемента, что позволяет вам просматривать HTML-разметку узлов содержимого элемента.
Возвращенный фрагмент HTML или XML создается на основе содержимого элемента в текущий момент времени, поэтому разметка и форматирование возвращенного фрагмента, скорее всего, не будут соответствовать разметке исходной страницы.
В следующем примере из documentElement извлекается текущая разметка HTML документа, символы «<» заменяются на сущность HTML «& lt;» , тем самым, по существу, преобразуя HTML в необработанный текст, который затем снова помещается в documentElement. В результате содержимое документа заменяется отображением всего исходного кода страницы:
1 2 3 4 |
document.documentElement.innerHTML = "<pre>" + document.documentElement.innerHTML.replace(/</g, "<") + "</pre>"; |
Метод insertAdjacentHTML() разбирает указанный текст как HTML или XML и вставляет полученные узлы (nodes) в DOM дерево в указанную позицию (т.е. не обеспечивает безопасную вставку HTML).
Метод insertAdjacentHTML() не переписывает имеющиеся элементы (что предотвращает дополнительную сериализацию) и поэтому работает быстрее, чем innerHTML.
Синтаксис:
1 |
targetElement.insertAdjacentHTML(position, text); |
где
- position - определяет позицию добавляемого элемента относительно элемента, вызвавшего метод, и должно соответствовать одному из следующих значений (чувствительно к регистру):
- 'beforebegin': до самого element (до открывающего тега);
- 'afterbegin': сразу после открывающего тега element (перед первым потомком);
- 'beforeend': сразу перед закрывающим тегом element (после последнего потомка);
- 'afterend': после element (после закрывающего тега).
- text - строка, которая будет проанализирована как HTML или XML и вставлена в DOM дерево документа.
Позиции 'beforebegin' и 'afterend' работают только если узел имеет родительский элемент.
Пример:
1 2 3 |
document.body .querySelector("div") .insertAdjacentHTML("beforeend", "<b>divInnerText_1</b>"); |
ВАЖНО! Будьте осторожны при использовании вставки HTML на страницу с помощью insertAdjacentHTML(), не используйте пользовательский ввод, который не был проверен на вредоносное содержимое. Не рекомендуется использовать insertAdjacentHTML(), когда требуется ввести простой текст: используйте для этого свойство Node.textContent или метод Element.insertAdjacentText(), которые не будут интерпретировать текст как HTML, а вставят необработанный текст.
Метод insertAdjacentElement() добавляет переданный элемент в DOM-дерево относительно элемента, вызвавшего метод. Используется для вставки элемента, который уже находится в DOM (например, вы можете получить этот элемент с помощью getElementById()). Если элемент в DOM отсутствует, то его необходимо сначала создать, например, с помощью метода createElement().
Синтаксис:
1 |
targetElement.insertAdjacentElement(position, element); |
где
- position - определяет позицию добавляемого элемента относительно элемента, вызвавшего метод, и должно соответствовать одному из следующих значений (чувствительно к регистру):
- 'beforebegin': до самого element (до открывающего тега);
- 'afterbegin': сразу после открывающего тега element (перед первым потомком);
- 'beforeend': сразу перед закрывающим тегом element (после последнего потомка);
- 'afterend': после element (после закрывающего тега).
- element - элемент, добавляемый в DOM-дерево.
Метод возвращает добавляемый элемент, либо null, если добавление элемента завершилось ошибкой.
Пример:
1 2 3 4 |
let b = document.createElement("b"); document.body .querySelector("div") .insertAdjacentElement("beforeend", b); |
Приведенный выше код добавит элемент <b></b> перед закрывающим тегом </div>.
Удаление узлов или элементов DOM
1 |
document.body.innerHTML = ""; |
Метод removeChild() удаляет дочерний элемент, переданный в аргумент метода, из DOM и возвращает удалённый элемент.
Синтаксис:
1 2 |
let oldChild = node.removeChild(child); node.removeChild(child); |
где
- child - дочерний элемент который будет удалён из DOM;
- node - родительский узел удаляемого child;
- oldChild - переменная, в которую передана ссылка на удаляемый дочерний элемент (oldChild === child).
Удалённый дочерний элемент остаётся в памяти, но больше не является частью DOM. Вы можете повторно использовать удалённый элемент с помощью ссылки.
Метод генерирует исключение в случае:
- если child не является дочерним элементом node;
- если child являлся дочерним элементом node во время вызова метода, но был удалён во время вызова обработчика событий удаляющего элемент (т.e при удалении элемента непосредственно перед вызовом обработчика событий).
Метод Element.remove() удаляет элемент Element из DOM-дерева, в котором он находится.
Примеры удаления всех потомков в узле:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<script> // С использованием метода removeChild() while (node.firstChild) { node.removeChild(node.firstChild); } // или while (node.lastChild) { node.removeChild(node.lastChild); } // или while (node.hasChildNodes()) { node.removeChild(node.lastChild); } // С использованием метода remove() while (node.firstChild) { node.firstChild.remove(); } // или while (node.lastChild) { node.lastChild.remove(); } </script> |
Удаление элемента с известным родительским узлом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<html> <body> <div id="ID"> <p id="foo">Это 1-й дочерний элемент узла div</p> <li id="LI">Это 2-й дочерний элемент узла div</li> </div> <!-- <input type="text" id="textDel" /> --> </body> </html> <script> // Функция, принимающая родительский и дочерний узел, удаляющая дочерний узел function delChildNode(parentId, childID) { let parentNode = document.getElementById(parentId); let childNode = document.getElementById(childID); parentNode.removeChild(childNode); //удаляем дочерний узел childNode из родительского parentNode } setTimeout(delChildNode, 5000, "ID", "LI"); // задержка для иллюстрации работы </script> |
Удаление элемента без указания его родителя:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<html> <body> <div id="ID"> <p id="foo">Это 1-й дочерний элемент узла div</p> <li id="LI">Это 2-й дочерний элемент узла div</li> </div> <!-- <input type="text" id="textDel" /> --> </body> </html> <script> // Функция, удаляющая дочерний узел без указания его родителя function delChildNode(childID) { let childNode = document.getElementById(childID); if (childNode.parentNode) { childNode.parentNode.removeChild(childNode); //удаляем узел childNode } } setTimeout(delChildNode, 5000, "LI"); // задержка для иллюстрации работы </script> |
Удаление всех дочерних элементов выбранного узла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<html> <body> <div id="ID"> <p id="foo">Это 1-й дочерний элемент узла div</p> <li id="LI">Это 2-й дочерний элемент узла div</li> </div> <!-- <input type="text" id="textDel" /> --> </body> </html> <script> // Функция, удаляющая все дочерние узлы переданного в неё узла function delChildNode(myParNode) { let myParentNode = document.getElementById(myParNode); while (myParentNode.firstChild) { myParentNode.removeChild(myParentNode.firstChild); //удаляем все дочерние узлы } } setTimeout(delChildNode, 5000, "ID"); // задержка для иллюстрации работы </script> |
Удаление элемента коллекции NodeList с заданным номером:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<html> <body> <div id="ID"> <p id="foo">Это 1-й дочерний элемент узла div</p> <li id="LI">Это 2-й дочерний элемент узла div</li> </div> <input type="text" id="textDel" /> </body> </html> <script> function delChildNode() { let delElement = document.getElementById("ID"); console.log(delElement); // <div id="ID"> ... </div> console.log(delElement.childNodes); // NodeList(5) [text, p#foo, text, li#LI, text] delElement.removeChild(delElement.childNodes[3]); // удален узел li#LI let text = document.getElementById("textDel"); text.value = `дочерний элемент ${delElement} удален`; } setTimeout(delChildNode, 2000); // задержка для иллюстрации работы </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<body> <div>Начало</div> <ul> <li>Список_1</li> <li>Список_2</li> </ul> <div>hello</div> console.log("hello"); <style type="text/css"> { display: none !important; } </style> </body> <script> // Функция очистки HTML от заданных тегов function cleanHTML() { let root = document.implementation.createHTMLDocument().body; // создаем тело нового HTML документа root.innerHTML = this.document.body.innerHTML; // загружаем HTML разметку в созданный документ root.querySelectorAll("script, style, img").forEach(function (element) { element.remove(); // удаляем заданные теги }); console.log(root.innerHTML) // (выведем в консоль для контроля, удалены теги style и script) return root.innerHTML; // возвращаем очищенную HTML разметку } cleanHTML(); // вызов функции </script> |