I am making a custom element dialog box. It is NOT modal, so needs to detect a click outside of itself to close, but I should not close when the click is inside (unless the property closeOnClick
is set). It uses a default <slot>
for the contents of the dialog box. The html for it is like this (I use lit-element
but that is not relevant to this question).
<style>
:host {
display: block;
}
dialog {
position: fixed;
padding: 10px;
margin:0;
border: none;
border-radius: 2px;
box-shadow: 0 0 40px rgba(0,0,0,0.1), 0 0 10px rgba(0,0,0,0.25);
}
</style>
<dialog
id="dialog"
@close="${this._dialogClosed}"
@keys-pressed="${this._keysPressed}">
<slot></slot>
</dialog>
I manage multiple instances by holding a Map of instances with the z-index as the value. When there is at least one open dialog box I have an event listener on window
for the click
event. When I receive a click I use the following code to see whether to close the dialog (this.sizingTarget
is the dialog
element within the shadowRoot
of my element).
const keys = [...openDialogs.keys()];
const self = keys[keys.length -1];
if (self.clickReady && (self.closeOnClick || !self.sizingTarget.contains(e.composedPath()[0]))) {
//click was outside dialog (or we close on click), so close
self.close('click');
}
The problem is the test !self.sizingTarget.contains(e.composedPath()[0])
does not appear to work when the element clicked on is itself a custom element with some <slot>
elements in it. I found a long discussion on github about this issue and it appears they resolved it by adding Node.isConnected
property. But I can't work out how you are supposed to use it.
Can someone please explain how I should go about seeing if the element clicked is actually within the finally distributed nodes in my tree of elements and their (all open) shadowRoots.