User:Monster Domosed/common.js: Difference between revisions

No edit summary
Tag: Manual revert
No edit summary
Line 301: Line 301:
     }
     }
}());
}());
/**
* Custom Tooltips — replaces Extension:Popups for .item-link-wrapper and .ability-link-wrapper links
*/
( function () {
    'use strict';
    var tooltipCache = {};
    var $tooltip = null;
    var currentTarget = null;
    var showTimer = null;
    var hideTimer = null;
    var SHOW_DELAY = 250;
    var HIDE_DELAY = 300;
    var EDGE_MARGIN = 10; // margin from viewport edges
    /* ─── Create tooltip DOM element ─── */
    function getTooltip() {
        if ( !$tooltip ) {
            $tooltip = $( '<div>' )
                .addClass( 'custom-item-tooltip' )
                .hide()
                .appendTo( document.body )
                .on( 'mouseenter', function () {
                    clearTimeout( hideTimer );
                } )
                .on( 'mouseleave', function () {
                    scheduleHide();
                } );
        }
        return $tooltip;
    }
    /* ─── Positioning ─── */
    function positionTooltip( anchor ) {
        var tt = getTooltip();
        var rect = anchor.getBoundingClientRect();
        var scrollTop = window.scrollY || document.documentElement.scrollTop;
        var scrollLeft = window.scrollX || document.documentElement.scrollLeft;
        var vpW = window.innerWidth;
        var vpH = window.innerHeight;
        // Render offscreen to measure actual dimensions
        tt.css( { top: -9999, left: -9999, visibility: 'hidden' } ).show();
        var ttW = tt.outerWidth();
        var ttH = tt.outerHeight();
        tt.css( 'visibility', '' );
        // ─── Vertical positioning ───
        var top;
        var spaceBelow = vpH - rect.bottom - 8;
        var spaceAbove = rect.top - 8;
        if ( spaceBelow >= ttH + EDGE_MARGIN ) {
            // Fits below the anchor
            top = rect.bottom + scrollTop + 8;
        } else if ( spaceAbove >= ttH + EDGE_MARGIN ) {
            // Fits above the anchor
            top = rect.top + scrollTop - ttH - 8;
        } else {
            // Doesn't fit above or below — pin to the edge with more space
            if ( spaceBelow >= spaceAbove ) {
                top = scrollTop + vpH - ttH - EDGE_MARGIN;
            } else {
                top = scrollTop + EDGE_MARGIN;
            }
        }
        // ─── Horizontal positioning ───
        var left = rect.left + scrollLeft;
        // Overflows right edge
        if ( left + ttW > scrollLeft + vpW - EDGE_MARGIN ) {
            left = scrollLeft + vpW - ttW - EDGE_MARGIN;
        }
        // Overflows left edge
        if ( left < scrollLeft + EDGE_MARGIN ) {
            left = scrollLeft + EDGE_MARGIN;
        }
        tt.css( { top: top, left: left } );
    }
/* ability upgrade gadget CURRENTLY DOESN'T WORK WITH TOOLTIP*/
    /* ─── Initialize ability upgrade gadget for tooltip content ─── */
    function initAbilityUpgrades( $container ) {
        // Check if the gadget exists
        if ( !window.abilityUpgradeGadget ) {
            return;
        }
        var abilityCards = $container.find( '.ability-card' );
        if ( !abilityCards.length ) {
            return;
        }
        // Re-run the gadget's initialization for new ability cards
        abilityCards.each( function () {
            var container = this;
           
            // Add hover listeners
            $( container ).find( '.ability-upgrade' ).each( function () {
                var el = this;
                $( el ).off( 'mouseenter.abilityUpgrade mouseleave.abilityUpgrade' );
                $( el ).on( 'mouseenter.abilityUpgrade', function () {
                    window.abilityUpgradeGadget.onHover( container, el );
                } );
                $( el ).on( 'mouseleave.abilityUpgrade', function () {
                    window.abilityUpgradeGadget.onUnhover( container );
                } );
            } );
        } );
    }
    /* ─── Make ability name clickable ─── */
    function makeAbilityNameClickable( $container, abilityName ) {
        // Find the ability name text within the ability card
        $container.find( '.ability-card' ).each( function () {
            var $card = $( this );
           
            // Target the ability name span (based on your HTML structure)
            var $nameSpan = $card.find( 'span[style*="font-family"][style*="Valve Occult"]' );
           
            if ( $nameSpan.length ) {
                var nameText = $nameSpan.text().trim();
               
                // Create a link wrapping the ability name
                var $link = $( '<a>' )
                    .attr( 'href', mw.util.getUrl( abilityName ) )
                    .attr( 'title', 'Go to ' + abilityName + ' page' )
                    .css( {
                        'color': 'inherit',
                        'text-decoration': 'none'
                    } )
                    .on( 'mouseenter', function () {
                        $( this ).css( 'text-decoration', 'underline' );
                    } )
                    .on( 'mouseleave', function () {
                        $( this ).css( 'text-decoration', 'none' );
                    } )
                    .text( nameText );
               
                // Replace the text with the link
                $nameSpan.empty().append( $link );
            }
        } );
    }
    /* ─── Show tooltip ─── */
    function showTooltip( anchor, name, type ) {
        clearTimeout( hideTimer );
        clearTimeout( showTimer );
        showTimer = setTimeout( function () {
            var tt = getTooltip();
            currentTarget = anchor;
            var cacheKey = type + ':' + name;
            // Update tooltip classes based on type
            tt.removeClass( 'ability-tooltip item-tooltip' );
            if ( type === 'ability' ) {
                tt.addClass( 'ability-tooltip' );
            } else if ( type === 'item' ) {
                tt.addClass( 'item-tooltip' );
            }
            // Already cached — show immediately
            if ( tooltipCache[ cacheKey ] ) {
                tt.html( tooltipCache[ cacheKey ] ).show();
                positionTooltip( anchor );
               
                // Re-initialize ability upgrades for cached content
                if ( type === 'ability' ) {
                    initAbilityUpgrades( tt );
                    makeAbilityNameClickable( tt, name );
                }
                return;
            }
            // Loading indicator
            tt.html( '<div class="custom-item-tooltip__loading">Loading…</div>' ).show();
            positionTooltip( anchor );
            // Build template text based on type
            var templateText;
            if ( type === 'item' ) {
                templateText = '{{Infobox item/auto|default=true|' + name + '}}';
            } else if ( type === 'ability' ) {
                templateText = '{{Ability card v2' +
                    '|hero_name={{#invoke:Abilities/utils|find_hero_by_ability|' + name + '}}' +
                    '|ability_num={{#invoke:Abilities|get_ability_number|{{#invoke:Abilities/utils|find_hero_by_ability|' + name + '}}|' + name + '}}' +
                    '}}';
            }
            // Fetch rendered template
            new mw.Api().post( {
                action: 'parse',
                text: templateText,
                title: mw.config.get( 'wgPageName' ),
                prop: 'text',
                disablelimitreport: true,
                disableeditsection: true,
                wrapoutputclass: '',
                format: 'json'
            } ).then( function ( data ) {
                var html = data.parse.text[ '*' ];
                tooltipCache[ cacheKey ] = html;
                // Only show if the mouse is still on this element
                if ( currentTarget === anchor ) {
                    tt.html( html ).show();
                    positionTooltip( anchor );
                   
                    // Initialize ability upgrades for new content
                    if ( type === 'ability' ) {
                        // Trigger MediaWiki's content hook so other gadgets can initialize
                        mw.hook( 'wikipage.content' ).fire( tt );
                        initAbilityUpgrades( tt );
                        makeAbilityNameClickable( tt, name );
                    }
                }
            } ).catch( function () {
                if ( currentTarget === anchor ) {
                    tt.hide();
                }
            } );
        }, SHOW_DELAY );
    }
    /* ─── Hide tooltip ─── */
    function scheduleHide() {
        clearTimeout( showTimer );
        hideTimer = setTimeout( function () {
            if ( $tooltip ) {
                $tooltip.hide();
            }
            currentTarget = null;
        }, HIDE_DELAY );
    }
    /* ─── Attach handlers to wrapper ─── */
    function attachTooltipHandlers( $wrapper, name, type ) {
        // All links inside the wrapper, not just the first one
        var $links = $wrapper.find( 'a[href]' );
       
        // If no links found, attach to the wrapper itself (for icon-only mode)
        if ( !$links.length ) {
            $links = $wrapper;
        }
        $links.each( function () {
            var $link = $( this );
            // Remove native title from each link
            $link.removeAttr( 'title' );
            $link.on( 'mouseenter.customTooltip', function () {
                showTooltip( this, name, type );
            } ).on( 'mouseleave.customTooltip', function () {
                scheduleHide();
            } );
        } );
    }
    /* ─── Initialization ─── */
    mw.hook( 'wikipage.content' ).add( function ( $content ) {
        // Item tooltips
        $content.find( '.item-link-wrapper' ).each( function () {
            var $wrapper = $( this );
            var itemName = $wrapper.attr( 'data-item-name' );
            if ( !itemName ) return;
            attachTooltipHandlers( $wrapper, itemName, 'item' );
        } );
        // Ability tooltips
        $content.find( '.ability-link-wrapper' ).each( function () {
            var $wrapper = $( this );
            var abilityName = $wrapper.attr( 'data-ability-name' );
            if ( !abilityName ) return;
            attachTooltipHandlers( $wrapper, abilityName, 'ability' );
        } );
    } );
} )();