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

Blanked the page
Tag: Blanking
testing
Line 1: Line 1:
/**
* Custom Item Tooltips — replaces Extension:Popups for .item-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 } );
    }
    /* ─── Show tooltip ─── */
    function showTooltip( anchor, itemName ) {
        clearTimeout( hideTimer );
        clearTimeout( showTimer );
        showTimer = setTimeout( function () {
            var tt = getTooltip();
            currentTarget = anchor;
            // Already cached — show immediately
            if ( tooltipCache[ itemName ] ) {
                tt.html( tooltipCache[ itemName ] ).show();
                positionTooltip( anchor );
                return;
            }
            // Loading indicator
            tt.html( '<div class="custom-item-tooltip__loading">Loading…</div>' ).show();
            positionTooltip( anchor );
            // Fetch rendered template
            new mw.Api().post( {
                action: 'parse',
                text: '{{Infobox item/auto|default=true|' + itemName + '}}',
                title: itemName,
                prop: 'text',
                disablelimitreport: true,
                disableeditsection: true,
                wrapoutputclass: '',
                format: 'json'
            } ).then( function ( data ) {
                var html = data.parse.text[ '*' ];
                tooltipCache[ itemName ] = html;
                // Only show if the mouse is still on this element
                if ( currentTarget === anchor ) {
                    tt.html( html ).show();
                    positionTooltip( anchor );
                }
            } ).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 );
    }
    /* ─── Initialization ─── */
    mw.hook( 'wikipage.content' ).add( function ( $content ) {
        $content.find( '.item-link-wrapper' ).each( function () {
            var $wrapper = $( this );
            var itemName = $wrapper.attr( 'data-item-name' );
            if ( !itemName ) return;
            // All links inside the wrapper, not just the first one
            var $links = $wrapper.find( 'a[href]' );
            if ( !$links.length ) return;
            $links.each( function () {
                var $link = $( this );
                // Remove native title from each link
                $link.removeAttr( 'title' );
                $link.on( 'mouseenter.itemTooltip', function () {
                    showTooltip( this, itemName );
                } ).on( 'mouseleave.itemTooltip', function () {
                    scheduleHide();
                } );
            } );
        } );
    } );
} )();