2012-05-23 11 views
19

इसी तरह के प्रश्न हैं, लेकिन सभी उत्तर केवल सामग्री के लिए HTML तत्वों को स्वैप करने के लिए हैं।2 एचटीएमएल तत्वों को स्वैप करें और उन पर ईवेंट श्रोताओं को संरक्षित करें

मुझे तत्वों पर घटना श्रोताओं के साथ कई सामग्री (टेबल, चयन बॉक्स, इनपुट आदि) के साथ दो divs स्वैप करने की आवश्यकता है। सभी को नष्ट किए बिना।

मेरे पास jQuery 1.5 का उपयोग है। तो इसके साथ जवाब ठीक है।

उत्तर

43

ईवेंट हैंडलर खोने या डोम संदर्भों को तोड़ने के बिना दो divs स्वैप करने के लिए, आप उन्हें केवल DOM में ले जा सकते हैं। कुंजी आंतरिक HTML को बदलने के लिए नहीं है क्योंकि यह नए डीओएम नोड्स को स्क्रैच से दोबारा शुरू करता है और उन डीओएम ऑब्जेक्ट्स पर सभी पूर्व ईवेंट हैंडलर खो जाते हैं।

लेकिन, यदि आप डीओएम तत्वों को डीओएम में एक नए स्थान पर ले जाते हैं, तो सभी घटनाएं संलग्न रहती हैं क्योंकि डीओएम तत्व केवल डीओएम तत्वों को बदलने के बिना ही पुनर्निर्मित होते हैं।

यहां एक त्वरित कार्य है जो डोम में दो तत्वों को स्वैप करेगा। के रूप में एक अन्य का एक बच्चा नहीं है यह लंबे समय के रूप में किसी भी दो तत्वों के साथ काम करना चाहिए:

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-first या n-last आइटम। – philk

+1

@philk - मुझे नहीं पता कि किन कोने के मामलों में आपको लगता है कि काम नहीं करते हैं। कृपया समझाएँ। शायद एक jsFiddle दिखाओ। – jfriend00

+0

वास्तव में यहां अच्छा काम है! प्रदर्शन के अनुसार, आप क्या करने का सुझाव देते हैं? – Jessica

0

यह कुछ हद तक इस बात पर निर्भर करता है कि आपकी घटनाएं आपके द्वारा स्वैप किए जा रहे तत्वों से कैसे बंधी हुई हैं। यदि आप jQuery का उपयोग कर रहे हैं, तो this उत्तर आपको वास्तव में चाहिए, वास्तव में।

मुख्य बात delete या removeChildnode तत्वों के लिए नहीं है, और बस कहीं और HTML को कॉपी-पेस्ट करें। ऐसा करने में, कुछ ब्राउज़र सभी संसाधनों को साफ़ करेंगे (ईवेंट हैंडलर शामिल हैं) ताकि बाध्य घटनाएं खो जाएंगी। हालांकि गतिशील रूप से बाध्य घटनाओं की बात आती है जब आईई स्मृति को लीक करने के लिए कुख्यात है। भविष्यवाणी करना मुश्किल है कि वास्तव में विभिन्न ब्राउज़र कैसे व्यवहार करेंगे।

असल में, मैं कहूंगा: किसी भी तरह से तत्वों को स्वैप करें, कॉपी/पेस्ट HTML स्ट्रिंग को छोड़कर, और jQuery की .live() विधि का उपयोग करके अपनी घटनाओं को बाध्य करें। चूंकि मुझे नहीं लगता कि 1.5 में .on विधि

+0

कॉपी, कहीं और एचटीएमएल चिपकाने ब्रांड के नए नोड्स मूल नोड्स के रूप में एक ही घटना संचालकों न हो पैदा करेगा। तो, यह काम नहीं करेगा। – jfriend00

+0

मुझे पता है, यही कारण है कि मैंने कहा है कि एचटीएमएल स्ट्रिंग्स कॉपी/पेस्ट करने के अलावा, किसी भी तरह से तत्वों को स्वैप करें। मैंने इसे दो बार भी जोर दिया। कॉपी-पेस्टिंग एचटीएमएल शैतान का काम है, आईएमओ। इसके बारे में सोचने के लिए आओ, इस मामले में मैं नोड्स क्लोनिंग का सुझाव दूंगा ... –

1

यदि आप दो तत्वों के पैरेंट नोड्स और अगली सिब्लिंग का ट्रैक रखते हैं, तो आप बिना किसी अस्थायी प्लेसहोल्डर के अपने बच्चों के साथ दो तत्वों को स्वैप कर सकते हैं।

यदि दूसरा तत्व एकमात्र बच्चा है, या उसके माता-पिता का अंतिम बच्चा है, तो इसका प्रतिस्थापन माता-पिता को जोड़ दिया गया है।

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

यह वास्तव में तत्व को पुन: लोड के बिना दो तत्वों की अदला-बदली के लिए एक सरल कार्य है ...

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

नोट: अगर obj1 यूट्यूब की तरह एक एम्बेडेड वीडियो है, यह जब बदली को फिर से लोड नहीं होंगे। यह केवल उन तत्वों की स्थिति है जो बदले गए हैं।

+2

बहुत ही सुरुचिपूर्ण और मार्कर div उत्तर के बिना सबसे अधिक वोट दिया गया था – philk

+2

मुझे इस जवाब में विश्वास है, 'obj2'' obj1' के बाद होना चाहिए। यदि 'obj1' 'obj2' से पहले थे, तो वे स्वैप नहीं करेंगे। @ jfriend00 उत्तर दोनों तत्वों को स्वैप करेगा चाहे वे एक दूसरे के पहले या बाद में हों। – aug

+1

यह केवल तभी काम करता है जब तत्व एक ही माता-पिता के साथ एक दूसरे के बगल में हों। उन्हें कुछ तत्वों से अलग करें या उन्हें अलग-अलग माता-पिता दें और यह उन्हें स्वैप नहीं करता है। यह सिर्फ एक दूसरे से पहले चलता है। बस [यह jsFiddle] (http://jsfiddle.net/jfriend00/pp3op71k/) आज़माएं और "स्वैप ए सी" बटन दबाएं। – jfriend00

0

मेरा सरल कार्य सबसे छोटा और सबसे व्यापक रूप से संगत लगता है। यह प्लेसहोल्डर की जरूरत नहीं है या तत्वों या कुछ भी ऐसा गंदा फिर से लोड:

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

यह है कि:

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 समाधान है। jQuery इसे नए स्थान पर काट/पेस्ट करेगा।


यह भी सहायक हो सकता है:

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

संबंधित मुद्दे