Подтвердить что ты не робот

Смените 2 html-элемента и сохраните на них прослушиватели событий

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

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

У меня есть доступ к jQuery 1.5. Поэтому ответы с ним в порядке.

4b9b3361

Ответ 1

Чтобы поменять местами два div без потери обработчиков событий или разрыва ссылок DOM, вы можете просто переместить их в DOM. Ключ НЕ должен меняться innerHTML, поскольку он воссоздает новые узлы DOM с нуля и все предыдущие обработчики событий на этих объектах DOM теряются.

Но если вы просто перемещаете элементы DOM на новое место в DOM, все события остаются прикрепленными, потому что элементы DOM восстанавливаются только без изменения самих элементов DOM.

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

function swapElements(obj1, obj2) {
    // create marker element and insert it where obj1 is
    var temp = document.createElement("div");
    obj1.parentNode.insertBefore(temp, obj1);

    // move obj1 to right before obj2
    obj2.parentNode.insertBefore(obj1, obj2);

    // move obj2 to right before where obj1 used to be
    temp.parentNode.insertBefore(obj2, temp);

    // remove temporary marker node
    temp.parentNode.removeChild(temp);
}

Вы можете увидеть, как он работает здесь: http://jsfiddle.net/jfriend00/NThjN/


И здесь версия, которая работает без вставленного временного элемента:

function swapElements(obj1, obj2) {
    // save the location of obj2
    var parent2 = obj2.parentNode;
    var next2 = obj2.nextSibling;
    // special case for obj1 is the next sibling of obj2
    if (next2 === obj1) {
        // just put obj1 before obj2
        parent2.insertBefore(obj1, obj2);
    } else {
        // insert obj2 right before obj1
        obj1.parentNode.insertBefore(obj2, obj1);

        // now insert obj1 where obj2 was
        if (next2) {
            // if there was an element after obj2, then insert obj1 right before that
            parent2.insertBefore(obj1, next2);
        } else {
            // otherwise, just append as last child
            parent2.appendChild(obj1);
        }
    }
}

Рабочая демонстрация: http://jsfiddle.net/jfriend00/oq92jqrb/

Ответ 2

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

function swapElements(obj1, obj2) {
    obj2.nextSibling === obj1
    ? obj1.parentNode.insertBefore(obj2, obj1.nextSibling)
    : obj1.parentNode.insertBefore(obj2, obj1); 
}

Примечание. Если obj1 имеет встроенное видео, например YouTube, он не перезагружается при замене. Это просто положение элементов, которые изменились.

Ответ 3

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

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

function swap(a, b){
    var p1= a.parentNode, p2= b.parentNode, sib= b.nextSibling;
    if(sib=== a) sib= sib.nextSibling;
    p1.replaceChild(b, a);
    if(sib) p2.insertBefore(a, sib);
    else p2.appendChild(a);
    return true;
}

Ответ 4

Это зависит от того, как ваши события привязаны к элементам, которые вы меняете. Если вы используете jQuery, то этот ответ - это все, что вам нужно.

Главное - не delete или removeChildnode элементы, а просто скопировать-вставить html в другое место. При этом некоторые браузеры очистят все ресурсы (включенные обработчики событий), поэтому связанные события будут потеряны. Хотя IE пресловут утечкой памяти, когда дело доходит до динамически связанных событий. Трудно предсказать, как будут себя вести разные браузеры.

В принципе, я бы сказал: обменивайте элементы любым способом, за исключением скопировать/вставить строки HTML и связать свои события с помощью метода jQuery .live(). Поскольку я не думаю, что у 1.5 есть метод .on

Ответ 5

Моя простая функция, кажется, самая короткая и наиболее широко совместимая. Ему не нужны заполнители или элементы перезагрузки или что-то грязное:

function swapElements(el1, el2) {
    var p2 = el2.parentNode, n2 = el2.nextSibling
    if (n2 === el1) return p2.insertBefore(el1, el2)
    el1.parentNode.insertBefore(el2, el1);
    p2.insertBefore(el1, n2);
}

Ответ 6

Поскольку jQuery помечен в вопросе, вот решение jQuery:

  $('#el_to_move').appendTo('#target_parent_el');

Что это. jQuery вырезает/вставляет его в новое место.


Это также может быть полезно:

https://api.jquery.com/detach/

Ответ 7

Это все очень странно, учитывая тот факт, что o1.swapNode(o2); очень хорошо работает в IE в течение очень долгого времени. В моем случае объект и текстовые узлы смешаны, работает только одна версия (уже показана здесь):

let t = document.createElement("div");
o1.parentNode.insertBefore(t, o1);
o2.parentNode.insertBefore(o1, o2);
t.parentNode.insertBefore(o2, t);
t.parentNode.removeChild(t);

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

Ответ 8

Это действительно легко, если вы меняете элементы рядом друг с другом:

<div class="container">
   <div class="item">Item 1</div>
   <div class="item">Item 2</div>
</div>

$('.container.item:nth-child(2)').insertBefore('.container.item:nth-child(1)');