Jest insertBefore()
w JavaScript, ale jak mogę wstawić element za innym elementem bez użycia jQuery lub innej biblioteki?
Jest insertBefore()
w JavaScript, ale jak mogę wstawić element za innym elementem bez użycia jQuery lub innej biblioteki?
Odpowiedzi:
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
Gdzie referenceNode
jest węzeł, po którym chcesz umieścić newNode
. Jeśli referenceNode
jest ostatnim dzieckiem w swoim elemencie nadrzędnym, to w porządku, ponieważ referenceNode.nextSibling
będzie null
i insertBefore
obsługuje tę sprawę, dodając na końcu listy.
Więc:
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
Możesz to przetestować za pomocą następującego fragmentu:
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()
współpracuje z węzłami tekstowymi. Dlaczego chcesz insertAfter()
być inny? Należy utworzyć osobną parę nazwanych insertBeforeElement()
i insertAfterElement()
do tego celu.
Dołącz przed:
element.parentNode.insertBefore(newElement, element);
Dołącz po:
element.parentNode.insertBefore(newElement, element.nextSibling);
Budując następujące prototypy, będziesz mógł wywoływać te funkcje bezpośrednio z nowo tworzonych elementów.
newElement.appendBefore(element);
newElement.appendAfter(element);
.appendBefore (element) Prototyp
Element.prototype.appendBefore = function (element) {
element.parentNode.insertBefore(this, element);
},false;
.appendAfter (element) Prototyp
Element.prototype.appendAfter = function (element) {
element.parentNode.insertBefore(this, element.nextSibling);
},false;
existingElement.appendAfter(newElement);
. Zobacz, co mam na myśli w tym zaktualizowanym jsfiddle .
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
Plusy:
insertBefore
(nawet jeśli istniejąca nazwa zmiennej węzła ma długość 3 znaków)Wady:
outerHTML
konwertuje element na ciąg. Potrzebujemy tego, ponieważ insertAdjacentHTML
dodaje treść z ciągów zamiast elementów..insertAdjacentElement()
Szybkie wyszukiwanie w Google ujawnia ten skrypt
// 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
zwróci null
. Gdy node.insertBefore
jest wywoływany null
jako jako drugi argument, doda węzeł na końcu kolekcji. Innymi słowy, if(parent.lastchild == targetElement) {
gałąź jest zbyteczna, ponieważ parent.insertBefore(newElement, targetElement.nextSibling);
będzie poprawnie obsługiwać wszystkie przypadki, nawet jeśli na początku może się wydawać inaczej. Wielu już to zauważyło w innych komentarzach.
Chociaż insertBefore()
(patrz MDN ) jest świetny i zawiera większość odpowiedzi tutaj. Aby zwiększyć elastyczność i być bardziej precyzyjnym, możesz użyć:
insertAdjacentElement()
(patrz MDN ) Pozwala to na odwołanie się do dowolnego elementu i wstawienie elementu, który ma zostać przeniesiony, dokładnie tam, gdzie chcesz:
<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
<!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
... content ...
<!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->
Inne do rozważenia w podobnych przypadkach użycia: insertAdjacentHTML()
iinsertAdjacentText()
Bibliografia:
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
Metoda node.after
( doc ) wstawia węzeł za innym węzłem.
Dla dwóch węzłów DOM node1
i node2
,
node1.after(node2)
wstawia node2
po node1
.
Ta metoda nie jest dostępna w starszych przeglądarkach, dlatego zwykle potrzebny jest wielopełniacz.
Wiem, że to pytanie jest starożytne, ale dla wszystkich przyszłych użytkowników, oto zmodyfikowany prototyp, jest to po prostu mikro-wypełnienie dla funkcji .insert Po tym, który nie istnieje, ten prototyp bezpośrednio dodaje nową funkcję baseElement.insertAfter(element);
do prototypu Element:
Element.prototype.insertAfter = function(new) {
this.parentNode.insertBefore(new, this.nextSibling);
}
Po umieszczeniu wypełniacza w bibliotece, treści lub po prostu w kodzie (lub w innym miejscu, do którego można się odwołać) Po prostu napisz document.getElementById('foo').insertAfter(document.createElement('bar'));
Nowa edycja: NIE WOLNO STOSOWAĆ PROTOTYPÓW. Zastępują one domyślną bazę kodu i nie są bardzo wydajne ani bezpieczne i mogą powodować błędy zgodności, ale jeśli dotyczy to projektów niekomercyjnych, nie powinno to mieć znaczenia. jeśli chcesz bezpieczną funkcję do użytku komercyjnego, po prostu użyj funkcji domyślnej. to nie jest ładne, ale działa:
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
Aktualne standardy sieciowe dla ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode
Jest obecnie w Living Standards i jest BEZPIECZNY.
W przypadku nieobsługiwanych przeglądarek skorzystaj z funkcji Polyfill: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js
Ktoś wspomniał, że Polyfill używa Protos, kiedy powiedziałem, że to zła praktyka. Są, szczególnie gdy są używane nieprawidłowo, podobnie jak moje rozwiązanie na 2018 rok. Jednak ta polifill znajduje się w Dokumentacji MDN i korzysta z bezpieczniejszej inicjalizacji i wykonania. Plus JEST dla starszych przeglądarek, w czasach, gdy nadpisywanie prototypów nie było takie złe.
Jak korzystać z rozwiązania 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
Lub możesz po prostu zrobić:
referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
Krok 1. Przygotuj elementy:
var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;
Krok 2. Dołącz po:
elementParent.insertBefore(newElement, element.nextSibling);
Metoda insertBefore () jest używana jak parentNode.insertBefore()
. Aby to naśladować i stworzyć metodę parentNode.insertAfter()
, możemy napisać następujący kod.
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>
Pamiętaj, że rozszerzenie DOM może nie być właściwym rozwiązaniem dla Ciebie, jak stwierdzono w tym artykule .
Jednak ten artykuł został napisany w 2010 roku i teraz może być inaczej. Zdecyduj więc sam.
Idealnie insertAfter
powinien działać podobnie do insertBefore . Poniższy kod wykona następujące czynności:
Node
jest dołączaneNode
, nowe Node
jest dodawaneNode
po referencji Node
, nowa Node
jest dołączanaNode
ma później rodzeństwo, nowy Node
jest wstawiany przed tym rodzeństwemNode
Rozsuwalny Node
Node.prototype.insertAfter = function(node, referenceNode) {
if (node)
this.insertBefore(node, referenceNode && referenceNode.nextSibling);
return node;
};
Jeden wspólny przykład
node.parentNode.insertAfter(newNode, node);
Zobacz działający kod
Wiem, że na to pytanie ma już zbyt wiele odpowiedzi, ale żadne z nich nie spełniło moich dokładnych wymagań.
Chciałem funkcji, która ma dokładnie odwrotne zachowanieparentNode.insertBefore
- to znaczy musi zaakceptować wartość zerową referenceNode
(czego nie przyjmuje zaakceptowana odpowiedź ) i gdzie insertBefore
wstawiłaby na końcu dzieci, którą należy wstawić na początku , ponieważ w przeciwnym razie ' d nie można w żaden sposób wstawić w miejscu początkowym z tą funkcją; ten sam powód insertBefore
wstawia na końcu.
Ponieważ wartość null referenceNode
wymaga zlokalizowania elementu nadrzędnego, musimy znać element nadrzędny - insertBefore
jest to metoda parentNode
, więc ma on w ten sposób dostęp do elementu nadrzędnego; nasza funkcja nie, więc musimy przekazać parametr nadrzędny jako parametr.
Wynikowa funkcja wygląda następująco:
function insertAfter(parentNode, newNode, referenceNode) {
parentNode.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : parentNode.firstChild
);
}
Lub (jeśli musisz, nie polecam) możesz oczywiście ulepszyć Node
prototyp:
if (! Node.prototype.insertAfter) {
Node.prototype.insertAfter = function(newNode, referenceNode) {
this.insertBefore(
newNode,
referenceNode ? referenceNode.nextSibling : this.firstChild
);
};
}
Ten kod jest praca, aby wstawić właściwą pozycję Link po ostatnim istniejącym dziecka inline mały plik 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);
Możesz użyć appendChild
funkcji do wstawienia po elemencie.
Odniesienie: http://www.w3schools.com/jsref/met_node_appendchild.asp
solidna implementacja 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'."));
};
Pozwala obsłużyć wszystkie scenariusze
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);
};
}
Można tak naprawdę wywołać metodę after()
w nowszej wersji Chrome, Firefox i Opera. Minusem tej metody jest to, że Internet Explorer jeszcze jej nie obsługuje.
Przykład:
// 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)
Prosty kod HTML do przetestowania, który jest:
<!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>
Zgodnie z oczekiwaniami przesuwa element w górę za elementem w dół