也有類似的問題,但所有的答案都是針對html內容進行交換的。交換2個html元素並保留它們上的事件監聽器
我需要用很多內容(表格,選擇框,輸入等)與元素等事件監聽器交換兩個div。不破壞所有這些。
我有權訪問jQuery 1.5。所以答案是可以的。
也有類似的問題,但所有的答案都是針對html內容進行交換的。交換2個html元素並保留它們上的事件監聽器
我需要用很多內容(表格,選擇框,輸入等)與元素等事件監聽器交換兩個div。不破壞所有這些。
我有權訪問jQuery 1.5。所以答案是可以的。
要交換兩個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);
}
}
}
這在某種程度上取決於您的事件如何綁定到要交換的元素。如果你使用jQuery,那麼this的答案就是你所需要的,真的。
最主要的不是delete
或removeChildnode
的元素,而只是將html複製粘貼到其他地方。這樣做時,一些瀏覽器將清除所有資源(包括事件處理程序),綁定的事件將會丟失。儘管IE在動態綁定事件方面因內存泄漏而臭名昭着。真的很難預測各種瀏覽器的行爲。
基本上,我會說:以任何你喜歡的方式交換元素,除了複製/粘貼HTML字符串,並使用jQuery的.live()
方法綁定事件。因爲我不認爲1.5有.on
方法
複製,粘貼HTML別的地方將創造全新的節點不具有相同的事件處理程序的原始節點。所以,這是行不通的。 – jfriend00
我知道,這就是爲什麼我說'以任何你喜歡的方式交換元素,除了複製/粘貼HTML字符串。我甚至兩次強調這一點。複製粘貼HTML是惡魔的工作,國際海事組織。想想看,在這種情況下,我會建議克隆節點... –
如果跟蹤兩個元素的父節點和下一個元素的兄弟節點,則可以將兩個元素與其子元素交換而不需要任何臨時佔位符。
如果第二個元素是唯一的子元素或其父元素的最後一個子元素,則將其替換(正確)添加到父元素中。
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;
}
這是交換兩個元素,而無需實際重新加載元素的簡單功能...
function swapElements(obj1, obj2) {
obj2.nextSibling === obj1
? obj1.parentNode.insertBefore(obj2, obj1.nextSibling)
: obj1.parentNode.insertBefore(obj2, obj1);
}
注:如果OBJ1有一個嵌入式的視頻,如YouTube,換的時候也不會重新加載。 這只是變化的元素的位置。
我的簡單功能似乎是最短和最廣泛的兼容。它並不需要佔位符或重載元件或任何凌亂的那樣:
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);
}
由於jQuery是在標籤的問題,這裏是一個jQuery的解決方案:
$('#el_to_move').appendTo('#target_parent_el');
就是這樣。 jQuery將剪切/粘貼到新位置。
這也可能是有益的:
我可能會補充說,除了2個角落案例外,這個代碼是唯一實際工作的代碼:交換n首或n最後項目。 – philk
@philk - 我不明白你認爲哪些角落案件無效。請解釋。也許展示一個jsFiddle。 – jfriend00
這裏真的很棒!在性能方面,你建議做什麼? – Jessica