Jak przenieść element do innego elementu?

1688

Chciałbym przenieść jeden element DIV do innego. Na przykład chcę to przenieść (w tym wszystkie dzieci):

<div id="source">
...
</div>

zaangażowany w to:

<div id="destination">
...
</div>

więc mam to:

<div id="destination">
  <div id="source">
    ...
  </div>
</div>
Mark Richman
źródło
21
Wystarczy użyć $ (element_elementowy) .append (to_be_inserted_element);
Mohammad Areeb Siddiqui
2
Lub: destination.appendChild (źródło) przy użyciu zwykłego javascript
Łukasz
czy możemy to osiągnąć za pomocą CSS? czy to jest możliwe ?
RajKumar Samala
6
@RajKumarSamala CSS nie może zmieniać struktury HTML, tylko jego prezentację.
Mark Richman,

Odpowiedzi:

38

Czy kiedykolwiek próbowałeś zwykłego JavaScript ... destination.appendChild(source);?

onclick = function(){ destination.appendChild(source); }
div{ margin: .1em; } 
#destination{ border: solid 1px red; }
#source {border: solid 1px gray; }
<!DOCTYPE html>
<html>

 <body>

  <div id="destination">
   ###
  </div>
  <div id="source">
   ***
  </div>

 </body>
</html>

Bekim Bacaj
źródło
* ktoś poprzedził globalne wydarzenie onclick fragmentu wersji demo słowem kluczowym varw swojej próbie ulepszenia posta - ale to źle!
Bekim Bacaj,
6
To niesamowite, jak ludzie nadal myślą, że jQuery równa się JavaScript. Naprawdę nie ma już potrzeby korzystania z jQuery w 2017 roku.
nkkollaw
2
w 2017 roku nie ma potrzeby wysyłania jquery, ale czasami pomaga to zastosować coś lżejszego i podobnego do zadań, które wykonujesz w kółko w każdym projekcie. używam cash-dom jako łatwego sposobu na nasłuchiwanie zdarzeń document.ready, window.load w sposób przyjazny dla różnych przeglądarek. bułka z masłem.
eballeste,
1
Zmieniając to na przyjętą odpowiedź, teraz jest 2020 r. :)
Mark Richman
1
To niesamowite, jak ludzie nadal myślą, że jQuery równa się JavaScript. Naprawdę nie ma już potrzeby korzystania z jQuery w 2020 roku.
ii iml0sto1
1793

Możesz użyć appendTofunkcji (która dodaje się do końca elementu):

$("#source").appendTo("#destination");

Alternatywnie możesz użyć prependTofunkcji (która dodaje się do początku elementu):

$("#source").prependTo("#destination");

Przykład:

Andrew Hare
źródło
23
Ostrzeżenie, że może to nie działać poprawnie w jQuery mobile, ponieważ może zamiast tego utworzyć kolejną kopię elementu.
Jordan Reiter,
32
czy appenTo tworzy kopię, czy faktycznie przenosi cały div do miejsca docelowego? (ponieważ jeśli kopiuje,
50
Oto doskonały artykuł na temat usuwania, zastępowania i przenoszenia elementów w jQuery: elated.com/articles/jquery-removing-replacing-moving-elements
xhh
42
Zwróć uwagę na dokumentację jQuery dla appendTo stwierdza, że ​​element został przeniesiony: it will be moved into the target (not cloned) and a new set consisting of the inserted element is returned- api.jquery.com/appendto
John K
15
Nie przenosisz go, tylko dołączasz. Poniższa odpowiedź zawiera właściwy ruch.
Aaron
913

moje rozwiązanie:

RUSZAJ SIĘ:

jQuery("#NodesToMove").detach().appendTo('#DestinationContainerNode')

KOPIUJ:

jQuery("#NodesToMove").appendTo('#DestinationContainerNode')

Zwróć uwagę na użycie .detach (). Podczas kopiowania uważaj, aby nie powielać identyfikatorów.

Alejandro Illecas
źródło
86
Najlepsza odpowiedź. Zaakceptowana odpowiedź tworzy kopię, nie przesuwa elementu tak, jak pyta pytanie.
paulscode
97
Przepraszamy, ale zaakceptowana odpowiedź Andrew Hare'a jest poprawna - odłączanie jest niepotrzebne. Wypróbuj to w JSFiddle Pixic powyżej - jeśli usuniesz wywołania detach, działa dokładnie tak samo, tzn. Wykonuje ruch, NIE kopiuje. Oto rozwidlenie z tylko jedną zmianą: jsfiddle.net/D46y5 Jak udokumentowano w interfejsie API: api.jquery.com/appendTo : „Jeśli element wybrany w ten sposób zostanie wstawiony w jedno miejsce w innym miejscu w DOM, zostanie on przeniesiony do celu (nie sklonowany) i zwracany jest nowy zestaw składający się z wstawionego elementu ”
John - Not A Number
8
@ John-NotANumber ma rację - detach () nie jest tutaj potrzebne. Przyjęta odpowiedź JEST najlepsza, wystarczy właściwie przeczytać dokumentację.
LeonardChallis,
11
Dokumentacja appendTo mówi również: „Jeśli istnieje więcej niż jeden element docelowy, sklonowane kopie wstawionego elementu zostaną utworzone dla każdego celu po pierwszym, a ten nowy zestaw (oryginalny element plus klony) zostanie zwrócony.”. Tak więc w ogólnym przypadku to rozwiązanie MOŻE również tworzyć kopie!
Vincent Pazeller
świetny! Możesz też użyć tego, aby sprecyzować, gdzie się przenieść$('#nodeToMove').insertAfter('#insertAfterThisElement');
Victor Augusto
108

Właśnie użyłem:

$('#source').prependTo('#destination');

Który stąd złapałem .

kjc26ster
źródło
7
Cóż, odłączanie jest przydatne, gdy chcesz zatrzymać element i włożyć go później, ale w twoim przykładzie i tak wstawiasz go natychmiast.
Tim Büthe,
1
Obawiam się, że nie do końca rozumiem, o co ci chodzi, czy możesz podać przykładowy kod?
kjc26ster,
1
Mam na myśli, prependTo, odłącza element od jego pierwotnej pozycji i wstawia go do nowego. Z drugiej strony funkcja odłączania po prostu odłącza wybrany element i można zapisać go w zmiennej, aby wstawić go do DOM w późniejszym czasie. Chodzi o to, że połączenie typu „odłącz” jest niepotrzebne. Usuń go, a osiągniesz ten sam efekt.
Tim Büthe,
1
Niesamowite, że zmiany całkowicie zmieniły tę odpowiedź do tego stopnia, że ​​rok później została dodana inna odpowiedź (identyczna z oryginałem) i uzyskała ponad 800 głosów pozytywnych ...
hlscalon
96

Co z rozwiązaniem JavaScript ?

// Declare a fragment:
var fragment = document.createDocumentFragment();

// Append desired element to the fragment:
fragment.appendChild(document.getElementById('source'));

// Append fragment to desired element:
document.getElementById('destination').appendChild(fragment);

Sprawdź to.

Ali Bassam
źródło
8
Dlaczego warto korzystać z createDocumentFragment zamiast po prostu document.getElementById ('destination'). AppendChild (document.getElementById ('source'))?
Gunar Gessner
6
@ GunarC.Gessner zakładając, że musisz zmodyfikować obiekt źródłowy przed dodaniem go do obiektu docelowego, wówczas najlepszym podejściem jest użycie fragmentu, który jest urojonym obiektem i nie jest częścią drzewa DOM, uzyskujesz lepszą wydajność podczas modyfikowania obiekt źródłowy, gdy został przeniesiony ze swojego pierwotnego miejsca (teraz znajduje się wewnątrz fragmentu) zamiast modyfikować go w swoim pierwotnym miejscu przed dołączeniem.
Ali Bassam,
5
Chcę dodać do znaczenia oferowania czystego rozwiązania JavaScript. Nie należy zakładać, że jQuery jest zawsze używane
Alexander Fradiani
1
Pytanie: Czy dołączając węzeł potomny tracimy dołączone zdarzenia?
jimasun
1
Odpowiedź na moje własne pytanie brzmi: tak, zachowuje załączone wydarzenia.
jimasun
95

Jeśli w divmiejscu, w którym chcesz umieścić element, znajduje się treść, a chcesz, aby element wyświetlał się po głównej zawartości:

  $("#destination").append($("#source"));

Jeśli w divmiejscu, w którym chcesz umieścić element, znajduje się zawartość, a chcesz pokazać element przed główną treścią:

$("#destination").prepend($("#source"));

Jeśli miejsce, w divktórym chcesz umieścić element, jest puste lub chcesz go całkowicie zastąpić :

$("#element").html('<div id="source">...</div>');

Jeśli chcesz powielić element przed którymkolwiek z powyższych:

$("#destination").append($("#source").clone());
// etc.
sbaaaang
źródło
Uważam, że cała pogrubiona czcionka jest nieco trudna do odczytania, ale jest to najbardziej pouczająca odpowiedź, więc zyskuje moje poparcie.
Michael Scheper
32

Możesz użyć:

Aby wstawić po,

jQuery("#source").insertAfter("#destination");

Aby wstawić do innego elementu,

jQuery("#source").appendTo("#destination");
Subrahmanyam
źródło
20

Jeśli chcesz mieć szybkie demo i więcej szczegółów na temat przenoszenia elementów, wypróbuj ten link:

http://html-tuts.com/move-div-in-another-div-with-jquery


Oto krótki przykład:

Aby przenieść POWYŻEJ elementu:

$('.whatToMove').insertBefore('.whereToMove');

Aby przejść PO elemencie:

$('.whatToMove').insertAfter('.whereToMove');

Aby poruszać się w elemencie, POWYŻEJ WSZYSTKIE elementy w tym kontenerze:

$('.whatToMove').prependTo('.whereToMove');

Aby poruszać się wewnątrz elementu, PO WSZYSTKICH elementach w tym kontenerze:

$('.whatToMove').appendTo('.whereToMove');
Dan
źródło
19

Możesz użyć następującego kodu, aby przenieść źródło do miejsca docelowego

 jQuery("#source")
       .detach()
       .appendTo('#destination');

spróbuj działać codepen

Subodh Ghulaxe
źródło
11

Stare pytanie, ale dotarłem tutaj, ponieważ muszę przenosić zawartość z jednego kontenera do drugiego, w tym wszystkich detektorów zdarzeń .

jQuery nie ma na to sposobu, ale robi to standardowa funkcja DOM appendChild.

//assuming only one .source and one .target
$('.source').on('click',function(){console.log('I am clicked');});
$('.target')[0].appendChild($('.source')[0]);

Użycie appendChild usuwa .source i umieszcza go w celu, w tym w detektorach zdarzeń: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild

HMR
źródło
6

Możesz także spróbować:

$("#destination").html($("#source"))

Ale to całkowicie zastąpi wszystko, co masz #destination.

Tamas
źródło
2
I przerywaj detektory zdarzeń na przeniesionym elemencie.
Igor Pomaranskiy
4

Zauważyłem ogromny przeciek pamięci i różnicę wydajności między insertAfteri afterlub insertBeforei before. Jeśli masz mnóstwo elementów DOM lub potrzebujesz użyć after()lub before()wewnątrz zdarzenia MouseMove , pamięć przeglądarki prawdopodobnie wzrośnie, a kolejne operacje będą przebiegać naprawdę wolno.

Rozwiązaniem, którego właśnie doświadczyłem, jest użycie insertBefore zamiast before()i insertAfter zamiast after().

spetsnaz
źródło
To brzmi jak problem związany z implementacją silnika JavaScript. W jakiej wersji przeglądarki i silniku JS to widzisz?
Mark Richman
1
Używam przeglądarki Chrome w wersji 36.0.1985.125 i korzystam z jQuery v1.11.1. W zdarzeniu mousemove wiążę funkcję, która przesuwa prosty DIV w dół lub w górę elementu, nad którym znajduje się mysz. Dlatego to zdarzenie i funkcja działają podczas przeciągania kursora. Wyciek pamięci występuje w przypadku funkcji after () i before (), jeśli przesuwasz kursor przez 30 sekund +, i znika, jeśli zamiast tego użyję insertAfter i insertBefore.
spetsnaz
1
W tym przypadku otworzyłbym błąd w Google.
Mark Richman
2

Możesz użyć czystego JavaScript, używając appendChild()metody ...

Metoda appendChild () dołącza węzeł jako ostatnie dziecko węzła.

Wskazówka: Jeśli chcesz utworzyć nowy akapit z tekstem, pamiętaj o utworzeniu tekstu jako węzła tekstowego, który dołączasz do akapitu, a następnie dołącz akapit do dokumentu.

Możesz także użyć tej metody, aby przenieść element z jednego elementu do drugiego.

Wskazówka: Użyj metody insertBefore (), aby wstawić nowy węzeł potomny przed określonym, istniejącym węzłem potomnym.

Aby to zrobić, możesz to zrobić, oto, co dla ciebie stworzyłem, używając appendChild(), uruchamiając i sprawdzając, jak to działa w twoim przypadku:

function appendIt() {
  var source = document.getElementById("source");
  document.getElementById("destination").appendChild(source);
}
#source {
  color: white;
  background: green;
  padding: 4px 8px;
}

#destination {
  color: white;
  background: red;
  padding: 4px 8px;
}

button {
  margin-top: 20px;
}
<div id="source">
  <p>Source</p>
</div>

<div id="destination">
  <p>Destination</p>
</div>

<button onclick="appendIt()">Move Element</button>

Alireza
źródło
0

Dla kompletności istnieje inne podejście wrap()lub wrapAll()wspomniane w tym artykule . Pytanie OP może więc zostać rozwiązane w ten sposób (tzn. Zakładając, że <div id="destination" />jeszcze nie istnieje, poniższe podejście utworzy takie opakowanie od zera - PO nie było jasne, czy opakowanie już istnieje, czy nie):

$("#source").wrap('<div id="destination" />')
// or
$(".source").wrapAll('<div id="destination" />')

Brzmi obiecująco. Jednak gdy próbowałem zrobić $("[id^=row]").wrapAll("<fieldset></fieldset>")na wielu zagnieżdżonych strukturach, takich jak to:

<div id="row1">
    <label>Name</label>
    <input ...>
</div>

To właściwie zawija te <div>...</div>i <input>...</input>ale jakoś pominięto <label>...</label>. Więc $("row1").append("#a_predefined_fieldset")zamiast tego użyłem jawnego . Więc YMMV.

RayLuo
źródło