-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathn-tooltip.js
142 lines (141 loc) · 4.64 KB
/
n-tooltip.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Component Tooltip – start
(function() {
let setTipPosition = (tool, tip) => {
// Take up the most area available on top/right/bottom/left of the tool. Relative to body.
let rect = tool.getBoundingClientRect();
let top = rect.top;
let left = rect.left;
let right = window.innerWidth - left - rect.width;
let bottom = window.innerHeight - top - rect.height; // To do: check when body is shorter than viewport
let area_top = top * window.innerWidth;
let area_right = right * window.innerHeight;
let area_bottom = bottom * window.innerWidth;
let area_left = left * window.innerHeight;
let body_rect = document.body.getBoundingClientRect();
tip.removeAttribute("style");
delete tip.dataset.position;
tip.classList.add('n-tooltip__content-visible');
let positionTop = () => {
tip.style.bottom = 20 + body_rect.height + body_rect.y - top + "px";
tip.style.maxHeight = top - 40 + "px";
tip.style.left = `${rect.x + rect.width / 2 - tip.scrollWidth / 2 - document.body.getBoundingClientRect().x}px`;
tip.dataset.nPosition = "top";
};
let positionBottom = () => {
tip.style.top = 20 - body_rect.y + top + rect.height + "px";
tip.style.maxHeight = bottom - 40 + "px";
tip.style.left = `${rect.x + rect.width / 2 - tip.scrollWidth / 2 - document.body.getBoundingClientRect().x}px`;
tip.dataset.nPosition = "bottom";
};
let positionLeft = () => {
tip.style.left = "auto";
tip.style.right = 20 + body_rect.width + body_rect.x - window.innerWidth + right + rect.width + "px";
tip.style.maxWidth = left - 40 + "px";
tip.style.top = `${-1 * body_rect.y + rect.top + rect.height / 2 - tip.scrollHeight / 2}px`;
tip.dataset.nPosition = "left";
};
let positionRight = () => {
tip.style.left = rect.x - body_rect.x + rect.width + 20 + "px";
tip.style.maxWidth = right - 40 + "px";
tip.style.top = `${-1 * body_rect.y + rect.top + rect.height / 2 - tip.scrollHeight / 2}px`;
tip.dataset.nPosition = "right";
};
if (area_left > area_right) {
if (area_top > area_bottom) {
if (area_top > area_left) {
// Top
positionTop();
} else {
// Left
positionLeft();
}
} else {
if (area_bottom > area_left) {
// Bottom
positionBottom();
} else {
// Left
positionLeft();
}
}
} else {
if (area_top > area_bottom) {
if (area_top > area_right) {
// Top
positionTop();
} else {
// Right
positionRight();
}
} else {
if (area_bottom > area_right) {
// Bottom
positionBottom();
} else {
// Right
positionRight();
}
}
}
let rect_tip = tip.getBoundingClientRect();
let offset_y = 0;
if (rect_tip.y < 0) {
offset_y = Math.abs(rect_tip.y) + 10;
} else {
if (rect_tip.bottom > window.innerHeight) {
offset_y = window.innerHeight - rect_tip.bottom - 10;
}
}
tip.style.setProperty("--offset_y", offset_y + "px");
let offset_x = 0;
if (rect_tip.x < 0) {
offset_x = Math.abs(rect_tip.x) + 10;
} else {
if (rect_tip.right > window.innerWidth) {
offset_x = window.innerWidth - rect_tip.right - 10;
}
}
tip.style.setProperty("--offset_x", offset_x + "px");
};
function getToolTip(tool) {
return document.getElementById(tool.getAttribute('aria-describedby')) || tool.nextElementSibling;
}
const hideTipFunction = tool => {
let tip = getToolTip(tool);
tool.removeAttribute("aria-expanded");
tool.after(tip);
tip.removeAttribute("style");
delete tip.dataset.position;
tip.classList.remove('n-tooltip__content-visible');
}
let hideTip = (e) => {
hideTipFunction(e.target.closest(".n-tooltip"));
};
const hideTipOnScroll = e => {
document.querySelectorAll('.n-tooltip').forEach(el => hideTipFunction(el));
document.removeEventListener('scroll', hideTipOnScroll);
};
let showTip = (e) => {
let tool = e.target.closest(".n-tooltip");
let tip = getToolTip(tool);
tool.setAttribute("aria-expanded", true);
document.body.appendChild(tip);
setTipPosition(tool, tip);
document.addEventListener('scroll', hideTipOnScroll, true);
};
const init = (host = document) => {
/* Tooltip */
let tooltips = host.querySelectorAll(".n-tooltip")?.length;
host.querySelectorAll(".n-tooltip:not([data-ready])").forEach((el) => {
el.setAttribute("tabindex", 0);
el.addEventListener('touchend', showTip);
el.addEventListener('mouseover', showTip);
el.addEventListener('focus', showTip);
el.addEventListener('mouseout', hideTip);
el.addEventListener('blur', hideTip);
el.dataset.ready = true;
});
};
(typeof nui !== 'undefined' && typeof nui.registerComponent === "function") ? nui.registerComponent("n-tooltip", init): init();
})();
// Component Tooltip – end