确定用户是否在阴影dom外部单击 [英] Determine if user clicked outside shadow dom

查看:68
本文介绍了确定用户是否在阴影dom外部单击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施一个下拉菜单,你可以点击外面关闭。下拉列表是自定义日期输入的一部分,并封装在输入的影子DOM中。

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.

我想写下这样的内容:

window.addEventListener('mousedown', function (evt) {
  if (!componentNode.contains(evt.target)) {
    closeDropdown();
  }
});

然而,该事件被重新定位,所以 evt.target 总是元素之外。事件在到达窗口之前会有多个阴影边界,因此似乎无法真正了解用户是否在组件内部点击。

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.

注意:我没有在任何地方使用聚合物 - 我需要一个适用于通用阴影DOM的答案,而不是聚合物特定的黑客。

Note: I'm not using polymer anywhere -- I need an answer which applies to generic shadow DOM, not a polymer specific hack.

推荐答案

您可以尝试使用事件对象的路径属性。 尚未找到实际参考资料且MDN还没有页面。 HTML5Rocks 在那里有一小部分关于它的内容dom教程虽然。因此,我不知道这些浏览器的兼容性。

You can try using the path property of the event object. Haven't found a actual reference for it and 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.

找到 W3 Spec 关于事件路径,不确定这是否完全适用于 Event.path 属性,但它是我能找到的最接近的参考。

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.

如果有人知道对 Event.path 的实际规范引用(如果链接的规范页面是'n'已经可以随意编辑了。

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.

它保存了事件经历的路径。它将包含阴影dom中的元素。列表中的第一个元素( path [0] )应该是实际点击的元素。请注意,您需要从影子dom引用中调用 contains ,例如 shadowRoot.contains(e.path [0])或阴影dom中的一些子元素。

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 call contains from the shadow dom reference, eg shadowRoot.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.

var host = document.querySelector('#host');
var root = host.createShadowRoot();
d = document.createElement("div");
d.id = "shadowdiv";

d.innerHTML = `
  <div id="menu">
    <div class="menu-item menu-toggle">Menu</div>
    <div class="menu-item">Item 1</div>
    <div class="menu-item">Item 2</div>
    <div class="menu-item">Item 3</div>
  </div>
  <div id="other">Other shadow element</div>
`;
var menuToggle = d.querySelector(".menu-toggle");
var menu = d.querySelector("#menu");
menuToggle.addEventListener("click",function(e){
  menu.classList.toggle("active");
});
root.appendChild(d)

//Use document instead of window
document.addEventListener("click",function(e){
  if(!menu.contains(e.path[0])){
    menu.classList.remove("active");
  }
});

#host::shadow #menu{
  height:24px;
  width:150px;
  transition:height 1s;
  overflow:hidden;
  background:black;
  color:white;
}
#host::shadow #menu.active {
  height:300px;
}
#host::shadow #menu .menu-item {
  height:24px;
  text-align:center;
  line-height:24px;
}

#host::shadow #other {
  position:absolute;
  right:100px;
  top:0px;
  background:yellow;
  width:100px;
  height:32px;
  font-size:12px;
  padding:4px;
}

<div id="host"></div>

这篇关于确定用户是否在阴影dom外部单击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆