Node.insertbefore()

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

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


Возвращаясь к нашему примеру, давайте удалим последний пункт списка:

// Удалить последний элемент спискаlist.removeChild(list.lastElementChild);

Вот результат:

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

// Удалить третий элемент спискаlist.children.remove();

Используя и , можно удалить любые узлы из DOM.

Изменение атрибутов

Атрибуты часто используются в HTML для предоставления дополнительной информации об элементе. Некоторые распространенные примеры: атрибут тега , тега , а также , и . Встречаются атрибуты, начинающиеся с — это пользовательские атрибуты, которые тоже можно изменять.

Вот методы, которые используются в JavaScript для изменения атрибутов:

— возвращает булев тип.

— возвращает значение определенного атрибута.

— добавляет или обновляет значение определенного атрибута.

— удаляет атрибут из элемента.

В качестве примера используем данный HTML:

<!DOCTYPE html><html lang="en"><body><img src="https://res.cloudinary.com/trobes/image/upload/c_scale,w_400/v1549941322/before.png"></body></html>

Откроем console и протестируем методы атрибутов:

// Назначить изображение элементуconst image = document.querySelector('img');image.hasAttribute('src');       // trueimage.getAttribute('src');       // returns the src linkimage.removeAttribute('src');    // removes the src

Давайте используем , чтобы назначить новое изображение :

image.setAttribute('src', 'https://res.cloudinary.com/trobes/image/upload/c_scale,w_400/v1549941322/after.png');

Методы and часто используются с условными операторами, в то время как и чаще используются для изменения DOM напрямую.

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

Old-school insert/remove methods

Old school This information helps to understand old scripts, but not needed for new development.

There are also “old school” DOM manipulation methods, existing for historical reasons.

These methods come from really ancient times. Nowadays, there’s no reason to use them, as modern methods, such as , , , , , , are more flexible.

The only reason we list these methods here is that you can find them in many old scripts:

Appends as the last child of .

The following example adds a new to the end of :

Inserts before into .


The following code inserts a new list item before the second :

To insert as the first element, we can do it like this:

Replaces with among children of .

Removes from (assuming is its child).

The following example removes first from :

All these methods return the inserted/removed node. In other words, returns . But usually the returned value is not used, we just run the method.

Изменение классов

В работе с CSS мы используем классы для применения стилей к нескольким элементам. Давайте посмотрим, как можно работать с атрибутом класса в JavaScript, используя и .

— получает или задает значение класса.

—добавляет значения классов.

— отобразить/скрыть класс.

— проверяет, существует ли определенное значение.

— заменяет старое значение на новое.

— удаляет значение.

В следующем примере поработаем с каждым из этих методов:

<!DOCTYPE html><html lang="en"><style>    .active {        border: 5px solid green;    }    .alert {        border: 5px solid red;    }    .hidden {        display: none;    }    div {        border: 5px solid lightgrey;        padding: 15px;        margin: 5px;    }</style><body>    <div>Div #1</div>    <div class="active">Div #2</div></body></html>

Начальный выводимый результат:

Используем , чтобы применить значение к классам:

// Выбрать div #1const div = document.querySelector('div');// Класс alert назначить div #1div.className = 'alert';

Теперь класс , определенный в HTML, назначен первому :

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

Другой способ изменять классы — использование свойства , у которого есть несколько полезных методов:

// Выбрать div #2 const activeDiv = document.querySelector('.active');// Добавить класс hiddenactiveDiv.classList.add('hidden');   // Удалить класс hiddenactiveDiv.classList.remove('hidden'); // Переключаться между hidden true и falseactiveDiv.classList.toggle('hidden');// Заменить класс active на класс alertactiveDiv.classList.replace('active', 'alert');

После запуска всех этих методов, наш HTML отобразится так:

Пометка: добавит новый класс к списку существующих (помните, что изменяет любые существующие классы). Также можно добавлять несколько классов строками, разделенными запятыми.

Insertion methods

To make the show up, we need to insert it somewhere into . For instance, into element, referenced by .

There’s a special method for that: .

Here’s the full code:


Here we called on , but we can call method on any other element, to put another element into it. For instance, we can append something to by calling .

Here are more insertion methods, they specify different places where to insert:

  • – append nodes or strings at the end of ,
  • – insert nodes or strings at the beginning of ,
  • –- insert nodes or strings before ,
  • –- insert nodes or strings after ,
  • –- replaces with the given nodes or strings.

Arguments of these methods are an arbitrary list of DOM nodes to insert, or text strings (that become text nodes automatically).

Let’s see them in action.

Here’s an example of using these methods to add items to a list and the text before/after it:

Here’s a visual picture of what the methods do:

So the final list will be:

As said, these methods can insert multiple nodes and text pieces in a single call.

For instance, here a string and an element are inserted:

Please note: the text is inserted “as text”, not “as HTML”, with proper escaping of characters such as , .

So the final HTML is:

In other words, strings are inserted in a safe way, like does it.

So, these methods can only be used to insert DOM nodes or text pieces.

But what if we’d like to insert an HTML string “as html”, with all tags and stuff working, in the same manner as does it?

insertAdjacentHTML/Text/Element

For that we can use another, pretty versatile method: .

The first parameter is a code word, specifying where to insert relative to . Must be one of the following:

  • – insert immediately before ,
  • – insert into , at the beginning,
  • – insert into , at the end,
  • – insert immediately after .

The second parameter is an HTML string, that is inserted “as HTML”.

For instance:

…Would lead to:

That’s how we can append arbitrary HTML to the page.

Here’s the picture of insertion variants:

We can easily notice similarities between this and the previous picture. The insertion points are actually the same, but this method inserts HTML.

The method has two brothers:

  • – the same syntax, but a string of is inserted “as text” instead of HTML,
  • – the same syntax, but inserts an element.

They exist mainly to make the syntax “uniform”. In practice, only is used most of the time. Because for elements and text, we have methods – they are shorter to write and can insert nodes/text pieces.

So here’s an alternative variant of showing a message:

Оптимизация вставки в документ

Рассмотрим задачу: сгенерировать список .

Есть две возможных последовательности:

  1. Сначала вставить в документ, а потом добавить к нему :

  2. Полностью создать список «вне DOM», а потом – вставить в документ:

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


Почему же? Иногда говорят: «потому что браузер перерисовывает каждый раз при добавлении элемента». Это не так. Дело вовсе не в перерисовке.

Браузер достаточно «умён», чтобы ничего не перерисовывать понапрасну. В большинстве случаев процессы перерисовки и сопутствующие вычисления будут отложены до окончания работы скрипта, и на тот момент уже совершенно без разницы, в какой последовательности были изменены узлы.

Тем не менее, при вставке узла происходят разные внутренние события и обновления внутренних структур данных, скрытые от наших глаз.

Что именно происходит – зависит от конкретной, внутренней браузерной реализации DOM, но это отнимает время. Конечно, браузеры развиваются и стараются свести лишние действия к минимуму.

Чтобы легко проверить текущее состояние дел – вот два бенчмарка.

Оба они создают таблицу 20×20, наполняя элементами .

При этом первый вставляет все в документ тут же, второй – задерживает вставку в документ до конца процесса.

Кликните, чтобы запустить.

Код для тестов находится в файле insert-bench.js.

insertAdjacentHTML

Рассмотренные выше методы вставки добавляют либо отдельные теги, либо текстовую информацию. Причем, текст вставляется именно как текст, то есть, теги внутри текста будут отображены как текст. Например:

document.body.append("Текст с тегом");

Но, что если мы хотим вставить строку как HTML-строку с обработкой всех тегов, а не как обычный текст? Как раз для этого используется метод insertAdjacentHTML, который имеет следующий синтаксис:

elem.insertAdjacentHTML(where, html)

здесь where может принимать значения:

  • «beforebegin» – для вставки html непосредственно перед elem;

  • «afterbegin» – для вставки html как первого дочернего элемента в elem;

  • «beforeend» – для вставки html как последнего дочернего элемента в elem;

  • «afterend» – для вставки html непосредственно после elem.

Для примера возьмем вот такой список:

<ul>
<li>Меркурий
<li>Венера
<li>Земля
</ul>

И сделаем такие вставки:

let list = document.querySelector("ul.list");
list.insertAdjacentHTML("beforebegin", "Список планет<hr>");
list.insertAdjacentHTML("afterend", "<hr>Конец списка");
list.insertAdjacentHTML("afterbegin", "<li>Солнце");
list.insertAdjacentHTML("beforeend", "<li>Марс");

Смотрите как разместились эти элементы.

Существует еще два похожих метода, но более специализированных:

  • insertAdjacentText(where, text) – для вставки строки текста text;

  • insertAdjacentElement(where, elem) – для вставки элемента elem.

Например:

list.insertAdjacentText("beforebegin", "Список планет<hr>");

вставит текст как строку, а

let li = document.createElement("li");
li.innerHTML="Солнце";
list.insertAdjacentElement("afterbegin", li);

добавит соответствующий элемент.

Однако, на практике эти два метода почти не применяются. Вместо них удобнее использовать методы append/prepend/before/after просто потому, что легче писать. Если нам нужно удалить какой-либо узел из DOM-дерева, то для этого часто используется метод

node.remove()

Например, имеется список:

<ul class="list">
<li>Солнце
<li>Меркурий
<li>Венера
<li>Земля
<li>Марс
</ul>

И мы из него хотим из него удалять последние пункты, пока полностью не очистим. Это можно сделать так:

let idRemove = setInterval(function() {
    let li = document.querySelector("ul.list > li:last-child");
    if(li === null) {
       clearInterval(idRemove);
       alert("Список удален");
    }
    else li.remove();
}, 500);

cloneNode

Следующий метод cloneNode позволяет создавать клон узла DOM-дерева. Он имеет следующий синтаксис:

elem.cloneNode(flDeep);

Если flDeep равен true, то создается «глубокий» клон объекта со всеми его свойствами и дочерними элементами. При значении false получаем клон без дочерних элементов.

Когда может пригодиться такая операция. Например, у нас есть вот такая таблица:

<table border=1 cellpadding="10">
<tr><td>Солнце</td><td>Звезда</td></tr>
<tr><td>Меркурий</td><td>Планета</td></tr>
</table>

Мы хотим добавить в нее еще одну строку с планетой Венерой. Это можно сделать путем клонирования существующей строки и добавления клона в конец таблицы:

let t = document.querySelector("table");
let r = document.querySelector("table>tbody>tr:last-child");
let row = r.cloneNode(true);
row.firstChild.innerHTML = "Венера"; 
t.append(row);

Все, теперь у нас появилась еще одна строчка с Венерой.

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

A word about “document.write”

There’s one more, very ancient method of adding something to a web-page: .

The syntax:

The call to writes the into page “right here and now”. The string can be dynamically generated, so it’s kind of flexible. We can use JavaScript to create a full-fledged webpage and write it.

The method comes from times when there was no DOM, no standards… Really old times. It still lives, because there are scripts using it.

In modern scripts we can rarely see it, because of the following important limitation:

The call to only works while the page is loading.

If we call it afterwards, the existing document content is erased.

For instance:

So it’s kind of unusable at “after loaded” stage, unlike other DOM methods we covered above.

That’s the downside.

There’s an upside also. Technically, when is called while the browser is reading (“parsing”) incoming HTML, and it writes something, the browser consumes it just as if it were initially there, in the HTML text.

So it works blazingly fast, because there’s no DOM modification involved. It writes directly into the page text, while the DOM is not yet built.

So if we need to add a lot of text into HTML dynamically, and we’re at page loading phase, and the speed matters, it may help. But in practice these requirements rarely come together. And usually we can see this method in scripts just because they are old.

Примеры

Добавление элемента в начало

var parent = document.createElement("div");
var p = document.createElement("p");
var span = document.createElement("span");
parent.append(p);
parent.prepend(span);

console.log(parent.childNodes); // NodeList 

Добавление текста в начало

var parent = document.createElement("div");
parent.append("Some text");
parent.prepend("Headline: ");

console.log(parent.textContent); // "Headline: Some text"

Добавление элемента и текста

var parent = document.createElement("div");
var p = document.createElement("p");
parent.prepend("Some text", p);

console.log(parent.childNodes); // NodeList 

не имеет области видимости

Метод  не входит в область видимости оператора . Смотрите для детальной информации.

var parent = document.createElement("div");

with(parent) { 
  prepend("foo");
}
// ReferenceError: prepend is not defined 

С этим читают