如何将单击传播到光标下的所有div?

我有一堆divs绝对相互搭配。 当我将click事件绑定到所有这些事件时,只有top div响应。 如何将事件发送到光标下的所有div?

考虑到FelixKling的建议使用document.elementFromPoint()和Amberlamps的小提琴,并使用jQuery进行DOM交互,我最终得到以下内容:

 $divs = $("div").on('click.passThrough', function (e, ee) { var $el = $(this).hide(); try { console.log($el.text());//or console.log(...) or whatever ee = ee || { pageX: e.pageX, pageY: e.pageY }; var next = document.elementFromPoint(ee.pageX, ee.pageY); next = (next.nodeType == 3) ? next.parentNode : next //Opera $(next).trigger('click.passThrough', ee); } catch (err) { console.log("click.passThrough failed: " + err.message); } finally { $el.show(); } }); 

DEMO

try/catch/finally用于确保元素再次显示,即使发生错误也是如此。

有两种机制允许click事件通过或不通过:

  • 将处理程序仅附加到选定的元素(标准jQuery)。
  • 命名空间click事件, click.passThrough类似于event.stopPropagation()

单独地或组合地,这些机制在控制“passThrough”行为的附着和传播方面提供了一些灵活性。 例如,在DEMO中,尝试从“b”元素中删除类p ,并查看传播行为是如何更改的。

就目前而言,需要编辑代码以获得不同的应用程序级行为。 更通用的解决方案是:

  • 允许以程序身份附加特定于应用的行为
  • 允许以编程方式抑制“passThrough”传播,类似于event.stopPropagation()

这两个目标都可以通过在jQuery中建立一个clickPassthrough事件来实现,具有潜在的“passThrough”行为,但实现这一目标还需要做更多的工作。 也许有人想要去。

这并不像你想象的那么容易。 这是我提出的解决方案。 我只在Chrome中测试过,我没有使用任何框架。

以下代码段仅用于向文档中的每个div添加一个click事件,该事件在触发时输出其类名。

 var divs = document.getElementsByTagName("div"); for(var i = 0; i < divs.length; i++) { divs[i].onclick = function() { console.log("class clicked: " + this.className); }; } 

将click事件附加到body元素,以便我们的脚本注意到每个单击事件。

 if(document.addEventListener) { document.body.addEventListener("click", countDivs); } else if(document.attachEvent) { document.attachEvent("onclick", countDivs); } 

迭代你要检查的所有div(你可能想在这里调整你喜欢的div范围)。 生成他们的计算样式并检查鼠标坐标是否在div的位置加上其宽度和高度的范围内。 当div是我们的源元素时,不要触发click事件,因为click事件已经被触发了。

 function countDivs(e) { e = e || window.event; for(var i = 0; i < divs.length; i++) { var cStyle = window.getComputedStyle(divs[i]); if(divs[i] !== e.target && e.pageX >= parseInt(cStyle.left) && e.pageX <= (parseInt(cStyle.left) + parseInt(cStyle.width)) && e.pageY >= parseInt(cStyle.top) && e.pageY <= (parseInt(cStyle.top) + parseInt(cStyle.height))) { divs[i].click(); } } } 

CSS:

 .a, .b, .c { position: absolute; height: 100px; width: 100px; border: 1px #000 solid } .a { top: 100px; left: 100px; } .b { top: 120px; left: 120px; } .c { top: 140px; left: 140px; } 

HTML:

 

我还添加了一个jsFiddle

一种简单的方法可以是使用elementFromPoint():

http://jsfiddle.net/SpUeN/1/

 var clicks = 0,cursorPosition={}; $('div').click(function (e) { if(typeof cursorPosition.X === 'undefined') { cursorPosition.X = e.pageX; cursorPosition.Y = e.pageY; } clicks++; e.stopPropagation(); $(this).addClass('hided'); var underELEM = document.elementFromPoint(cursorPosition.X, cursorPosition.Y); if (underELEM.nodeName.toUpperCase() === "DIV") $(underELEM).click(); else { $('#clicks').html("Clicks: " + clicks); $('.hided').removeClass('hided'); clicks=0; cursorPosition = {}; } }); 

如果要绝对堆叠元素,将它们全部堆叠在已定位的容器中可能更简单,并处理来自此父级的事件。 然后你可以操纵它的孩子,而不必测量任何东西。