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.