czydojade/resources/ts/components/tooltip.ts
2020-01-28 22:04:48 +01:00

89 lines
2.4 KiB
TypeScript

import Vue from 'vue';
import Component from "vue-class-component";
import { Prop, Watch } from "vue-property-decorator";
type Events = {
[evnet: string]: (...any) => void,
}
type Trigger = "hover" | "focus";
const longPressTimeout = 1000;
@Component({ template: require('../../components/tooltip.html') })
export class TooltipComponent extends Vue {
@Prop({ type: String, default: "auto" }) public placement: string;
@Prop({ type: Number, default: 200 }) public delay: number;
@Prop({ type: Array, default: () => ["hover", "focus"]}) public triggers: Trigger[];
public show: boolean = false;
public root: Element = null;
private _events: Events = {};
mounted() {
this.root = (this.$refs['root'] as HTMLSpanElement).parentElement;
this.updateTriggers();
}
beforeDestroy() {
this._removeEventListeners();
}
@Watch('triggers')
updateTriggers() {
this._removeEventListeners();
this._events = {};
let blocked: boolean = false;
if (this.triggers.includes("hover")) {
let timeout;
this._events['mouseenter'] = () => {
timeout = window.setTimeout(() => { this.show = !blocked }, this.delay);
};
this._events['mouseleave'] = () => {
window.clearTimeout(timeout);
this.show = false
};
}
if (this.triggers.includes("focus") || (this.triggers.includes("hover") && this.$isTouch)) {
if (this.$isTouch) {
this._events['touchstart'] = () => {
// this is to prevent showing tooltips after tap
blocked = true;
setTimeout(() => blocked = false, longPressTimeout);
}
}
this._events['focus'] = () => {
this.show = !blocked;
};
this._events['blur'] = () => {
this.show = false
};
}
this._registerEventListeners();
}
private _registerEventListeners() {
for (const [event, handler] of Object.entries(this._events)) {
this.root.addEventListener(event, handler);
}
}
private _removeEventListeners() {
for (const [event, handler] of Object.entries(this._events)) {
this.root.removeEventListener(event, handler);
}
}
}
Vue.component('Tooltip', TooltipComponent);