Spostamento dell'elemento DOM senza perdere lo stato

Funzionalità web: moveBefore()

Quando si cambia l'elemento principale degli elementi DOM utilizzando metodi tradizionali come appendChild() o insertBefore(), il browser rimuove implicitamente l'elemento dal DOM e lo inserisce nella nuova posizione. Questa operazione di "rimozione e inserimento" reimposta molti stati interni, causando il ricaricamento degli elementi <iframe>, il riavvio delle animazioni CSS e la perdita dello stato attivo dei campi di immissione.

Per spostare un elemento mantenendo il suo stato, utilizza l'API moveBefore(). Questo metodo esegue uno spostamento atomico, ignorando completamente i passaggi di rimozione e inserimento.

Spostamento di un elemento con stato

Utilizza moveBefore() esattamente come utilizzeresti insertBefore(). Richiede due argomenti: il nodo da spostare e un nodo di riferimento da inserire prima (o null da aggiungere alla fine del nuovo elemento principale).

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

Spostamento di elementi personalizzati (componenti web)

Se sposti elementi personalizzati utilizzando moveBefore(), i relativi metodi del ciclo di vita connectedCallback e disconnectedCallback non verranno attivati.

Se l'elemento personalizzato deve eseguire una logica specifica quando viene spostato, implementa il metodo connectedMoveCallback() all'interno della definizione dell'elemento personalizzato.

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.
  }
}

Strategie di riserva

Poiché moveBefore() è un potenziamento progressivo, DEVI utilizzare il rilevamento delle funzionalità prima di chiamarlo, tornando alle operazioni tradizionali insertBefore() o appendChild() per i browser meno recenti.

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);
}