naver / hammer.js

A javascript library for multi-touch gestures :// You can touch this
http://hammerjs.github.io
MIT License
43 stars 11 forks source link

Events not fired when used in Polymer/shadow-dom #18

Closed mpilone closed 5 years ago

mpilone commented 5 years ago

I ran into this issue a long while back while working with VisJs Timeline. My original comment is on the Timeline because it uses Hammer internally and used to bundle the old version. It has since switched to using this version via npm.

The root issue is that shadow-dom does event retargeting so when events are captured outside of a shadow-dom element, the event target is retargeted to the shadow-dom element. This causes issues in Hammer because it checks if the input target element has a parent matching the element Hammer was created on. If this check is done by an event handler outside the element Hammer was created on, the information may be incorrect.

For example, if I have the structure:

<my-custom-element>
  #shadow-root
    <span>Click here</span>
</my-custom-element>

If I create a Hammer instance on the span, I will not get "tap" events. I believe this is because Hammer must be capturing the events outside of my-custom-element so the events are already retargeted to my-custom-element and not the span.

In the old version of Hammer I was able to hack around this by modifying the file hammerjs/src/input.js at line 190 to read:

    // find the correct target
    var target = manager.element;
    // if (hasParent(input.srcEvent.target, target)) {
    //     target = input.srcEvent.target;
    // }
    // MIKE FIX
    var eventTarget = input.srcEvent.composedPath().length > 0 ? 
        input.srcEvent.composedPath()[0] : input.srcEvent.target;
    if (hasParent(eventTarget, target)) {
        target = eventTarget;
    }
    input.target = target;

That same code appears in compute-input-data.js at line 65 and has the same problem.

I'm not sure if the right fix is to use the composedPath as I did in my original hack or if Hammer should be listening for events directly on the element so it handles them inside the shadow-dom before event retargeting. I'm not familiar with Hammer enough to know why it would be listening outside the element it was constructed on.

I've attached a simple test case that was made from the Polymer3 starter. I added Hammer as a dependency and added a quick span you can click on. There are two lines where Hammer is constructed. The one targeting the "clickArea" will demonstrate the problem while the one targeting the top most element will work.

You can run "node install" and then use the polymer cli to run "polymer server" and see the issue.

start-polymer3.zip

jongmoon commented 5 years ago

@mpilone Sorry for late to response. We'll check it as soon as possible. Unfortunately, other work is in progress, so it's difficult to check quickly. Please understand.

WoodNeck commented 5 years ago

Hello @mpilone, I've just tested start-polymer3.zip you given but I couldn't reproduce the issue. I'm not sure whether I'm doing it right, so could you give me some more information on how to reproduce it?

image

Oct-01-2019 15-27-59

Tested on OS: macOS mojave 10.14.6 Browser: Chrome 77.0.3865.90 (Also tested on Firefox / Safari latest)

mpilone commented 5 years ago

Thanks for looking into it. I think you're right that it is working. I was thrown off by putting a break point in the compute-input-data.js file which I think was messing up tap detection.

I'm still having the issue with the Timeline component recognizing a tap on the wrong element while it is recognizing a press on the right element. But I'll have to open a bug with them because I can only reproduce the issue within the Timeline and not in Hammer directly. I did notice that they are using propagating-hammer so maybe that is causing some issue.

I attached the full test case with the Timeline if you want to take a look but I know it is outside the scope of just Hammer. In this test case, try to select an item on the timeline by single clicking on it. Then try to select an item with a long press. For some reason one works and the other doesn't. Sorry for wasting your time and you can close this ticket as can't reproduce if you'd like.

start-polymer3-timeline.zip

WoodNeck commented 5 years ago

Thanks for checking @mpilone. As you said, the issue may reside in vis-timeline but I'm afraid I don't have time to test that. I'll check that back when I'm free. I'll close this issue for now, but if you think that is the bug of @naver/hammerjs, feel free to open this issue again. I'll fix it asap 😉