Persistente Top-Layer-UI

Webfunktionen: moveBefore()

Wenn Sie ein geöffnetes <dialog>-, popover- oder Vollbildelement im DOM mit herkömmlichen Methoden wie appendChild() oder insertBefore() verschieben, entfernt der Browser das Element implizit aus dem DOM und fügt es wieder ein. Dadurch wird der Status zurückgesetzt, sodass geöffnete Modale, Popover und Vollbildelemente abrupt geschlossen werden.

Wenn Sie Elemente der obersten Ebene neu zuordnen möchten, ohne die Nutzererfahrung zu beeinträchtigen oder die Elemente zu schließen, verwenden Sie stattdessen die atomare moveBefore() API.

Übergeordnete Elemente von offenen Elementen der obersten Ebene ändern

moveBefore() verwendet zwei Argumente: den zu verschiebenden Knoten und einen Referenzknoten, vor dem der Knoten eingefügt werden soll (oder null, um ihn am Ende des neuen übergeordneten Knotens anzuhängen).

const newParent = document.getElementById('new-container');
const dialogElement = document.getElementById('my-dialog');

// MANDATORY: Use moveBefore to ensure the <dialog> or popover stays open.
// Passing null appends it to the end of newParent.
newParent.moveBefore(dialogElement, null);

Fallback-Strategien

Da moveBefore() eine progressive Verbesserung ist, MÜSSEN Sie die Funktionserkennung verwenden, bevor Sie sie aufrufen. Bei älteren Browsern müssen Sie auf das herkömmliche Reparenting zurückgreifen.

OBLIGATORISCH: Bei <dialog>-Elementen in nicht unterstützten Browsern wird das Dialogfeld durch die herkömmliche Bewegung geschlossen. Wenn Sie möchten, dass es geöffnet bleibt, müssen Sie es nach dem Verschieben manuell wieder öffnen.

const targetParent = document.getElementById('target-container');
const popoverOrDialog = document.getElementById('my-top-layer-element');

// Check if moveBefore is supported
if ('moveBefore' in Element.prototype) {
  targetParent.moveBefore(popoverOrDialog, null);
} else {
  // Fallback: traditional move.
  // Note: This WILL close <dialog>, popover, and fullscreen elements.
  const wasOpen = popoverOrDialog.hasAttribute('open') || popoverOrDialog.matches(':popover-open');
  targetParent.insertBefore(popoverOrDialog, null);
  
  // Manually restore state if possible
  if (wasOpen && typeof popoverOrDialog.showModal === 'function') {
    popoverOrDialog.showModal();
  } else if (wasOpen && typeof popoverOrDialog.showPopover === 'function') {
    popoverOrDialog.showPopover();
  }
}