Рис. 29.2. Вставленный элемент находится между элементами h1 и script
Вы можете подумать, что если есть метод insertBefore, то должен быть и метод insertAfter. Но на самом деле это не так. Здесь нет встроенного способа для вставки элемента после, а не до другого элемента. Мы можем только перехитрить функцию insertBefore, сказав ей вставить элемент перед элементом, следующим за нужным. Но будет ли в этом смысл? Сначала я покажу пример и затем все объясню:
let newElement = document.createElement("p");
let bodyElement = document.querySelector("body");
let h1Element = document.querySelector("h1");
newElement.textContent = "I exist entirely in your imagination.";
bodyElement.insertBefore(newElement, h1Element.nextSibling);
Обратите внимание на выделенные строки, а затем взгляните на рис. 29.3, где видно положение до и после выполнения кода.
Рис. 29.3. Трюк для имитирования действия insertAfter
Вызов hiElement.nextSibling находит элемент script. Вставка newElement перед элементом script удовлетворяет нашу цель вставить элемент после h1. А что, если нет элемента-брата, на который можно указать? В таком случае функция insertBefore достаточно умна и просто автоматически вставляет элемент в конец.
УДОБНАЯ ФУНКЦИЯ
Если по какой-то причине вам нужно все время вставлять элементы после другого потомка, то можете использовать эту функцию, чтобы немного упростить себе жизнь:
function insertAfter(target, newElement) {
target.parentNode.insertBefore(newElement,
target.nextSibling);
}
Да, я понимаю, что это окольный путь, но он работает, и весьма прилично. Вот пример этой функции в действии:
let newElement = document.createElement("p");
let bodyElement = document.querySelector("body");
let h1Element = document.querySelector("h1");
newElement.textContent = "I exist entirely in your imagination.";
function insertAfter(target, element) {
target.parentNode.insertBefore(element, target.nextSibling);
}
insertAfter(bodyElement, newElement);
Можно пойти еще дальше и расширить этой функцией HTML-элемент, чтобы предоставить ее функциональность для всех HTML-элементов. В главе 19 «Расширение встроенных объектов» рассматривается, как сделать нечто подобное. Имейте в виду, что некоторые разработчики не одобряют расширение DOM, поэтому заготовьте какие-нибудь остроумные отговорки на случай, если эти некоторые начнут вам досаждать.
Более обобщенный подход к добавлению потомков родителю основан на понимании, что элементы-родители рассматривают потомков как точки входа в массив. Чтобы обратиться к этому массиву потомков, у нас есть свойства children и childNodes. Свойство children возвращает только HTML-элементы, а childNodes возвращает более обобщенные узлы, представляющие много того, до чего нам нет дела. Да, я осознаю, что повторяюсь, и вы можете пересмотреть главу 28 «Перемещение по DOM», чтобы лучше разобраться в способах точного указания на элемент.
Удаление элементов
Мне кажется, что следующая фраза принадлежит какому-то умному человеку: «То, что имеет силу создавать, имеет силу и удалять». В предыдущем разделе мы видели, как можно использовать метод createElement для создания элементов. В текущем разделе мы рассмотрим метод removeChild, который, несмотря на пугающее имя, занимается именно удалением элементов.
Взгляните на следующий фрагмент кода, который можно создать для работы со знакомым нам примером:
let newElement = document.createElement("p");
let bodyElement = document.querySelector("body");
let h1Element = document.querySelector("h1");
newElement.textContent = "I exist entirely in your imagination.";
bodyElement.appendChild(newElement);
bodyElement.removeChild(newElement);
Элемент p, хранящийся в newElement, добавляется к элементу body с помощью метода appendChild. Это мы уже видели раньше. Чтобы удалить этот элемент, вызывается removeChild для элемента body и передается указатель на элемент, который нужно удалить. Конечно же, это элемент newElement. Как только будет выполнен метод removeChild, все станет так, как будто DOM никогда не знала о существовании newElement.
Главное, обратите внимание, что нужно вызывать removeChild из родителя потомка, которого мы хотим удалить. Этот метод не будет отыскивать элемент для удаления по всей DOM. А теперь предположим, что у нас нет прямого доступа к родителю элемента и тратить время на его поиск мы не хотим. При этом все равно с легкостью можно удалить его с помощью свойства parentNode:
let newElement = document.createElement("p");
let bodyElement = document.querySelector("body");
let h1Element = document.querySelector("h1");
newElement.textContent = "I exist entirely in your imagination.";
bodyElement.appendChild(newElement);
newElement.parentNode.removeChild(newElement);
В этом варианте мы удаляем newElement, вызывая removeChild для его родителя, указав newElement.parentNode. Выглядит замысловато, но работает.