Last active
December 1, 2023 14:39
-
-
Save samthor/babe9fad4a65625b301ba482dad284d1 to your computer and use it in GitHub Desktop.
Revisions
-
samthor revised this gist
Jun 30, 2017 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,7 +15,7 @@ var registerFocusRestoreDialog = (function() { previousFocus = ev.target; }, true); return function registerFocusRestoreDialog(dialog) { if (dialog.localName !== 'dialog') { throw new Error('Failed to upgrade focus on dialog: The element is not a dialog.'); } @@ -36,7 +36,6 @@ var registerFocusRestoreDialog = (function() { // watch for 'open' change and clear saved var mo = new MutationObserver(function() { if (!dialog.hasAttribute('open')) { registered.set(dialog, null); } else { -
samthor created this gist
Jun 30, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,72 @@ /** * Updates the passed dialog to retain focus and restore it when the dialog is closed. Won't * upgrade a dialog more than once. Supports IE11+ and is a no-op otherwise. * @param {!HTMLDialogElement} dialog to upgrade */ var registerFocusRestoreDialog = (function() { if (!window.WeakMap || !window.MutationObserver) { return function() {}; } var registered = new WeakMap(); // store previous focused node centrally var previousFocus = null; document.addEventListener('focusout', function(ev) { previousFocus = ev.target; }, true); return function restoreFocusDialog(dialog) { if (dialog.localName !== 'dialog') { throw new Error('Failed to upgrade focus on dialog: The element is not a dialog.'); } if (registered.has(dialog)) { return; } registered.set(dialog, null); // replace showModal method directly, to save focus var realShowModal = dialog.showModal; dialog.showModal = function() { var savedFocus = document.activeElement; if (savedFocus === document || savedFocus === document.body) { // some browsers read activeElement as body savedFocus = previousFocus; } registered.set(dialog, savedFocus); realShowModal.call(this); }; // watch for 'open' change and clear saved var mo = new MutationObserver(function() { console.info('mo is called', dialog, dialog.hasAttribute('open')); if (!dialog.hasAttribute('open')) { registered.set(dialog, null); } else { // if open was cleared/set in the same frame, then the dialog will still be a modal (Y) } }); mo.observe(dialog, {attributes: true, attributeFilter: ['open']}); // on close, try to focus saved, if possible dialog.addEventListener('close', function(ev) { if (dialog.hasAttribute('open')) { return; // in native, this fires the frame later } var savedFocus = registered.get(dialog); if (document.contains(savedFocus)) { var wasFocus = document.activeElement; savedFocus.focus(); if (document.activeElement !== savedFocus) { wasFocus.focus(); // restore focus, we couldn't focus saved } } savedFocus = null; }); // FIXME: If a modal dialog is readded to the page (either remove/add or .appendChild), it will // be a non-modal. It will still have its 'close' handler called and try to focus on the saved // element. // // These could basically be solved if 'close' yielded whether it was a modal or non-modal // being closed. But it doesn't. It could also be solved by a permanent MutationObserver, as is // done inside the polyfill. } }());