The HTML <dialog> element was introduced ten years ago by Google Chrome. However, dialog didn't become a web standard until 2022, when Firefox and Safari added support for the element. A dialog is a box shown in front of all other web page content, similar to an alert, but a dialog is much more configurable than an alert and can be shown either modally or non-modally.
The HTML dialog element has an open attribute indicating whether the dialog is shown on the page, as well as a corresponding open property. (An attribute is part of the HTML, whereas a property is JavaScript.) There are several different ways to show a dialog on a page. In JavaScript, you can call showModal() to show the dialog modally or show() to show the dialog non-modally. Both functions set the open attribute on the dialog.
You can also show a dialog without using JavaScript by setting the open attribute in HTML.
<dialog open>
If the open attribute is set when the dialog element is created, then the dialog is shown non-modally.
Since the open attribute is set in all of these situations, the attribute doesn't tell you whether the dialog is shown modally or non-modally. Moreover, the HTML dialog element lacks a "modal" attribute or property. No API exists to determine whether a dialog is shown modally or non-modally. Nonetheless, the element does have an internal is modal flag, which is not accessible to JavaScript. By default, the "is modal" flag is false; if you call showModal(), the flag gets set to true.
If you accidentally use the API incorrectly, the dialog element can throw exceptions… in some cases. For example,
<dialog id="test" open>
<p>Testing</p>
</dialog>
<script>
window.onload = function() {
document.getElementById("test").showModal();
};
</script>
This code throws InvalidStateError, because when showModal() is called, the dialog was already shown non-modally from the open attribute.
According to the documentation,
However, this documentation is no longer accurate! Last year the major web browser vendors decided to change the standard (remember, HTML is now a "living standard") so that exceptions are not thrown for redundant actions, e.g., opening an already open dialog, but only for attempting to switch modes, e.g., calling showModal() on an open non-modal dialog.
At this point, you might be wondering how I know so much about the dialog element. Honestly, it's a lot more than I ever wanted to know. The knowledge was essentially thrust upon me by unfortunate circumstances. It turns out that the change in the HTML standard with regard to throwing exceptions corresponded with the release of Safari version 17, which adopted the new behavior. Safari 16 still has the old behavior. In December I introduced StopTheMadness Pro, a major update to my Safari extension StopTheMadness. On iPhone and iPad, StopTheMadness Pro initially required iOS 17, which includes Safari 17. I had several reasons for requiring iOS 17, one of which was that I don't own any devices with iOS 16 installed. I was worried that I couldn't adequately test iOS 16 support for StopTheMadness Pro. Ultimately, though, I caved in to customer demand and added iOS 16 support a couple of weeks ago in StopTheMadness Pro version 4.0. This was followed the same day by StopTheMadness Pro version 4.1, an emergency bug fix update.
The bug was that in one particular situation, showModal() could be called twice on the same dialog. The two calls occurred in two separate functions, which is why I didn't notice in the source code, and in Safari 17 the redundant calls were harmless, which is why I didn't notice at all during the long development of StopTheMadness Pro. In Safari 16, on the other hand, the harmless redundancy became an exception, breaking the Safari extension popup. I did of course test iOS 16 support for StopTheMadness Pro in the Xcode simulator, but the lack of a physical iOS 16 device and the short development period left gaps in my testing, and this bug fell through the gaps. My original fear, which had motivated me to require iOS 17, now became a reality.
The web browser vendors believed that they were doing a favor for developers by changing the (already convoluted) dialog API to make it less strict. Yet their good intentions backfired on me. I don't think we can say that the API was well-designed or well-managed.