Como mover um elemento para outro elemento?

1689

Eu gostaria de mover um elemento DIV para dentro de outro. Por exemplo, eu quero mover isso (incluindo todos os filhos):

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

nisso:

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

para que eu tenha isso:

<div id="destination">
  <div id="source">
    ...
  </div>
</div>
Mark Richman
fonte
21
Basta usar $ (target_element) .append (to_be_inserted_element);
Mohammad Areeb Siddiqui
2
Ou: destination.appendChild (origem) usando javascript simples
luke
podemos conseguir isso usando CSS? isso é possível ?
RajKumar Samala
6
O @RajKumarSamala CSS não pode alterar a estrutura do HTML, apenas sua apresentação.
Mark Richman

Respostas:

39

Já tentou JavaScript simples ... 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
fonte
* alguém prefixou o evento global onclick do snippet de demonstração com a palavra-chave varem sua tentativa de aprimorar a publicação - mas isso está errado!
Bekim Bacaj
6
É incrível como as pessoas ainda pensam que jQuery é igual a JavaScript. Não há mais necessidade de jQuery em 2017, realmente.
Nckollaw
2
não há necessidade de jquery em 2017, mas às vezes ajuda a usar algo mais leve e semelhante para tarefas que você se encontra fazendo repetidas vezes em cada projeto. Eu uso o cash-dom como uma maneira fácil de escutar os eventos document.ready, window.load de uma maneira amigável entre navegadores. mole-mole.
eballeste
1
Alterando isso para a resposta aceita, agora que é 2020 :)
Mark Richman
1
É incrível como as pessoas ainda pensam que jQuery é igual a JavaScript. Não há mais necessidade de jQuery em 2020, realmente.
ii iml0sto1 23/04
1794

Você pode querer usar a appendTofunção (que adiciona ao final do elemento):

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

Como alternativa, você pode usar a prependTofunção (que adiciona ao início do elemento):

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

Exemplo:

Andrew Hare
fonte
23
Um aviso de que isso pode não funcionar corretamente no jQuery mobile, pois pode criar outra cópia do elemento.
Jordan Reiter
32
o appenTo cria uma cópia ou realmente move toda a div para o destino? (porque se copia, criaria Erros ao chamar o div pela id)
50
Aqui está um excelente artigo sobre como remover, substituir e mover elementos no jQuery: elated.com/articles/jquery-removing-replacing-moving-elements
xhh
42
Observe a documentação do jQuery para os estados appendTo em que o elemento é movido: 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
Você não está movendo, apenas anexando. A resposta abaixo faz um bom MOVIMENTO.
Aaron
913

minha solução:

MOVER:

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

CÓPIA DE:

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

Observe o uso de .detach (). Ao copiar, tenha cuidado para não duplicar IDs.

Alejandro Illecas
fonte
86
Melhor resposta. A resposta aceita cria uma cópia, não move o elemento como a pergunta pede.
paulscode
97
Desculpe, mas a resposta aceita por Andrew Hare está correta - a remoção é desnecessária. Experimente no JSFiddle da Pixic acima - se você remover as chamadas de desanexação, funciona exatamente da mesma forma, ou seja, faz uma jogada, NÃO uma cópia. Aqui está a bifurcação com apenas uma alteração: jsfiddle.net/D46y5 Conforme documentado na API: api.jquery.com/appendTo : "Se um elemento selecionado dessa maneira for inserido em um único local em outro local do DOM, ele será movido no destino (não clonado) e um novo conjunto que consiste no elemento inserido é retornado "
John - Não é um número
8
@ John-NotANumber está certo - detach () não é necessário aqui. A resposta aceita é a melhor, você só precisa ler a documentação corretamente.
LeonardChallis 23/09
11
A documentação appendTo também diz: "Se houver mais de um elemento de destino, no entanto, cópias clonadas do elemento inserido serão criadas para cada destino após o primeiro e esse novo conjunto (o elemento original mais os clones) será retornado.". Portanto, no caso geral, esta solução também pode criar cópias!
Vincent Pazeller
ótimo! Ou você pode usar isso para ser mais específico sobre onde mover$('#nodeToMove').insertAfter('#insertAfterThisElement');
Victor Augusto
108

Eu apenas usei:

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

Que eu peguei daqui .

kjc26ster
fonte
7
Bem, desanexar é útil quando você deseja manter o elemento e reinseri-lo mais tarde, mas no seu exemplo, você o reinsere instantaneamente de qualquer maneira.
Tim Büthe
1
Receio não estar entendendo o que você está falando, você poderia fornecer um código de exemplo?
precisa saber é o seguinte
1
Quero dizer, prependTo, desconecta o elemento de sua posição original e o insere no novo. A função de desanexação, por outro lado, apenas desanexa o elemento selecionado e você pode salvá-lo em uma variável para inseri-lo no DOM posteriormente. O problema é que sua chamada de desanexação é desnecessária. Remova-o e você obterá o mesmo efeito.
Tim Büthe
1
Incrível que as edições mudou esta resposta completamente a tal ponto que uma outra resposta foi adicionado um ano depois (idêntico ao original) e tem mais de 800 upvotes ...
hlscalon
96

Que tal uma solução 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);

Confira.

Ali Bassam
fonte
8
Por que usar createDocumentFragment em vez de simplesmente document.getElementById ('destination'). AppendChild (document.getElementById ('source'))?
Gunar Gessner
6
@ GunarC.Gessner supondo que você precise modificar o objeto de origem antes de adicioná-lo ao objeto de destino, a melhor abordagem é usar o fragmento que é um objeto imaginário e não faz parte da árvore do DOM, você obtém um melhor desempenho ao modificar o objeto de origem quando ele foi transferido de seu local original (agora está dentro do fragmento) em vez de modificá-lo no local inicial antes de anexá-lo.
Ali Bassam
5
Quero acrescentar a relevância de oferecer uma solução pura para JavaScript. Não deve ser assumido jQuery está sempre sendo usado
Alexander Fradiani
1
Pergunta: Ao anexar o nó filho, estamos perdendo os eventos anexados?
jimasun
1
A resposta para minha própria pergunta é sim, ela mantém os eventos em anexo.
jimasun
95

Se o divlocal em que você deseja colocar seu elemento possui conteúdo e você deseja que o elemento seja exibido após o conteúdo principal:

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

Se o divlocal em que você deseja colocar seu elemento possui conteúdo e você deseja mostrar o elemento antes do conteúdo principal:

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

Se o divlocal em que você deseja colocar seu elemento estiver vazio, ou você desejar substituí- lo totalmente:

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

Se você deseja duplicar um elemento antes de qualquer uma das opções acima:

$("#destination").append($("#source").clone());
// etc.
sbaaaang
fonte
Estou achando um pouco difícil de ler todo o negrito, mas esta é a resposta mais informativa, por isso recebe meu voto positivo.
Michael Scheper
32

Você pode usar:

Para inserir depois,

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

Para inserir dentro de outro elemento,

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

Se você quiser uma demonstração rápida e mais detalhes sobre como mover elementos, tente este link:

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


Aqui está um pequeno exemplo:

Para mover ACIMA de um elemento:

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

Para mover APÓS um elemento:

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

Para mover-se dentro de um elemento, ACIMA DE TODOS os elementos dentro desse contêiner:

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

Para mover-se dentro de um elemento, APÓS TODOS os elementos dentro desse contêiner:

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

Você pode usar o seguinte código para mover a origem para o destino

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

tente trabalhar codepen

Subodh Ghulaxe
fonte
11

Pergunta antiga, mas cheguei aqui porque preciso mover o conteúdo de um contêiner para outro, incluindo todos os ouvintes do evento .

O jQuery não tem como fazê-lo, mas a função DOM padrão appendChild possui.

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

O uso de appendChild remove o .source e o coloca no destino, incluindo seus ouvintes de eventos: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild

HMR
fonte
6

Você também pode tentar:

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

Mas isso substituirá completamente tudo o que você possui #destination.

Tamas
fonte
2
E interrompa os ouvintes de eventos no elemento movido.
Igor Pomaranskiy
4

Percebi uma grande perda de memória e diferença de desempenho entre insertAfter& afterou insertBefore& before.. Se você possui vários elementos DOM ou precisa usar after()ou before()dentro de um evento MouseMove , a memória do navegador provavelmente aumentará e as próximas operações serão muito lentas.

A solução que acabei de experimentar é usar o insertBefore before()e depois o insertAfter after().

spetsnaz
fonte
Parece um problema dependente da implementação do mecanismo JavaScript. Com qual versão do navegador e mecanismo JS você vê isso?
Mark Richman
1
Estou na versão 36.0.1985.125 do Chrome e estou usando o jQuery v1.11.1. Vinculo uma função ao evento mousemove, que move um DIV simples para baixo ou para cima do elemento sobre o qual o mouse está. Portanto, esse evento e função é executado enquanto você arrasta o cursor. O vazamento de memória ocorre com after () e before (), se você mover o cursor por 30seg +, e desaparece se eu apenas usar insertAfter & insertBefore.
Spetsnaz
1
Eu abriria um bug com o Google nesse caso.
Mark Richman
2

Você pode usar JavaScript puro, usando o appendChild()método ...

O método appendChild () anexa um nó como o último filho de um nó.

Dica: Se você deseja criar um novo parágrafo, com texto, lembre-se de criar o texto como um nó Texto que você anexa ao parágrafo e, em seguida, anexa o parágrafo ao documento.

Você também pode usar esse método para mover um elemento de um elemento para outro.

Dica: Use o método insertBefore () para inserir um novo nó filho antes de um nó filho especificado e existente.

Para que você possa fazer isso, é isso que eu criei para você, usando appendChild(), execute e veja como funciona no seu 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
fonte
0

Por uma questão de integridade, há outra abordagem wrap()ou wrapAll()mencionada neste artigo . Portanto, a questão do OP poderia ser resolvida com isso (ou seja, assumindo <div id="destination" />que ainda não exista, a seguinte abordagem criará esse invólucro do zero - o OP não ficou claro se o invólucro já existe ou não):

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

Parece promissor. No entanto, quando eu estava tentando fazer $("[id^=row]").wrapAll("<fieldset></fieldset>")em várias estruturas aninhadas como esta:

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

Ela envolve corretamente os <div>...</div>e <input>...</input>mas de alguma forma deixa de fora a <label>...</label>. Então acabei usando o explícito $("row1").append("#a_predefined_fieldset"). Então, YMMV.

RayLuo
fonte
0

melhoria de tamanho sujo da resposta 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
fonte