Постоянный верхний слой интерфейса

Веб-функции: moveBefore()

При перемещении открытого элемента <dialog>, popover или полноэкранного элемента в DOM с помощью традиционных методов, таких как appendChild() или insertBefore(), браузер неявно удаляет элемент из DOM и повторно вставляет его. Это приводит к сбросу состояния, из-за чего открытые модальные окна, всплывающие окна и полноэкранные элементы резко закрываются.

Чтобы изменить родительский элемент для элементов верхнего слоя, не прерывая работу пользователя и не закрывая их, используйте API moveBefore().

Изменение родительского элемента для открытых элементов верхнего слоя

moveBefore() принимает два аргумента: узел, который нужно переместить, и узел, перед которым нужно вставить перемещаемый узел (или null, чтобы добавить его в конец нового родительского узла).

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

Резервные стратегии

Поскольку moveBefore() – это прогрессивное улучшение, перед вызовом необходимо использовать обнаружение функций. Для более старых браузеров вам придется использовать традиционный метод смены родительского элемента.

ОБЯЗАТЕЛЬНО. Для элементов <dialog> в неподдерживаемых браузерах традиционное перемещение закроет диалоговое окно. Если вы хотите, чтобы он оставался открытым, вам нужно будет открыть его вручную после переноса.

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