Existe insertBefore()
em JavaScript, mas como posso inserir um elemento após outro sem usar o jQuery ou outra biblioteca?
Existe insertBefore()
em JavaScript, mas como posso inserir um elemento após outro sem usar o jQuery ou outra biblioteca?
Respostas:
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
Onde referenceNode
está o nó que você deseja colocar newNode
depois. Se referenceNode
é o último filho dentro de seu elemento pai, tudo bem, porque referenceNode.nextSibling
será null
e insertBefore
lida com esse caso, adicionando ao final da lista.
Assim:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
Você pode testá-lo usando o seguinte snippet:
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>
insertBefore()
trabalha com nós de texto. Por que você quer insertAfter()
ser diferente? Você deve criar um par separado de funções nomeadas insertBeforeElement()
e insertAfterElement()
para isso.
Anexar antes:
element.parentNode.insertBefore(newElement, element);
Anexar após:
element.parentNode.insertBefore(newElement, element.nextSibling);
Ao criar os seguintes protótipos, você poderá chamar essas funções diretamente dos 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 .appendAfter (elemento)
Element.prototype.appendAfter = function (element) {
element.parentNode.insertBefore(this, element.nextSibling);
},false;
existingElement.appendAfter(newElement);
. Veja o que quero dizer neste jsfiddle atualizado .
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
De cabeça para baixo:
insertBefore
(quebra mesmo se o nome da variável do nó existente tiver 3 caracteres)Desvantagens:
outerHTML
converte o elemento em uma sequência. Precisamos disso porque insertAdjacentHTML
adiciona conteúdo de strings em vez de elementos..insertAdjacentElement()
Uma rápida pesquisa no Google revela esse script
// 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);
}
}
targetElement.nextSibling
retornará null
. Quando node.insertBefore
é chamado com null
o segundo argumento, ele adiciona o nó no final da coleção. Em outras palavras, o if(parent.lastchild == targetElement) {
ramo é supérfluo, porque parent.insertBefore(newElement, targetElement.nextSibling);
lidará adequadamente com todos os casos, mesmo que pareça de outra forma à primeira vista. Muitos já apontaram isso em outros comentários.
Embora insertBefore()
(consulte MDN ) seja ótimo e faça referência à maioria das respostas aqui. Para maior flexibilidade e para ser um pouco mais explícito, você pode usar:
insertAdjacentElement()
(consulte MDN ) Permite fazer referência a qualquer elemento e inserir o elemento a ser movido exatamente para onde você deseja:
<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
<!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
... content ...
<!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->
Outros a serem considerados para casos de uso semelhantes: insertAdjacentHTML()
einsertAdjacentText()
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
( doc ) insere um nó após outro nó.
Para dois nós DOM node1
e node2
,
node1.after(node2)
insere node2
depois node1
.
Esse método não está disponível em navegadores mais antigos; portanto, geralmente é necessário um polyfill.
Eu sei que essa pergunta é antiga, mas para qualquer usuário futuro, aqui está um protótipo modificado, este é apenas um micro-preenchimento para a função .insertAfter que não existe, esse protótipo adiciona diretamente uma nova função baseElement.insertAfter(element);
ao protótipo Element:
Element.prototype.insertAfter = function(new) {
this.parentNode.insertBefore(new, this.nextSibling);
}
Depois de colocar o polyfill em uma biblioteca, essência ou apenas no seu código (ou em qualquer outro lugar onde ele possa ser referenciado), basta escrever document.getElementById('foo').insertAfter(document.createElement('bar'));
Nova edição: você não deve usar protótipos. Eles substituem 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, isso não deve importar. Se você deseja uma função segura para uso comercial, basta usar uma função padrão. 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
Padrões da Web atuais para ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode
Está atualmente nos padrões vivos e é SEGURO.
Para navegadores não suportados, use este Polyfill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js
Alguém mencionou que o Polyfill usa Protos, quando eu disse que eram más práticas. Eles são, especialmente quando usados incorretamente, como minha solução para 2018. No entanto, esse polyfill está na documentação do MDN e usa um tipo de inicialização e execução mais segura. Além disso, é para suporte a navegadores mais antigos, nos dias em que a substituição de protótipo não era tão ruim.
Como usar a solução 2020:
const el = document.querySelector(".class");
// Create New Element
const newEl = document.createElement("div");
newEl.id = "foo";
// Insert New Element BEFORE
el.before(newEl);
// Insert New Element AFTER
el.after(newEl);
// Remove Element
el.remove();
// Remove Child
newEl.remove(); // This one wasnt tested but should work
Ou você pode simplesmente fazer:
referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
Etapa 1. Prepare elementos:
var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;
Etapa 2. Anexar após:
elementParent.insertBefore(newElement, element.nextSibling);
O método insertBefore () é usado como parentNode.insertBefore()
. Então, para imitar isso e criar 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>
Observe que estender o DOM pode não ser a solução certa para você, conforme declarado neste artigo .
No entanto, este artigo foi escrito em 2010 e as coisas podem ser diferentes agora. Então, decida por si próprio.
Idealmente, insertAfter
deve funcionar de forma semelhante ao insertBefore . O código abaixo fará o seguinte:
Node
será anexadoNode
, o novo Node
será anexadoNode
após a referência Node
, o novo Node
será anexadoNode
tiver um irmão depois, o novo Node
será inserido antes desse irmãoNode
Estendendo 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
Eu sei que esta pergunta já tem muitas respostas, mas nenhuma delas atendeu exatamente aos meus requisitos.
Eu queria uma função que tivesse exatamente o comportamento oposto deparentNode.insertBefore
- isto é, ela deve aceitar um nulo referenceNode
(o qual a resposta aceita não) e onde insertBefore
seria inserida no final dos filhos, que esta deve ser inserida no início , pois caso contrário haverá ' d não há como inserir no local inicial com esta função; o mesmo motivo é insertBefore
inserido no final.
Como um nulo referenceNode
exige que você localize o pai, precisamos conhecê-lo - insertBefore
é um método doparentNode
, para que ele tenha acesso ao pai dessa maneira; como nossa função não funciona, precisamos passar o pai como parâmetro.
A função resultante é assim:
function insertAfter(parentNode, newNode, referenceNode) {
parentNode.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : parentNode.firstChild
);
}
Ou (se você precisar, eu não recomendo), é claro que você pode aprimorar o Node
protótipo:
if (! Node.prototype.insertAfter) {
Node.prototype.insertAfter = function(newNode, referenceNode) {
this.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : this.firstChild
);
};
}
Este código é um trabalho para inserir um item de link logo após o último filho existente para incluir um pequeno arquivo 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);
Você pode usar appendChild
função para inserir após um elemento.
Referência: http://www.w3schools.com/jsref/met_node_appendchild.asp
uma implementação robusta do 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'."));
};
Vamos lidar com todos os cenários
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);
};
}
Você pode realmente usar 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, ele move o elemento para cima após o elemento para baixo