imported>Dawning
Im Wiking It
imported>Dawning
Im Wiking It
Line 461: Line 461:
          
          
         createTabs(container, gifMap);
         createTabs(container, gifMap);
 
       
        // Display the first GIF by default
         const firstTabName = Object.keys(gifMap)[0];
         const firstTabName = Object.keys(gifMap)[0];
         console.log('Tab GIF Display: Showing first tab:', firstTabName);
         console.log('Tab GIF Display: Showing first tab:', firstTabName);
Line 548: Line 549:
             tab.textContent = tabName;
             tab.textContent = tabName;
             tab.setAttribute('data-tab-name', tabName);
             tab.setAttribute('data-tab-name', tabName);
             tab.type = 'button';  
             tab.type = 'button';
              
              
             if (isFirst) {
             if (isFirst) {
Line 570: Line 571:
     function handleTabClick(container, gifMap, tabName) {
     function handleTabClick(container, gifMap, tabName) {
         console.log('Tab GIF Display: Handling tab click for', tabName);
         console.log('Tab GIF Display: Handling tab click for', tabName);
 
       
         const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
         const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
         tabs.forEach(tab => {
         tabs.forEach(tab => {
Line 616: Line 617:
                 imgContainer.classList.remove('loading');
                 imgContainer.classList.remove('loading');
             } else {
             } else {
                 imgContainer.classList.add('loading');
                 const oldImg = imgContainer.querySelector('img');
                imgContainer.innerHTML = '';  
                  
                  
                 const img = document.createElement('img');
                 const img = document.createElement('img');
Line 623: Line 623:
                 img.alt = tabName;
                 img.alt = tabName;
                 img.style.maxHeight = gifSize + 'px';
                 img.style.maxHeight = gifSize + 'px';
                img.style.opacity = '0';
                img.style.position = 'absolute';
                img.style.transition = 'opacity 0.2s ease';
                  
                  
                 img.onload = () => {
                 img.onload = () => {
                     imgContainer.innerHTML = '';
                     if (oldImg) {
                     imgContainer.appendChild(img);
                        oldImg.style.transition = 'opacity 0.15s ease';
                    imgContainer.classList.remove('loading');
                        oldImg.style.opacity = '0';
                        setTimeout(() => {
                            imgContainer.innerHTML = '';
                            img.style.position = 'relative';
                            img.style.opacity = '1';
                            imgContainer.appendChild(img);
                            imgContainer.classList.remove('loading');
                        }, 150);
                     } else {
                        imgContainer.innerHTML = '';
                        img.style.position = 'relative';
                        img.style.opacity = '1';
                        imgContainer.appendChild(img);
                        imgContainer.classList.remove('loading');
                    }
                     console.log('Tab GIF Display: GIF loaded successfully');
                     console.log('Tab GIF Display: GIF loaded successfully');
                 };
                 };
Line 637: Line 654:
                     console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                     console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                 };
                 };
               
                if (!oldImg) {
                    imgContainer.appendChild(img);
                    imgContainer.classList.add('loading');
                }
             }
             }
         }
         }
Line 668: Line 690:
      
      
     window.addEventListener('load', init);
     window.addEventListener('load', init);
 
   
     if (typeof mw !== 'undefined' && mw.hook) {
     if (typeof mw !== 'undefined' && mw.hook) {
         mw.hook('wikipage.content').add(init);
         mw.hook('wikipage.content').add(init);
     }
     }
 
   
     const observer = new MutationObserver(function(mutations) {
     const observer = new MutationObserver(function(mutations) {
         let shouldReinit = false;
         let shouldReinit = false;

Revision as of 04:50, 3 November 2025

/* Any JavaScript here will be loaded for all users on every page load. */

/* DRUID */
$(function () {
  $(".druid-main-images-label").off("click");
  $(".druid-main-images-label").click(function () {
    var $parent = $(this).closest(".druid-container");
    $parent.find(".druid-toggleable").removeClass("focused");
    var i = $(this).attr("data-druid");
    $parent.find(".druid-toggleable[data-druid=" + i + "]").addClass("focused");
  });

  $(".druid-collapsible").off("click");
  $(".druid-collapsible").click(function () {
    var kind = $(this).attr("data-druid-section");
    $(this).toggleClass("druid-collapsible-collapsed");
    $(this)
      .closest(".druid-container")
      .find("[data-druid-section-row=" + kind + "]")
      .toggleClass("druid-collapsed");
  });
});
/* End DRUID */

/* [[Template:Spoiler]] */
$(function () {
	$('.spoiler-content')
	.off('click') // in case this code is loaded twice
	.on('click', function(e){
		$(this).toggleClass('show');
	}).find('a').on('click', function(e){
		e.stopPropagation();
	});

});
/* End Template:Spoiler */


/* Link to imported modules from Lua code */
$(function() {
    var config = mw.config.get([
        'wgCanonicalNamespace',
        'wgFormattedNamespaces'
    ]);
    if (config.wgCanonicalNamespace !== 'Module') {
        return;
    }
    var localizedNamespace = config.wgFormattedNamespaces[828];
    $('.s1, .s2, .s').each(function() {
        var $this = $(this);
        var html = $this.html();
        var quote = html[0];
        var isLongStringQuote = quote === '[';
        var quoteRE = new RegExp('^\\' + quote + '|\\' + quote + '$', 'g');
        if (isLongStringQuote) {
            quoteRE = /^\[\[|\]\]$/g;
        }
        var name = html.replace(quoteRE, '');
        var isEnglishPrefix = name.startsWith('Module:');
        var isLocalizedPrefix = name.startsWith(localizedNamespace + ':');
        var isDevPrefix = name.startsWith('Dev:');
        if (isEnglishPrefix || isLocalizedPrefix || isDevPrefix) {
            var attrs = {
                href: mw.util.getUrl(name)
            };
            if (isDevPrefix) {
                attrs.href = 'https://commons.wiki.gg/wiki/Module:' + mw.util.wikiUrlencode(name.replace('Dev:', ''));
                attrs.target = '_blank';
                attrs.rel = 'noopener';
            }
            var link = mw.html.element('a', attrs, name);
            var str = quote + link + quote;
            if (isLongStringQuote) {
                str = '[[' + link + ']]';
            }
            $this.html(str);
        }
    });
});

/* dynamic gif displayer ONLY TOUCH IF YOU KNOW WHAT YOU ARE DOING */

(function() {
    'use strict';
    
    console.log('Dynamic GIF Displayer: Script loading...');
    
    // Configuration
    const CONFIG = {
        containerClass: 'dynamic-gif-container',
        displayClass: 'gif-display-area',
        autoExpand: true,
        expandDelay: 200,
        collapseDelay: 1000
    };
    
    let expandTimer = null;
    let collapseTimer = null;
    let currentGif = null;
    
    function safeCreateError(message) {
        const div = document.createElement('div');
        div.className = 'gif-error';
        div.textContent = message;
        return div;
    }
    
    function safeCreatePlaceholder(message) {
        const div = document.createElement('div');
        div.className = 'gif-placeholder';
        div.textContent = message;
        return div;
    }
    
    function init() {
        console.log('Dynamic GIF Displayer: Initializing...');
        
        const containers = document.querySelectorAll('.' + CONFIG.containerClass);
        console.log('Dynamic GIF Displayer: Found', containers.length, 'containers');
        
        containers.forEach(container => {
            console.log('Dynamic GIF Displayer: Setting up container', container.id);
            setupContainer(container);
            attachTooltipListeners(container);
        });
    }
    
    function setupContainer(container) {
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
        if (!displayArea) {
            console.error('Dynamic GIF Displayer: No display area found');
            return;
        }
        
        displayArea.addEventListener('mouseenter', () => {
            clearTimeout(collapseTimer);
        });
        
        displayArea.addEventListener('mouseleave', () => {
            scheduleCollapse(container);
        });
    }
    
    function attachTooltipListeners(container) {
        console.log('Dynamic GIF Displayer: Attaching tooltip listeners...');
        
        const gifMap = buildGifMap(container);
        console.log('Dynamic GIF Displayer: GIF map', gifMap);
        
        const tooltips = document.querySelectorAll('.advanced-tooltip');
        console.log('Dynamic GIF Displayer: Found', tooltips.length, 'tooltips');
        
        tooltips.forEach((tooltip) => {
            const skillTitle = tooltip.querySelector('.skill-title');
            if (!skillTitle) return;
            
            const skillName = skillTitle.textContent.trim();
            const gifUrl = gifMap[skillName];
            
            console.log('Dynamic GIF Displayer: Processing tooltip:', skillName, 'GIF:', gifUrl);
            
            if (gifUrl) {
                tooltip.removeEventListener('mouseenter', tooltip._gifHoverHandler);
                tooltip.removeEventListener('mouseleave', tooltip._gifLeaveHandler);
                
                tooltip._gifHoverHandler = () => handleTooltipHover(container, gifUrl, skillName);
                tooltip._gifLeaveHandler = () => scheduleCollapse(container);
                
                tooltip.addEventListener('mouseenter', tooltip._gifHoverHandler);
                tooltip.addEventListener('mouseleave', tooltip._gifLeaveHandler);
                
                console.log('Dynamic GIF Displayer: Attached listeners to', skillName);
            }
        });
    }
    
    function buildGifMap(container) {
        const gifMap = {};
        const listData = container.getAttribute('data-gif-list');
        
        if (!listData) {
            console.error('Dynamic GIF Displayer: No data-gif-list attribute found');
            return gifMap;
        }
        
        console.log('Dynamic GIF Displayer: Raw list data:', listData);
        
        const entries = listData.split(';').filter(e => e.trim());
        console.log('Dynamic GIF Displayer: Found', entries.length, 'entries');
        
        entries.forEach(entry => {
            const parts = entry.split(':');
            if (parts.length >= 2) {
                const skillName = parts[0].trim();
                const gifFile = parts.slice(1).join(':').trim();
                
                if (skillName && gifFile) {
                    let gifUrl;
                    if (typeof mw !== 'undefined' && mw.config) {
                        const scriptPath = mw.config.get('wgScriptPath') || '';
                        gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                    } else {
                        gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                    }
                    
                    gifMap[skillName] = gifUrl;
                    console.log('Dynamic GIF Displayer: Mapped "' + skillName + '" to', gifUrl);
                }
            }
        });
        
        return gifMap;
    }
    
    function handleTooltipHover(container, gifUrl, skillName) {
        console.log('Dynamic GIF Displayer: Hovering', skillName);
        clearTimeout(collapseTimer);
        clearTimeout(expandTimer);
        
        expandTimer = setTimeout(() => {
            showGif(container, gifUrl, skillName);
        }, CONFIG.expandDelay);
    }

    function showGif(container, gifUrl, skillName) {
        console.log('Dynamic GIF Displayer: Showing GIF for', skillName, gifUrl);
        
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
        if (!displayArea) return;
        
        const gifSize = container.getAttribute('data-gif-size') || '400';
        
        if (!container.classList.contains('expanded')) {
            container.classList.add('expanded');
            console.log('Dynamic GIF Displayer: Expanded container');
        }
        
        if (currentGif !== gifUrl) {
            const imgContainer = displayArea.querySelector('.gif-image-container');
            const caption = displayArea.querySelector('.gif-caption');
            
            if (imgContainer) {
                const placeholder = imgContainer.querySelector('.gif-placeholder');
                if (placeholder) {
                    placeholder.remove();
                }
                
                imgContainer.style.height = gifSize + 'px';
                imgContainer.style.minHeight = gifSize + 'px';
                
                const gifFilename = gifUrl.split('/').pop();
                if (gifFilename.toLowerCase() === 'blank' || gifFilename.toLowerCase() === 'blank.gif') {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreatePlaceholder('This node does not require a GIF due to its simplicity.'));
                    imgContainer.classList.remove('loading');
                } else {
                    imgContainer.classList.add('loading');
                    
                    const img = document.createElement('img');
                    img.src = gifUrl;
                    img.alt = skillName;
                    img.style.maxHeight = gifSize + 'px';
                    
                    img.onload = () => {
                        imgContainer.innerHTML = '';
                        imgContainer.appendChild(img);
                        imgContainer.classList.remove('loading');
                        console.log('Dynamic GIF Displayer: GIF loaded successfully');
                    };
                    
                    img.onerror = () => {
                        imgContainer.innerHTML = '';
                        imgContainer.appendChild(safeCreateError('GIF not found: ' + gifUrl));
                        imgContainer.classList.remove('loading');
                        console.error('Dynamic GIF Displayer: Failed to load GIF', gifUrl);
                    };
                }
            }
            
            if (caption) {
                caption.textContent = skillName;
                caption.style.display = 'block';
            }
            
            currentGif = gifUrl;
        }
    }
    
    function scheduleCollapse(container) {
        // Keep the most recent GIF displayed instead of clearing it
        // GIF will only change when a different skill node is hovered
        clearTimeout(collapseTimer);
        console.log('Dynamic GIF Displayer: Keeping current GIF displayed');
    }
    
    window.toggleGifDisplay = function(containerId) {
        console.log('Dynamic GIF Displayer: Toggle clicked for', containerId);
        const container = document.getElementById(containerId);
        if (!container) {
            console.error('Dynamic GIF Displayer: Container not found', containerId);
            return;
        }
        
        clearTimeout(collapseTimer);
        
        if (container.style.display === 'none') {
            container.style.display = 'block';
        } else {
            container.style.display = 'none';
        }
        
        // Only clear the GIF when manually toggling the display off
        if (container.style.display === 'none') {
            const displayArea = container.querySelector('.' + CONFIG.displayClass);
            if (displayArea) {
                const imgContainer = displayArea.querySelector('.gif-image-container');
                const caption = displayArea.querySelector('.gif-caption');
                
                if (imgContainer) {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
                    imgContainer.style.height = '';
                    imgContainer.style.minHeight = '';
                }
                
                if (caption) {
                    caption.textContent = '';
                    caption.style.display = 'none';
                }
            }
            
            container.classList.remove('expanded');
            currentGif = null;
        }
    };
    
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
    
    window.addEventListener('load', init);
    
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(init);
    }
    
    const observer = new MutationObserver(function(mutations) {
        let shouldReinit = false;
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1 && (
                        node.classList && node.classList.contains('advanced-tooltip') ||
                        node.querySelector && node.querySelector('.advanced-tooltip')
                    )) {
                        shouldReinit = true;
                    }
                });
            }
        });
        if (shouldReinit) {
            console.log('Dynamic GIF Displayer: Content changed, reinitializing...');
            setTimeout(init, 100);
        }
    });
    
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
    
    console.log('Dynamic GIF Displayer: Script loaded');
})();


(function() {
    'use strict';
    
    console.log('Tab GIF Display: Script loading...');
    
    // Configuration
    const CONFIG = {
        containerClass: 'tab-gif-container',
        displayClass: 'tab-gif-display-area',
        tabsClass: 'tab-gif-tabs',
        tabClass: 'tab-gif-tab',
        activeTabClass: 'tab-gif-active'
    };
    
    let currentContainers = new Map();
    let initAttempts = 0;
    const MAX_INIT_ATTEMPTS = 5;
    
    function safeCreateError(message) {
        const div = document.createElement('div');
        div.className = 'gif-error';
        div.textContent = message;
        return div;
    }
    
    function safeCreatePlaceholder(message) {
        const div = document.createElement('div');
        div.className = 'gif-placeholder';
        div.textContent = message;
        return div;
    }
    
    function init() {
        initAttempts++;
        console.log('Tab GIF Display: Initializing... (attempt ' + initAttempts + ')');
        
        const containers = document.querySelectorAll('.' + CONFIG.containerClass);
        console.log('Tab GIF Display: Found', containers.length, 'containers');
        
        if (containers.length === 0 && initAttempts < MAX_INIT_ATTEMPTS) {
            console.log('Tab GIF Display: No containers found yet, will retry...');
            setTimeout(init, 500);
            return;
        }
        
        let setupCount = 0;
        containers.forEach(container => {
            const containerId = container.id;
            console.log('Tab GIF Display: Checking container', containerId);
            
            if (!currentContainers.has(containerId)) {
                console.log('Tab GIF Display: Setting up NEW container', containerId);
                const success = setupContainer(container);
                if (success) {
                    currentContainers.set(containerId, container);
                    setupCount++;
                }
            } else {
                console.log('Tab GIF Display: Container already initialized', containerId);
            }
        });
        
        console.log('Tab GIF Display: Successfully set up', setupCount, 'containers');
    }
    
    function setupContainer(container) {
        console.log('Tab GIF Display: setupContainer called for', container.id);
        
        const gifMap = buildGifMap(container);
        console.log('Tab GIF Display: GIF map built', gifMap);
        
        if (Object.keys(gifMap).length === 0) {
            console.error('Tab GIF Display: No GIFs found for container', container.id);
            const displayArea = container.querySelector('.' + CONFIG.displayClass);
            if (displayArea) {
                const imgContainer = displayArea.querySelector('.gif-image-container');
                if (imgContainer) {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreateError('No GIFs configured. Check your list parameter.'));
                }
            }
            return false;
        }
        
        createTabs(container, gifMap);
        
        // Display the first GIF by default
        const firstTabName = Object.keys(gifMap)[0];
        console.log('Tab GIF Display: Showing first tab:', firstTabName);
        showGif(container, gifMap[firstTabName], firstTabName);
        
        return true;
    }
    
    function buildGifMap(container) {
        const gifMap = {};
        const listData = container.getAttribute('data-gif-list');
        
        console.log('Tab GIF Display: Building map for container', container.id);
        console.log('Tab GIF Display: data-gif-list attribute:', listData);
        
        if (!listData) {
            console.error('Tab GIF Display: No data-gif-list attribute found on', container.id);
            return gifMap;
        }
        
        if (listData.trim() === '') {
            console.error('Tab GIF Display: data-gif-list is empty on', container.id);
            return gifMap;
        }
        
        const entries = listData.split(';').filter(e => e.trim());
        console.log('Tab GIF Display: Found', entries.length, 'entries in list');
        
        entries.forEach((entry, index) => {
            console.log('Tab GIF Display: Processing entry', index, ':', entry);
            const parts = entry.split(':');
            
            if (parts.length < 2) {
                console.warn('Tab GIF Display: Invalid entry format (no colon):', entry);
                return;
            }
            
            const tabName = parts[0].trim();
            const gifFile = parts.slice(1).join(':').trim();
            
            console.log('Tab GIF Display: Parsed - Tab:', tabName, 'File:', gifFile);
            
            if (!tabName) {
                console.warn('Tab GIF Display: Empty tab name in entry:', entry);
                return;
            }
            
            if (!gifFile) {
                console.warn('Tab GIF Display: Empty gif file in entry:', entry);
                return;
            }
            
            let gifUrl;
            if (typeof mw !== 'undefined' && mw.config) {
                const scriptPath = mw.config.get('wgScriptPath') || '';
                gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
            } else {
                gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
            }
            
            gifMap[tabName] = gifUrl;
            console.log('Tab GIF Display: Mapped "' + tabName + '" to', gifUrl);
        });
        
        console.log('Tab GIF Display: Final map has', Object.keys(gifMap).length, 'entries');
        return gifMap;
    }
    
    function createTabs(container, gifMap) {
        const tabsContainer = container.querySelector('.' + CONFIG.tabsClass);
        if (!tabsContainer) {
            console.error('Tab GIF Display: No tabs container found in', container.id);
            return;
        }
        
        console.log('Tab GIF Display: Creating tabs in', container.id);
        
        tabsContainer.innerHTML = '';
        
        let isFirst = true;
        let tabCount = 0;
        
        Object.keys(gifMap).forEach(tabName => {
            const tab = document.createElement('button');
            tab.className = CONFIG.tabClass;
            tab.textContent = tabName;
            tab.setAttribute('data-tab-name', tabName);
            tab.type = 'button';
            
            if (isFirst) {
                tab.classList.add(CONFIG.activeTabClass);
                isFirst = false;
            }
            
            tab.addEventListener('click', () => {
                console.log('Tab GIF Display: Tab clicked:', tabName);
                handleTabClick(container, gifMap, tabName);
            });
            
            tabsContainer.appendChild(tab);
            tabCount++;
            console.log('Tab GIF Display: Created tab button for', tabName);
        });
        
        console.log('Tab GIF Display: Created', tabCount, 'tabs total');
    }
    
    function handleTabClick(container, gifMap, tabName) {
        console.log('Tab GIF Display: Handling tab click for', tabName);
        
        const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
        tabs.forEach(tab => {
            if (tab.getAttribute('data-tab-name') === tabName) {
                tab.classList.add(CONFIG.activeTabClass);
            } else {
                tab.classList.remove(CONFIG.activeTabClass);
            }
        });
        
        const gifUrl = gifMap[tabName];
        showGif(container, gifUrl, tabName);
    }
    
    function showGif(container, gifUrl, tabName) {
        console.log('Tab GIF Display: Showing GIF for', tabName, '-', gifUrl);
        
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
        if (!displayArea) {
            console.error('Tab GIF Display: No display area found');
            return;
        }
        
        const rawSize = container.getAttribute('data-gif-size') || '400';
        const gifSize = rawSize.replace(/[^0-9]/g, '') || '400';
        
        const imgContainer = displayArea.querySelector('.gif-image-container');
        const caption = displayArea.querySelector('.gif-caption');
        
        if (imgContainer) {
            const placeholder = imgContainer.querySelector('.gif-placeholder');
            if (placeholder) {
                placeholder.remove();
            }
            
            imgContainer.style.height = gifSize + 'px';
            imgContainer.style.minHeight = gifSize + 'px';
            
            const gifFilename = gifUrl.split('/').pop();
            const decodedFilename = decodeURIComponent(gifFilename);
            
            if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                imgContainer.innerHTML = '';
                imgContainer.appendChild(safeCreatePlaceholder('No GIF available for this tab.'));
                imgContainer.classList.remove('loading');
            } else {
                const oldImg = imgContainer.querySelector('img');
                
                const img = document.createElement('img');
                img.src = gifUrl;
                img.alt = tabName;
                img.style.maxHeight = gifSize + 'px';
                img.style.opacity = '0';
                img.style.position = 'absolute';
                img.style.transition = 'opacity 0.2s ease';
                
                img.onload = () => {
                    if (oldImg) {
                        oldImg.style.transition = 'opacity 0.15s ease';
                        oldImg.style.opacity = '0';
                        setTimeout(() => {
                            imgContainer.innerHTML = '';
                            img.style.position = 'relative';
                            img.style.opacity = '1';
                            imgContainer.appendChild(img);
                            imgContainer.classList.remove('loading');
                        }, 150);
                    } else {
                        imgContainer.innerHTML = '';
                        img.style.position = 'relative';
                        img.style.opacity = '1';
                        imgContainer.appendChild(img);
                        imgContainer.classList.remove('loading');
                    }
                    console.log('Tab GIF Display: GIF loaded successfully');
                };
                
                img.onerror = () => {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                    imgContainer.classList.remove('loading');
                    console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                };
                
                if (!oldImg) {
                    imgContainer.appendChild(img);
                    imgContainer.classList.add('loading');
                }
            }
        }
        
        if (caption) {
            caption.textContent = tabName;
            caption.style.display = 'block';
        }
    }
    
    window.toggleTabGifDisplay = function(containerId) {
        console.log('Tab GIF Display: Toggle clicked for', containerId);
        const container = document.getElementById(containerId);
        if (!container) {
            console.error('Tab GIF Display: Container not found', containerId);
            return;
        }
        
        if (container.style.display === 'none') {
            container.style.display = 'block';
        } else {
            container.style.display = 'none';
        }
    };
    
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
    
    window.addEventListener('load', init);
    
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(init);
    }
    
    const observer = new MutationObserver(function(mutations) {
        let shouldReinit = false;
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1 && (
                        node.classList && node.classList.contains(CONFIG.containerClass) ||
                        node.querySelector && node.querySelector('.' + CONFIG.containerClass)
                    )) {
                        shouldReinit = true;
                    }
                });
            }
        });
        if (shouldReinit) {
            console.log('Tab GIF Display: Content changed, reinitializing...');
            setTimeout(init, 100);
        }
    });
    
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
    
    console.log('Tab GIF Display: Script loaded and ready');
})();