Actions

MediaWiki

MediaWiki:Gadget-ResourcePage.js

From Dune Awakening DB

Revision as of 12:49, 3 June 2025 by Operator (talk | contribs) (Created page with "* * ResourcePage Gadget * Handles recipe popups and search functionality for resource pages * * @requires jquery * @requires mediawiki.api * @requires mediawiki.util: (function($, mw) { 'use strict'; // Only run on pages with resource page elements if (!$('.crafting-section, .recipe-table').length) { return; } // Cache for storing recipe data var recipeCache = { craftedWith: null, craftedFrom: null...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
 * ResourcePage Gadget
 * Handles recipe popups and search functionality for resource pages
 * 
 * @requires jquery
 * @requires mediawiki.api
 * @requires mediawiki.util
 */

(function($, mw) {
    'use strict';
    
    // Only run on pages with resource page elements
    if (!$('.crafting-section, .recipe-table').length) {
        return;
    }
    
    // Cache for storing recipe data
    var recipeCache = {
        craftedWith: null,
        craftedFrom: null
    };
    
    // Initialize module
    function init() {
        // Add table search functionality
        initTableSearch();
        
        // Add popup handlers
        initPopupHandlers();
        
        // Format tables
        formatTables();
        
        // Add animation styles once
        addAnimationStyles();
    }
    
    // Format tables to ensure proper styling
    function formatTables() {
        $('.recipe-table').each(function() {
            var $table = $(this);
            
            // Ensure proper header styling
            $table.find('thead tr').addClass('tr-dark');
        });
    }
    
    // Initialize table search functionality
    function initTableSearch() {
        // Crafted With search
        $('#craftedWithSearch').on('input', function() {
            filterTable('#craftedWithTable', $(this).val());
        });
        
        // Crafted From search
        $('#craftedFromSearch').on('input', function() {
            filterTable('#craftedFromTable', $(this).val());
        });
    }
    
    // Filter table rows based on search input
    function filterTable(tableId, searchTerm) {
        var $table = $(tableId);
        var term = searchTerm.toLowerCase();
        
        $table.find('tbody tr').each(function() {
            var $row = $(this);
            var text = $row.text().toLowerCase();
            
            if (text.indexOf(term) > -1) {
                $row.show();
            } else {
                $row.hide();
            }
        });
    }
    
    // Initialize popup handlers
    function initPopupHandlers() {
        // View All Crafted With button
        $(document).on('click', '.view-all-crafted-with', function(e) {
            e.preventDefault();
            var resourceName = $(this).data('resource');
            showRecipePopup('craftedWith', resourceName);
        });
        
        // View All Crafted From button
        $(document).on('click', '.view-all-crafted-from', function(e) {
            e.preventDefault();
            var resourceName = $(this).data('resource');
            showRecipePopup('craftedFrom', resourceName);
        });
        
        // Close popup handlers
        $(document).on('click', '.recipe-popup-overlay, .popup-close', function(e) {
            if (e.target === this || $(e.target).hasClass('popup-close')) {
                closeRecipePopup();
            }
        });
        
        // Escape key to close popup
        $(document).on('keydown', function(e) {
            if (e.key === 'Escape' && $('.recipe-popup-overlay').hasClass('active')) {
                closeRecipePopup();
            }
        });
    }
    
    // Show recipe popup
    function showRecipePopup(type, resourceName) {
        var title = type === 'craftedWith' 
            ? 'All Recipes Using ' + resourceName
            : 'All Recipes Creating ' + resourceName;
        
        // Show loading state
        showLoadingPopup();
        
        // First, check for full data in hidden elements
        var $fullDataElement = $('.' + type.replace('craftedWith', 'crafted-with').replace('craftedFrom', 'crafted-from') + '-full-data');
        
        if ($fullDataElement.length && $fullDataElement.text().trim()) {
            try {
                // Parse JSON data from hidden element
                var jsonData = JSON.parse($fullDataElement.text());
                var rows = jsonData.results || [];
                
                // Transform to expected format
                var formattedRows = rows.map(function(row) {
                    return {
                        item: row.OutputItem || row.output_item || '',
                        resources: row.Resources || row.resources || '',
                        stations: row.Stations || row.station || '',
                        water: row.WaterML || row.water_ml || 'N/A',
                        craftTime: row.CraftTime || row.craft_time || 'N/A',
                        schematic: row.Schematic || row.schematic || 'N/A'
                    };
                });
                
                displayPopup(title, formattedRows, false);
                return;
            } catch (e) {
                console.warn('Failed to parse full recipe data:', e);
            }
        }
        
        // Fallback to visible data
        var $table = $(type === 'craftedWith' ? '#craftedWithTable' : '#craftedFromTable');
        var rows = getVisibleRows(type);
        displayPopup(title, rows, true);
    }
    
    // Get visible rows as fallback
    function getVisibleRows(type) {
        var $table = $(type === 'craftedWith' ? '#craftedWithTable' : '#craftedFromTable');
        var rows = [];
        
        $table.find('tbody tr:visible').each(function() {
            var $row = $(this);
            var $cells = $row.find('td');
            
            if ($cells.length >= 3) {
                rows.push({
                    item: $cells.eq(0).html(),
                    resources: $cells.eq(1).html(),
                    stations: $cells.eq(2).html(),
                    water: 'N/A',
                    craftTime: 'N/A',
                    schematic: 'N/A'
                });
            }
        });
        
        return rows;
    }
    
    // Show loading popup
    function showLoadingPopup() {
        var loadingHtml = '<div class="recipe-popup-overlay active">' +
            '<div class="recipe-popup">' +
                '<div class="popup-content" style="text-align: center; padding: 60px;">' +
                    '<div style="font-size: 24px; color: #fce7c8; margin-bottom: 20px;">Loading recipes...</div>' +
                    '<div class="loading-spinner">⟳</div>' +
                '</div>' +
            '</div>' +
        '</div>';
        
        $('body').append(loadingHtml);
    }
    
    // Display popup with data
    function displayPopup(title, rows, isLimited) {
        // Remove any existing popup
        $('.recipe-popup-overlay').remove();
        
        // Build table rows HTML
        var tableRowsHtml = '';
        rows.forEach(function(row) {
            tableRowsHtml += '<tr>' +
                '<td>' + row.item + '</td>' +
                '<td>' + row.resources + '</td>' +
                '<td>' + row.stations + '</td>' +
                '<td>' + row.water + '</td>' +
                '<td>' + row.craftTime + '</td>' +
                '<td>' + row.schematic + '</td>' +
            '</tr>';
        });
        
        // Note if data is limited
        var limitedNote = isLimited ? 
            '<div class="popup-note">Note: Showing only visible recipes. Full data requires server-side implementation.</div>' : 
            '';
        
        // Build popup HTML
        var popupHtml = '<div class="recipe-popup-overlay">' +
            '<div class="recipe-popup">' +
                '<div class="popup-header">' +
                    '<h3 class="popup-title">' + title + '</h3>' +
                    '<button class="popup-close">×</button>' +
                '</div>' +
                '<div class="popup-content">' +
                    limitedNote +
                    '<div class="popup-search-container">' +
                        '<input type="text" class="popup-search-input" placeholder="Search recipes..." id="popupSearchInput">' +
                    '</div>' +
                    '<div class="popup-table-wrapper">' +
                        '<table class="infobox-dune-standard-table recipe-popup-table" id="popupRecipeTable">' +
                            '<thead>' +
                                '<tr class="tr-dark">' +
                                    '<th data-sort="item">Item Created</th>' +
                                    '<th data-sort="resources">Resources Needed</th>' +
                                    '<th data-sort="stations">Stations</th>' +
                                    '<th data-sort="water">Water (mL)</th>' +
                                    '<th data-sort="time">Craft Time</th>' +
                                    '<th data-sort="schematic">Schematic</th>' +
                                '</tr>' +
                            '</thead>' +
                            '<tbody>' + tableRowsHtml + '</tbody>' +
                        '</table>' +
                    '</div>' +
                '</div>' +
            '</div>' +
        '</div>';
        
        // Add to page
        $('body').append(popupHtml);
        
        // Activate popup
        setTimeout(function() {
            $('.recipe-popup-overlay').addClass('active');
        }, 10);
        
        // Initialize popup functionality
        initPopupFunctionality();
    }
    
    // Initialize popup functionality (search and sort)
    function initPopupFunctionality() {
        // Search functionality
        $('#popupSearchInput').on('input', function() {
            var searchTerm = $(this).val().toLowerCase();
            
            $('#popupRecipeTable tbody tr').each(function() {
                var $row = $(this);
                var text = $row.text().toLowerCase();
                
                if (text.indexOf(searchTerm) > -1) {
                    $row.show();
                } else {
                    $row.hide();
                }
            });
        });
        
        // Sort functionality
        $('#popupRecipeTable thead th').on('click', function() {
            var $th = $(this);
            var sortKey = $th.data('sort');
            var $tbody = $('#popupRecipeTable tbody');
            var rows = $tbody.find('tr').toArray();
            
            // Determine sort direction
            var ascending = !$th.hasClass('sort-desc');
            
            // Remove sort classes from all headers
            $('#popupRecipeTable thead th').removeClass('sort-asc sort-desc');
            
            // Add appropriate class to clicked header
            $th.addClass(ascending ? 'sort-asc' : 'sort-desc');
            
            // Sort rows
            rows.sort(function(a, b) {
                var aText = $(a).find('td').eq($th.index()).text().trim();
                var bText = $(b).find('td').eq($th.index()).text().trim();
                
                // Try to parse as number
                var aNum = parseFloat(aText);
                var bNum = parseFloat(bText);
                
                if (!isNaN(aNum) && !isNaN(bNum)) {
                    return ascending ? aNum - bNum : bNum - aNum;
                }
                
                // Sort as text
                return ascending 
                    ? aText.localeCompare(bText)
                    : bText.localeCompare(aText);
            });
            
            // Re-append sorted rows
            $tbody.empty();
            rows.forEach(function(row) {
                $tbody.append(row);
            });
        });
    }
    
    // Close recipe popup
    function closeRecipePopup() {
        $('.recipe-popup-overlay').removeClass('active');
        
        setTimeout(function() {
            $('.recipe-popup-overlay').remove();
        }, 300);
    }
    
    // Add required CSS for animations
    function addAnimationStyles() {
        if ($('#resourcePageGadgetStyles').length === 0) {
            var styles = '<style id="resourcePageGadgetStyles">' +
                '.loading-spinner { font-size: 48px; animation: spin 1s linear infinite; }' +
                '@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }' +
                '.recipe-popup-table th.sort-asc::after { content: " ↑"; color: #fce7c8; }' +
                '.recipe-popup-table th.sort-desc::after { content: " ↓"; color: #fce7c8; }' +
                '.popup-note { background: rgba(252,231,200,.1); border: 1px solid rgba(252,231,200,.3); ' +
                    'padding: 10px; margin-bottom: 15px; color: #E3BB7A; text-align: center; }' +
            '</style>';
            $('head').append(styles);
        }
    }
    
    // Initialize when DOM is ready
    $(init);
    
})(jQuery, mediaWiki);