26

I need to discover which html element was under the finger when the touchend event is called. The code I am using;

$('.wsSquare').on("mouseup touchend",function(event){
    event.preventDefault();
    event.stopPropagation();
    console.log($(event.target).data());    
});

Using the mouse on a (non-touch) device, this code correctly logs the data associated with the element under the mouse at the time of the mouseup event.

However on a touch device (ipad safari), event.target is the element that was under the finger during the touchstart event and logs the data of the element under the touchstart event

I've also examined the behavior of the touchmove event, this also has the same behaviour (the event.target is touchstart element). It seems that the target for all the touch events is the element touched at the beginning of the gesture.

I need to access the element under the finger when the touchend event is called. My gesture potentially traverses many elements.

Edit

Further research dug up this from the specification.

5.5 The touchend event

A user agent must dispatch this event type to indicate when the user removes a touch point from the touch surface, also including cases where the touch point physically leaves the touch surface, such as being dragged off of the screen.

The target of this event must be the same Element on which the touch point started when it was first placed on the surface, even if the touch point has since moved outside the interactive area of the target element.

The touch point or points that were removed must be included in the changedTouches attribute of the TouchEvent, and must not be included in the touches and targetTouches attributes.

So the observed behavior is correct, how can I change this behavior?

Ken
  • 4,367
  • 4
  • 28
  • 41

1 Answers1

38

Use document.elementFromPoint and feed it the co-ordinates from the events, for example, like this:

$('.wsSquare').on("mouseup touchend",function(event){
    event.preventDefault();
    event.stopPropagation();
    var changedTouch = event.changedTouches[0];
    var elem = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
    // Do something with elem
});
willlma
  • 7,353
  • 2
  • 30
  • 45
Some Guy
  • 15,854
  • 10
  • 58
  • 67
  • 4
    I think the `TouchEvent` itself has no coordinates, but the [`.changedTouches.item(0)`](http://www.w3.org/TR/2011/WD-touch-events-20110505/#widl-TouchEvent-changedTouches) should have `pageX/Y`. – Bergi Jul 17 '12 at 13:53
  • @Bergi As far as I've used TouchEvents, it depends on which device and browser is being used more. But that link should help the OP find what works for him. Also, [this](https://developer.mozilla.org/en/DOM/Touch_events) – Some Guy Jul 17 '12 at 13:56
  • 2
    This threw an error where mouse events were involved. A better approach would probably be to use it like this: `var quit = e.changedTouches;` and then check if it is not a falsy before applying the next line. `if (quit) var elem = document.elementFromPoint(quit[0].clientX, quit[0].clientY);`. I've used different variables for readability. – Shikkediel Dec 13 '17 at 08:25
  • I would have upvoted because it was otherwise quite useful. But it just doesn't work: [demo](https://codepen.io/anon/pen/OzVpPb?editors=0010). – Shikkediel Dec 14 '17 at 16:10