Как удалить только родительский элемент, а не его дочерние элементы в JavaScript?

89

Скажем:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

к этому:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

Я пытался использовать Mootools, jQuery и даже (необработанный) JavaScript, но не мог понять, как это сделать.

Cheeaun
источник

Ответы:

139

Используя jQuery, вы можете сделать это:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

Быстрые ссылки на документацию:

jk.
источник
Хотел бы я реализовать (эээ .. найти ) это 3 часа назад ... просто и элегантно - круто!
Татхагата
3
каково значение «cnt»?
Стивен Лу
1
«cnt» - это просто имя переменной, которая содержит «содержимое»
Джордж Андерсон
1
Я не знаю почему, но у меня это не сработало при использовании contents (). Однако когда я использовал html () вместо contents (), он работал как шарм!
Vertigoelectric
версия всего в $('.remove-just-this').replaceWith(function() { return $(this).html(); });
одну
36

Независимый от библиотеки метод заключается в том, чтобы вставить все дочерние узлы удаляемого элемента перед собой (что неявно удаляет их из их старой позиции), прежде чем вы удалите его:

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

Это переместит все дочерние узлы в нужное место в правильном порядке.

Джонни Бьюкенен
источник
3
Modern JS поддерживает это:node.replaceWith(...node.childNodes);
Gibolt
34

Вы должны сделать это с DOM, а не innerHTML(и если вы используете решение jQuery, предоставляемое jk, убедитесь, что оно перемещает узлы DOM, а не использует их innerHTMLвнутри), чтобы сохранить такие вещи, как обработчики событий.

Мой ответ очень похож на insin, но будет лучше работать для больших структур (добавление каждого узла по отдельности может облагаться налогом на перерисовку, где CSS необходимо повторно применять для каждого appendChild; с a DocumentFragmentэто происходит только один раз, так как он не становится видимым до тех пор, пока не будет все дочерние элементы добавляются, и он добавляется в документ).

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
без век
источник
Спасибо; короткие и прямые.
brunoais
22

Более элегантный способ

$('.remove-just-this').contents().unwrap();
Юнда
источник
2
Лучший ответ. Спасибо.
user706420
9

Используйте современный JS!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode) действительно ES5

...array - оператор распространения, передающий каждый элемент массива в качестве параметра

Гибольт
источник
2

Какую бы библиотеку вы ни использовали, вы должны клонировать внутренний div перед удалением внешнего div из DOM. Затем вам нужно добавить клонированный внутренний div в то место в DOM, где был внешний div. Итак, шаги:

  1. Сохраните ссылку на внешний родительский элемент div в переменной
  2. Скопируйте внутренний div в другую переменную. Это можно сделать быстро и грязно, сохранивinnerHTML внутренний div в переменной, или вы можете рекурсивно скопировать внутреннее дерево узел за узлом.
  3. Вызовите removeChildродительский элемент внешнего div с внешним div в качестве аргумента.
  4. Вставьте скопированное внутреннее содержимое в родительский элемент внешнего div в правильной позиции.

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

Домг Блэквелл
источник
2

И, поскольку вы также пробовали использовать mootools, вот решение в mootools.

var children = $('remove-just-this').getChildren();
children.replaces($('remove-just-this');

Обратите внимание, что это полностью непроверено, но я уже работал с mootools раньше, и он должен работать.

http://mootools.net/docs/Element/Element#Element:getChildren

http://mootools.net/docs/Element/Element#Element:replaces

TJ L
источник
1

Замените div его содержимым:

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

Йоханнес Бухгольц
источник
0

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

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)
user362834
источник
1
Какой это язык?
brunoais
Похоже на python - что имеет смысл, поскольку пользователь упоминает pyjamas.
mgilson
0

Я искал лучший ответ с точки зрения производительности , работая над важной DOM.

Ответ безглазости указывал на то, что использование javascript будет лучшим.

Я провел следующие тесты времени выполнения для 5000 строк и 400000 символов со сложной структурой DOM внутри раздела, который нужно удалить. Я использую идентификатор вместо класса по удобной причине при использовании javascript.

Использование $ .unwrap ()

$('#remove-just-this').contents().unwrap();

201,237 мс

Использование $ .replaceWith ()

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);

156.983 мс

Использование DocumentFragment в javascript

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

147,211 мс

Вывод

С точки зрения производительности даже в относительно большой структуре DOM разница между использованием jQuery и javascript невелика. На удивление $.unwrap()дороже $.replaceWith(). Тесты проводились с помощью jQuery 1.12.4.

maxime_039
источник
0

Если вы имеете дело с несколькими строками, как это было в моем случае, вам, вероятно, лучше будет что-то вроде этих строк:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });
Исо
источник