javascript - 在被光 DOM 中的元素(不是父元素)覆盖的影子 DOM 元素上触发事件

标签 javascript css addeventlistener shadow-dom

我正在尝试获取影子 DOM 表格单元格的坐标,该表格单元格可能(或可能不)在其前面显示叠加元素。可点击的覆盖元素可能跨越多个单元格,因此它们不一定是我需要坐标的单元格的子元素。

我无法让事件像我预期的那样在表格中冒泡。我相信影子 DOM 的事件重新定位会阻止事件在光 DOM 中发起时击中单元格(我有点认为这是错误的方法,因为覆盖元素不是我想要坐标开始的单元格)

“pointer-events: none;”属性几乎可以满足我的要求,但是,我还需要事件在轻型 DOM 覆盖元素上触发,所以我不知道这是否是一个选项。

我认为避免将监听器附加到每个单元格以解决性能问题是个好主意(在最终应用程序中将有数百个单元格)

我正在使用原生 JavaScript

在提供的示例中,是否可以在单击覆盖的 div 灰色时获取底层表格单元格的正确坐标?

class Custom_Grid extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({
      mode: 'open'
    });
    this.shadowRoot.innerHTML = `
        <style>
          td {
            height:50px; width:50px; border: 1px solid grey;            
          }
        </style>
        <table>
        <tr>
        <td id='x0y0'><slot name='x0y0'></slot></td>
        <td id='x0y1'><slot name='x0y1'></slot></td>
        <td id='x0y2'><slot name='x0y2'></slot></td>
        </tr>
        <tr>
        <td id='x1y0'><slot name='x1y0'></slot></td>
        <td id='x1y1'><slot name='x1y1'></slot></td>
        <td id='x1y2'><slot name='x1y2'></slot></td>
        </tr>
        <tr>
        <td id='x2y0'><slot name='x2y0'></slot></td>
        <td id='x2y1'><slot name='x2y1'></slot></td>
        <td id='x2y2'><slot name='x2y2'></slot></td>
        </tr>
        
      `;
  }
  connectedCallback() {
    this.shadowRoot.addEventListener("click", (e) => {
      if (e.target.matches('td'))
        console.log(`Grid Cell: ${e.target.id}`)
    });
  }

}

window.customElements.define('custom-grid', Custom_Grid);


document.getElementById('grid_overlay').addEventListener("click", (e) => {
  console.log("#overGrid Click")
});
#grid_overlay {
  width: 100px;
  height: 100px;
  background-color: grey;
  position: absolute;
  /*pointer-events: none; <-- not an option?*/
}
<custom-grid>
  <div slot='x1y0' id='grid_overlay'></div>
</custom-grid>

最佳答案

一种解决方案是暂时隐藏覆盖元素,以便通过 elementFromPoint() 获得被覆盖的元素。方法。

if ( e.target.id === 'grid_overlay' ) {        
   console.log( 'overlay click' )
   e.target.hidden = true 
   var el = this.shadowRoot.elementFromPoint( e.x, e.y )
   if (el.id)
     console.log( 'under: ', el.id )
   e.target.hidden = false
}

class Custom_Grid extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
        <style>
          td {
            height:50px; width:50px; border: 1px solid grey;            
          }
        </style>
        <table>
        <tr>
        <td id='x0y0'><slot name='x0y0'></slot></td>
        <td id='x0y1'><slot name='x0y1'></slot></td>
        <td id='x0y2'><slot name='x0y2'></slot></td>
        </tr>
        <tr>
        <td id='x1y0'><slot name='x1y0'></slot></td>
        <td id='x1y1'><slot name='x1y1'></slot></td>
        <td id='x1y2'><slot name='x1y2'></slot></td>
        </tr>
        <tr>
        <td id='x2y0'><slot name='x2y0'></slot></td>
        <td id='x2y1'><slot name='x2y1'></slot></td>
        <td id='x2y2'><slot name='x2y2'></slot></td>
        </tr>
        
      `;
  }
  connectedCallback() {
    this.shadowRoot.addEventListener("click", (e) => {
      if (e.target.matches('td'))
        console.log(`Grid Cell: ${e.target.id}`)
      else if (e.target.id === 'grid_overlay' ) {        
        console.log( 'overlay click ' )
        e.target.hidden = true 
        var el = this.shadowRoot.elementFromPoint( e.x, e.y )
        if (el.id)
          console.log( 'under: ', el.id )
        e.target.hidden = false
      }
    });
  }
}

window.customElements.define('custom-grid', Custom_Grid);
#grid_overlay {
  width: 100px;
  height: 100px;
  background-color: grey;
  position: absolute;
}
<custom-grid>
  <div slot='x1y0' id='grid_overlay'></div>
</custom-grid>

关于javascript - 在被光 DOM 中的元素(不是父元素)覆盖的影子 DOM 元素上触发事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57749564/

相关文章:

javascript - 将对象添加到另一个对象中的另一个对象

javascript - 从另一台计算机访问 Chrome 扩展程序

javascript - Chrome 移动模拟器中的 ReactJS 升级导致触摸事件中断

Javascript - 单击一个元素以将其内容复制到剪贴板

javascript - 禁用双击 body 标签

javascript - 更改工具栏背景颜色并在 body 滚动时使用react

jquery - 如何正确地将 Bootstrap 文件实现为 html?

html - 背景图片仅在内容位于 div 中时出现

javascript - 表单 onSubmit 触发错误的按钮

javascript - 强制 javascript EventListener 执行一次?