A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
1import {isMobile} from "../util/functions";
2
3export const showTooltip = (message: string, target: Element, tooltipClass?: string) => {
4 if (isMobile()) {
5 return;
6 }
7 const targetRect = target.getBoundingClientRect();
8 if (targetRect.height === 0 || !message) {
9 hideTooltip();
10 return;
11 }
12
13 const messageElement = document.getElementById("tooltip");
14 messageElement.className = tooltipClass ? `tooltip tooltip--${tooltipClass}` : "tooltip";
15 messageElement.innerHTML = message;
16 // 避免原本的 top 和 left 影响计算
17 messageElement.removeAttribute("style");
18
19
20 const position = target.getAttribute("data-position");
21 const parentRect = target.parentElement.getBoundingClientRect();
22
23 let left;
24 let top;
25 if (position === "parentE") {
26 // parentE: file tree and outline、backlink & viewcard
27 top = Math.max(0, parentRect.top - (messageElement.clientHeight - parentRect.height) / 2);
28 if (top > window.innerHeight - messageElement.clientHeight) {
29 top = window.innerHeight - messageElement.clientHeight;
30 }
31 left = parentRect.right + 8;
32 if (left + messageElement.clientWidth > window.innerWidth) {
33 left = parentRect.left - messageElement.clientWidth - 8;
34 }
35 } else if (position === "parentW") {
36 // ${number}parentW: av 属性视图 & col & select
37 top = Math.max(0, parentRect.top - (messageElement.clientHeight - parentRect.height) / 2);
38 if (top > window.innerHeight - messageElement.clientHeight) {
39 top = window.innerHeight - messageElement.clientHeight;
40 }
41 left = parentRect.left - messageElement.clientWidth;
42 if (left < 0) {
43 left = parentRect.right;
44 }
45 } else if (position?.endsWith("west")) {
46 // west: gutter & 标题图标 & av relation
47 const positionDiff = parseInt(position) || 0.5;
48 top = Math.max(0, targetRect.top - (messageElement.clientHeight - targetRect.height) / 2);
49 if (top > window.innerHeight - messageElement.clientHeight) {
50 top = window.innerHeight - messageElement.clientHeight;
51 }
52 left = targetRect.left - messageElement.clientWidth - positionDiff;
53 if (left < 0) {
54 left = targetRect.right;
55 }
56 } else if (position === "north") {
57 // north: av 视图,列,多选描述
58 const positionDiff = 0.5;
59 left = Math.max(0, targetRect.left - (messageElement.clientWidth - targetRect.width) / 2);
60 top = targetRect.top - messageElement.clientHeight - positionDiff;
61 if (top < 0) {
62 if (targetRect.top < window.innerHeight - targetRect.bottom) {
63 top = targetRect.bottom + positionDiff;
64 messageElement.style.maxHeight = (window.innerHeight - top) + "px";
65 } else {
66 top = 0;
67 messageElement.style.maxHeight = (targetRect.top - positionDiff) + "px";
68 }
69 }
70 if (left + messageElement.clientWidth > window.innerWidth) {
71 left = window.innerWidth - messageElement.clientWidth;
72 }
73 } else {
74 // ${number}south & 默认值
75 const positionDiff = parseInt(position) || 0.5;
76 left = Math.max(0, targetRect.left - (messageElement.clientWidth - targetRect.width) / 2);
77 top = targetRect.bottom + positionDiff;
78
79 if (top + messageElement.clientHeight > window.innerHeight) {
80 if (targetRect.top - positionDiff > window.innerHeight - top) {
81 top = targetRect.top - positionDiff - messageElement.clientHeight;
82 messageElement.style.maxHeight = (targetRect.top - positionDiff) + "px";
83 } else {
84 messageElement.style.maxHeight = (window.innerHeight - top) + "px";
85 }
86 }
87 if (left + messageElement.clientWidth > window.innerWidth) {
88 left = window.innerWidth - messageElement.clientWidth;
89 }
90 }
91 messageElement.style.top = top + "px";
92 messageElement.style.left = left + "px";
93};
94
95export const hideTooltip = () => {
96 document.getElementById("tooltip").classList.add("fn__none");
97};