it-swarm.com.de

Gibt es eine native jQuery-Funktion zum Wechseln von Elementen?

Kann ich zwei Elemente mit jQuery problemlos austauschen?

Ich suche, wenn möglich, mit einer Zeile zu tun.

Ich habe ein select-Element und ich habe zwei Schaltflächen, um die Optionen nach oben oder unten zu verschieben, und ich habe bereits die Auswahl und die Zielselektoren an Ort und Stelle, ich mache es mit einem if, aber ich habe mich gefragt, ob es einen einfacheren Weg gibt.

163
juan

Ich habe einen interessanten Weg gefunden, um dieses Problem nur mit jQuery zu lösen:

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

oder 

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

:)

216
lotif

Paulo hat recht, aber ich weiß nicht, warum er die betroffenen Elemente klont. Dies ist nicht wirklich notwendig und führt dazu, dass Referenzen oder Ereignis-Listener, die mit den Elementen und ihren Nachkommen verknüpft sind, verloren gehen.

Hier ist eine nicht klonende Version mit einfachen DOM-Methoden (da jQuery keine speziellen Funktionen hat, um diese bestimmte Operation zu vereinfachen):

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);
}
75
bobince

Nein, das ist nicht der Fall, aber Sie könnten eines ausbauen:

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

Verwendungszweck:

$(selector1).swapWith(selector2);

Beachten Sie, dass dies nur funktioniert, wenn die Selektoren jeweils nur 1 Element enthalten. Andernfalls können ungewöhnliche Ergebnisse erzielt werden.

65

Es gibt viele Edge-Fälle für dieses Problem, die nicht von der akzeptierten Antwort oder der Antwort von Bobince behandelt werden. Andere Lösungen, die das Klonen beinhalten, sind auf dem richtigen Weg, aber das Klonen ist teuer und unnötig. Wir sind in der Versuchung, zu klonen, weil es seit Jahrhunderten ein Problem ist, zwei Variablen auszutauschen. In einem der Schritte müssen Sie einer temporären Variablen eine der Variablen zuweisen. Die Zuordnung (Klonen) ist in diesem Fall nicht erforderlich. Hier ist eine jQuery-basierte Lösung:

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

Viele dieser Antworten sind für den allgemeinen Fall einfach falsch, andere sind unnötig kompliziert, wenn sie überhaupt funktionieren. Die jQuery-Methoden .before und .after erfüllen die meisten Aufgaben, die Sie möchten, aber Sie benötigen ein drittes Element, wie viele Swap-Algorithmen funktionieren. Es ist ziemlich einfach: Erstellen Sie ein temporäres DOM-Element als Platzhalter, während Sie die Dinge verschieben. Es besteht keine Notwendigkeit, Eltern oder Geschwister anzusehen, und sicherlich keine Notwendigkeit, zu klonen ...

$.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) Setze die temporäre div temp vor this 

2) bewege this vor that

3) that nach temp verschieben

3b) entferne temp

Dann einfach

$(selectorA).swapWith(selectorB);

DEMO: http://codepen.io/anon/pen/akYajE

13
robisrob

Sie sollten nicht zwei Klone brauchen, einer wird es tun. Mit der Antwort von Paolo Bergantino haben wir:

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

Sollte schneller sein. Das Übergeben des kleineren der beiden Elemente sollte die Sache ebenfalls beschleunigen.

11

Ich habe vorher eine solche Technik verwendet. Ich verwende es für die Connectorliste auf 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');
7
Eric Warnke

eine andere ohne klonen:

Ich habe ein tatsächliches und ein nominales Element, das ich austauschen kann:

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

dann wird insert <div> before und die remove danach nur benötigt, wenn Sie nicht sicherstellen können, dass es immer ein Element gibt (in meinem Fall ist es)

3
halfbit

Ich habe eine Funktion erstellt, mit der Sie mehrere ausgewählte Optionen nach oben oder unten verschieben können

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

Abhängigkeiten:

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

Zuerst wird geprüft, ob die erste/letzte ausgewählte Option in der Lage ist, sich nach oben/unten zu bewegen ..__, und durchläuft alle Elemente und Aufrufe

swapWith (element.next () oder 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);
}
3

Dies ist meine Lösung, um mehrere untergeordnete Elemente innerhalb des übergeordneten Elements nach oben und unten zu verschieben. __ Funktioniert gut, um ausgewählte Optionen in der Listbox (<select multiple></select>) zu verschieben.

Nach oben bewegen:

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

Sich abwärts bewegen:

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

schauen Sie sich das jQuery-Plugin "Swapable" an.

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

es ist auf "Sortable" aufgebaut und sieht aus wie sortierbar (Drag-n-Drop, Platzhalter usw.). Tauschen Sie jedoch nur zwei Elemente aus: Drag & Drop. Alle anderen Elemente sind nicht betroffen und bleiben auf ihrer aktuellen Position. 

2
vadimk

Dies ist eine Antwort, die auf der Antwortlogik von @lotif basiert, jedoch etwas verallgemeinert ist

Wenn Sie nach/vor/anfügen, werden die Elemente tatsächlich verschoben
=> kein Verbinden erforderlich
=> Ereignisse gehalten 

Es gibt zwei Fälle, die passieren können

  1. Ein Ziel hat etwas ".prev() ious" => wir können das andere Ziel .after() dazu setzen.
  2. Ein Ziel ist das erste untergeordnete Element von .parent() => wir können .prepend() das andere übergeordnete Ziel.

Der Code

Dieser Code könnte noch kürzer ausgeführt werden, aber aus Gründen der Lesbarkeit habe ich ihn so beibehalten. Beachten Sie, dass das Vorladen von Eltern (falls erforderlich) und vorherigen Elementen obligatorisch ist.

$(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 );

});

... den inneren Code in eine Funktion einpacken :)

Beispiel-Geige hat zusätzliche Klickereignisse, um die Ereigniserhaltung zu demonstrieren ...
Beispiel-Geige:https://jsfiddle.net/ewroodqa/

... wird für verschiedene Fälle funktionieren - auch eine wie:

<div>
  <div id="one">ONE</div>
</div>
<div>Something in the middle</div>
<div>
  <div></div>
  <div id="two">TWO</div>
</div>
2
jave.web

Ich habe eine Tabelle zum Ändern der Reihenfolge von obj in der Datenbank verwendet, die .after () .before () verwendet wurde. Dies ist also aus dem, was ich experimentiert habe.

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

Ist obj1 vor obj2 und

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

mach das Umgekehrte.

Wenn also obj1 nach obj3 und obj2 nach obj4 ist, und wenn Sie den Ort obj1 und obj2 ändern möchten, tun Sie es gerne

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

Dies sollte es tun Übrigens können Sie .prev () und .next () verwenden, um obj3 und obj4 zu finden, wenn Sie nicht bereits über einen Index dafür verfügen.

1

Wenn Sie mehrere Kopien jedes Elements haben, müssen Sie natürlich etwas in einer Schleife ausführen. Ich hatte diese Situation vor kurzem. Die zwei sich wiederholenden Elemente, die ich wechseln musste, hatten Klassen und ein Container-Divisat:

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

Mit dem folgenden Code konnte ich alles durchlaufen und umkehren ...

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

Ich habe es mit diesem Ausschnitt gemacht

// 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
zveljkovic

Ich wollte eine Lösung, die clone () nicht verwendet, da sie Nebeneffekte mit angehängten Ereignissen hat

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

es darf nicht mit jQuery-Objekten verwendet werden, die mehr als ein DOM-Element enthalten

1
Mistic

Wenn Sie zwei im jQuery-Objekt ausgewählte Elemente austauschen möchten, können Sie diese Methode verwenden 

http://www.vertstudios.com/blog/swap-jquery-plugin/

1

wenn nodeA und nodeB Geschwister sind, wie zwei <tr> in demselben <tbody>, können Sie sie einfach mit $(trA).insertAfter($(trB)) oder $(trA).insertBefore($(trB)) austauschen. und Sie müssen $(trA).remove() nicht vorher aufrufen, andernfalls müssen Sie einige Klickereignisse auf $(trA) erneut binden.

0
Spark.Bao