Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Gadget-VaultAltarComponent.js: Difference between revisions

MediaWiki interface page
No edit summary
No edit summary
 
(One intermediate revision by the same user not shown)
Line 3: Line 3:


     // ------------------------ Configurable ------------------------- //
     // ------------------------ Configurable ------------------------- //
    // Title (in the page namespace) of the raw JSON data. Change this
    // if you decide to store the file elsewhere.
     const JSON_PAGE = 'MediaWiki:Vault_altar_ingredients.json';
     const JSON_PAGE = 'MediaWiki:Vault_altar_ingredients.json';
 
     const PLACEHOLDER_SELECTOR = '.js-vault-altar#vault-altar-component';
    // Where in the DOM do we inject the component? Default is the
    // beginning of the article body.
     const TARGET_NODE_SELECTOR = '#vault-altar-component';


     // ---------------------- Helper Functions ----------------------- //
     // ---------------------- Helper Functions ----------------------- //
    /**
    * Given a sorted numeric array of available levels, find the
    * greatest level that is <= the user‑selected value.
    */
     function nearestLevel ( levels, val ) {
     function nearestLevel ( levels, val ) {
         let chosen = levels[ 0 ];
         let chosen = levels[ 0 ];
Line 26: Line 17:
         }
         }
         return chosen;
         return chosen;
    }
    /** Return canonical file‑path URL for a given filename. */
    function filePath ( filename ) {
        return mw.util.getUrl( 'Special:FilePath/' + filename );
    }
    /** Convert an item id like "iron_ingot" → "Iron_Ingot" */
    function toIconName ( id ) {
        return id.split( '_' ).map( w => w.charAt( 0 ).toUpperCase() + w.slice( 1 ) ).join( '_' );
     }
     }


     /**
     /**
     * Render the output tables for a particular vault level.
     * Render the output tables for a particular vault level.
    *
     * @param {Object} data – Parsed JSON object (the entire file).
     * @param {Object} data – Parsed JSON object (the entire file).
     * @param {string} levelKey – The exact level key to show (e.g. "10").
     * @param {string} levelKey – The exact level key to show (e.g. "10").
Line 36: Line 36:
     */
     */
     function renderLevel ( data, levelKey, $out ) {
     function renderLevel ( data, levelKey, $out ) {
         $out.empty();
    const levelData = data.LEVELS[ levelKey ];
    if ( !levelData ) {
        $out.html( $( '<p>' ).text( 'No data found for level ' + levelKey + '.' ) );
        return;
    }
 
    Object.entries( levelData ).forEach( ( [ catName, entries ] ) => {
        const catId = 'vault-altar-cat-' + catName.toLowerCase().replace(/\s+/g, '-');
         let $details = $out.find( '#' + catId );


         const levelData = data.LEVELS[ levelKey ];
         // If category section doesn't exist, create it
         if ( !levelData ) {
         if ( $details.length === 0 ) {
             $out.append( $( '<p>' ).text( 'No data found for level ' + levelKey + '.' ) );
             $details = $( '<details>' )
             return;
                .addClass( 'vault-altar-cat' )
                .attr( 'id', catId )
                .append( $( '<summary>' ).text( catName.charAt( 0 ).toUpperCase() + catName.slice( 1 ) ) );
             $out.append( $details );
         }
         }


         // For each category (resource, mob, farmable, misc) create a
         // Remove old table, if any
         // collapsible <details> section containing a wikitable.
        $details.find( 'table' ).remove();
        Object.entries( levelData ).forEach( ( [ catName, entries ] ) => {
 
            const $details = $( '<details>' ).addClass( 'vault-altar-cat' );
         // Create new table for this level
            $details.append( $( '<summary>' ).text( catName.charAt( 0 ).toUpperCase() + catName.slice( 1 ) ) );
        const $table = $( '<table>' )
            .addClass( 'wikitable sortable' )
            .append( $( '<thead>' ).append( $( '<tr>' )
                .append( $( '<th>' ).text( 'Items' ) )
                .append( $( '<th>' ).text( 'Amount (min‒max)' ) )
                .append( $( '<th>' ).text( 'Scale' ) )
                .append( $( '<th>' ).text( 'Weight' ) )
            ) );
 
        entries.forEach( entry => {
            const itemNames = entry.value.items.map( o => o.item.replace( /^minecraft:/, '' ).replace( /_/g, ' ' ) );
            const itemsText = itemNames.join( ', ' );


             const $table = $( '<table>' )
             const firstId = entry.value.items[ 0 ].item.replace( /^minecraft:/, '' );
                .addClass( 'wikitable sortable' )
            const iconFile = 'Invicon_' + toIconName( firstId ) + '.png';
                .append( $( '<thead>' ).append( $( '<tr>' )
            const $img = $( '<img>' )
                    .append( $( '<th>' ).text( 'Items' ) )
                .attr( 'src', filePath( iconFile ) )
                    .append( $( '<th>' ).text( 'Amount (min‒max)' ) )
                .attr( {
                     .append( $( '<th>' ).text( 'Scale' ) )
                    width: 20,
                     .append( $( '<th>' ).text( 'Weight' ) )
                    height: 20,
                 ) );
                    loading: 'lazy'
                } )
                .css( {
                     'vertical-align': 'middle',
                     'margin-right'  : '0.25em'
                 } );


             entries.forEach( entry => {
             const amt   = entry.value.amount.min + '‒' + entry.value.amount.max;
                const items = entry.value.items.map( o => o.item.replace( /^minecraft:/, '' ) ).join( ', ' );
            const scale = entry.value.scale;
                const amt = entry.value.amount.min + '‒' + entry.value.amount.max;
            const weight = entry.weight;
                const scale = entry.value.scale;
                const weight = entry.weight;


                $table.append( $( '<tr>' )
            const $itemCell = $( '<td>' ).append( $img ).append( document.createTextNode( ' ' + itemsText ) );
                    .append( $( '<td>' ).text( items ) )
                    .append( $( '<td>' ).text( amt ) )
                    .append( $( '<td>' ).text( scale ) )
                    .append( $( '<td>' ).text( weight ) )
                );
            } );


             $details.append( $table );
             $table.append( $( '<tr>' )
            $out.append( $details );
                .append( $itemCell )
                .append( $( '<td>' ).text( amt ) )
                .append( $( '<td>' ).text( scale ) )
                .append( $( '<td>' ).text( weight ) )
            );
         } );
         } );
     }
 
        $details.append( $table );
     } );
}


     // -------------------------- Main ------------------------------- //
     // -------------------------- Main ------------------------------- //
     function init () {
     function init () {
         // Build the basic UI skeleton first so the page doesn’t feel
         const host = document.querySelector( PLACEHOLDER_SELECTOR );
         // empty if the JSON request is slow.
         if ( !host ) return; // Only activate where template is present
         const $wrapper = $( '<div>' ).addClass( 'vault-altar-wrapper' );
 
         const $wrapper   = $( '<div>' ).addClass( 'vault-altar-wrapper' );
         const $sliderRow = $( '<div>' ).addClass( 'vault-altar-slider' );
         const $sliderRow = $( '<div>' ).addClass( 'vault-altar-slider' );


         const $label = $( '<label>' )
         const $label     = $( '<label>' ).attr( 'for', 'vault-altar-level' ).text( 'Vault Level: ' );
            .attr( 'for', 'vault-altar-level' )
            .text( 'Vault Level: ' );
         const $valDisplay = $( '<span>' ).attr( 'id', 'vault-altar-level-val' ).text( '0' );
         const $valDisplay = $( '<span>' ).attr( 'id', 'vault-altar-level-val' ).text( '0' );
         const $input = $( '<input>' )
         const $input     = $( '<input>' ).attr( {
            .attr( {
            id   : 'vault-altar-level',
                id: 'vault-altar-level',
            type : 'range',
                type: 'range',
            min : 0,
                min: 0,
            max : 100,
                max: 100,
            step : 1,
                step: 1,
            value: 0
                value: 0
        } ).css( 'width', '100%' );
            } )
            .css( 'width', '100%' );


         $sliderRow.append( $label, $valDisplay, $input );
         $sliderRow.append( $label, $valDisplay, $input );
Line 105: Line 128:
         $wrapper.append( $output );
         $wrapper.append( $output );


        // Inject into page.
         $( host ).empty().append( $wrapper );
         $( TARGET_NODE_SELECTOR ).first().prepend( $wrapper );


        // Fetch JSON data (raw content).
         $.getJSON( mw.util.wikiScript( 'index' ), {
         $.getJSON( mw.util.wikiScript( 'index' ), {
             title: JSON_PAGE,
             title : JSON_PAGE,
             action: 'raw',
             action: 'raw',
             ctype: 'application/json'
             ctype : 'application/json'
         } ).done( function ( data ) {
         } ).done( function ( data ) {
            // Prepare slider limits based on actual data keys.
             const levels = Object.keys( data.LEVELS ).map( Number ).sort( ( a, b ) => a - b );
             const levels = Object.keys( data.LEVELS ).map( Number ).sort( ( a, b ) => a - b );
             $input.attr( {
             $input.attr( { min: levels[ 0 ], max: levels[ levels.length - 1 ] } );
                min: levels[ 0 ],
                max: levels[ levels.length - 1 ]
            } );


            /**
            * Update handler for the slider.
            */
             function update () {
             function update () {
                 const userVal = parseInt( $input.val(), 10 );
                 const userVal = parseInt( $input.val(), 10 );
Line 132: Line 146:


             $input.on( 'input change', update );
             $input.on( 'input change', update );
             update(); // Initial render.
             update();
         } ).fail( function () {
         } ).fail( function () {
             $output.text( 'Failed to load Vault Altar data – please check that ' + JSON_PAGE + ' exists and is valid JSON.' );
             $output.text( 'Failed to load Vault Altar data – please check that ' + JSON_PAGE + ' exists and is valid JSON.' );
Line 138: Line 152:
     }
     }


    // Kick‑off when DOM is ready.
     $( init );
     $( init );


} )( mediaWiki, jQuery );
} )( mediaWiki, jQuery );

Latest revision as of 23:19, 11 July 2025

( function ( mw, $ ) {
    'use strict';

    // ------------------------ Configurable ------------------------- //
    const JSON_PAGE = 'MediaWiki:Vault_altar_ingredients.json';
    const PLACEHOLDER_SELECTOR = '.js-vault-altar#vault-altar-component';

    // ---------------------- Helper Functions ----------------------- //
    function nearestLevel ( levels, val ) {
        let chosen = levels[ 0 ];
        for ( const lv of levels ) {
            if ( val >= lv ) {
                chosen = lv;
            } else {
                break;
            }
        }
        return chosen;
    }

    /** Return canonical file‑path URL for a given filename. */
    function filePath ( filename ) {
        return mw.util.getUrl( 'Special:FilePath/' + filename );
    }

    /** Convert an item id like "iron_ingot" → "Iron_Ingot" */
    function toIconName ( id ) {
        return id.split( '_' ).map( w => w.charAt( 0 ).toUpperCase() + w.slice( 1 ) ).join( '_' );
    }

    /**
     * Render the output tables for a particular vault level.
     * @param {Object} data – Parsed JSON object (the entire file).
     * @param {string} levelKey – The exact level key to show (e.g. "10").
     * @param {jQuery} $out – jQuery node where HTML will be injected.
     */
    function renderLevel ( data, levelKey, $out ) {
    const levelData = data.LEVELS[ levelKey ];
    if ( !levelData ) {
        $out.html( $( '<p>' ).text( 'No data found for level ' + levelKey + '.' ) );
        return;
    }

    Object.entries( levelData ).forEach( ( [ catName, entries ] ) => {
        const catId = 'vault-altar-cat-' + catName.toLowerCase().replace(/\s+/g, '-');
        let $details = $out.find( '#' + catId );

        // If category section doesn't exist, create it
        if ( $details.length === 0 ) {
            $details = $( '<details>' )
                .addClass( 'vault-altar-cat' )
                .attr( 'id', catId )
                .append( $( '<summary>' ).text( catName.charAt( 0 ).toUpperCase() + catName.slice( 1 ) ) );
            $out.append( $details );
        }

        // Remove old table, if any
        $details.find( 'table' ).remove();

        // Create new table for this level
        const $table = $( '<table>' )
            .addClass( 'wikitable sortable' )
            .append( $( '<thead>' ).append( $( '<tr>' )
                .append( $( '<th>' ).text( 'Items' ) )
                .append( $( '<th>' ).text( 'Amount (min‒max)' ) )
                .append( $( '<th>' ).text( 'Scale' ) )
                .append( $( '<th>' ).text( 'Weight' ) )
            ) );

        entries.forEach( entry => {
            const itemNames = entry.value.items.map( o => o.item.replace( /^minecraft:/, '' ).replace( /_/g, ' ' ) );
            const itemsText = itemNames.join( ', ' );

            const firstId = entry.value.items[ 0 ].item.replace( /^minecraft:/, '' );
            const iconFile = 'Invicon_' + toIconName( firstId ) + '.png';
            const $img = $( '<img>' )
                .attr( 'src', filePath( iconFile ) )
                .attr( {
                    width: 20,
                    height: 20,
                    loading: 'lazy'
                } )
                .css( {
                    'vertical-align': 'middle',
                    'margin-right'  : '0.25em'
                } );

            const amt    = entry.value.amount.min + '‒' + entry.value.amount.max;
            const scale  = entry.value.scale;
            const weight = entry.weight;

            const $itemCell = $( '<td>' ).append( $img ).append( document.createTextNode( ' ' + itemsText ) );

            $table.append( $( '<tr>' )
                .append( $itemCell )
                .append( $( '<td>' ).text( amt ) )
                .append( $( '<td>' ).text( scale ) )
                .append( $( '<td>' ).text( weight ) )
            );
        } );

        $details.append( $table );
    } );
}

    // -------------------------- Main ------------------------------- //
    function init () {
        const host = document.querySelector( PLACEHOLDER_SELECTOR );
        if ( !host ) return; // Only activate where template is present

        const $wrapper   = $( '<div>' ).addClass( 'vault-altar-wrapper' );
        const $sliderRow = $( '<div>' ).addClass( 'vault-altar-slider' );

        const $label      = $( '<label>' ).attr( 'for', 'vault-altar-level' ).text( 'Vault Level: ' );
        const $valDisplay = $( '<span>' ).attr( 'id', 'vault-altar-level-val' ).text( '0' );
        const $input      = $( '<input>' ).attr( {
            id   : 'vault-altar-level',
            type : 'range',
            min  : 0,
            max  : 100,
            step : 1,
            value: 0
        } ).css( 'width', '100%' );

        $sliderRow.append( $label, $valDisplay, $input );
        $wrapper.append( $sliderRow );
        const $output = $( '<div>' ).attr( 'id', 'vault-altar-output' );
        $wrapper.append( $output );

        $( host ).empty().append( $wrapper );

        $.getJSON( mw.util.wikiScript( 'index' ), {
            title : JSON_PAGE,
            action: 'raw',
            ctype : 'application/json'
        } ).done( function ( data ) {
            const levels = Object.keys( data.LEVELS ).map( Number ).sort( ( a, b ) => a - b );
            $input.attr( { min: levels[ 0 ], max: levels[ levels.length - 1 ] } );

            function update () {
                const userVal = parseInt( $input.val(), 10 );
                const lvl = nearestLevel( levels, userVal );
                $valDisplay.text( userVal + ' (showing ' + lvl + ')' );
                renderLevel( data, String( lvl ), $output );
            }

            $input.on( 'input change', update );
            update();
        } ).fail( function () {
            $output.text( 'Failed to load Vault Altar data – please check that ' + JSON_PAGE + ' exists and is valid JSON.' );
        } );
    }

    $( init );

} )( mediaWiki, jQuery );