PageSourceSearch

https://pupwife.com/projects/chatroom/scripts/components/Tooltip.js

js pupwife.com collected 2026-09-30 15:06:48 UTC 3,953 bytes, 124 lines download raw bytes

1/**
2 * Tooltip Component (Vencord-inspired)
3 * Reusable tooltip component
4 */
5
6window.ChatroomTooltip = (function() {
7    'use strict';
8
9    let currentTooltip = null;
10
11    /**
12     * Show tooltip
13     */
14    function show(element, text, options = {}) {
15        hide();
16
17        const {
18            position = 'top', // top, bottom, left, right
19            delay = 0,
20            className = ''
21        } = options;
22
23        const tooltip = document.createElement('div');
24        tooltip.className = `chatroom-tooltip chatroom-tooltip-${position} ${className}`;
25        tooltip.textContent = text;
26
27        document.body.appendChild(tooltip);
28
29        const updatePosition = () => {
30            const rect = element.getBoundingClientRect();
31            const tooltipRect = tooltip.getBoundingClientRect();
32
33            switch (position) {
34                case 'top':
35                    tooltip.style.left = rect.left + (rect.width / 2) - (tooltipRect.width / 2) + 'px';
36                    tooltip.style.top = rect.top - tooltipRect.height - 8 + 'px';
37                    break;
38                case 'bottom':
39                    tooltip.style.left = rect.left + (rect.width / 2) - (tooltipRect.width / 2) + 'px';
40                    tooltip.style.top = rect.bottom + 8 + 'px';
41                    break;
42                case 'left':
43                    tooltip.style.left = rect.left - tooltipRect.width - 8 + 'px';
44                    tooltip.style.top = rect.top + (rect.height / 2) - (tooltipRect.height / 2) + 'px';
45                    break;
46                case 'right':
47                    tooltip.style.left = rect.right + 8 + 'px';
48                    tooltip.style.top = rect.top + (rect.height / 2) - (tooltipRect.height / 2) + 'px';
49                    break;
50            }
51
52            // Adjust if tooltip goes off screen
53            const tooltipRectFinal = tooltip.getBoundingClientRect();
54            if (tooltipRectFinal.left < 0) {
55                tooltip.style.left = '8px';
56            }
57            if (tooltipRectFinal.right > window.innerWidth) {
58                tooltip.style.left = (window.innerWidth - tooltipRectFinal.width - 8) + 'px';
59            }
60            if (tooltipRectFinal.top < 0) {
61                tooltip.style.top = '8px';
62            }
63            if (tooltipRectFinal.bottom > window.innerHeight) {
64                tooltip.style.top = (window.innerHeight - tooltipRectFinal.height - 8) + 'px';
65            }
66        };
67
68        setTimeout(() => {
69            tooltip.classList.add('show');
70            updatePosition();
71        }, delay);
72
73        currentTooltip = {
74            element: tooltip,
75            updatePosition
76        };
77
78        // Update position on scroll/resize
79        const updateHandler = () => updatePosition();
80        window.addEventListener('scroll', updateHandler, true);
81        window.addEventListener('resize', updateHandler);
82
83        return {
84            hide: () => {
85                window.removeEventListener('scroll', updateHandler, true);
86                window.removeEventListener('resize', updateHandler);
87                hide();
88            }
89        };
90    }
91
92    /**
93     * Hide tooltip
94     */
95    function hide() {
96        if (currentTooltip) {
97            currentTooltip.element.remove();
98            currentTooltip = null;
99        }
100    }
101
102    /**
103     * Attach tooltip to element
104     */
105    function attach(element, text, options = {}) {
106        let tooltipInstance = null;
107
108        element.addEventListener('mouseenter', () => {
109            tooltipInstance = show(element, text, options);
110        });
111
112        element.addEventListener('mouseleave', () => {
113            if (tooltipInstance) {
114                tooltipInstance.hide();
115            }
116        });
117    }
118
119    return {
120        show,
121        hide,
122        attach
123    };
124})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.