عند نقل عنصر <dialog> أو popover أو عنصر ملء الشاشة مفتوح في DOM باستخدام الطرق التقليدية، مثل appendChild() أو insertBefore()، يزيل المتصفّح العنصر ضمنيًا من DOM ويعيد إدراجه. وتؤدي هذه الإزالة إلى إعادة ضبط الحالة، ما يؤدي إلى إغلاق النوافذ المشروطة والعناصر المنبثقة وعناصر ملء الشاشة بشكل مفاجئ.
لإعادة تحديد العناصر الرئيسية في الطبقة العليا بدون مقاطعة تجربة المستخدم أو إغلاقها، استخدِم واجهة برمجة التطبيقات 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();
}
}