在我的网页上,我有两个div,A和B:
DOM如下所示(简化)。这里需要注意的主要问题是,div在DOM层次结构中处于同一级别,并且它们不按任何顺序排序。此外,外部div不仅包含A和B,还包含更多div,C,D,E等.B可能不一定与A重叠。它也可能是C,位于A后面。
<div>
<div style="...">B</div>
<div style="...">A</div>
</div>
单击处理程序附加到外部div,在冒泡阶段捕获A或B上的鼠标单击事件。单击进入A和B的交叉点将导致A上的单击事件,该事件会冒泡到我现在触发的单击处理程序。
现在问题:在某些条件下,处理程序决定事件不应由A处理但应该属于B.如果事件应由B处理,则将触发相同的单击处理程序,但事件对象{ {1}}属性将是B而不是A.
我怎样才能做到这一点?
我已经在JS中查看了css3指针处理程序和一些事件调度方法,但是在这里找不到解决方案。
可能的解决方案1(不兼容跨浏览器)?:
我想我可以使用pointer-events css3 property。如果处理程序决定该事件应由B处理,则它将指针事件设置为无。然后,它重新触发鼠标点击。 问题:是否可以仅使用坐标重新触发鼠标,而不指定特定元素?
无论如何,指针事件的支持是有限的:http://caniuse.com/pointer-events
答案 0 :(得分:3)
您可以尝试将事件传递给B
(使用jQuery):
(伪代码)
var $A = $('#A'), $B = $('#B');
$B.on('click', function () {
console.log('B clicked');
});
$('#outer').on('click', function (evt) {
if (Math.random() < 0.1) { // << pseudo condition
$B.trigger(evt);
}
});
<强>更新强>:
使用这样的函数:
// this function should (did not enough testing) return all elements at a given
// point in the order of top to bottom.
var elementsFromPoint = function (x, y, root) {
var buffer = [], result = [], el, i = 0, lim;
while ((el = document.elementFromPoint(x, y)) && [root, document.body, document.body.parentNode].indexOf(el) < 0) {
result.push(el);
buffer.push({el: el, visibility: el.style.visibility});
el.style.visibility = 'hidden';
}
for (lim = buffer.length; i < lim; i += 1) {
buffer[i].el.style.visibility = buffer[i].visibility;
}
return result;
};
您可以获取给定x / y坐标的元素。它有点hacky,但需要更多的测试。
$('#outer').on('click', function (evt) {
var elements = elementsFromPoint(
evt.pageX + $(this).offset().left,
evt.pageY + $(this).offset().top,
this
);
console.log(elements);
});
演示:http://jsfiddle.net/hzErh/1/
更新2 :此版本应为许多元素提供更好的性能:
// this function should (did not enough testing) return all elements at a given
// point, though the order is not representative for the visible order.
var elementsFromPoint = function (root, x, y) {
var result = [], i = 0, lim = root.childNodes.length, bb;
for (; i < lim; i += 1) {
bb = root.childNodes[i].getBoundingClientRect();
if (bb.left <= x && x <= bb.right && bb.top <= y && y <= bb.bottom) {
result.push(root.childNodes[i]);
}
}
return result;
};