CloseWatcher
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
The CloseWatcher
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.
The CloseWatcher
interface inherits from EventTarget
.
Constructor
CloseWatcher()
Experimental-
Creates a new
CloseWatcher
instance.
Instance methods
This interface also inherits methods from its parent, EventTarget
.
CloseWatcher.requestClose()
Experimental-
Fires a
cancel
event and if that event is not canceled withEvent.preventDefault()
, proceeds to fire aclose
event, and then finally deactivates the close watcher as ifdestroy()
was called. CloseWatcher.close()
Experimental-
Immediately fires the
close
event, without firingcancel
first, and deactivates the close watcher as ifdestroy()
was called. CloseWatcher.destroy()
Experimental-
Deactivates the close watcher so that it will no longer receive
close
events.
Events
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 the Esc key, but Android might use the back button. For built-in components, such as popover 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.
The CloseWatcher
interface solves this problem by delivering a cancel
event, followed by a close
event, when the user executes the device-specific close action.
Web applications can use the onclose
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 common close
event handling for both the application- and device-specific close action.
Once the onclose
event handler completes the CloseWatcher
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 the close
event from being emitted by implementing a handler for the cancel
event that calls Event.preventDefault()
if the UI element is not ready to close.
You can create CloseWatcher
instances without user activation, and this can be useful to implement cases like session inactivity timeout dialogs. However, if you create more than one CloseWatcher
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 a CloseWatcher
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. the Esc key) and your custom close method (a close button).
You create a CloseWatcher
to handle all close
events.
The onclick
handler of your UI component can call requestClose
to request a close and to route your close request through the same onclose
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 the open
class is added or removed from the sidebar and content elements (this CSS is hidden because it is not relevant to the example).
<button id="sidebar-open" type="button">Open</button>
<button id="sidebar-close" type="button">Close</button>
<div class="sidebar">Sidebar</div>
<div class="main-content">Main content</div>
JavaScript
The code first gets variables for the buttons and <div>
elements defined in the HTML.
It also defines a function closeSidebar()
that is called when the sidebar is closed, to remove the open
class from the <div>
elements, and adds a click
event listener that calls the openSidebar()
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 of openSidebar()
is given below.
The method first checks if the sidebar is already open, and if not, adds the open
class to the elements so that the sidebar is displayed.
We then create a new CloseWatcher
and add a listener that will call close()
on it if the "Close" button is clicked.
This ensures that the close
event is called when either platform native close methods or the "Close" button are used.
The implementation of the onclose()
event handler simply closes the sidebar, and the CloseWatcher
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 call close()
on the watcher instead of CloseWatcher.requestClose()
because we don't need the cancel
event to be emitted (we would use requestClose()
and the cancel
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 the Esc key on Windows.
Specifications
Specification |
---|
HTML Standard # closewatcher |
Browser compatibility
BCD tables only load in the browser
See also
close
event onHTMLDialogElement