¿Cómo mover un elemento a otro elemento?

1689

Me gustaría mover un elemento DIV dentro de otro. Por ejemplo, quiero mover esto (incluidos todos los niños):

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

dentro de esto:

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

para que tenga esto:

<div id="destination">
  <div id="source">
    ...
  </div>
</div>
Mark Richman
fuente
21
Simplemente use $ (target_element) .append (to_be_inserted_element);
Mohammad Areeb Siddiqui 27/0613
2
O bien: destination.appendChild (fuente) usando JavaScript simple
luke
¿podemos lograr esto usando CSS? es eso posible ?
RajKumar Samala
66
@RajKumarSamala CSS no puede alterar la estructura del HTML, solo su presentación.
Mark Richman

Respuestas:

39

¿Alguna vez has probado JavaScript simple ... 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
fuente
* alguien prefijo el evento global onclick del fragmento de demostración con la palabra clave varen su intento de mejorar la publicación, ¡pero está mal!
Bekim Bacaj
66
Es sorprendente cómo la gente todavía piensa que jQuery es igual a JavaScript. Ya no es necesario usar jQuery en 2017.
nkkollaw
2
no es necesario usar jquery en 2017, pero a veces ayuda usar algo más liviano y similar para las tareas que te encuentras haciendo una y otra vez en cada proyecto. Utilizo cash-dom como una manera fácil de escuchar eventos document.ready, window.load de una manera amigable para todos los navegadores. pan comido.
eballeste
1
Cambiando esto a la respuesta aceptada, ahora que es 2020 :)
Mark Richman
1
Es sorprendente cómo la gente todavía piensa que jQuery es igual a JavaScript. Ya no hay necesidad de jQuery en 2020, de verdad.
ii iml0sto1
1794

Es posible que desee utilizar la appendTofunción (que se agrega al final del elemento):

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

Alternativamente, podría usar la prependTofunción (que se agrega al comienzo del elemento):

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

Ejemplo:

Andrew Hare
fuente
23
Una advertencia de que esto puede no funcionar correctamente en jQuery mobile, ya que puede crear otra copia del elemento.
Jordan Reiter
32
¿el appenTo crea una copia o mueve todo el div al destino? (porque si se copia, crearía errores al llamar al div por la identificación)
50
Aquí hay un excelente artículo sobre Eliminar, reemplazar y mover elementos en jQuery: elated.com/articles/jquery-removing-replacing-moving-elements
xhh
42
Tenga en cuenta que la documentación de jQuery para appendTo indica que el elemento se mueve: 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
No lo estás moviendo, solo agregando. La siguiente respuesta hace un MOVIMIENTO apropiado.
Aaron
913

mi solución:

MOVERSE:

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

COPIAR:

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

Tenga en cuenta el uso de .detach (). Al copiar, tenga cuidado de no duplicar ID.

Alejandro Illecas
fuente
86
La mejor respuesta. La respuesta aceptada crea una copia, no mueve el elemento como pide la pregunta.
paulscode
97
Lo sentimos, pero la respuesta aceptada de Andrew Hare es correcta: la separación es innecesaria. Pruébelo en el JSFiddle de Pixic anterior: si elimina las llamadas de desconexión, funciona exactamente igual, es decir, hace un movimiento, NO una copia. Aquí está la bifurcación con solo ese cambio: jsfiddle.net/D46y5 Como se documenta en la API: api.jquery.com/appendTo : "Si un elemento seleccionado de esta manera se inserta en una sola ubicación en otra parte del DOM, se moverá en el objetivo (no clonado) y se devuelve un nuevo conjunto que consiste en el elemento insertado "
John - No es un número
8
@ John-NotANumber tiene razón: no se necesita detach () aquí. La respuesta aceptada es la mejor, solo necesita leer la documentación correctamente.
LeonardChallis
11
La documentación de appendTo también dice: "Si hay más de un elemento de destino, sin embargo, se crearán copias clonadas del elemento insertado para cada destino después del primero, y se devolverá ese nuevo conjunto (el elemento original más los clones)". Entonces, en el caso general, ¡esta solución también PUEDE crear copias!
Vincent Pazeller
¡estupendo! O puede usar esto para ser más específico sobre dónde moverse$('#nodeToMove').insertAfter('#insertAfterThisElement');
Victor Augusto el
108

Acabo de usar:

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

Lo que agarré de aquí .

kjc26ster
fuente
77
Bueno, la desconexión es útil cuando desea retener el elemento y volver a insertarlo más tarde, pero en su ejemplo lo reinsertará instantáneamente de todos modos.
Tim Büthe
1
Me temo que no estoy asimilando lo que estás diciendo, ¿podrías proporcionar un código de muestra?
kjc26ster
1
Quiero decir, prependTo, separa el elemento de su posición original y lo inserta en el nuevo. Por otro lado, la función de desconexión simplemente separa el elemento seleccionado y puede guardarlo en una variable para insertarlo en el DOM en un momento posterior. La cuestión es que su llamada de desconexión es innecesaria. Elimínalo y lograrás el mismo efecto.
Tim Büthe el
1
Increíble que las modificaciones cambiaron esta respuesta por completo hasta el punto de que otra respuesta se añadió un año más tarde (idéntica a la original) y consiguieron más de 800 upvotes ...
hlscalon
96

¿Qué pasa con una solución de 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);

Echale un vistazo.

Ali Bassam
fuente
8
¿Por qué usar createDocumentFragment en lugar de simplemente document.getElementById ('destino'). AppendChild (document.getElementById ('fuente'))?
Gunar Gessner
66
@ GunarC.Gessner, suponiendo que necesite modificar el objeto fuente antes de agregarlo al objeto de destino, entonces el mejor enfoque es usar el fragmento que es un objeto imaginario y no es parte del árbol DOM, obtiene un mejor rendimiento al modificar el objeto de origen cuando se ha hecho la transición desde su lugar original (ahora está dentro del fragmento) en lugar de modificarlo en su lugar inicial antes de agregarlo.
Ali Bassam
55
Quiero agregar por la relevancia de ofrecer una solución pura de JavaScript. No se debe suponer que jQuery siempre se usa
Alexander Fradiani
1
Pregunta: Al agregar el nodo hijo, ¿estamos perdiendo los eventos adjuntos?
jimasun
1
La respuesta a mi propia pregunta es sí, mantiene los eventos adjuntos.
jimasun
95

Si el lugar divdonde desea colocar su elemento tiene contenido dentro y desea que el elemento se muestre después del contenido principal:

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

Si el lugar divdonde desea colocar su elemento tiene contenido adentro y desea mostrar el elemento antes del contenido principal:

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

Si el lugar divdonde desea colocar su elemento está vacío, o si desea reemplazarlo por completo:

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

Si desea duplicar un elemento antes de cualquiera de los anteriores:

$("#destination").append($("#source").clone());
// etc.
sbaaaang
fuente
Me parece un poco difícil leer todas las letras en negrita, pero esta es la respuesta más informativa, por lo que recibe mi voto positivo.
Michael Scheper
32

Puedes usar:

Para insertar después,

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

Para insertar dentro de otro elemento,

jQuery("#source").appendTo("#destination");
Subrahmanyam
fuente
20

Si desea una demostración rápida y más detalles sobre cómo mover elementos, pruebe este enlace:

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


Aquí hay un breve ejemplo:

Para mover ARRIBA un elemento:

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

Para moverse DESPUÉS de un elemento:

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

Para moverse dentro de un elemento, ARRIBA TODOS los elementos dentro de ese contenedor:

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

Para moverse dentro de un elemento, DESPUÉS DE TODOS los elementos dentro de ese contenedor:

$('.whatToMove').appendTo('.whereToMove');
Dan
fuente
19

Puede usar el siguiente código para mover el origen al destino

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

intente trabajar codepen

Subodh Ghulaxe
fuente
11

Antigua pregunta, pero llegó aquí porque necesito mover el contenido de un contenedor a otro, incluidos todos los oyentes de eventos .

jQuery no tiene una forma de hacerlo, pero la función DOM estándar appendChild sí.

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

El uso de appendChild elimina el .source y lo coloca en el destino, incluidos sus oyentes de eventos: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild

HMR
fuente
6

También puedes probar:

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

Pero esto sobrescribirá completamente todo lo que tenga #destination.

Tamas
fuente
2
Y rompa los oyentes de eventos en el elemento movido.
Igor Pomaranskiy
4

Noté una gran pérdida de memoria y una diferencia de rendimiento entre insertAfter& aftero insertBefore& before.. Si tiene toneladas de elementos DOM, o necesita usar after()o before()dentro de un evento MouseMove , la memoria del navegador probablemente aumentará y las próximas operaciones se ejecutarán muy lentamente.

La solución que acabo de experimentar es usar inserBefore en su lugar before()e insertAfter en su lugar after().

Spetsnaz
fuente
Esto suena como un problema dependiente de la implementación del motor JavaScript. ¿Con qué versión de navegador y motor JS ves esto?
Mark Richman
1
Estoy en la versión 36.0.1985.125 de Chrome y estoy usando jQuery v1.11.1. Ato una función en el evento mousemove, que mueve un DIV simple hacia arriba o hacia abajo sobre el elemento sobre el que está el mouse. Por lo tanto, este evento y función se ejecuta mientras arrastra el cursor. La pérdida de memoria ocurre con after () y before (), si mueve el cursor durante 30 segundos +, y desaparece si solo uso insertAfter & insertBefore en su lugar.
spetsnaz
1
Abriría un error con Google en eso.
Mark Richman
2

Puedes usar JavaScript puro, usando el appendChild()método ...

El método appendChild () agrega un nodo como el último hijo de un nodo.

Consejo: Si desea crear un nuevo párrafo, con texto, recuerde crear el texto como un nodo de texto que agregue al párrafo, luego agregue el párrafo al documento.

También puede usar este método para mover un elemento de un elemento a otro.

Consejo: Utilice el método insertBefore () para insertar un nuevo nodo secundario antes de un nodo secundario específico existente.

Entonces puede hacer eso para hacer el trabajo, esto es lo que creé para usted, usar appendChild(), ejecutar y ver cómo funciona para su caso:

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
fuente
0

En aras de la exhaustividad, hay otro enfoque wrap()o wrapAll()mencionado en este artículo . Por lo tanto, la pregunta del OP podría resolverse de esta manera (es decir, suponiendo <div id="destination" />que aún no exista, el siguiente enfoque creará un contenedor de este tipo desde cero: el OP no tenía claro si el contenedor ya existe o no):

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

Suena prometedor Sin embargo, cuando intentaba hacer $("[id^=row]").wrapAll("<fieldset></fieldset>")en múltiples estructuras anidadas como esta:

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

Los envuelve correctamente <div>...</div>y <input>...</input>PERO ALGUNA DEJA EL <label>...</label>. Así que terminé usando el explícito en su $("row1").append("#a_predefined_fieldset")lugar. Entonces, YMMV.

RayLuo
fuente
0

mejora del tamaño sucio de la respuesta de Bekim Bacaj

div { border: 1px solid ; margin: 5px }
<div id="source" onclick="destination.appendChild(this)">click me</div>
<div id="destination" >...</div>

Kamil Kiełczewski
fuente