29

I want to display an image under the mouse (a finger to simulate a touch screen) when a mousedown event occurs and hide it when the mouseup event occurs, but when I do this, the image I display blocks the subsequent mouse events ("click" in particular) on elements under this image. I'm using jQuery, by the way.

I'm sure this is something to do with event bubbling or propagating or somewhat, but I couldn't figure it out. Any pointers please?

isherwood
  • 58,414
  • 16
  • 114
  • 157
Paul Higgins
  • 1,126
  • 1
  • 14
  • 15
  • Give the image low `z-index` and the parent element underneath it higher `z-index` - you also have to give that parent `position: relative;` to make it work properly. – Shadow The GPT Wizard Mar 22 '11 at 22:55
  • 1
    Thanks @Shadow Wizard but I need the finger image to appear on top of everything, so it looks like a finger is pressing the screen. – Paul Higgins Mar 22 '11 at 23:30
  • Using Hussein code as base to new idea, how about this? http://jsfiddle.net/yahavbr/2cSj4/10/ As the finger now move with the mouse you should be able to click anything you like. – Shadow The GPT Wizard Mar 23 '11 at 11:54
  • 1
    possible duplicate of [Click through a DIV to underlying elements](http://stackoverflow.com/questions/3680429/click-through-a-div-to-underlying-elements) – Luke Stevenson Feb 26 '13 at 04:50

4 Answers4

46

Check out this answer to on this post:

https://stackoverflow.com/a/4839672/589909

It seems to do what I understand what you want to achieve using a pure cross browser CSS approach.

pointer-events:none; touch-action:none;

brenjt
  • 15,997
  • 13
  • 77
  • 118
  • 2
    eehh not exactly cross browser. Everything lower than IE11 does not know `pointer-events: none`. There is a JS fallback though: http://www.vinylfox.com/forwarding-mouse-events-through-layers/ – ProblemsOfSumit Mar 13 '14 at 13:34
  • 4
    Also **note:** if you use `pointer-events: none;` to an outer element in the DOM you can apply `pointer-events: auto;` to an inner element to catch the event. – BeatnikDude Jul 15 '16 at 18:03
  • 2
    Pointer-events:none; very nice :D. (also, just let IE die already) Oh wait you posted that in 2014. – Andrew Jan 31 '18 at 01:22
16

Billy Moon, your code was almost working. You just have to use hide and show instead of css :

$('#finger').click(function(e){
  evt = e || window.event;

  // make finger disappear
  $('#finger').hide(0);

  // get element at point of click
  starter = document.elementFromPoint(evt.clientX, evt.clientY);

  // send click to element at finger point
  $(starter).click();

  // bring back the finger
  $('#finger').show(0);
});
Pouf
  • 161
  • 1
  • 5
  • 2
    I believe jQuery takes care of setting `e` properly so the `evt = e || window.event` is redundant. – Alex W Nov 12 '13 at 14:15
2

This is untested - but is based on a working script of mine, so should be along the right lines. Basically, you have to make the layer that is in the way disappear for a moment, so you can use the elementFromPoint method and then make it come back.

$('.selector').click(function(e){
    evt = e || window.event;

    // make finger disappear
    $('.finger').css({display:'none'});

    // get element at point of click
    starter = document.elementFromPoint(evt.clientX, evt.clientY);

    // send click to element at finger point
    $(starter).click();

    // bring back the finger
    $('.finger').css({display:''});
});
Community
  • 1
  • 1
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • Thanks @Billy Moon, that looks promising (I wasn't aware of elementFromPoint) but so far I'm not getting the right element back - I seem to be getting some top level element (like "html" or "document" as far as I can tell). I'll keep playing around with it and update if I get it working using this. – Paul Higgins Mar 22 '11 at 23:50
0

You can do this

$(document).bind('mousedown mouseup', function() {
    $('.finger').toggle();
});

Check working example at http://jsfiddle.net/2cSj4/2/

Hussein
  • 42,480
  • 25
  • 113
  • 143
  • Thanks, this displays/hides the finger but the events are still blocked. – Paul Higgins Mar 22 '11 at 23:24
  • @paul Can you explain what you mean by events still blocked. – Hussein Mar 22 '11 at 23:36
  • @paul Here's an example where i added an click event. Click is not blocked. http://jsfiddle.net/2cSj4/3/ – Hussein Mar 22 '11 at 23:39
  • @Hussein, thanks again - what I mean is that if there is a html element on the page with an onclick attribute, if the finger image appears over that element, then the onclick event doesn't trigger on that element. I'm using firefox/Linux, but I don't think that makes a difference. – Paul Higgins Mar 22 '11 at 23:47
  • @Hussein, ok thanks I will try that - it's a bit tricky to do that (there are onclick attributes all over the site, and also a google map with its own event structure) but it is probably the right way to go in the long run. – Paul Higgins Mar 22 '11 at 23:56
  • @paul If you want to use onclick, you can set `position:absolute;` and use `z-index:-1;` Check it out http://jsfiddle.net/2cSj4/4/ – Hussein Mar 22 '11 at 23:58
  • @paul, it's best to use jQuery to handle all your events rather then mixing jQuery events with inline events such as onclick. That will make your code much easier to read and troubleshoot as it gets bigger. – Hussein Mar 23 '11 at 00:01
  • @Hussein, thanks (again!) - unfortunately I can't use a z-index of -1 because I need the finger to appear on top of everything else (hence the problem). Thanks also for showing me jsfiddle, a very handy tool. – Paul Higgins Mar 23 '11 at 00:13