Existe insertBefore()
en JavaScript, pero ¿cómo puedo insertar un elemento después de otro elemento sin usar jQuery u otra biblioteca?
Existe insertBefore()
en JavaScript, pero ¿cómo puedo insertar un elemento después de otro elemento sin usar jQuery u otra biblioteca?
Respuestas:
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
¿Dónde referenceNode
está el nodo que quieres poner newNode
después? Si referenceNode
es el último hijo dentro de su elemento padre, está bien, porque referenceNode.nextSibling
lo será null
y insertBefore
manejará ese caso al agregarlo al final de la lista.
Entonces:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
Puede probarlo con el siguiente fragmento:
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()
trabaja con nodos de texto. ¿Por qué quieres insertAfter()
ser diferente? Debería crear un par separado de funciones con el nombre insertBeforeElement()
y insertAfterElement()
para eso.
Añadir antes:
element.parentNode.insertBefore(newElement, element);
Añadir después:
element.parentNode.insertBefore(newElement, element.nextSibling);
Al construir los siguientes prototipos, podrá llamar a estas funciones directamente desde los elementos recién creados.
newElement.appendBefore(element);
newElement.appendAfter(element);
.appendBefore (elemento) Prototipo
Element.prototype.appendBefore = function (element) {
element.parentNode.insertBefore(this, element);
},false;
.appendAfter (elemento) Prototipo
Element.prototype.appendAfter = function (element) {
element.parentNode.insertBefore(this, element.nextSibling);
},false;
existingElement.appendAfter(newElement);
. Vea lo que quiero decir en este jsfiddle actualizado .
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
Upsides:
insertBefore
(descanso incluso si el nombre de la variable de nodo existente es de 3 caracteres de largo)Desventajas:
outerHTML
convierte el elemento en una cadena. Lo necesitamos porque insertAdjacentHTML
agrega contenido de cadenas en lugar de elementos..insertAdjacentElement()
Una búsqueda rápida en Google revela este 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
regresará null
. Cuando node.insertBefore
se llama con null
su segundo argumento, agregará el nodo al final de la colección. En otras palabras, la if(parent.lastchild == targetElement) {
rama es superflua, porque parent.insertBefore(newElement, targetElement.nextSibling);
se ocupará adecuadamente de todos los casos, aunque al principio parezca lo contrario. Muchos ya lo han señalado en otros comentarios.
Aunque insertBefore()
(ver MDN ) es excelente y se hace referencia en la mayoría de las respuestas aquí. Para mayor flexibilidad y para ser un poco más explícito, puede usar:
insertAdjacentElement()
(ver MDN ) Esto le permite hacer referencia a cualquier elemento e insertar el elemento a mover exactamente donde lo desee:
<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
<!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
... content ...
<!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->
Otros a tener en cuenta para casos de uso similares: insertAdjacentHTML()
yinsertAdjacentText()
Referencias
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdarestElement https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdarestHTML https: // developer.mozilla.org/en-US/docs/Web/API/Element/insertAdarestText
El método node.after
( doc ) inserta un nodo después de otro nodo.
Para dos nodos DOM node1
y node2
,
node1.after(node2)
inserta node2
después node1
.
Este método no está disponible en navegadores antiguos, por lo que generalmente se necesita un polyfill.
Sé que esta pregunta es antigua, pero para cualquier usuario futuro, aquí hay un prototipo modificado, esto es solo un micro polyfill para la función .insertAfter que no existe, este prototipo agrega directamente una nueva función baseElement.insertAfter(element);
al prototipo Element:
Element.prototype.insertAfter = function(new) {
this.parentNode.insertBefore(new, this.nextSibling);
}
Una vez que haya colocado el polyfill en una biblioteca, gist, o simplemente en su código (o en cualquier otro lugar donde pueda ser referenciado) Simplemente escriba document.getElementById('foo').insertAfter(document.createElement('bar'));
Nueva edición: NO DEBE USAR LOS PROTOTIPOS. Sobrescriben la base de código predeterminada y no son muy eficientes o seguros y pueden causar errores de compatibilidad, pero si es para proyectos no comerciales, no debería importar. Si desea una función segura para uso comercial, utilice una función predeterminada. no es bonito pero 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
Estándares web actuales para ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode
Actualmente está en los estándares de vida y es SEGURO.
Para navegadores no compatibles, use este Polyfill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js
Alguien mencionó que Polyfill usa Protos, cuando dije que eran malas prácticas. Lo son, especialmente cuando se usan incorrectamente, como mi solución para 2018. Sin embargo, ese polyfill está en la documentación de MDN y usa un tipo de inicialización y ejecución que es más seguro. Además, ES para soporte de navegador antiguo, en la época en que la sobrescritura de prototipos no era tan mala.
Cómo usar la Solución 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
O simplemente puedes hacer:
referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
Paso 1. Preparar elementos:
var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;
Paso 2. Agregar después de:
elementParent.insertBefore(newElement, element.nextSibling);
El método insertBefore () se usa como parentNode.insertBefore()
. Entonces, para imitar esto y hacer un método parentNode.insertAfter()
, podemos escribir el siguiente 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>
Tenga en cuenta que extender el DOM podría no ser la solución adecuada para usted, como se indica en este artículo .
Sin embargo, este artículo fue escrito en 2010 y las cosas pueden ser diferentes ahora. Así que decide por tu cuenta.
Idealmente insertAfter
debería funcionar de manera similar a insertBefore . El siguiente código realizará lo siguiente:
Node
se agrega el nuevoNode
, Node
se agrega el nuevoNode
después de la referencia Node
, Node
se agrega el nuevoNode
tiene un hermano después, entonces el nuevo Node
se inserta antes de ese hermanoNode
Extensible Node
Node.prototype.insertAfter = function(node, referenceNode) {
if (node)
this.insertBefore(node, referenceNode && referenceNode.nextSibling);
return node;
};
Un ejemplo común
node.parentNode.insertAfter(newNode, node);
Ver el código en ejecución
Sé que esta pregunta ya tiene demasiadas respuestas, pero ninguna de ellas cumplió con mis requisitos exactos.
Quería una función que tenga el comportamiento exactamente opuesto deparentNode.insertBefore
, es decir, debe aceptar un valor nulo referenceNode
(que la respuesta aceptada no acepta ) y dónde insertBefore
se insertaría al final de los hijos, este debe insertar al principio , ya que de lo contrario allí ' d no hay forma de insertar en la ubicación de inicio con esta función en absoluto; la misma razón se insertBefore
inserta al final.
Desde un nulo referenceNode
requiere que ubique al padre, necesitamos conocer al padre - insertBefore
es un método deparentNode
, por lo que tiene acceso al padre de esa manera; nuestra función no lo hace, por lo que tendremos que pasar el padre como parámetro.
La función resultante se ve así:
function insertAfter(parentNode, newNode, referenceNode) {
parentNode.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : parentNode.firstChild
);
}
O (si es necesario, no lo recomiendo), por supuesto, puede mejorar el Node
prototipo:
if (! Node.prototype.insertAfter) {
Node.prototype.insertAfter = function(newNode, referenceNode) {
this.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : this.firstChild
);
};
}
Este código es un trabajo para insertar un elemento de enlace justo después del último elemento secundario existente para incluir un pequeño archivo 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);
Puedes usar appendChild
función para insertar después de un elemento.
Referencia: http://www.w3schools.com/jsref/met_node_appendchild.asp
Una implementación 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'."));
};
Vamos a manejar todos los escenarios
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);
};
}
En realidad, puede utilizar un método llamado after()
en la versión más reciente de Chrome, Firefox y Opera. La desventaja de este método es que Internet Explorer aún no lo admite.
Ejemplo:
// 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)
Un código HTML simple para probar que es:
<!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 se esperaba, mueve el elemento hacia arriba después del elemento hacia abajo