@yossiz שיפרתי את הקוד, ההערות שלך תוקנו. כעת אם יהיו שיפורים אעדכן את התגובה הזו כל הזמן.
import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
/**
* This directive help us to manage user single click and double click
* In regular DOM events, when a user click double click - twoo events of "click" will be fired, and one event of "dblclick"
* This behevior make troubles. becose if we need one event, and the user click twice, twoo events will be fired.
* So:
* the basic behvior of this directive, is to emit a new event called "singleClick". this event is fired only once,
* and is not affected by the second click of user.
*
* ====================================================================================================================
*
* In addition can you use an event called "singleOrDblclick" so that only one event between them will be triggered,
* and they will not contradict each other.
* So if you have problems with such a scenario
* for example opening dialogs they may close on the second click if they are opened on the first click
* you can solve the problem by listening to the "singleOrDblclick" event.
*
* More beheviors documented bellow in the code
*/
@Directive({
selector: '[mtrSingleClick]'
})
export class SingleClickDirective {
/**
* a flag that tell us if was there a single click before less than the time allotted in the variable "doubleClickSpeed"
*/
private singleClickWasClickedRecently_FLAG = false;
/**
* a flag that tell us if we now after a dblclick event
*/
private isdblClick_FLAG = false;
/**
* the maximum time (in ms) between clicks, that the DOM fired a dblclick event.
*/
@Input() public doubleClickSpeed = 500;
/**
* if you wand that not fired an single click event when the user click double click.
*/
@Input() public ignoreSingleClickWhenDblClick = true;
/**
* use $event.stopPropagation()?
*/
@Input('mtrSingleClickStopPropagation') public stopPropagation = false;
/**
* an event that emmitted once for single click only and not emmitted twice when the user click double click.
* if you choise "ignoreSingleClickWhenDblClick" then this event will not be fired at all - if the user make a double click.
*/
@Output() singleClick = new EventEmitter<any>();
/**
* this event will fired once when the user make a single click or a dblclick
* if the user make a dblclick then the event will be fired only by the dblclick DOM event.
*/
@Output() singleOrDblclick = new EventEmitter<any>();
@HostListener('click', ['$event'])
onClick($event): void {
if (this.stopPropagation) {
$event.stopPropagation();
}
// if singleClickWasClickedRecently we do nothing
if (this.singleClickWasClickedRecently_FLAG) {
return;
}
// Raise a flag
this.singleClickWasClickedRecently_FLAG = true;
// If we ignoreSingleClickWhenDblClick we cannot fire event before checking that the user not click twice
if (this.ignoreSingleClickWhenDblClick) {
// So we have to wait until we make sure we are not in a double click mode
const mainTimer = setTimeout(() => {
// Either way we have to lower the flag
this.singleClickWasClickedRecently_FLAG = false;
if (this.isdblClick_FLAG) {
clearTimeout(mainTimer);
return;
}
// If is not dblclick we emit a single click event
this.emitSingleClickEvent($event);
clearTimeout(mainTimer);
}, this.doubleClickSpeed + 10);
} else {
this.emitSingleClickEvent($event);
const timer = setTimeout(() => {
this.singleClickWasClickedRecently_FLAG = false;
clearTimeout(timer);
}, this.doubleClickSpeed + 10);
}
}
emitSingleClickEvent($event): void {
// console.log('emitSingleClickEvent');
this.singleClick.emit($event);
this.singleOrDblclick.emit($event);
}
@HostListener('dblclick', ['$event'])
onDblclick($event): void {
if (this.stopPropagation) {
$event.stopPropagation();
}
this.isdblClick_FLAG = true;
this.singleOrDblclick.emit($event);
const timer = setTimeout(() => {
this.isdblClick_FLAG = false;
clearTimeout(timer);
}, this.doubleClickSpeed + 100);
}
constructor() { }
}