ui/Button.tstypescript
import { stringTemplate } from "../utils/shared";
import { View } from "./View";
import type { IViewParams, ViewEventsList } from "./View";
import type { EventsHandler } from "../Events";
const TEMPLATE = `<div class="og-button" title="{title}">
<div class="og-button-icon">{icon}</div>
<div class="og-button-text">{text}</div>
</div>`;
interface HTMLElementExt extends HTMLElement {
__og_button__: Button;
}
export type ButtonEventsList = ["click", "mousedown", "mouseup", "touchstart", "touchend", "touchcancel"];
const BUTTON_EVENTS: ButtonEventsList = ["click", "mousedown", "mouseup", "touchstart", "touchend", "touchcancel"];
export interface IButtonParams extends IViewParams {
icon?: string;
text?: string;
title?: string;
name?: string;
}
class Button extends View<null> {
public override events: EventsHandler<ButtonEventsList> & EventsHandler<ViewEventsList>;
public override el: HTMLElementExt | null;
public name: string;
public $icon: HTMLElement | null;
public $text: HTMLElement | null;
protected _skipMouseClickOnce: boolean;
constructor(options: IButtonParams = {}) {
super({
template: stringTemplate(TEMPLATE, {
icon: options.icon || "",
text: options.text || "",
title: options.title || ""
}),
...options
});
//@ts-ignore
this.events = this.events.registerNames(BUTTON_EVENTS);
this.el = null;
this.name = options.name || "";
this.$icon = null;
this.$text = null;
this._skipMouseClickOnce = false;
}
public override render(params: any): this {
super.render(params);
this.$icon = this.select(".og-button-icon");
this.$text = this.select(".og-button-text");
this.el!.__og_button__ = this;
this._initEvents();
return this;
}
public override afterRender(parentNode: HTMLElement) {
this._initEvents();
}
protected _initEvents() {
if (this.el) {
this.el.addEventListener("click", this._onClick);
this.el.addEventListener("mousedown", this._onMouseDown);
this.el.addEventListener("mouseup", this._onMouseUp);
this.el.addEventListener("pointerdown", this._onPointerDown);
this.el.addEventListener("pointerup", this._onPointerUp);
this.el.addEventListener("pointercancel", this._onPointerCancel);
}
}
protected _onMouseDown = (e: MouseEvent) => {
e.preventDefault();
this.events.dispatch(this.events.mousedown, this, e);
};
protected _onMouseUp = (e: MouseEvent) => {
e.preventDefault();
this.events.dispatch(this.events.mouseup, this, e);
};
protected _onPointerDown = (e: PointerEvent) => {
if (e.pointerType !== "touch") {
return;
}
e.preventDefault();
this.el?.setPointerCapture(e.pointerId);
this.events.dispatch(this.events.touchstart, this, e);
};
protected _onPointerUp = (e: PointerEvent) => {
if (e.pointerType !== "touch") {
return;
}
e.preventDefault();
if (this.el?.hasPointerCapture(e.pointerId)) {
this.el.releasePointerCapture(e.pointerId);
}
this.events.dispatch(this.events.touchend, this, e);
this._skipMouseClickOnce = true;
this._onMouseClick(e as unknown as MouseEvent);
};
protected _onPointerCancel = (e: PointerEvent) => {
if (e.pointerType !== "touch") {
return;
}
e.preventDefault();
if (this.el?.hasPointerCapture(e.pointerId)) {
this.el.releasePointerCapture(e.pointerId);
}
this.events.dispatch(this.events.touchcancel, this, e);
};
protected _mouseClickHandler(e: MouseEvent) {
e.preventDefault();
this.events.dispatch(this.events.click, this, e);
}
protected _onClick = (e: MouseEvent) => {
if (this._skipMouseClickOnce) {
this._skipMouseClickOnce = false;
e.preventDefault();
return;
}
this._onMouseClick(e);
};
protected _onMouseClick = (e: MouseEvent) => {
this._mouseClickHandler(e);
};
public override remove() {
this._clearEvents();
super.remove();
}
protected _clearEvents() {
if (this.el) {
this.el.removeEventListener("click", this._onClick);
this.el.removeEventListener("mousedown", this._onMouseDown);
this.el.removeEventListener("mouseup", this._onMouseUp);
this.el.removeEventListener("pointerdown", this._onPointerDown);
this.el.removeEventListener("pointerup", this._onPointerUp);
this.el.removeEventListener("pointercancel", this._onPointerCancel);
}
}
}
export { Button };