139 lines
3.8 KiB
TypeScript
139 lines
3.8 KiB
TypeScript
import { Tooltip } from "bootstrap";
|
|
|
|
|
|
type ConstructorTypeParent = "parent";
|
|
type ConstructorTypeDom = "dom";
|
|
|
|
interface ParentSelectorTooltips {
|
|
type: ConstructorTypeParent
|
|
/** The parent element that contains Dom elements for which tooltips shall be created. */
|
|
parentSelector: string;
|
|
}
|
|
|
|
interface DomProvidedTooltips {
|
|
type: ConstructorTypeDom;
|
|
/** Dom elements for which tooltips shall be created. */
|
|
elements: HTMLElement | NodeListOf<HTMLElement>;
|
|
}
|
|
|
|
interface TooltipsOptions {
|
|
/** Tooltip options. */
|
|
options: Partial<Tooltip.Options>|null|undefined;
|
|
}
|
|
|
|
export type TooltipsConstructor = TooltipsOptions & (ParentSelectorTooltips|DomProvidedTooltips);
|
|
|
|
export class Tooltips {
|
|
/** BS tooltips instances */
|
|
private tooltips: Array<Tooltip> = [];
|
|
|
|
/** The parent element that contains Dom elements for which tooltips shall be created. */
|
|
private parentSelector: string | null = null;
|
|
|
|
/** Dom elements for which tooltips shall be created. */
|
|
private elements: Array<HTMLElement> = [];
|
|
|
|
/** Tooltip default options. */
|
|
private static readonly defaultOptions: Partial<Tooltip.Options> = {
|
|
container: "body",
|
|
placement: "auto",
|
|
delay: {
|
|
show: 1250,
|
|
hide: 0,
|
|
},
|
|
};
|
|
|
|
/** Tooltip options. */
|
|
private options: Partial<Tooltip.Options> = {};
|
|
|
|
/**
|
|
* @param parentSelector
|
|
* @param options Tooltip options.
|
|
*/
|
|
constructor(params: TooltipsConstructor) {
|
|
if (params.type === "parent") {
|
|
this.parentSelectorConstructor(params);
|
|
}
|
|
if (params.type === "dom") {
|
|
this.domPrividedTooltipsContructor(params);
|
|
}
|
|
}
|
|
|
|
public static make(params?: TooltipsConstructor) {
|
|
let fullParams: TooltipsConstructor;
|
|
if (!params || params.type === "parent") {
|
|
fullParams = {
|
|
type: "parent",
|
|
parentSelector: "body",
|
|
options: {},
|
|
...params
|
|
} as TooltipsOptions & ParentSelectorTooltips;
|
|
} else {
|
|
fullParams = {
|
|
type: "dom",
|
|
elements: (params as DomProvidedTooltips).elements,
|
|
options: params.options ?? {},
|
|
} as TooltipsOptions & DomProvidedTooltips;
|
|
}
|
|
return new Tooltips(fullParams);
|
|
}
|
|
|
|
private parentSelectorConstructor({ parentSelector, options }: TooltipsOptions & ParentSelectorTooltips) {
|
|
this.parentSelector = parentSelector;
|
|
this.options = { ...Tooltips.defaultOptions, ...options };
|
|
this.initTooltips();
|
|
}
|
|
|
|
private domPrividedTooltipsContructor({ elements, options }: TooltipsOptions & DomProvidedTooltips) {
|
|
if (elements instanceof HTMLElement) {
|
|
this.elements = [elements];
|
|
} else {
|
|
this.elements = Array.from(elements);
|
|
}
|
|
this.options = { ...Tooltips.defaultOptions, ...options };
|
|
this.initTooltips();
|
|
}
|
|
|
|
/**
|
|
* Close all Bootstrap tooltips and reinstanciate them.
|
|
*/
|
|
public refreshTooltips(): void {
|
|
this.closeBootstrapTooltip();
|
|
this.initTooltips();
|
|
}
|
|
|
|
/**
|
|
* Close all Bootstrap tooltips for ever.
|
|
*/
|
|
public closeBootstrapTooltip(): void {
|
|
for (const tooltip of this.tooltips) {
|
|
tooltip.hide();
|
|
// * Prevent pending tooltips beeing shown after we asked to hide them
|
|
tooltip.disable();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Completely dispose all tooltips immediately.
|
|
*/
|
|
public destroy(): void {
|
|
for (const tooltip of this.tooltips) {
|
|
tooltip.dispose();
|
|
}
|
|
this.tooltips = [];
|
|
}
|
|
|
|
/**
|
|
* Initialize tooltips
|
|
*/
|
|
private initTooltips() {
|
|
this.closeBootstrapTooltip();
|
|
/** data-bs-toggle tooltips elements */
|
|
const elements = this.parentSelector ? Array.prototype.slice
|
|
.call(document.querySelectorAll(`${this.parentSelector} [data-bs-toggle="tooltip"]`)) :
|
|
this.elements;
|
|
this.tooltips = elements.map((tooltipTriggerEl) => {
|
|
return new Tooltip(tooltipTriggerEl, this.options);
|
|
});
|
|
}
|
|
}
|