Como inserir um elemento após outro elemento em JavaScript sem usar uma biblioteca?
Há insertBefore()
em JavaScript, mas como posso inserir um elemento Depois de Outro elemento sem usar o jQuery ou outra biblioteca?
19 answers
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
Onde referenceNode
é o nó que queres colocar newNode
depois. Se referenceNode
for a última criança dentro do seu elemento pai, tudo bem, porque referenceNode.nextSibling
será null
e insertBefore
lida com esse caso adicionando ao final da lista.
Então:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
Pode testá-lo usando o seguinte trecho:
function insertAfter(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
var el = document.createElement("span");
el.innerHTML = "test";
var div = document.getElementById("foo");
insertAfter(div, el);
<div id="foo">Hello</div>
JavaScript simples seria o seguinte:
Adicionar Antes:
element.parentNode.insertBefore(newElement, element);
Adicionar Depois:
element.parentNode.insertBefore(newElement, element.nextSibling);
Mas, atira alguns protótipos para lá para facilitar a sua utilização {[[11]}
Ao construir os seguintes protótipos, você será capaz de chamar estas funções diretamente a partir de elementos recém-criados.
newElement.appendBefore(element);
newElement.appendAfter(element);
.appendBefore (elemento) Protótipo
Element.prototype.appendBefore = function (element) {
element.parentNode.insertBefore(this, element);
},false;
.protótipo do apêndice (elemento)
Element.prototype.appendAfter = function (element) {
element.parentNode.insertBefore(this, element.nextSibling);
},false;
E, para ver tudo em acção, execute o seguinte excerto de código
/* Adds Element BEFORE NeighborElement */
Element.prototype.appendBefore = function(element) {
element.parentNode.insertBefore(this, element);
}, false;
/* Adds Element AFTER NeighborElement */
Element.prototype.appendAfter = function(element) {
element.parentNode.insertBefore(this, element.nextSibling);
}, false;
/* Typical Creation and Setup A New Orphaned Element Object */
var NewElement = document.createElement('div');
NewElement.innerHTML = 'New Element';
NewElement.id = 'NewElement';
/* Add NewElement BEFORE -OR- AFTER Using the Aforementioned Prototypes */
NewElement.appendAfter(document.getElementById('Neighbor2'));
div {
text-align: center;
}
#Neighborhood {
color: brown;
}
#NewElement {
color: green;
}
<div id="Neighborhood">
<div id="Neighbor1">Neighbor 1</div>
<div id="Neighbor2">Neighbor 2</div>
<div id="Neighbor3">Neighbor 3</div>
</div>
Põe no JSFiddle.
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
Uppsides:
- Secador: não é necessário armazenar o nó anterior numa variável e usá-lo duas vezes. Se você mudar o nome da variável, em menor ocorrência para modificar.
- o golfe é melhor que o
insertBefore
(quebra mesmo que o nome da variável do nó existente tenha 3 caracteres de comprimento)
Desvantagens:
- suporte de navegador mais baixo desde o mais recente: https://caniuse.com/#feat=insert-adjacent
- vai perder propriedades do elemento como eventos Porque
outerHTML
converte o elemento para uma cadeia de caracteres. Precisamos dele porqueinsertAdjacentHTML
adiciona conteúdo de cadeias de caracteres em vez de elementos.
Uma pesquisa rápida no Google revela Este programa
// create function, it expects 2 values.
function insertAfter(newElement,targetElement) {
// target is what you want it to go after. Look for this elements parent.
var parent = targetElement.parentNode;
// if the parents lastchild is the targetElement...
if (parent.lastChild == targetElement) {
// add the newElement after the target element.
parent.appendChild(newElement);
} else {
// else the target has siblings, insert the new element between the target and it's next sibling.
parent.insertBefore(newElement, targetElement.nextSibling);
}
}
Embora insertBefore()
(ver MDN) seja grande e referenciado pela maioria das respostas aqui. Para maior flexibilidade, e para ser um pouco mais explícito, você pode usar:
insertAdjacentElement()
(Veja MDN ) isto permite-lhe referenciar qualquer elemento e inserir o elemento a mover exactamente onde quiser:
<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
<!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
... content ...
<!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->
Outros a considerar para casos de Utilização semelhante: insertAdjacentHTML()
e insertAdjacentText()
Referências:
Https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentText
O método node.after
(o doc insere um nó após outro nó.
Para dois nós DOM node1
e node2
,
node1.after(node2)
insere node2
Depois de node1
.
Este método não está disponível em navegadores mais antigos, por isso normalmente é necessário um polifill.
Solução de 2018 (má prática, ir para 2020)
Eu sei que esta pergunta é antiga, mas para qualquer utilizador futuro, é um protótipo modificado. isto é apenas um micro polifill para o.inserir uma função após a qual não existe este protótipo adiciona directamente uma nova funçãobaseElement.insertAfter(element);
ao protótipo do elemento:
Element.prototype.insertAfter = function(new) {
this.parentNode.insertBefore(new, this.nextSibling);
}
Uma vez que você colocou o polifill em uma biblioteca, gist, ou apenas em seu código (ou em qualquer outro lugar onde ele pode ser referenciado)
Escreve.document.getElementById('foo').insertAfter(document.createElement('bar'));
Solução de 2019 (feio, ir para 2020)
Não deve utilizar protótipos. Eles sobrepõem a base de código padrão e não são muito eficientes ou seguros e podem causar erros de compatibilidade, mas se for para projetos não comerciais, não deve importar. Se quiser uma função segura para uso comercial, basta usar uma função predefinida. não é bonito, mas funciona.:
function insertAfter(el, newEl) {
el.parentNode.insertBefore(newEl, this.nextSibling);
}
// use
const el = document.body || document.querySelector("body");
// the || means "this OR that"
el.insertBefore(document.createElement("div"), el.nextSibling);
// Insert Before
insertAfter(el, document.createElement("div"));
// Insert After
Solução para 2020
Normas Web actuais para ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode
Está actualmente no nível de vida e é seguro.Para Navegadores não suportados, use este Polifill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js
Alguém mencionou que o Polifill usa Protos, quando eu disse que eram más práticas. Eles são, especialmente quando eles são usados cegamente e overwrited, como com a minha solução 2018. No entanto, o polifill Está ligado a documentação MDN e usa um tipo de inicialização e execução que é mais seguro.
Como utilizar a solução 2020:
// Parent Element
const el = document.querySelector(".class");
// Create New Element
const newEl = document.createElement("div");
newEl.id = "foo";
// Insert New Element BEFORE an Element
el.before(newEl);
// Insert New Element AFTER an Element
el.after(newEl);
// Remove an Element
el.remove();
// Even though it’s a created element,
// newEl is still a reference to the HTML,
// so using .remove() on it should work
// if you have already appended it somewhere
newEl.remove();
Ou podes simplesmente fazer:
referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
Passo 1. Preparar Os Elementos :
var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;
Passo 2. Adicionar depois :
elementParent.insertBefore(newElement, element.nextSibling);
O método InsertBefore () é usado como parentNode.insertBefore()
.
Então para imitar isso e fazer um método parentNode.insertAfter()
podemos escrever o seguinte código.
JavaScript
Node.prototype.insertAfter = function(newNode, referenceNode) {
return referenceNode.parentNode.insertBefore(
newNode, referenceNode.nextSibling); // based on karim79's solution
};
// getting required handles
var refElem = document.getElementById("pTwo");
var parent = refElem.parentNode;
// creating <p>paragraph three</p>
var txt = document.createTextNode("paragraph three");
var paragraph = document.createElement("p");
paragraph.appendChild(txt);
// now we can call it the same way as insertBefore()
parent.insertAfter(paragraph, refElem);
HTML
<div id="divOne">
<p id="pOne">paragraph one</p>
<p id="pTwo">paragraph two</p>
</div>
Note que estender o DOM pode não ser a solução certa para si, tal como indicado em Este artigo.
Hovewer, este artigo foi escrito em 2010 e as coisas podem ser diferentes agora. Então decide por ti.Esta é a maneira mais simples de adicionar um elemento depois de outro usando vanilla javascript
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
Referência: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
Idealmente insertAfter
deveria funcionar de forma semelhante ainsertbeefore . O código abaixo irá executar o seguinte:
- Se não houver crianças, o novo
Node
é adicionado - Se não houver referência
Node
, o novoNode
é adicionado - Se não houver
Node
após a referênciaNode
, o novoNode
é adicionado - se a referência
Node
tiver um irmão depois, então o novoNode
é inserido antes desse irmão - Devolve o novo
Node
Prorrogação Node
Node.prototype.insertAfter = function(node, referenceNode) {
if (node)
this.insertBefore(node, referenceNode && referenceNode.nextSibling);
return node;
};
Um exemplo comum
node.parentNode.insertAfter(newNode, node);
Veja o código em execução
// First extend
Node.prototype.insertAfter = function(node, referenceNode) {
if (node)
this.insertBefore(node, referenceNode && referenceNode.nextSibling);
return node;
};
var referenceNode,
newNode;
newNode = document.createElement('li')
newNode.innerText = 'First new item';
newNode.style.color = '#FF0000';
document.getElementById('no-children').insertAfter(newNode);
newNode = document.createElement('li');
newNode.innerText = 'Second new item';
newNode.style.color = '#FF0000';
document.getElementById('no-reference-node').insertAfter(newNode);
referenceNode = document.getElementById('no-sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Third new item';
newNode.style.color = '#FF0000';
referenceNode.parentNode.insertAfter(newNode, referenceNode);
referenceNode = document.getElementById('sibling-after');
newNode = document.createElement('li');
newNode.innerText = 'Fourth new item';
newNode.style.color = '#FF0000';
referenceNode.parentNode.insertAfter(newNode, referenceNode);
<h5>No children</h5>
<ul id="no-children"></ul>
<h5>No reference node</h5>
<ul id="no-reference-node">
<li>First item</li>
</ul>
<h5>No sibling after</h5>
<ul>
<li id="no-sibling-after">First item</li>
</ul>
<h5>Sibling after</h5>
<ul>
<li id="sibling-after">First item</li>
<li>Third item</li>
</ul>
Eu queria uma função que tem exatamente o oposto do comportamento de parentNode.insertBefore
- que é, ele deve aceitar um valor nulo referenceNode
(que o aceitas respostas não) e que insertBefore
irá inserir no end dos filhos isso deve-se inserir no iniciar, pois de outra forma não haveria maneira de inserir no local de início com esta função em todos; a mesma razão insertBefore
insere no fim.
Uma vez que um null referenceNode
requer que você localize o pai, precisamos saber que o pai - insertBefore
é um método do parentNode
, por isso tem acesso ao pai dessa forma; a nossa função não, por isso teremos de passar o pai como um parâmetro.
A função resultante é assim:
function insertAfter(parentNode, newNode, referenceNode) {
parentNode.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : parentNode.firstChild
);
}
Ou (se for preciso, não o recomendo) podes, claro, melhorar o protótipo Node
:
if (! Node.prototype.insertAfter) {
Node.prototype.insertAfter = function(newNode, referenceNode) {
this.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : this.firstChild
);
};
}
Você pode realmente um método chamado after()
na versão mais recente do Chrome, Firefox e Opera. A desvantagem deste método é que o Internet Explorer ainda não o suporta.
Exemplo:
// You could create a simple node
var node = document.createElement('p')
// And then get the node where you want to append the created node after
var existingNode = document.getElementById('id_of_the_element')
// Finally you can append the created node to the exisitingNode
existingNode.after(node)
Um código HTML simples para testar que é:
<!DOCTYPE html>
<html>
<body>
<p id='up'>Up</p>
<p id="down">Down</p>
<button id="switchBtn" onclick="switch_place()">Switch place</button>
<script>
function switch_place(){
var downElement = document.getElementById("down")
var upElement = document.getElementById("up")
downElement.after(upElement);
document.getElementById('switchBtn').innerHTML = "Switched!"
}
</script>
</body>
</html>
Como esperado, move o elemento para cima após o elemento para baixo
Este código é trabalho para inserir um item de ligação logo após a última criança existente para inlining {[4] } um pequeno ficheiro css
var raf, cb=function(){
//create newnode
var link=document.createElement('link');
link.rel='stylesheet';link.type='text/css';link.href='css/style.css';
//insert after the lastnode
var nodes=document.getElementsByTagName('link'); //existing nodes
var lastnode=document.getElementsByTagName('link')[nodes.length-1];
lastnode.parentNode.insertBefore(link, lastnode.nextSibling);
};
//check before insert
try {
raf=requestAnimationFrame||
mozRequestAnimationFrame||
webkitRequestAnimationFrame||
msRequestAnimationFrame;
}
catch(err){
raf=false;
}
if (raf)raf(cb); else window.addEventListener('load',cb);
Pode usar a função appendChild
para inserir depois de um elemento.
Referência: http://www.w3schools.com/jsref/met_node_appendchild.asp
function insertAfter(newNode, referenceNode) {
if(referenceNode && referenceNode.nextSibling && referenceNode.nextSibling.nodeName == '#text')
referenceNode = referenceNode.nextSibling;
if(!referenceNode)
document.body.appendChild(newNode);
else if(!referenceNode.nextSibling)
document.body.appendChild(newNode);
else
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
if( !Element.prototype.insertAfter ) {
Element.prototype.insertAfter = function(item, reference) {
if( reference.nextSibling )
reference.parentNode.insertBefore(item, reference.nextSibling);
else
reference.parentNode.appendChild(item);
};
}
Uma implementação robusta de "insertAfter".
// source: https://github.com/jserz/domPlus/blob/master/src/insertAfter()/insertAfter.js
Node.prototype.insertAfter = Node.prototype.insertAfter || function (newNode, referenceNode) {
function isNode(node) {
return node instanceof Node;
}
if(arguments.length < 2){
throw(new TypeError("Failed to execute 'insertAfter' on 'Node': 2 arguments required, but only "+ arguments.length +" present."));
}
if(isNode(newNode)){
if(referenceNode === null || referenceNode === undefined){
return this.insertBefore(newNode, referenceNode);
}
if(isNode(referenceNode)){
return this.insertBefore(newNode, referenceNode.nextSibling);
}
throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 2 is not of type 'Node'."));
}
throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 1 is not of type 'Node'."));
};