Jegged-Tooltips

Adds tooltips to Jegged game gudies.

Stan na 26-03-2025. Zobacz najnowsza wersja.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

// ==UserScript==
// @name        Jegged-Tooltips
// @description Adds tooltips to Jegged game gudies.
// @version 1.0
// @license GPL-3.0-or-later
// @include http://jegged.com/*
// @include https://jegged.com/*
// @run-at document-end
// @namespace https://greasyfork.org/users/115055
// ==/UserScript==

let HOLD_TOOLTIP = false;

function showCardTooltip(card, elem, x, y) {
    removeCardTooltip();
    
    let tooltip = document.createElement("div");
    const margin = 10;
    const maxWidth = 650;
    
    let left = x;
    let top = y + window.scrollY;
       
    tooltip.id = "JeggedTooltip";
    tooltip.style.position = "absolute";

    tooltip.style.maxWidth = `${maxWidth}px`;
    tooltip.style.marginTop = `${margin}px`;
    tooltip.style.marginBottom = `${margin}px`;
    tooltip.style.marginRight = `${margin}px`;
    tooltip.style.marginLeft = `${margin}px`;
            
    card.style.marginTop = 0;
    card.style.marginBottom = 0;
       
    tooltip.append(card); 
    document.body.append(tooltip);
  
    const elemRect = elem.getBoundingClientRect();
    const tooltipRect = tooltip.getBoundingClientRect();
    let headerHeight;
    
    const headerElem = document.getElementById("header");
    if (headerElem !== null) {
        headerHeight = headerElem.getBoundingClientRect().height;
    } else {
        headerHeight = 0;
    }
    
    // if destination position goes beyond viewport width, clamp position
    // within viewport or at 0
    if (x + tooltipRect.width + (margin*2) > window.innerWidth) {
        left = Math.max(window.innerWidth - tooltipRect.width - (margin*2), 0)
    }

    // never cover target element with tooltip
    if (y < elemRect.top + elemRect.height + window.scrollY) {
        top = elemRect.top + elemRect.height + window.scrollY;
    }
    
    tooltip.style.left = `${left}px`;
    tooltip.style.top = `${top}px`;
    
    // if destination position goes beyond viewport height, 
    // and tooltip fits above elem, display above elem
    if (top + tooltipRect.height + (margin*2) > window.scrollY + window.innerHeight) {
        if (elemRect.top - tooltipRect.height - (margin*2) - headerHeight >= 0) {
            top = window.scrollY + elemRect.top - tooltipRect.height - (margin*2);
        }    
    }
    
    tooltip.style.left = `${left}px`;
    tooltip.style.top = `${top}px`;
}

function removeCardTooltip() {
    const tooltip = document.getElementById("JeggedTooltip");
    if (tooltip) {
        tooltip.remove();        
    }
}

async function onMouseEnterLink(event) {
    const href = event.target.href;
    const url = URL.parse(href);
    
    if (url.origin !== window.location.origin) {
        // only follow same-origin links
        return;
    }
    
    if (url.hash === "") {
        // only follow anchor links 
        return;   
    }
    
    
    let x = event.x;
    let y = event.y;
    
    const onMouseMove = (e) => {
        x = e.x;
        y = e.y;
    }
    
    document.addEventListener("mousemove", onMouseMove);
    
    try {
        const r = await fetch(url)
        if (!r.ok) {
          throw new Error(`Response status: ${r.status}`);
        }

        const text = await r.text();

        const parser = new DOMParser();
        const page = parser.parseFromString(text, "text/html");

        const destination = page.getElementById(url.hash.slice(1));
        if (destination === null) {
            throw new Error(`Destination anchor not found on linked page.`)
        }

        let card; 
        if (destination.closest(".alert") !== null) {
            // if destination belongs to a card-style alert, use this
            card = destination.closest(".alert");
        } else if (destination.closest("tr") !== null) {
            // if destination belongs to a table, use nearest row
            card = document.createElement("div");
            card.innerHTML = destination.closest("tr").innerHTML;
            card.classList = "alert alert-secondary";
        } else {
            // element does not have associated card, do not display tooltip
            return;
        };
        
        showCardTooltip(card, event.target, x, y);
    } finally {
        document.removeEventListener("mousemove", onMouseMove);
    }
}

function onMouseLeaveLink() {
    if (HOLD_TOOLTIP === false) {
        removeCardTooltip();        
    }
}

function onKeyDown(e) {
    if (e.key === "Shift") {
        HOLD_TOOLTIP = !HOLD_TOOLTIP;
        
        if (!HOLD_TOOLTIP) {
            removeCardTooltip();
        }
    } else if (e.key === "Escape") {
        removeCardTooltip();
    }
}

function addEventListenersToLinks() {
    const links = document.getElementsByTagName("a");
    
    for (const l of links) {
        console.log(l);
        l.addEventListener("mouseenter", onMouseEnterLink);
        l.addEventListener("mouseleave", onMouseLeaveLink);
    }
    
    document.addEventListener("keydown", onKeyDown);
}

(() => {
    addEventListenersToLinks();
})();