Déplacer un élément DOM sans perdre l'état

Fonctionnalités Web : moveBefore()

Lorsque vous modifiez le parent d'éléments DOM à l'aide de méthodes traditionnelles telles que appendChild() ou insertBefore(), le navigateur supprime implicitement l'élément du DOM, puis l'insère à son nouvel emplacement. Cette opération de suppression et d'insertion réinitialise de nombreux états internes, ce qui entraîne l'actualisation des éléments <iframe>, le redémarrage des animations CSS et la perte de la sélection des champs de saisie.

Pour déplacer un élément tout en conservant son état, utilisez l'API moveBefore(). Cette méthode effectue un déplacement atomique, en contournant complètement les étapes de suppression et d'insertion.

Déplacer un élément avec un état

Utilisez moveBefore() exactement comme vous utiliseriez insertBefore(). Elle nécessite deux arguments : le nœud à déplacer et un nœud de référence à insérer avant (ou null pour l'ajouter à la fin du nouveau parent).

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

Déplacement d'éléments personnalisés (composants Web)

Si vous déplacez des éléments personnalisés à l'aide de moveBefore(), leurs méthodes de cycle de vie connectedCallback et disconnectedCallback ne seront pas déclenchées.

Si votre élément personnalisé doit exécuter une logique spécifique lorsqu'il est déplacé, implémentez la méthode connectedMoveCallback() dans la définition de l'élément personnalisé.

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

Stratégies de remplacement

Étant donné que moveBefore() est une amélioration progressive, vous DEVEZ utiliser la détection de fonctionnalités avant de l'appeler, en revenant aux opérations insertBefore() ou appendChild() traditionnelles pour les anciens navigateurs.

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