2012-05-23 15 views
19

同様の質問がありますが、すべての答えは内部のコンテンツのみのhtml要素を交換するためのものです。2つのhtml要素を入れ替えて、イベントリスナーを保持する

要素のイベントリスナーなどで多くのコンテンツ(テーブル、選択ボックス、入力など)で2つのdivをスワップする必要があります。

私はjQuery 1.5にアクセスしています。それで答えはOKです。

答えて

43

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/

+0

2コーナーの場合を除いて、このコードが実際に動作する唯一のコードです:nファーストまたはnラストのスワッピング項目。 – philk

+1

@philk - 私はどのコーナーケースがうまくいかないと思いますか分かりません。説明してください。おそらくjsFiddleを表示します。 – jfriend00

+0

ここで本当に素敵な仕事!パフォーマンス上の賢明さ。あなたはやってみることをお勧めしますか? – Jessica

0

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

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

基本的には、HTML文字列のコピー/ペーストを除いて、任意の方法で要素をスワップし、jQueryの.live()メソッドを使用してイベントをバインドします。私は1.5が.onメソッドを持っているとは思わないので

+0

コピーし、どこかにHTMLを貼り付けると、元のノードと同じイベントハンドラを持っていないブランドの新しいノードを作成します。だから、これはうまくいきません。 – jfriend00

+0

それは、私が 'あなたが好きな方法で要素をスワップする、コピー&ペーストのHTML文字列を除いて'と言った理由です。私はこれを2回強調しました。コピー貼り付けのHTMLは、悪魔の仕事、IMOです。これについて考えてみてください。この場合、ノードのクローン作成をお勧めします... –

1

2つの要素のparentNodesと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; 
} 
8

これは、実際に要素をリロードせずに2つの要素を交換するためのシンプルな機能です...

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

注:OBJ1と、YouTubeのようなビデオを持っている場合は交換されたときに、それがリロードされません。 変更された要素の位置にすぎません。

+2

非常にエレガントで、ここで最も投票されたマーカーdivの回答なし – philk

+2

私はこの答えを信じています、 'obj2'は' obj1'の後になければなりません。 'obj1'が' obj2'の前にあった場合、それらは入れ替えられません。 @ jfriend00答えは、前後にあるかどうかにかかわらず、両方の要素を入れ替えます。 – aug

+1

これは、要素が同じ親で互いに隣接している場合にのみ正しく機能します。それらをいくつかの要素で区切ったり、それらを異なる親にしたり、それらを入れ替えたりすることはありません。それはちょうどもう一つの前に移動します。 [this jsFiddle](http://jsfiddle.net/jfriend00/pp3op71k/)を試して、 "Swap A C"ボタンを押してください。 – jfriend00

0

私の単純な機能は、最も短く、最も広く互換性があるようです。これは、プレースホルダを必要とするか、またはそのような厄介な要素か何かを再ロードしません。それだけです

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

:jQueryの以来

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); 
} 
0

は質問にタグ付けされ、ここでjQueryのソリューションです。 jQueryはそれを新しい場所にカット/ペーストします。


これも役立つことができます。

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

関連する問題