27

Does anybody know of either a jQuery or native JavaScript way to enable mouse events through layers? e.g. enable a link underneath a div.

Other solutions that cannot use in my case:

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
davivid
  • 5,910
  • 11
  • 42
  • 71

6 Answers6

38

You can do all that or you can just use this CSS for that div:

pointer-events: none

Anubhav Gupta
  • 1,176
  • 11
  • 12
  • Solution for Internet Explorer is a bit tricky, You can find it [here](http://stackoverflow.com/questions/5855135/css-pointer-events-property-alternative-for-ie) – Anubhav Gupta Aug 13 '13 at 07:40
  • 2
    For reference: IE11 does appear to support this property, which is slightly helpful. – Topher Fangio Feb 04 '15 at 00:17
19

I did it once. Here's the code:

quickDelegate = function(event, target) {
            var eventCopy = document.createEvent("MouseEvents");
            eventCopy.initMouseEvent(event.type, event.bubbles, event.cancelable, event.view, event.detail,
                event.pageX || event.layerX, event.pageY || event.layerY, event.clientX, event.clientY, event.ctrlKey, event.altKey,
                event.shiftKey, event.metaKey, event.button, event.relatedTarget);
            target.dispatchEvent(eventCopy);
            // ... and in webkit I could just dispatch the same event without copying it. eh.
        };

please note that I was only targeting new versions of Firefox and Chrome.

Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
wildcard
  • 7,353
  • 3
  • 27
  • 25
  • This should be the correct answer. I run into this problem when using an SVG overlayed over a canvas. Nothing, and I mean nothing else (libraries, CSS or otherwise) could solve this, and this piece of code above was the only thing that works flawlessly! Kudos dear Sir, thank you! – Ælex Apr 28 '15 at 19:55
  • i also add && (!event.repeat) – Vlad Mysla May 29 '15 at 01:06
  • 4
    How would you apply this? – jmchauv Nov 23 '15 at 19:33
  • 1
    I'm also a little confused as to how to implement this. Can someone explain (or show) it? – birgersp Dec 16 '15 at 09:28
  • replacing target with event.target I am getting a dispatchEvent is not a function error. – a1an Jul 19 '17 at 10:55
3

There is now a jQuery implementation of the ExtJS event forwarding script:

JQuery Forward Mouse Event Example

Nathan Arthur
  • 8,287
  • 7
  • 55
  • 80
Donal
  • 550
  • 1
  • 6
  • 14
2

The jQuery Forward Mouse Event example given here is part of a larger framework and even just figuring that much out from the given website was a chore.

I therefore rewrote the code as a standalone jQuery plugin.

Here's the Github repository:
https://github.com/MichaelPote/jquery.forwardevents

Unfortunately, the purpose I was using it for - overlaying a mask over Google Maps did not capture click and drag events, and the mouse cursor does not change which degrades the user experience enough that I just decided to hide the mask under IE and Opera - the two browsers which dont support pointer events.

Mikepote
  • 6,042
  • 3
  • 34
  • 38
1

You could try using jquery to change the z-index of the div when you hover over it, so that the link is temporarily above the div while hovering over said div.

Seth Archer Brown
  • 1,141
  • 4
  • 12
  • 27
0

Since the JQuery Forward Mouse Event Example link is currently dead, I wrote some jQuery code to handle a simple case:

  1. overlay div with a transparent image and no links
  2. underlay div with links

Goal: keep overlay visible, make links work and cursor change when over a link.

Method: compare the mouse location to each link offset().

I don't handle general mouse events, I just treat the events I need ad-hoc. So it's really a workaround instead of the best solution, which would handle every mouse event abstractly, something like using Wildcard's above quickDelegate() after checking the geometry. Also I only care about certain link elements, not the whole layered DOM.

function mouse_event_over_element(evt, elem) {
  var o= elem.offset();
  var w= elem.width();
  var h= elem.height();
  return evt.pageX >= o.left && evt.pageX <= o.left + w && evt.pageY >= o.top && evt.pageY <= o.top + h;
}

$(overlay_selector).click(function(e){
  $(underlay_selector + ' a').each(function() {
    if (mouse_event_over_element(e, $(this))) {
      // $(this).click(); // trigger a jQuery click() handler
      // quickDelegate(e, this); // not in IE8
      // this.click(); // maybe not in Mozilla pre-HTML5
      window.location.href= this.href;
      return false;
    }
  });
});

$(overlay_selector).mousemove(function(e){
  var newcursor= 'default';
  $(underlay_selector + ' a').each(function() {
    if (mouse_event_over_element(e, $(this))) {
      newcursor= 'pointer';
      // $(this).mouseenter(); // trigger a one-argument jQuery hover() event (no mouseleave)
      return false;
    }
  });
  $(overlay_selector).css('cursor', newcursor);
});

Using the geometry function 'mouse_event_over_element()' you can handle other events and elements.

To do: figure out what mouse events trigger the tooltip over <a title="foo">, and trigger() them, or replicate showing the tooltip. Same for the status line.

..............................

Edit 2014/09

..............................

User user2273627 sggested:

For the default tooltip and status-line you can use the z-index css-property. Check if the mouse is over a link and set the z-index for that link. $(this).css('z-index','9'); Put an else when the mouse is not over an element and set the z-index to auto. Make sure you set the underlying links position: relative in the css-file, otherwise z-index will not work.

kitchin
  • 774
  • 6
  • 9