whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.16k stars 2.68k forks source link

Proposal: Window.openModal(url) #5593

Open a-p-f opened 4 years ago

a-p-f commented 4 years ago

This is a proposal for a new Window method, allowing for easy creation of modal dialogs/overlays. It can be thought of as an asynchronous version of showModalDialog(), which overlays the new window over top of the opening window.

Motivation

Multi-window workflows allow developers to create highly decoupled, reusable, widget-type windows. These workflows can work very well for CRUD apps, content editing apps, etc.

There is no current means to create a new window which is both modal and "reasonable decoupled" from its parent. New windows/tabs are decoupled, but not modal. Iframes can be be made modal, but share history and sessionStorage with the parent window.

Alternative Solutions

This proposal cannot be fully implemented using current APIs. I've been working on an iframe-based solution called openModal.js (github repo). openModal.js demonstrates the concept, and is quite usable in it's own right, but fails to implement a few of the properties specified in this proposal.

API Basics

window.openModal(url, [options]) will act like window.open(url), except that it will create a "modal window", which has a transparent background, no browser UI, and completely covers the parent window. All user interaction with the parent window will be blocked while the modal window is open, but javascript will still execute in the parent window.

The modal can dismiss itself, via window.closeModal([closeValue]).

openModal() should be infinitely nestable. Any modal window can open another modal window.

Inter-window Communication

The opening/parent window can communicate with the modal window via the options argument to openModal(). options.onload (function(window) -> undefined) will be called each time the modal window loads, with the modal window as the sole argument.

openModal() will return a promise, which will resolve when the modal window calls closeModal([closeValue]). The promise will resolve with the value that is passed to closeModal. If the modal window is cross origin, any value passed to closeModal must be serializable.

The modal window can also access the parent window via window.parent, and can navigate the parent using links or forms with [target="_parent"].

History and Session Storage

The newly created modal window will have its own history stack (starting out with history.length == 1), and its own sessionStorage.

If the user hits the back button while a modal window is open, the browser should first try to go back in the modal window's history. If the modal window is on its first history entry, the modal window will be closed (and the promise returned by openModal() will resolve with undefined). Clicking the forward button should not reopen the modal window.

Other Features

Links or forms with [target="_modal"] will open a new modal window.

Any background-color on the body element within a modal window should not extend beyond the bounds of the body element (as it does in a normal window). This would simplify the creation of "alert style" modal windows, eliminating the need for a wrapper div around all of the alert content.

keithamus commented 1 year ago

I believe since this issue was filed, there now exists <dialog> with a showModal() API. What benefit would window.showModal/closeModal give us that dialog.showModal() does not?

Is it worth closing this issue now?