Sunday, October 16, 2022

[FIXED] How to trigger long-press (click-and-hold) on mobile devices with Vue / JavaScript

Issue

This is only on Mobile devices. It works as intended on desktop, so I'll omit all those styles and functionality.

I have a Vue-component like this:

Template

<div class="container">

  <div class="invisible-overlay-styles">
    <button
      v-if="! videoIsPlaying"
      @click="playVideo()"
      @mousedown="playVideo()"
    >
    </button>

    <a
      v-if="videoIsPlaying"
    >
    </a>
  </div> <!-- invisible-overlay-styles -->

  <video ... /> 

</div>

All the divs, buttons, anchors and videos are stacked on top of one-another, using display: block and position: absolute; width: 100%; etc. etc. etc.

Method

  playVideo(){
    console.log( 'Im playing!!' );
    if( this.player ){
      if( this.player.paused ){
        this.player.play()
      }
    }
  }

If i click it, it works as it should:

  • On the first click, the video plays.
  • On the second click, the link is clicked.

But if I click-and-hold, then neither @click nor @mousedown is triggered. This is both in:

  • Chrome on my Samsung Android-device
  • On Safari on my iPhone 7
  • In iOS Simulator on my Mac. ... I've checked, and no console.logs occur, when I click-and-hold (long-press).

So two questions:

  1. I get why @click isn't triggered, since that's a combination of @mousedown and @mouseup. But why doesn't @mousedown get triggered, when I long-press?
  2. How do I target long-press on mobile devices using Vue (or JavaScript)?

Solution

You'll need to use either the TouchEvent API or the PointerEvent API.

The browser compatibility for both is good:

They each have similar events to the MouseEvent API, i.e. touchstart = mousedown.

I've personally found TouchEvents better than PointerEvents, but, you might have to do some testing to see which is best in your case.


So, as you can guess with Vue, you can use @touchstart:

<button
    v-if="!videoIsPlaying"
    @click="playVideo()"
    @mousedown="playVideo()"
    @touchstart="playVideo()"
/>

If you want to determine it as a long-press, you'll have to store a value on touchstart and change it on touchend:

<button
    @touchstart="touching = true"
    @touchend="touching = false"
/>
...
data() {
    return {
        touching: false
    }
}


Answered By - Daniel_Knights
Answer Checked By - Timothy Miller (PHPFixing Admin)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.