Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

Remove e.preventDefault from handleTouchEnd #102

Merged
merged 9 commits into from
Apr 28, 2017

Conversation

danbovey
Copy link
Contributor

As far as I'm aware, this isn't needed. Fixes #98.

As far as I'm aware, this isn't needed. Fixes vkbansal#98.
@vkbansal
Copy link
Owner

Are you sure, this is not needed? This should have been added for a reason.

@danbovey
Copy link
Contributor Author

It works for my use case. And all tests still pass.

@vkbansal
Copy link
Owner

@danbovey I agree that it works for your use case, but it should not break for hundreds of others people who depend on this package. I hope you understand my concern.

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

I would also like it removed to be honest, we haven't seen any adverse effect to removing it, but maybe @bjarkig82 can tell us more as he added it in e0df3b3

@bjarkig82
Copy link
Contributor

bjarkig82 commented Apr 27, 2017

I was working on adding a feature that would trigger the context menu if the element is pressed for sertain amount of time. Have you tested this using a touch screen on a windows device? They fire the left click event if the screen is touched for half a second or so. If I remember correctly, I added this to prevent the default browser context menu to appear over the custom context menu in these cases.

Sorry about the horrible commit message habit :-)

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

Maybe a better solution then would be to keep track of the state of the touch action and make sure that we prevent default only if we showed a contextmenu, but if not then we let the default action occur in touchend:

Something like:

  • on touchstart event set this.touchHandled = false;
  • in touchstart timeout callback, set this.touchHandled=true; then call this.handleContextClick(event);
  • then in touchend check if this.touchHandled === true before calling e.preventDefault()?

@bjarkig82
Copy link
Contributor

I agree, that would be a more elegant solution :-)

@danbovey
Copy link
Contributor Author

Thanks @bjarkig82, at least it does have a purpose being there right now. I've updated this PR with @Seldaek's solution 🎉

@@ -28,6 +28,7 @@ export default class ContextMenuTrigger extends Component {
renderTag: 'div'
};

static touchHandled = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be static but a regular instance property if you address it with this below. i.e. just remove the static keyword and all is fine.

@@ -50,6 +51,8 @@ export default class ContextMenuTrigger extends Component {
if (this.props.holdToDisplay >= 0) {
event.persist();

this.touchHandled = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be inside the lambda function at line 57, otherwise it'll always be true not just when the touch actually triggered the "hold-to-display" functionality, and we're back at the point where preventDefault fires every time.

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

Thanks for updating it :) Hopefully now it's safe enough to be merged.

this.touchstartTimeoutId = setTimeout(
() => this.handleContextClick(event),
this.props.holdToDisplay
this.props.holdToDisplay,
this.touchHandled = true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woops, that's still not good I'm afraid.. To be fair the short syntax is easy to get confused by, but it should be expanded to this:

             this.touchstartTimeoutId = setTimeout(
                 () => {
                     this.handleContextClick(event);
                     this.touchHandled = true;
                 },
                 this.props.holdToDisplay
             );

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to, I hate comma separated stuff

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But setTimeout takes two args, a callback and then a timeout (this.props.holdToDisplay). The way you fixed it now you left the timeout in the middle of the callback, so that's not gonna work :)

Copy link
Contributor Author

@danbovey danbovey Apr 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woops, yeah, this is why you should add curly brackets and semicolons as soon as you start doing more than one thing.

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

Right now you have:

            this.touchstartTimeoutId = setTimeout(
                () => {
                    this.handleContextClick(event),
                    this.props.holdToDisplay,
                    this.touchHandled = true
                }
            );

But this essentially does setTimeout(function() { ... }); without timeout so it executes instantly. The right version should be:

             this.touchstartTimeoutId = setTimeout(
                 () => {
                     this.handleContextClick(event);
                     this.touchHandled = true;
                 },
                 this.props.holdToDisplay
             );

@danbovey
Copy link
Contributor Author

After all of this, I'm not sure it fixing the problem. Running it in Chrome Dev tools which converts clicks to touch events and it's still cancelling regular click events.

@danbovey
Copy link
Contributor Author

Pushed these changes to my app and running it on Android Chrome = same results

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

There is still one issue with the PR I think, in the beginning of handleTouchstart it should set this.touchHandled = false always, otherwise as soon as you once open the context menu then touchHandled remains true always and the preventDefault always trigger from that point on.

Curious if you can try if that fixes it or not..

@danbovey
Copy link
Contributor Author

danbovey commented Apr 27, 2017

@Seldaek that last change fixes it! The file changes make sense to me now 😃

Tested on Chrome Dev Tools and Android and it appears to work.

@Seldaek
Copy link
Collaborator

Seldaek commented Apr 27, 2017

Nice good to hear :)

@vkbansal vkbansal merged commit 646865d into vkbansal:master Apr 28, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants