तत्वों को स्विच करने के लिए एक देशी jQuery फ़ंक्शन है?


174

क्या मैं आसानी से jQuery के साथ दो तत्वों को स्वैप कर सकता हूं?

यदि संभव हो तो मैं एक पंक्ति के साथ ऐसा करना चाह रहा हूं।

मेरे पास एक चयन तत्व है और मेरे पास विकल्पों को ऊपर या नीचे ले जाने के लिए दो बटन हैं, और मेरे पास पहले से ही चयनित और गंतव्य चयनकर्ता हैं, मैं इसे एक के साथ करता हूं, लेकिन मैं सोच रहा था कि क्या कोई आसान तरीका है।


क्या आप मार्कअप और कोड नमूना पोस्ट कर सकते हैं?
कॉन्स्टेंटिन टर्कस

यह jQuery की बात नहीं है, लेकिन जावास्क्रिप्ट: आप डोम तत्वों को एक निर्देश में स्वैप नहीं कर सकते । हालांकि, [पाओलो का जवाब] (# 698386) एक महान प्लगइन है;)
सेब

1
Google से यहां आने वाले लोगों के लिए: लॉटिफ़ के उत्तर को देखें, बहुत ही सरल और मेरे लिए पूरी तरह से काम किया।
मौरिस

1
@ मौरिस, मैंने स्वीकार किए गए उत्तर को बदल दिया
जुआन

1
यह केवल तत्वों को स्वैप करता है यदि वे एक दूसरे के बगल में हैं! कृपया, स्वीकृत उत्तर को बदल दें।
सेरही

जवाबों:


233

मैंने केवल jQuery का उपयोग करके इसे हल करने का एक दिलचस्प तरीका पाया है:

$("#element1").before($("#element2"));

या

$("#element1").after($("#element2"));

:)


2
हाँ, यह काम करना चाहिए: दस्तावेज़ीकरण कहता है: "यदि इस तरह से चयनित किसी तत्व को कहीं और डाला जाता है, तो इसे लक्ष्य से पहले ले जाया जाएगा (क्लोन नहीं किया गया)"।
Ridcully

12
मुझे यह विकल्प सबसे अच्छा लगता है! सरल और अच्छी तरह से संगत। हालाँकि, मैं पठनीयता के लिए el1.insertBefore (el2) और el1.insertAfter (el2) का उपयोग करना पसंद करता हूं।
मौरिस

6
यद्यपि हम यहाँ DOM का हेरफेर कर रहे हैं, लेकिन एक (जो मुझे लगता है कि इस पृष्ठ पर सभी समाधानों पर लागू होता है)। जब आप चल रहे तत्व के भीतर एक iframe मौजूद होता है, तो निकालना और जोड़ना अच्छी तरह से काम नहीं करता है। आईफ्रेम पुनः लोड होगा। इसके अलावा यह वर्तमान के बजाय मूल यूआरएल को फिर से लोड करेगा। बहुत कष्टप्रद लेकिन सुरक्षा-संबंधी। मुझे इसके लिए कोई हल नहीं मिला है
मौरिस

202
यह दो तत्वों की अदला-बदली नहीं करता है जब तक कि दो तत्व तुरंत एक-दूसरे के बगल में न हों।
बोनीटी

12
यह स्वीकृत उत्तर नहीं होना चाहिए। यह सामान्यीकृत मामले में काम नहीं करता है।
वाकिंगफ्रूट

79

पाउलो का अधिकार है, लेकिन मुझे यकीन नहीं है कि वह संबंधित तत्वों को क्यों क्लोन कर रहा है। यह वास्तव में आवश्यक नहीं है और तत्वों और उनके वंश से जुड़े किसी भी संदर्भ या घटना के श्रोताओं को खो देगा।

यहाँ सादे डोम तरीकों का उपयोग करके एक गैर-क्लोनिंग संस्करण है (क्योंकि jQuery के पास वास्तव में इस विशेष ऑपरेशन को आसान बनाने के लिए कोई विशेष कार्य नहीं है):

function swapNodes(a, b) {
    var aparent = a.parentNode;
    var asibling = a.nextSibling === b ? a : a.nextSibling;
    b.parentNode.insertBefore(a, b);
    aparent.insertBefore(b, asibling);
}

2
docs.jquery.com/Clone - इसे "सत्य" मानकर घटनाओं को भी क्लोन करता है। मैंने इसे पहले क्लोनिंग के बिना करने की कोशिश की लेकिन यह वही कर रहा था जो वर्तमान में आपका है: यह पहले वाले को दूसरे के साथ स्वैप कर रहा है और पहले वाले को छोड़ रहा है।
पाओलो बरगिनिनो

अगर मेरे पास <div id = "div1"> 1 </ div> <div id = "div2"> 2 </ div> और swapNodes (document.getElementById ('div1'), document .getElementById ('div2') है। ); मुझे मिलता है <div id = "div1"> 1 </ div> <div id = "div2"> 1 </ div>
पाओलो बरगेंटिनो

3
आह, एक कोने का मामला है जहां एक अगला भाई-बहन खुद बी है। उपरोक्त स्निपेट में तय किया गया। jQuery ठीक यही काम कर रहा था।
बॉब

मेरे पास एक बहुत ही आदेश-संवेदनशील सूची है जिसे घटनाओं और आईडी को बनाए रखने की आवश्यकता है और यह एक आकर्षण की तरह काम करता है! धन्यवाद!
टेकिन

1
मुझे लगता है कि आपको इस प्रश्न के शीर्षक को तकनीकी रूप से संतुष्ट करने के लिए एक jQuery संस्करण जोड़ना चाहिए। :)
वाकिंगफ्रूट

70

नहीं, वहाँ नहीं है, लेकिन आप एक कोड़ा मार सकते हैं:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        var copy_from = $(this).clone(true);
        $(to).replaceWith(copy_from);
        $(this).replaceWith(copy_to);
    });
};

उपयोग:

$(selector1).swapWith(selector2);

ध्यान दें कि यह केवल तभी काम करता है जब चयनकर्ता केवल 1 तत्व से मेल खाते हैं, अन्यथा यह अजीब परिणाम दे सकता है।


2
क्या उन्हें क्लोन करना आवश्यक है?
जुआन

शायद आप उन्हें सीधे html () का उपयोग करके लिख सकते हैं?
एड जेम्स

2
@ ईडी वुडकॉक यदि आप करते हैं, तो आप उन तत्वों पर बाध्य घटनाओं को खो देंगे जो मुझे पूरा यकीन है।
एलेक्स

2
महान कार्य करता है जब divs एक दूसरे के बगल में नहीं होते हैं :)
Elmer

यह स्वीकृत उत्तर होना चाहिए। यह प्रदान करने के लिए jQuery का विस्तार करता है।
एलिस वंडर

40

इस समस्या के बहुत सारे किनारे हैं, जिन्हें स्वीकार किए गए उत्तर या बॉबिन के उत्तर द्वारा नियंत्रित नहीं किया जाता है। क्लोनिंग को शामिल करने वाले अन्य समाधान सही रास्ते पर हैं, लेकिन क्लोनिंग महंगी और अनावश्यक है। हम क्लोन करने के लिए ललचा रहे हैं, क्योंकि दो चर को स्वैप करने की उम्र-पुरानी समस्या है, जिसमें से एक चरण में से एक चर को अस्थायी चर में असाइन करना है। असाइनमेंट, (क्लोनिंग), इस मामले में जरूरत नहीं है। यहाँ एक jQuery- आधारित समाधान है:

function swap(a, b) {
    a = $(a); b = $(b);
    var tmp = $('<span>').hide();
    a.before(tmp);
    b.before(a);
    tmp.replaceWith(b);
};

7
यह स्वीकृत उत्तर होना चाहिए। क्लोनिंग किसी भी घटना ट्रिगर को हटा देती है और आवश्यक नहीं है। मैं अपने कोड में इस सटीक विधि का उपयोग करता हूं।

1
यह बेहतर उत्तर है! मैं अपने अदला-बदली वाले तत्वों के एक बच्चे के रूप में उल्टा खुश हूं, जो कि एक जॉकरी सॉर्टेबल तत्व था। पाओलो बेरेगिनो के जवाब के साथ स्वैप करने के बाद सूची आइटम अब और नहीं गिराए जा सकते। User2820356 के जवाब के साथ अभी भी सब कुछ ठीक है।
अगस्त २४'१५

20

इनमें से कई उत्तर सामान्य मामले के लिए गलत हैं, अन्य अनावश्यक रूप से जटिल हैं यदि वे वास्तव में भी काम करते हैं। JQuery .beforeऔर .afterविधियाँ जो आप करना चाहते हैं उनमें से अधिकांश करते हैं, लेकिन आपको एक 3 तत्व की आवश्यकता होती है जिस तरह से कई स्वैप एल्गोरिदम काम करते हैं। यह बहुत आसान है - जब आप चीजों को घुमाते हैं तो एक प्लेसहोल्डर के रूप में एक अस्थायी डोम तत्व बनाते हैं। माता-पिता या भाई-बहनों को देखने की कोई आवश्यकता नहीं है, और निश्चित रूप से क्लोन करने की आवश्यकता नहीं है ...

$.fn.swapWith = function(that) {
  var $this = this;
  var $that = $(that);

  // create temporary placeholder
  var $temp = $("<div>");

  // 3-step swap
  $this.before($temp);
  $that.before($this);
  $temp.after($that).remove();

  return $this;
}

1) tempपहले अस्थायी div डाल दियाthis

2) thisपहले चलेंthat

3) के thatबाद कदमtemp

3 बी) हटा दें temp

फिर बस

$(selectorA).swapWith(selectorB);

डेमो: http://codepen.io/anon/pen/akYajE


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

11

आपको दो क्लोन की आवश्यकता नहीं है, एक करना होगा। पाओलो बर्गोनिनो जवाब ले हमारे पास है:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        $(to).replaceWith(this);
        $(this).replaceWith(copy_to);
    });
};

जल्दी होना चाहिए। दो तत्वों के छोटे में पास होने से चीजों को गति भी मिलनी चाहिए।


4
इस के साथ समस्या है, और पाओलो, यह है कि वे एक आईडी के साथ तत्वों को स्वैप नहीं कर सकते क्योंकि आईडी अद्वितीय होना चाहिए ताकि क्लोनिंग काम न करे। इस मामले में बोबसन का समाधान काम करता है।
रूड

एक और समस्या यह है कि इससे घटनाओं को copy_to से हटा दिया जाएगा।
जान विल्म बी

8

मैंने पहले भी इस तरह की तकनीक का इस्तेमाल किया था। मैं इसे http://mybackupbox.com पर कनेक्टर सूची के लिए उपयोग करता हूं

// clone element1 and put the clone before element2
$('element1').clone().before('element2').end();

// replace the original element1 with element2
// leaving the element1 clone in it's place
$('element1').replaceWith('element2');

यह सबसे अच्छा समाधान imo है, लेकिन end()आप श्रृंखला जारी नहीं कर रहे हैं, तो कोई ज़रूरत नहीं है। कैसे के बारे में$('element1').clone().before('element2').end().replaceWith('element2');
लूटने

1
जब तक आप निर्दिष्ट नहीं करते हैं, तब तक clone()कोई भी ध्यान नहीं देता है - यदि आप छँटाई कर रहे हैं तो एक महत्वपूर्ण अंतर है, ताकि आप अपना सारा डेटा न खोएंdata()clone(true)
डकैतीब्रोव

3

मैंने एक फ़ंक्शन बनाया है जो आपको कई चयनित विकल्पों को ऊपर या नीचे स्थानांतरित करने की अनुमति देता है

$('#your_select_box').move_selected_options('down');
$('#your_select_boxt').move_selected_options('up');

निर्भरता:

$.fn.reverse = [].reverse;
function swapWith() (Paolo Bergantino)

पहले यह जांचता है कि पहला / अंतिम चयनित विकल्प ऊपर / नीचे जाने में सक्षम है या नहीं। फिर यह सभी तत्वों और कॉल के माध्यम से छोरों

swapWith (element.next) (या element.prev ())

jQuery.fn.move_selected_options = function(up_or_down) {
  if(up_or_down == 'up'){
      var first_can_move_up = $("#" + this.attr('id') + ' option:selected:first').prev().size();
      if(first_can_move_up){
          $.each($("#" + this.attr('id') + ' option:selected'), function(index, option){
              $(option).swapWith($(option).prev());
          });
      }
  } else {
      var last_can_move_down = $("#" + this.attr('id') + ' option:selected:last').next().size();
      if(last_can_move_down){
        $.each($("#" + this.attr('id') + ' option:selected').reverse(), function(index, option){
            $(option).swapWith($(option).next());
        });
      }
  }
  return $(this);
}

यह अक्षम है, दोनों तरह से कोड लिखा गया है और यह कैसे प्रदर्शन करेगा।
Blaise

यह हमारे ऐप की एक प्रमुख विशेषता नहीं थी और मैं इसका उपयोग कम मात्रा में विकल्पों के साथ करता हूं। मुझे बस कुछ त्वरित और आसान चाहिए था ... अगर आप इसे सुधार सकते हैं तो मुझे यह पसंद आएगा! वह महान होगा!
टॉम मेकेलबर्गे

3

क्लोनिंग के बिना एक दूसरे को:

मेरे पास स्वैप करने के लिए एक वास्तविक और एक नाममात्र तत्व है:

            $nominal.before('<div />')
            $nb=$nominal.prev()
            $nominal.insertAfter($actual)
            $actual.insertAfter($nb)
            $nb.remove()

तब insert <div> beforeऔर removeबाद में केवल जरूरत होती है, यदि आप यह सुनिश्चित नहीं कर सकते कि हमेशा एक तत्व befor है (मेरे मामले में यह है)


या आप सिर्फ .prev()लंबाई के लिए जाँच कर सकते हैं , और यदि 0, तो :) .prepend()से .parent(): इस तरह आपको अतिरिक्त तत्व बनाने की आवश्यकता नहीं है।
jave.web

2

jQuery प्लगइन "स्वैपेबल" पर एक नज़र डालें

http://code.google.com/p/jquery-swapable/

यह "Sortable" पर बनाया गया है और यह Sortable (ड्रैग-एन-ड्रॉप, प्लेसहोल्डर, आदि) की तरह दिखता है, लेकिन केवल दो तत्वों को स्वैप करें: ड्रैग और ड्रॉप। अन्य सभी तत्व प्रभावित नहीं होते हैं और अपनी वर्तमान स्थिति पर बने रहते हैं।


2

यह @lotif पर आधारित एक उत्तर है के उत्तर तर्क है, लेकिन थोड़ा अधिक सामान्यीकृत है

यदि आप तत्वों को वास्तव में स्थानांतरित करने से पहले / बाद में जोड़ते हैं /
रोकते हैं => कोई क्लोनिंग की जरूरत नहीं है
= घटनाओं को रखा जाता है

दो मामले हैं जो हो सकते हैं

  1. एक लक्ष्य में कुछ " .prev()ious" => हम दूसरे लक्ष्य को रख सकते हैं .after()
  2. एक लक्ष्य यह का पहला बच्चा है .parent()=> हम .prepend()माता-पिता को दूसरा लक्ष्य दे सकते हैं ।

कोड

यह कोड और भी छोटा किया जा सकता था, लेकिन मैंने इसे पठनीयता के लिए इस तरह से रखा। ध्यान दें कि माता-पिता को पुरस्कृत करना (यदि आवश्यक हो) और पिछले तत्व अनिवार्य हैं।

$(function(){
  var $one = $("#one");
  var $two = $("#two");
  
  var $onePrev = $one.prev(); 
  if( $onePrev.length < 1 ) var $oneParent = $one.parent();

  var $twoPrev = $two.prev();
  if( $twoPrev.length < 1 ) var $twoParent = $two.parent();
  
  if( $onePrev.length > 0 ) $onePrev.after( $two );
    else $oneParent.prepend( $two );
    
  if( $twoPrev.length > 0 ) $twoPrev.after( $one );
    else $twoParent.prepend( $one );

});

... एक समारोह में आंतरिक कोड को लपेटने के लिए स्वतंत्र महसूस :)

उदाहरण फ़िडल में इवेंट संरक्षण को प्रदर्शित करने के लिए अतिरिक्त क्लिक ईवेंट हैं ...
उदाहरण फ़ेडल: https://jsfiddle.net/ewroodqa/

... विभिन्न मामलों के लिए काम करेगा - यहां तक ​​कि एक जैसे:

<div>
  <div id="one">ONE</div>
</div>
<div>Something in the middle</div>
<div>
  <div></div>
  <div id="two">TWO</div>
</div>

2

यह मूल तत्व के अंदर कई बच्चों के तत्वों को ऊपर और नीचे स्थानांतरित करने के लिए मेरा समाधान है। सूची बॉक्स में चयनित विकल्पों को स्थानांतरित करने के लिए अच्छी तरह से काम करता है ( <select multiple></select>)

बढ़ाना:

$(parent).find("childrenSelector").each((idx, child) => {
    $(child).insertBefore($(child).prev().not("childrenSelector"));
});

नीचे की ओर:

$($(parent).find("childrenSelector").get().reverse()).each((idx, child) => {
    $(opt).insertAfter($(child).next().not("childrenSelector"));
});


1

मैं चाहता था कि एक समाधान चुड़ैल क्लोन () का उपयोग नहीं करता है क्योंकि यह संलग्न घटनाओं के साथ दुष्प्रभाव है, यहाँ है कि मैं क्या करने के लिए समाप्त हो गया

jQuery.fn.swapWith = function(target) {
    if (target.prev().is(this)) {
        target.insertBefore(this);
        return;
    }
    if (target.next().is(this)) {
        target.insertAfter(this);
        return
    }

    var this_to, this_to_obj,
        target_to, target_to_obj;

    if (target.prev().length == 0) {
        this_to = 'before';
        this_to_obj = target.next();
    }
    else {
        this_to = 'after';
        this_to_obj = target.prev();
    }
    if (jQuery(this).prev().length == 0) {
        target_to = 'before';
        target_to_obj = jQuery(this).next();
    }
    else {
        target_to = 'after';
        target_to_obj = jQuery(this).prev();
    }

    if (target_to == 'after') {
        target.insertAfter(target_to_obj);
    }
    else {
        target.insertBefore(target_to_obj);
    }
    if (this_to == 'after') {
        jQuery(this).insertAfter(this_to_obj);
    }
    else {
        jQuery(this).insertBefore(this_to_obj);
    }

    return this;
};

इसका उपयोग jQuery ऑब्जेक्ट के साथ एक से अधिक DOM तत्व के साथ नहीं किया जाना चाहिए


1

यदि आपके पास प्रत्येक तत्व की कई प्रतियां हैं, तो आपको स्वाभाविक रूप से एक लूप में कुछ करने की आवश्यकता है। हाल ही में मेरी यह स्थिति थी। जिन दो दोहराए जाने वाले तत्वों की मुझे आवश्यकता थी, उनमें कक्षाएं और एक कंटेनर डिव शामिल था:

<div class="container">
  <span class="item1">xxx</span>
  <span class="item2">yyy</span>
</div> 
and repeat...

निम्न कोड ने मुझे सब कुछ और रिवर्स के माध्यम से पुनरावृति की अनुमति दी ...

$( ".container " ).each(function() {
  $(this).children(".item2").after($(this).children(".item1"));
});

1

मैंने इसे इस स्निपेट के साथ किया है

// Create comments
var t1 = $('<!-- -->');
var t2 = $('<!-- -->');
// Position comments next to elements
$(ui.draggable).before(t1);
$(this).before(t2);
// Move elements
t1.after($(this));
t2.after($(ui.draggable));
// Remove comments
t1.remove();
t2.remove();

1

मैंने डेटाबेस में obj के बदलते क्रम के लिए एक तालिका का उपयोग किया है। इसके बाद () .before (), इसलिए यह वह है जो मैंने प्रयोग किया है।

$(obj1).after($(obj2))

Obj2 से पहले obj1 डालें और

$(obj1).before($(obj2)) 

इसके विपरीत करें।

तो अगर obj1 obj3 के बाद है और obj4 के बाद obj2 है, और अगर आप obj1 और obj2 को बदलना चाहते हैं तो आप इसे पसंद करेंगे

$(obj1).before($(obj4))
$(obj2).before($(obj3))

यदि आप पहले से ही इसके लिए किसी प्रकार का सूचकांक नहीं रखते थे, तो इसे करना चाहिए। आप इसे .WV () और .next () का उपयोग कर सकते हैं।


यह स्वीकार किए गए उत्तरदाता का सिर्फ एक युक्ति नहीं है, इसमें एक खराब वाक्यविन्यास त्रुटि है। क्या आपने इसका मुकाबला किया?
क्लॉकवॉक

एह नहीं ?? यह मेरी पिछली कंपनी में मेरे काम का कोड काम कर रहा है। बगल में मैं कैसे और किस स्थिति में उपयोग करने के लिए इंगित करना सुनिश्चित किया। मुझे किसी को चीरने की आवश्यकता क्यों है? मैं यह भी बताता हूं कि वस्तु का सूचकांक कैसे प्राप्त किया जाए, यही वजह है कि स्वीकृत जवाब को टिप्पणी नहीं दी गई।
ट्रान वु डांग खोआ

उसके बाद ($ ()) के बजाय $ () के बाद क्यों है
घड़ी में

ओह, हाँ, मैंने इसे नहीं देखा, धन्यवाद। मैं इसे मेमोरी से इनपुट करता हूं, मेरे पास कंपनी छोड़ने के बाद उस कोड को रखने का अधिकार नहीं है
Tran Vu Dang Khoa

0

अगर नोडा और नोडबी भाई-बहन हैं, तो दो <tr>को पसंद करता है <tbody>, आप बस उनका उपयोग कर सकते हैं $(trA).insertAfter($(trB))या $(trA).insertBefore($(trB))उन्हें स्वैप कर सकते हैं, यह मेरे लिए काम करता है। और आपको $(trA).remove()पहले कॉल करने की आवश्यकता नहीं है , अन्यथा आपको कुछ क्लिक ईवेंट पर फिर से बाँधने की आवश्यकता है$(trA)


0
$('.five').swap('.two');

इस तरह एक jQuery फ़ंक्शन बनाएँ

$.fn.swap = function (elem) 
{
    elem = elem.jquery ? elem : $(elem);
    return this.each(function () 
    {
        $('<span></span>').insertBefore(this).before(elem.before(this)).remove();
    });
};

Https://jsfiddle.net/ARTsinn/TVjnr/ पर यानिक गिनीज का धन्यवाद



-2

मुझे लगता है कि आप इसे बहुत सरल कर सकते हैं। उदाहरण के लिए मान लीजिए कि आपके पास अगली संरचना है: ...

<div id="first">...</div>
<div id="second">...</div>

और परिणाम होना चाहिए

<div id="second">...</div>
<div id="first">...</div>

jQuery:

$('#second').after($('#first'));

मुझे उम्मीद है यह मदद करेगा!


2
यह समाधान पहले ही इंगित किया गया था और तब तक काम नहीं करता है, जब तक कि दोनों तत्व एक-दूसरे के बगल में तुरंत न हों।
बर्नमैरिएनो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.