I'm trying to implement a dropdown which you can click outside to close. The dropdown is part of a custom date input and is encapsulated inside the input's shadow DOM.
I want to write something like:
window.addEventListener('mousedown', function (evt) {
if (!componentNode.contains(evt.target)) {
closeDropdown();
}
});
however, the event is retargeted, so evt.target
is always the outside the element. There are multiple shadow boundaries that the event will cross before reaching the window, so there seems to be no way of actually knowing if the user clicked inside my component or not.
Note: I'm not using polymer anywhere -- I need an answer which applies to generic shadow DOM, not a polymer specific hack.
Another option is to check the event cursor offsets against the target element:
You can try using the
path
property of theevent
object.Haven't found a actual reference for itand MDN doesn't yet have a page for it. HTML5Rocks has a small section about it in there shadow dom tutorials though. As such I do not know the compatibility of this across browsers.Found the W3 Spec about event paths, not sure if this is meant exactly for the
Event.path
property or not, but it is the closest reference I could find.If anyone knows an actual spec reference to
Event.path
(if the linked spec page isn't already it) feel free to edit it in.It holds the path the event went through. It will contain elements that are in a shadow dom. The first element in the list (
path[0]
) should be the element that was actually clicked on. Note you will need to callcontains
from the shadow dom reference, egshadowRoot.contains(e.path[0])
or some sub element within your shadow dom.Demo: Click menu to expand, clicking anywhere except on the menu items will close menu.
The
event.target
of theshadowRoot
would be thehost
element. To close a<select>
element withinshadowDOM
ifevent.target
is nothost
element you can useif (evt.target !== hostElement)
, then call.blur()
onhostElement