Bagaimana cara memasukkan elemen setelah elemen lain dalam JavaScript tanpa menggunakan perpustakaan?

757

Ada insertBefore()dalam JavaScript, tetapi bagaimana saya bisa memasukkan elemen setelah elemen lain tanpa menggunakan jQuery atau perpustakaan lain?

Xah Lee
sumber
4
jika Anda memerlukan kasus spesifik dari simpul anak terakhir - stackoverflow.com/questions/5173545/...
2
@AlanLarimer itu hebat. Terima kasih. Anda tahu kapan insertAdjacentElement diperkenalkan?
Xah Lee
1
Menurut MDN itu didukung di IE8 dan Firefox 48 (2016 Agustus 08). Ikuti jejak: bugzilla.mozilla.org/show_bug.cgi?id=811259 -> w3.org/Bugs/Public/show_bug.cgi?id=19962 (2016 14 Maret)
Alan Larimer

Jawaban:

1276
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

Di mana referenceNodesimpul yang ingin Anda letakkan newNodesetelah. Jika referenceNodeanak terakhir dalam elemen induknya, tidak apa-apa, karena referenceNode.nextSiblingakan nulldan insertBeforemenangani kasus itu dengan menambahkan ke akhir daftar.

Begitu:

function insertAfter(newNode, referenceNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

Anda dapat mengujinya menggunakan cuplikan berikut:

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>

karim79
sumber
8
Terima kasih atas jawaban yang bagus, tetapi bukankah membingungkan untuk membalik referenceNode dan newNode dalam daftar argumen? Mengapa tidak mematuhi sintaks insertBefore?
GijsjanB
9
Cuplikan kode ini tidak menangani jika referenceNode adalah anak terakhir, di mana ia harus menambahkan anak.
Brad Vogel
72
Menurut MDN jika elemennya terakhir (dan nextSibling adalah nol) newNode akan ditambahkan seperti yang diharapkan
electroCutie
9
ReferenceNode.nextElementSibling adalah pilihan yang lebih baik untuk digunakan
Bhumi Singhal
8
@ BhumiSinghal: Salah. insertBefore()bekerja dengan node teks. Mengapa Anda ingin insertAfter()tampil beda? Anda harus membuat pasangan fungsi terpisah yang dinamai insertBeforeElement()dan insertAfterElement()untuk itu.
7vujy0f0hy
116

JavaScript Mudah Akan Menjadi Berikut:

Tambahkan sebelum:

element.parentNode.insertBefore(newElement, element);

Tambahkan setelah:

element.parentNode.insertBefore(newElement, element.nextSibling);

Tapi, Aduk Beberapa Prototipe Di Sana Untuk Kemudahan Penggunaan

Dengan membangun prototipe berikut, Anda akan dapat memanggil fungsi ini langsung dari elemen yang baru dibuat.

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.appendBefore (elemen) Prototype

Element.prototype.appendBefore = function (element) {
  element.parentNode.insertBefore(this, element);
},false;

.appendAfter (elemen) Prototipe

Element.prototype.appendAfter = function (element) {
  element.parentNode.insertBefore(this, element.nextSibling);
},false;

Dan, Untuk Melihat Semuanya Beraksi, Jalankan Cuplikan Kode Berikut

Jalankan di JSFiddle

Armando
sumber
4
Nama fungsi ekstensi menyesatkan. Itu pikir itu lebih baik disebut appendMeBefore dan appendMeAfter. Saya pikir itu digunakan seperti metode appendChild () , misalnya existingElement.appendAfter(newElement);. Lihat apa yang saya maksud di jsfiddle yang diperbarui ini .
stomtech
2
Tambah Setelah berfungsi, karena jika element.nextSibling tidak memiliki saudara berikutnya, nextSibling adalah NULL, dan kemudian akan ditambahkan pada akhirnya.
Stefan Steiger
45

insertAdjacentHTML + outerHTML

elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)

Kelemahan:

  • DRYer: Anda tidak perlu menyimpan node sebelum dalam variabel dan menggunakannya dua kali. Jika Anda mengubah nama variabel, lebih sedikit kemunculannya untuk dimodifikasi.
  • golf lebih baik daripada insertBefore(impas jika nama variabel node yang ada adalah 3 karakter)

Kerugian:

  • dukungan browser yang lebih rendah sejak yang lebih baru: https://caniuse.com/#feat=insert-adjacent
  • akan kehilangan properti elemen seperti peristiwa karena outerHTMLmengubah elemen menjadi string. Kami membutuhkannya karena insertAdjacentHTMLmenambahkan konten dari string daripada elemen.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
12
Jika Anda sudah memiliki elemen yang dibangun, Anda dapat menggunakan.insertAdjacentElement()
GetFree
6
Pada 2018, dukungan penampilan browser yang cukup solid: caniuse.com/#feat=insert-adjacent
madannes
Ini adalah solusi yang bagus, saya sarankan eveyone membaca xahlee.info/js/js_insert_after.html
Mehregan Rahmani
37

Pencarian Google cepat mengungkapkan skrip ini

// 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);
    }
}
James Long
sumber
29
Bagi siapa saja yang menemukan skrip ini, saya tidak merekomendasikan untuk menggunakannya. Ia mencoba untuk memecahkan masalah yang sudah dipecahkan oleh solusi asli @ karim79. Scriptnya lebih cepat dan lebih efisien - saya sangat merekomendasikan menggunakan script itu daripada yang ini.
James Long
10
Sebagai aturan umum dalam JavaScript, browser dapat melakukan tugas lebih cepat dari apa pun yang dapat Anda tulis. Meskipun kedua solusi secara fungsional sama, solusi JavaScript saya perlu dibaca dan dipahami oleh browser sebelum dapat digunakan dan memerlukan pemeriksaan tambahan setiap kali dijalankan. Solusi yang ditawarkan oleh karim79 akan melakukan semua ini secara internal, menghemat langkah-langkah tersebut. Perbedaannya akan sepele di terbaik, tetapi solusinya adalah yang lebih baik.
James Long
3
Dengan kata lain, ini berusaha menyelesaikan masalah yang tidak ada. Tidak ada yang salah secara inheren tentang pemeriksaan tambahan, tapi saya kira itu tidak menyebarkan pemahaman terbaik dari metode ini
1j01
3
Kurang lebih. Saya meninggalkan skrip di sini karena ini adalah jenis yang biasa saya tulis, tetapi jawaban yang diterima adalah yang lebih baik, menunjukkan pemahaman yang lebih baik tentang metode dan lebih cepat. Tidak ada alasan untuk menggunakan jawaban ini sebagai gantinya - Saya bahkan tidak yakin mengapa jawaban itu tetap mendapat upvotes
James Long
3
Jika targetElement adalah elemen terakhir di antara saudara kandungnya, maka targetElement.nextSiblingakan kembali null. Ketika node.insertBeforedipanggil dengan nullargumen kedua, maka akan menambahkan simpul di akhir koleksi. Dengan kata lain, if(parent.lastchild == targetElement) {cabang itu berlebihan, karena parent.insertBefore(newElement, targetElement.nextSibling);akan menangani semua kasus dengan benar, meskipun mungkin terlihat sebaliknya pada awalnya. Banyak yang sudah menunjukkan hal itu dalam komentar lain.
Rolf
26

Padahal insertBefore()(lihat MDN ) hebat dan direferensikan oleh sebagian besar jawaban di sini. Untuk menambah fleksibilitas, dan agar lebih eksplisit, Anda dapat menggunakan:

insertAdjacentElement()(lihat MDN ) Ini memungkinkan Anda mereferensikan elemen apa pun, dan menyisipkan elemen yang akan dipindahkan tepat di tempat yang Anda inginkan:

<!-- refElem.insertAdjacentElement('beforebegin', moveMeElem); -->
<p id="refElem">
    <!-- refElem.insertAdjacentElement('afterbegin', moveMeElem); -->
    ... content ...
    <!-- refElem.insertAdjacentElement('beforeend', moveMeElem); -->
</p>
<!-- refElem.insertAdjacentElement('afterend', moveMeElem); -->

Orang lain untuk dipertimbangkan untuk kasus penggunaan serupa: insertAdjacentHTML()daninsertAdjacentText()

Referensi:

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

sedikit kurang
sumber
Harus benar-benar memberikan jawaban ini beberapa cinta, itu adalah pendekatan modern untuk tahun 2020-an yang segera mendekat.
serraosays
1
Kenapa jawaban ini terkubur begitu dalam? Saya akan memberikan beberapa poin untuk memberi perhatian lebih.
Qwerty
16

Metode node.after( doc ) menyisipkan simpul setelah simpul lain.

Untuk dua simpul DOM node1dan node2,

node1.after(node2)sisipan node2setelah node1.

Metode ini tidak tersedia di browser lama, jadi biasanya diperlukan polyfill.

golopot
sumber
Ini membutuhkan sedikit kerja manual untuk diimplementasikan sebagai insertAfter yang berfungsi, jadi sayangnya saya tidak berpikir ini akan bekerja dengan benar.
Tuan SirCode
6

Solusi 2018 (Praktek Buruk, lanjut ke 2020)

Saya tahu pertanyaan ini adalah Kuno, tetapi untuk setiap pengguna di masa depan, ini adalah prototipe yang dimodifikasi Ini hanya polyfill mikro untuk .insert. Setelah fungsi yang tidak ada, prototipe ini secara langsung menambahkan fungsi baru baseElement.insertAfter(element);ke prototipe Elemen:

Element.prototype.insertAfter = function(new) {
    this.parentNode.insertBefore(new, this.nextSibling);
}

Setelah Anda meletakkan polyfill di perpustakaan, intisari, atau hanya di kode Anda (atau di mana pun tempat itu dapat direferensikan) Cukup tulis document.getElementById('foo').insertAfter(document.createElement('bar'));


Solusi 2019 (Jelek, pergi ke 2020)

Suntingan Baru: Anda TIDAK HARUS MENGGUNAKAN PROTOTIPE. Mereka menimpa basis kode default dan tidak sangat efisien atau aman dan dapat menyebabkan kesalahan kompatibilitas, tetapi jika itu untuk proyek-proyek non-komersial, itu tidak masalah. jika Anda ingin fungsi yang aman untuk penggunaan komersial, cukup gunakan fungsi default. itu tidak cantik tetapi berfungsi:

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 


Solusi 2020

Standar Web Saat Ini untuk ChildNode: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode

Saat ini dalam Standar Hidup dan AMAN.

Untuk Peramban yang Tidak Didukung, gunakan Polyfill ini: https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js

Seseorang menyebutkan bahwa Polyfill menggunakan Protos, ketika saya katakan itu praktik yang buruk. Mereka, terutama ketika mereka digunakan secara tidak benar, seperti solusi saya untuk 2018. Namun, polyfill itu ada di Dokumentasi MDN dan menggunakan semacam inisialisasi dan eksekusi yang lebih aman. Ditambah lagi IS untuk dukungan browser yang lebih lama, di zaman dan di mana Prototype Overwriting tidak terlalu buruk.

Cara menggunakan Solusi 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
Tuan SirCode
sumber
5

Atau Anda bisa melakukannya:

referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )
olvlvl
sumber
Saya tidak akan memikirkan pendekatan itu. Saya lebih suka menggunakan jawaban langsung @ karim79 , tapi bagus untuk diingat.
Ben J
5

Langkah 1. Siapkan Elemen:

var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;

Langkah 2. Tambahkan setelah:

elementParent.insertBefore(newElement, element.nextSibling);
Malik Khalil
sumber
3

Metode insertBefore () digunakan seperti parentNode.insertBefore(). Jadi untuk meniru ini dan membuat metode parentNode.insertAfter()kita dapat menulis kode berikut.

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>

Perhatikan, bahwa memperpanjang DOM mungkin bukan solusi yang tepat untuk Anda seperti yang dinyatakan dalam artikel ini .

Namun, artikel ini ditulis pada tahun 2010 dan segalanya mungkin berbeda sekarang. Jadi putuskan sendiri.

JavaScript DOM insertAfter () metode @ jsfiddle.net

Dmytro Dzyubak
sumber
2

Idealnya insertAfterharus bekerja mirip dengan insertBefore . Kode di bawah ini akan melakukan hal berikut:

  • Jika tidak ada anak, yang baru Nodeditambahkan
  • Jika tidak ada referensi Node, yang baru Nodeditambahkan
  • Jika tidak ada Nodesetelah referensi Node, yang baru Nodeditambahkan
  • Jika di sana referensi Nodememiliki saudara kandung, maka yang baru Nodedimasukkan sebelum saudara tersebut
  • Mengembalikan yang baru Node

Memperluas Node

Node.prototype.insertAfter = function(node, referenceNode) {

    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

Salah satu contoh umum

node.parentNode.insertAfter(newNode, node);

Lihat kode yang berjalan

Darlesson
sumber
2

Saya tahu pertanyaan ini sudah memiliki terlalu banyak jawaban, tetapi tidak satu pun dari mereka memenuhi persyaratan yang tepat.

Saya menginginkan fungsi yang memiliki perilaku sebaliknyaparentNode.insertBefore - yaitu, ia harus menerima nol referenceNode(yang tidak diterima jawaban yang diterima ) dan di mana insertBeforememasukkan di akhir anak-anak yang ini harus disisipkan di awal , karena kalau tidak ada ' d tidak ada cara untuk menyisipkan di lokasi awal dengan fungsi ini sama sekali; alasan yang sama insertBeforemenyisipkan di akhir.

Karena null referenceNodemengharuskan Anda untuk menemukan induknya, kami perlu mengetahui induknya - insertBeforeadalah metode dari parentNode, jadi ia memiliki akses ke induknya seperti itu; fungsi kami tidak, jadi kami harus meneruskan induk sebagai parameter.

Fungsi yang dihasilkan terlihat seperti ini:

function insertAfter(parentNode, newNode, referenceNode) {
  parentNode.insertBefore(
    newNode,
    referenceNode ? referenceNode.nextSibling : parentNode.firstChild
  );
}

Atau (jika Anda harus, saya tidak merekomendasikannya) Anda tentu saja dapat meningkatkan Nodeprototipe:

if (! Node.prototype.insertAfter) {
  Node.prototype.insertAfter = function(newNode, referenceNode) {
    this.insertBefore(
      newNode,
      referenceNode ? referenceNode.nextSibling : this.firstChild
    );
  };
}
mindplay.dk
sumber
0

Kode ini berfungsi untuk menyisipkan item tautan tepat setelah anak terakhir yang ada untuk menggarisbawahi file css kecil

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);
Chetabahana
sumber
0

Anda dapat menggunakan appendChildfungsi untuk menyisipkan setelah elemen.

Referensi: http://www.w3schools.com/jsref/met_node_appendchild.asp

Doug LN
sumber
Solusi ini tidak berfungsi untuk 2 tag p .. Anda tidak dapat menambahkan tag ap setelah tag p lain dengan fungsi ini ..
Mehregan Rahmani
0

implementasi insertAfter yang kuat.

// 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'."));

};

jszhou
sumber
Tambahkan beberapa penjelasan dengan jawaban untuk bagaimana jawaban ini membantu OP dalam memperbaiki masalah saat ini
ρяσѕρєя K
Jalankan kode di atas, maka Anda dapat memasukkan newNode setelah referenceNode yang ditentukan.
jszhou
0

Mari kita tangani semua skenario

 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);            
    }
Sami
sumber
0
if( !Element.prototype.insertAfter ) {
    Element.prototype.insertAfter = function(item, reference) {
        if( reference.nextSibling )
            reference.parentNode.insertBefore(item, reference.nextSibling);
        else
            reference.parentNode.appendChild(item);
    };
}
yavuzkavus
sumber
0

Anda sebenarnya bisa menggunakan metode yang disebut after()dalam versi Chrome, Firefox dan Opera yang lebih baru. Kelemahan dari metode ini adalah bahwa Internet Explorer belum mendukungnya.

Contoh:

// 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)

Kode HTML sederhana untuk mengujinya adalah:

<!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>

Seperti yang diharapkan, itu memindahkan elemen ke atas setelah elemen ke bawah

Anime no Sekai
sumber