Cuando se mueve un elemento <dialog>, popover o de pantalla completa abierto en el DOM con métodos tradicionales, como appendChild() o insertBefore(), el navegador quita implícitamente el elemento del DOM y lo vuelve a insertar. Esta eliminación restablece el estado, lo que hace que los modales, los popovers y los elementos de pantalla completa abiertos se cierren de forma abrupta.
Para cambiar el elemento superior de los elementos de la capa superior sin interrumpir la experiencia del usuario ni cerrarlos, usa la API de moveBefore() atómica.
Cambio de elemento superior de los elementos de la capa superior abiertos
moveBefore() toma dos argumentos: el nodo que se moverá y un nodo de referencia que se insertará antes (o null para agregarlo al final del nuevo elemento superior).
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);
Estrategias de resguardo
Dado que moveBefore() es una mejora progresiva, DEBES usar la detección de funciones antes de llamarla. En el caso de los navegadores más antiguos, deberás recurrir al cambio de elemento superior tradicional.
OBLIGATORIO: Para los elementos <dialog> en navegadores no compatibles, el movimiento tradicional cerrará el diálogo. Si necesitas que permanezca abierto, debes volver a abrirlo de forma manual después de moverlo.
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();
}
}