CloseWatcher
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Experimental:This is anexperimental technology
Check theBrowser compatibility table carefully before using this in production.
TheCloseWatcher interface allows a custom UI component with open and close semantics to respond to device-specific close actions in the same way as a built-in component.
TheCloseWatcher interface inherits fromEventTarget.
In this article
Constructor
CloseWatcher()ExperimentalCreates a new
CloseWatcherinstance.
Instance methods
This interface also inherits methods from its parent,EventTarget.
CloseWatcher.requestClose()ExperimentalFires a
cancelevent and if that event is not canceled withEvent.preventDefault(), proceeds to fire acloseevent, and then finally deactivates the close watcher as ifdestroy()was called.CloseWatcher.close()ExperimentalImmediately fires the
closeevent, without firingcancelfirst, and deactivates the close watcher as ifdestroy()was called.CloseWatcher.destroy()ExperimentalDeactivates the close watcher so that it will no longer receive
closeevents.
Events
cancelExperimentalAn event fired before the
closeevent, so thatclosecan be prevented from firing.closeExperimentalAn event fired when a close request was received.
Description
Some UI components have "close behavior", meaning that the component appears, and the user can close it when they are finished with it. For example: sidebars, popups, dialogs, or notifications.
Users generally expect to be able to use a particular mechanism to close these elements, and the mechanism tends to be device-specific. For example, on a device with a keyboard it might be theEsc key, but Android might use the back button. For built-in components, such aspopover or<dialog> elements, the browser takes care of these differences, closing the element when the user performs the close action appropriate for the device. However, when a web developer implements their own closable UI component (for example, a sidebar), it is hard to implement this kind of device-specific close behavior.
TheCloseWatcher interface solves this problem by delivering acancel event, followed by aclose event, when the user executes the device-specific close action.Web applications can use theonclose handler to close the UI element in response to the device-specific event.They can also trigger these same events in response to the UI element's normal closing mechanism, and then implement commonclose event handling for both the application- and device-specific close action.Once theonclose event handler completes theCloseWatcher is destroyed and the events will no longer be fired.
In some applications the UI element may only be allowed to close when it is in a particular state; for example, when some needed information is populated.To address these cases, applications can prevent theclose event from being emitted by implementing a handler for thecancel event that callsEvent.preventDefault() if the UI element is not ready to close.
You can createCloseWatcher instances withoutuser activation, and this can be useful to implement cases like session inactivity timeout dialogs. However, if you create more than oneCloseWatcher without user activation, then the watchers will be grouped, so a single close request will close them both.In addition, the first close watcher does not necessarily have to be aCloseWatcher object: it could be a modal dialog element, or a popover generated by an element with the popover attribute
Examples
>Processing close requests
In this example, you have your own UI component (a picker) and you want to support both, the platform's default close method (e.g., theEsc key) and your custom close method (a close button).
You create aCloseWatcher to handle allclose events.
Theonclick handler of your UI component can callrequestClose to request a close and to route your close request through the sameonclose handler the platform close method uses.
const watcher = new CloseWatcher();const picker = setUpAndShowPickerDOMElement();let chosenValue = null;watcher.onclose = () => { chosenValue = picker.querySelector("input").value; picker.remove();};picker.querySelector(".close-button").onclick = () => watcher.requestClose();Closing a sidebar using a platform close request
In this example we have a sidebar component that is displayed when an "Open" button is selected, and hidden using either a "Close" button or platform-native mechanisms.To make it more interesting, this is a live example!
Note also that the example is a little contrived, because normally we would use a toggle button to change a sidebar state.We could certainly do that, but using separate "Open" and "Close" buttons makes it easier to demonstrate the feature.
HTML
The HTML defines "Open" and "Close"<button> elements, along with<div> elements for the main content and the sidebar.CSS is used to animate the display of the sidebar element when theopen class is added or removed from the sidebar and content elements (this CSS is hidden because it is not relevant to the example).
<button type="button">Open</button><button type="button">Close</button><div>Sidebar</div><div>Main content</div>.sidebar { position: fixed; top: 20px; left: -300px; right: auto; bottom: 0; width: 300px; /* Adjust the width as needed */ background-color: lightblue;}.main-content { position: fixed; top: 20px; left: 0; right: 0; bottom: 0; width: auto; /* Adjust the width as needed */ background-color: green; margin-left: 0px; /* Adjust for the sidebar width */}.sidebar.open { left: 0; /* Slide the sidebar to the right when open */ transition: left 0.3s ease-in-out; /* Add a smooth transition effect */}.main-content.open { margin-left: 300px; /* Adjust for the sidebar width */ transition: margin-left 0.3s ease-in-out; background-color: green;}JavaScript
The code first gets variables for the buttons and<div> elements defined in the HTML.It also defines a functioncloseSidebar() that is called when the sidebar is closed, to remove theopen class from the<div> elements, and adds aclick event listener that calls theopenSidebar() method when the "Open" button is clicked.
const sidebar = document.querySelector(".sidebar");const mainContent = document.querySelector(".main-content");const sidebarOpen = document.getElementById("sidebar-open");const sidebarClose = document.getElementById("sidebar-close");function closeSidebar() { sidebar.classList.remove("open"); mainContent.classList.remove("open");}sidebarOpen.addEventListener("click", openSidebar);The implementation ofopenSidebar() is given below.The method first checks if the sidebar is already open, and if not, adds theopen class to the elements so that the sidebar is displayed.
We then create a newCloseWatcher and add a listener that will callclose() on it if the "Close" button is clicked.This ensures that theclose event is called when either platform native close methods or the "Close" button are used.The implementation of theonclose() event handler simply closes the sidebar, and theCloseWatcher is then destroyed automatically.
function openSidebar() { if (!sidebar.classList.contains("open")) { sidebar.classList.add("open"); mainContent.classList.add("open"); // Add new CloseWatcher const watcher = new CloseWatcher(); sidebarClose.addEventListener("click", () => watcher.close()); // Handle close event, invoked by platform mechanisms or "Close" button watcher.onclose = () => { closeSidebar(); }; }}Note that we chose to callclose() on the watcher instead ofCloseWatcher.requestClose() because we don't need thecancel event to be emitted (we would userequestClose() and thecancel event handler if there was a reason to ever prevent the sidebar from closing prematurely).
Result
Select the "Open" button to open the sidebar. You should be able to close the sidebar using the "Close" button or the usual platform method, such as theEsc key on Windows.
Specifications
| Specification |
|---|
| HTML> # closewatcher> |
Browser compatibility
See also
closeevent onHTMLDialogElement