4

How can we implement double tap and long press events in angular 7 in a proper way for ipad.

I have custom implementation for the above functionality using directives. But the problem is that it's killing the scroll functionality.

I have searched hammerJS for the respective events but couldn't find out.

Long Press Directive

 import { Directive, Input, Output, EventEmitter, HostListener, HostBinding } from '@angular/core';
    import { DataService } from '../services/data.service';

    @Directive({
     selector: '[appLongPress]'
     })
    export class LongPressDirective {

    @Input() duration: number = 1500;

    @Output() onLongPress: EventEmitter<any>  = new EventEmitter<any>();
    @Output() onLongPressing: EventEmitter<any>  = new EventEmitter<any>();
    @Output() onLongPressEnd: EventEmitter<any>  = new EventEmitter<any>();

    private pressing: boolean;
    private longPressing: boolean;
    private timeout: any;
    private mouseX:number = 0;
    private mouseY: number= 0;

    constructor(private dataService: DataService) { }

    @HostBinding('class.press')
  get press() { return this.pressing; }

  @HostBinding('class.longpress')
  get longPress() { return this.longPressing; }

  @HostListener('touchstart', ['$event'])
  onTouchStart(event) {
    this.pressing = true;
    this.longPressing = false;
    this.timeout = setTimeout(() => {
      this.longPressing = true;
      // Passing coordinates of the long tapped position
      this.mouseX = event.clientX;
      this.mouseY = event.clientY;
      this.onLongPress.emit(event);
      this.dataService.publishCoordinates({x: this.mouseX, y: this.mouseY});
      this.loop(event);
    }, this.duration);

    this.loop(event);
  }

  @HostListener('mousedown', ['$event'])
  onMouseDown(event) {
    // don't do right/middle clicks
    if(event.which !== 1) {
      return;
    }

    this.mouseX = event.clientX;
    this.mouseY = event.clientY;

    this.pressing = true;
    this.longPressing = false;

    this.timeout = setTimeout(() => {
      this.longPressing = true;
      this.mouseX = event.clientX;
      this.mouseY = event.clientY;
      this.onLongPress.emit(event);
      this.dataService.publishCoordinates({x: this.mouseX, y: this.mouseY});
      this.loop(event);
    }, this.duration);

    this.loop(event);
  }

  loop(event) {
    if(this.longPressing) {
      this.timeout = setTimeout(() => {
        this.onLongPressing.emit(event);
      }, 50);
    }
  }

  endPress() {
    clearTimeout(this.timeout);
    this.longPressing = false;
    this.pressing = false;
    this.onLongPressEnd.emit(true);
  }

  @HostListener('touchend')
  onTouchEnd() { this.endPress(); }

  @HostListener('mouseup')
  onMouseUp() { this.endPress(); }

   }

double tap directive

    import { Directive, HostListener, Output, EventEmitter } from '@angular/core';

@Directive({
  selector: '[appDoubleTap]'
})
export class DoubleTapDirective {

  @Output() doubleTap = new EventEmitter();
  @Output() tripleTap = new EventEmitter();

  constructor() { }

  @HostListener('tap',  ['$event'])
  onTap(e) {
    if (e.tapCount === 2) {
      this.doubleTap.emit(e)
    }

    if (e.tapCount === 3) {
      this.tripleTap.emit(e)
    }
  }
}

The template sample that I used is

 <div appDoubleTap appLongPress (onLongPressing)="lineRowLongPressed(line.lineNum)" (doubleTap)="doubleClick_calender(line)">
                            <div class="long-press-front">
                                <td>
                                    <p>{{line.orderNum}}</p>
                                </td>
                                <td>
                                    <p *ngIf="line.xxx"><img id="xxximg" style="width: 14px;" src="assets/icons/xxx.png"></p>
                                    <p *ngIf="line.yyy"><img id="yyy" style="width: 14px;" src="assets/icons/yyy.png"></p>
                                </td>
                                <td>
                                    <p>x</p>
                                </td>
                            </div>
                            <div class="long-press-dynamic-content" id="sortableLine">
                                <td *ngFor="let col of line.values" class="xxx-col-values">{{col}}</td>
                            </div>
                        </div>

I also tried the hammerjs (press) event but still the scroll isn't get smooth. Also is it possible to set the time span for press event in hammer?

leox
  • 1,315
  • 17
  • 26

1 Answers1

0

You can use

  1. Timers to achieve long tap
  2. Jquery 'taphold' event from Jquery mobile
  3. Or get a opensource javascript library or jquery plugin to do the job. For example: https://pressurejs.com (comes with polyfill)

Take a look at this question and you will find a suitable way for your needs Long Press in JavaScript?

Jp Vinjamoori
  • 1,173
  • 5
  • 16