Memindahkan Elemen DOM Tanpa Kehilangan Status

Fitur web: moveBefore()

Saat mengubah induk elemen DOM menggunakan metode tradisional seperti appendChild() atau insertBefore(), browser secara implisit menghapus elemen dari DOM, lalu menyisipkannya ke lokasi baru. Operasi "hapus dan sisipkan" ini mereset banyak status internal, sehingga menyebabkan elemen <iframe> dimuat ulang, animasi CSS dimulai ulang, dan kolom input kehilangan fokus.

Untuk memindahkan elemen sambil mempertahankan statusnya, gunakan moveBefore() API. Metode ini melakukan pemindahan atomik, yang sepenuhnya mengabaikan langkah penghapusan dan penyisipan.

Memindahkan elemen dengan status

Gunakan moveBefore() persis seperti Anda menggunakan insertBefore(). Metode ini memerlukan dua argumen: node yang akan dipindahkan, dan node referensi yang akan disisipkan sebelum (atau null untuk ditambahkan ke akhir induk baru).

const newParent = document.getElementById('new-parent');
const elementWithState = document.getElementById('iframe-or-focused-input');

// MANDATORY: Use moveBefore to preserve state. 
// Passing null as the second argument appends the element to the end of newParent.
newParent.moveBefore(elementWithState, null);

Memindahkan elemen kustom (Komponen Web)

Jika Anda memindahkan elemen kustom menggunakan moveBefore(), metode siklus proses connectedCallback dan disconnectedCallback-nya tidak akan diaktifkan.

Jika elemen kustom Anda perlu menjalankan logika tertentu saat dipindahkan, terapkan metode connectedMoveCallback() di dalam definisi elemen kustom.

class MyCustomElement extends HTMLElement {
  connectedCallback() {
    // Runs on initial insertion.
  }
  
  connectedMoveCallback() {
    // Runs when the element is moved via moveBefore().
    // Use this to update state that depends on the new DOM location.
  }
}

Strategi penggantian

Karena moveBefore() adalah progressive enhancement, Anda HARUS menggunakan deteksi fitur sebelum memanggilnya, dan beralih ke operasi insertBefore() atau appendChild() tradisional untuk browser lama.

const targetParent = document.getElementById('target-container');
const nodeToMove = document.getElementById('moving-element');

// Check if moveBefore is supported on the Element prototype
if ('moveBefore' in Element.prototype) {
  targetParent.moveBefore(nodeToMove, null);
} else {
  // Fallback: traditional move. 
  // Note: This WILL reset <iframe>, animation, and focus state in unsupported browsers.
  targetParent.insertBefore(nodeToMove, null);
}