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
Line 1: Line 1:
/*
( function ( mw, $ ) {
* Gadget: VaultAltarComponent
    'use strict';
* ----------------------------
* Activated only when a <div class="js-vault-altar" id="vault-altar-component"> is present.
* Loads Vault altar data from: MediaWiki:Vault_altar_ingredients.json
*/


(function () {
    // ------------------------ Configurable ------------------------- //
  const JSON_PAGE = 'MediaWiki:Vault_altar_ingredients.json';
    // 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';


  $(function () {
    // Where in the DOM do we inject the component? Default is the
     const host = document.querySelector('.js-vault-altar#vault-altar-component');
    // beginning of the article body.
    if (!host) return;
     const TARGET_NODE_SELECTOR = '#vault-altar-component';


     $.getJSON(getRawURL(JSON_PAGE, 'application/json'))
     // ---------------------- Helper Functions ----------------------- //
      .done(data => initialise(host, data))
    /**
      .fail(() => host.textContent = '❌ Could not load altar data.');
    * Given a sorted numeric array of available levels, find the
  });
    * greatest level that is <= the user‑selected value.
    */
    function nearestLevel ( levels, val ) {
        let chosen = levels[ 0 ];
        for ( const lv of levels ) {
            if ( val >= lv ) {
                chosen = lv;
            } else {
                break;
            }
        }
        return chosen;
    }
 
    /**
    * 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 ) {
        $out.empty();


  function getRawURL(title, type) {
        const levelData = data.LEVELS[ levelKey ];
    return mw.util.wikiScript() +
        if ( !levelData ) {
      '?title=' + encodeURIComponent(title) +
            $out.append( $( '<p>' ).text( 'No data found for level ' + levelKey + '.' ) );
      '&action=raw&ctype=' + encodeURIComponent(type || 'text/plain');
            return;
  }
        }


  function initialise(root, data) {
        // For each category (resource, mob, farmable, misc) create a
const levelData = data.LEVELS || {};
        // collapsible <details> section containing a wikitable.
const levels = Object.keys(levelData).map(Number).sort((a, b) => a - b);
        Object.entries( levelData ).forEach( ( [ catName, entries ] ) => {
            const $details = $( '<details>' ).addClass( 'vault-altar-cat' );
            $details.append( $( '<summary>' ).text( catName.charAt( 0 ).toUpperCase() + catName.slice( 1 ) ) );


  if (!levels.length) {
            const $table = $( '<table>' )
    root.textContent = 'No data.';
                .addClass( 'wikitable sortable' )
    return;
                .append( $( '<thead>' ).append( $( '<tr>' )
  }
                    .append( $( '<th>' ).text( 'Items' ) )
                    .append( $( '<th>' ).text( 'Amount (min‒max)' ) )
                    .append( $( '<th>' ).text( 'Scale' ) )
                    .append( $( '<th>' ).text( 'Weight' ) )
                ) );


  const defaultLevel = levels[0];
            entries.forEach( entry => {
  console.log('[VaultAltar] Default level to show:', defaultLevel);
                const items = entry.value.items.map( o => o.item.replace( /^minecraft:/, '' ) ).join( ', ' );
                const amt = entry.value.amount.min + '‒' + entry.value.amount.max;
                const scale = entry.value.scale;
                const weight = entry.weight;


    const header = $('<div>', { class: 'vault-altar-header' }).appendTo(root);
                $table.append( $( '<tr>' )
    header.append('<span>Vault Level </span>');
                    .append( $( '<td>' ).text( items ) )
    const valueEl = $('<span>', { class: 'vault-altar-slider-value' }).appendTo(header);
                    .append( $( '<td>' ).text( amt ) )
                    .append( $( '<td>' ).text( scale ) )
                    .append( $( '<td>' ).text( weight ) )
                );
            } );


    const slider = $('<input>', {
            $details.append( $table );
      type: 'range',
            $out.append( $details );
      min: levels[0],
        } );
      max: levels[levels.length - 1],
     }
      value: levels[0],
      class: 'vault-altar-level-slider'
     }).appendTo(header);


     const output = $('<div>', { class: 'vault-altar-output' }).appendTo(root);
     // -------------------------- Main ------------------------------- //
    function init () {
        // Build the basic UI skeleton first so the page doesn’t feel
        // empty if the JSON request is slow.
        const $wrapper = $( '<div>' ).addClass( 'vault-altar-wrapper' );
        const $sliderRow = $( '<div>' ).addClass( 'vault-altar-slider' );


    slider.on('input change', () => render(+slider.val()));
        const $label = $( '<label>' )
    render(levels[0]);
            .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%' );


    function render(level) {
        $sliderRow.append( $label, $valDisplay, $input );
      valueEl.text(level);
        $wrapper.append( $sliderRow );
      output.empty();
        const $output = $( '<div>' ).attr( 'id', 'vault-altar-output' );
        $wrapper.append( $output );


      const entry = levelData[level];
        // Inject into page.
      if (!entry) {
        $( TARGET_NODE_SELECTOR ).first().prepend( $wrapper );
        output.text('No data for this level.');
        return;
      }


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


        const table = $('<table>', { class: 'vault-altar-table' }).appendTo(catBox);
            /**
        table.append('<thead><tr><th>Item</th><th>Amount</th></tr></thead>');
            * Update handler for the slider.
        const tbody = $('<tbody>').appendTo(table);
            */
            function update () {
                const userVal = parseInt( $input.val(), 10 );
                const lvl = nearestLevel( levels, userVal );
                $valDisplay.text( userVal + ' (showing ' + lvl + ')' );
                renderLevel( data, String( lvl ), $output );
            }


        (entry[category] || []).forEach(row => {
            $input.on( 'input change', update );
          $('<tr>')
             update(); // Initial render.
             .append($('<td>').text(row.item))
        } ).fail( function () {
             .append($('<td>').text(row.amount))
             $output.text( 'Failed to load Vault Altar data – please check that ' + JSON_PAGE + ' exists and is valid JSON.' );
            .appendTo(tbody);
         } );
         });
      });
     }
     }
  }


  function capitalise(str) {
    // Kick‑off when DOM is ready.
     return str.charAt(0).toUpperCase() + str.slice(1);
     $( init );
  }
 
})();
} )( mediaWiki, jQuery );

Revision as of 05:39, 7 July 2025

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

    // ------------------------ 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';

    // 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 ----------------------- //
    /**
     * Given a sorted numeric array of available levels, find the
     * greatest level that is <= the user‑selected value.
     */
    function nearestLevel ( levels, val ) {
        let chosen = levels[ 0 ];
        for ( const lv of levels ) {
            if ( val >= lv ) {
                chosen = lv;
            } else {
                break;
            }
        }
        return chosen;
    }

    /**
     * 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 ) {
        $out.empty();

        const levelData = data.LEVELS[ levelKey ];
        if ( !levelData ) {
            $out.append( $( '<p>' ).text( 'No data found for level ' + levelKey + '.' ) );
            return;
        }

        // For each category (resource, mob, farmable, misc) create a
        // collapsible <details> section containing a wikitable.
        Object.entries( levelData ).forEach( ( [ catName, entries ] ) => {
            const $details = $( '<details>' ).addClass( 'vault-altar-cat' );
            $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 items = entry.value.items.map( o => o.item.replace( /^minecraft:/, '' ) ).join( ', ' );
                const amt = entry.value.amount.min + '‒' + entry.value.amount.max;
                const scale = entry.value.scale;
                const weight = entry.weight;

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

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

    // -------------------------- Main ------------------------------- //
    function init () {
        // Build the basic UI skeleton first so the page doesn’t feel
        // empty if the JSON request is slow.
        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 );

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

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

            /**
             * Update handler for the slider.
             */
            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(); // Initial render.
        } ).fail( function () {
            $output.text( 'Failed to load Vault Altar data – please check that ' + JSON_PAGE + ' exists and is valid JSON.' );
        } );
    }

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

} )( mediaWiki, jQuery );