Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Dispatching a mouse event to an element that is visually "behind" the receiving element

Dispatching a mouse event to an element that is visually "behind" the receiving element

Problem

On my web page I have two divs, A and B:

The DOM looks as follows (simplified). The main thing to note here, is that the divs are on the same level in the DOM hierarchy and they are not ordered by anything. Also, the outer div does not only contain A and B but also more divs C,D,E etc. B may not necessarily be overlapped by A. It could also be C, lying behind A.

B
A

A click handler is attached to the outer div, capturing mouse click events on A or B in the bubbling phase. A click into the intersection of A and B will cause an click event on A which bubbles up to my click handler that is now fired.

Now the problem: Under certain conditions the handler decides that the event should not be handled by A but should belong to B. If an event should be handled by B, the same click handler will be fired, but the event objects currentTarget property will be B instead of A.

How can I achieve this?

I've already looked at css3 pointer-handler and some event dispatching methods in JS, but could not really come up with a solution here.

Possible solution 1 (not cross-browser compatible) ?:

I think i might be possible to use the pointer-events css3 property. If the handler decides that the event should be handled by B, it sets the pointer-events to none. Then, it retriggers the mouse click. Question here: Is it possible to retrigger a mouse click with only the coordinates, not specifying a specific element?

Anyway, the support of pointer-events is limited: http://caniuse.com/pointer-events

Problem courtesy of: Erik

Solution

You can try to pass the event to B (using jQuery):

(pseudo-code)

var $A = $('#A'), $B = $('#B');

$B.on('click', function () {
  console.log('B clicked');   
});

$('#outer').on('click', function (evt) {
    if (Math.random() 

http://jsfiddle.net/hzErh/


Update:

using a Function like this:

// 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) 

you can get the elements for a given x/y coordinate. It's a bit hacky and needs more testing though.

$('#outer').on('click', function (evt) {
  var elements = elementsFromPoint(
    evt.pageX + $(this).offset().left,
    evt.pageY + $(this).offset().top,
    this
  );

  console.log(elements);
});

demo: http://jsfiddle.net/hzErh/1/


Update 2: this version should give better performance for many elements:

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

demo: http://jsfiddle.net/CTdZp/2/

Solution courtesy of: Yoshi

Discussion

View additional discussion.



This post first appeared on CSS3 Recipes - The Solution To All Your Style Problems, please read the originial post: here

Share the post

Dispatching a mouse event to an element that is visually "behind" the receiving element

×

Subscribe to Css3 Recipes - The Solution To All Your Style Problems

Get updates delivered right to your inbox!

Thank you for your subscription

×