将鼠标事件调度到视觉上在接收元素“后面”的元素

时间:2012-03-28 14:47:38

标签: javascript css css3

在我的网页上,我有两个div,A和B:

enter image description here

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

1 个答案:

答案 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);
    }
});​

http://jsfiddle.net/hzErh/


<强>更新

使用这样的函数:

// 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;
};

演示:http://jsfiddle.net/CTdZp/2/