31

同様の質問がありますが、すべての答えは、内部のコンテンツに対してのみhtml要素を交換することです。

たくさんのコンテンツ(テーブル、選択ボックス、入力など)を含む2つのdivを交換する必要があります。要素にはイベントリスナーが含まれているため、メインのdivを交換した後にそれらを保持する必要があります。

jQuery1.5にアクセスできます。だからそれで答えは大丈夫です。

4

8 に答える 8

69

イベントハンドラーを失ったり、DOM参照を壊したりせずに、2つのdivを交換するには、それらをDOM内で移動するだけです。重要なのは、innerHTMLを変更しないことです。これは、新しいDOMノードを最初から再作成し、それらのDOMオブジェクトの以前のイベントハンドラーがすべて失われるためです。

ただし、DOM要素をDOM内の新しい場所に移動するだけでは、DOM要素自体を変更せずにDOM要素の親が変更されるだけなので、すべてのイベントがアタッチされたままになります。

これは、DOM内の2つの要素を交換するクイック関数です。一方が他方の子でない限り、任意の2つの要素で機能するはずです。

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/

于 2012-05-23T09:48:02.940 に答える
8

これは、実際に要素をリロードせずに2つの要素を交換するためのより単純な関数です...

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

注:obj1にYouTubeのような埋め込みビデオがある場合、スワップ時にリロードされません。変更されたのは要素の位置だけです。

于 2013-08-30T10:49:35.333 に答える
1

2つの要素のparentNodesと1つのnextSiblingを追跡している場合は、一時的なプレースホルダーなしで2つの要素を子と交換できます。

2番目の要素が一人っ子、またはその親の最後の子である場合、その置換は(適切に)親に追加されます。

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;
}
于 2012-05-23T13:54:37.800 に答える
1

私の単純な関数は、最短で最も広く互換性があるようです。プレースホルダーやリロード要素など、面倒なものは必要ありません。

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);
}
于 2016-09-06T11:19:18.140 に答える
0

これは、イベントがスワップしている要素にどのようにバインドされているかによって多少異なります。jQueryを使用している場合、本当に必要なのはこの答えだけです。

主なことは、要素deleteremoveChildnode要素ではなく、htmlをコピーして別の場所に貼り付けることです。そうすることで、一部のブラウザはすべてのリソース(イベントハンドラを含む)をクリアするため、バインドされたイベントは失われます。IEは、動的にバインドされたイベントに関してはメモリリークで有名ですが。実際、さまざまなブラウザがどのように動作するかを予測するのは困難です。

.live()基本的には、HTML文字列のコピー/貼り付けを除いて、任意の方法で要素を交換し、jQueryのメソッドを使用してイベントをバインドします。.on1.5には方法がないと思うので

于 2012-05-23T09:41:15.437 に答える
0

jQueryは質問でタグ付けされているため、jQueryソリューションは次のとおりです。

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

それでおしまい。jQueryはそれを切り取って新しい場所に貼り付けます。


これも役立つ可能性があります。

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

于 2016-11-26T16:51:35.830 に答える
0

o1.swapNode(o2);という事実を考えると、これはすべて非常に奇妙です。IEでは非常に長い間うまく機能します。オブジェクトノードとテキストノードが混在している私の場合、1つのバージョンのみが機能します(すでにここに示されています):

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

はい、一時ノードを作成するのは嫌いですが、このトリックのない上記のバージョンは、(関数を呼び出さずに)まっすぐに使用すると失敗します。関数を呼び出したくない場合があります。

于 2019-04-14T10:26:45.377 に答える
0

要素を並べて交換する場合は、非常に簡単です。

<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)');

于 2019-06-24T21:47:21.077 に答える