rect gslate
user_8454105
typescript
a month ago
5.6 kB
2
Indexable
Never
/** @prettier */ const overlayCssClass: string = "hotkey-overlay"; function getTooltips() { return $("." + overlayCssClass); } function areTooltipsDisplayed() { return getTooltips().length > 0; } function removeTooltipsDOMElements() { getTooltips().remove(); return; } function insertTooltipDOMElement(hotkey, element) { if( !(element[0] instanceof Element)){ console.error("invalid element provided " + typeof element); return; } // Check if the element is hidden const computedStyle = window.getComputedStyle(element[0]); if (computedStyle.display === 'none') { // Execute certain code if the display property is 'none' console.warn("Element is hidden. Cannot attach tooltip."); return; } const tooltipId = 'Tooltip_' + hotkey.name.replace(/\s+/g, '').replace(/\+/g, '_'); let tooltipSpan = document.getElementById(tooltipId); if (!tooltipSpan) { tooltipSpan = document.createElement('span'); tooltipSpan.id = tooltipId; tooltipSpan.className = overlayCssClass; document.body.appendChild(tooltipSpan); } const replacements = { "CONTROL": "CTRL", "ALTERNATIVE": "ALT", "ARROWUP": "↑", "ARROWDOWN": "↓", "ARROWLEFT": "←", "ARROWRIGHT": "→", // Add other replacements as needed }; let modifierKbds = ""; hotkey.modifiers.forEach(modifier => { const replacedModifier = replacements[modifier] || modifier; const kbd = '<kbd>' + replacedModifier + '</kbd> + '; modifierKbds = modifierKbds + kbd; }); let kbdKey = replacements[hotkey.key] || hotkey.key; tooltipSpan.innerHTML = '<span class="htk-name">' + hotkey.name + '</span><span class="htk-key"> '+ modifierKbds + ' <kbd>' + kbdKey + '</kbd></span>'; document.body.appendChild(tooltipSpan); //positioning start ***************************** const rect = element[0].getBoundingClientRect(); tooltipSpan.style.position = 'absolute'; const padding = 5; // Add some padding from the element let tooltipRect = tooltipSpan.getBoundingClientRect(); let top, left, hotkeyClass, arrowClass; // Position tooltip based on the element's parent if (isDescendant(element[0], '#leftNav')) { // Position to the right and top of the element hotkeyClass = 'leftNav-hotkey'; arrowClass = 'element-left-center'; top = window.scrollY + rect.top; left = window.scrollX + rect.right + padding; } else if (isDescendant(element[0], '#header')) { // Position to the bottom of the element hotkeyClass = 'header-hotkey'; arrowClass = 'element-top-center'; top = window.scrollY + rect.bottom + padding; left = window.scrollX + rect.left; } else if (isDescendant(element[0], '#content')) { // Position to the bottom and align to the left of the element hotkeyClass = 'content-hotkey'; arrowClass = 'element-top-center'; top = window.scrollY + rect.bottom + padding; left = window.scrollX + rect.left; } else if (isDescendant(element[0], '.app-footer')) { // Position to the bottom left of the element hotkeyClass = 'footer-hotkey'; arrowClass = 'element-bottom-center'; top = window.scrollY + rect.bottom + padding; left = window.scrollX + rect.left; } else { // Default position to the bottom of the element hotkeyClass = 'free-hotkey'; arrowClass = ''; top = window.scrollY + rect.bottom + padding; left = window.scrollX + rect.left; } tooltipSpan.classList.add(hotkeyClass); tooltipSpan.classList.add(arrowClass); // Adjust position if the tooltip goes beyond the viewport boundaries if (top + tooltipRect.height > window.innerHeight) { top = window.scrollY + rect.top - tooltipRect.height - padding; // Move above the element } if (left + tooltipRect.width > window.innerWidth) { left = window.scrollX + rect.right - tooltipRect.width; // Align to the right edge of the element } else if (left < 0) { left = window.scrollX + rect.left; // Align to the left edge of the element } // Update tooltip dimensions after adjustments tooltipSpan.style.left = left + 'px'; tooltipSpan.style.top = top + 'px'; tooltipRect = tooltipSpan.getBoundingClientRect(); //Check if tooltip overlaps with other tooltips and adjust position const existingTooltips = document.querySelectorAll('.' + overlayCssClass); existingTooltips.forEach(existingTooltip => { if (existingTooltip !== tooltipSpan) { const existingRect = existingTooltip.getBoundingClientRect(); if (tooltipRect.top < existingRect.bottom && tooltipRect.bottom > existingRect.top && tooltipRect.left < existingRect.right && tooltipRect.right > existingRect.left) { // Adjust the position to avoid overlap top = existingRect.bottom + padding; tooltipSpan.style.top = top + 'px'; tooltipRect = tooltipSpan.getBoundingClientRect(); // Update the tooltip dimensions } } }); //positioning ENDS return; } function isDescendant(child, parentSelector) { const parent = document.querySelector(parentSelector); let node = child; while (node !== null) { if (node === parent) { return true; } node = node.parentNode; } return false; } export { areTooltipsDisplayed, removeTooltipsDOMElements, insertTooltipDOMElement }