MediaWiki

Common.js:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
标签已被回退
律Rhyme留言 | 贡献
无编辑摘要
 
(未显示同一用户的124个中间版本)
第1行: 第1行:
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */


// 切换标签
// 等待 mw 对象加载完成
mw.loader.using(['mediawiki.util'], function() {
   
    // 动态加载 PIXI.js
    function loadScript(url) {
        return new Promise(function(resolve, reject) {
            var script = document.createElement('script');
            script.src = url;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }
   
    // 按顺序加载库
    loadScript('https://cdn.jsdelivr.net/npm/pixi.js@5.3.12/dist/pixi.min.js')
        .then(function() {
            return loadScript('https://cdn.jsdelivr.net/npm/pixi-spine@3.0.12/dist/pixi-spine.js');
        })
        .then(function() {
            console.log('Spine libraries loaded successfully');
            initSpinePlayers();
        })
        .catch(function(error) {
            console.error('Failed to load Spine libraries:', error);
        });
   
    function initSpinePlayers() {
        var containers = document.querySelectorAll('.spine-player-container');
       
        if (containers.length === 0) {
            console.log('No spine containers found');
            return;
        }
       
        containers.forEach(function(container) {
            var skelUrl = container.getAttribute('data-skel');
            var atlasUrl = container.getAttribute('data-atlas');
            var animationName = container.getAttribute('data-animation') || 'idle';
            var skinName = container.getAttribute('data-skin') || 'default';
           
            if (!skelUrl || !atlasUrl) {
                console.error('Missing skel or atlas URL');
                return;
            }
           
            // 创建 PIXI 应用
            var app = new PIXI.Application({
                width: container.clientWidth || 800,
                height: container.clientHeight || 600,
                backgroundColor: 0x2c3e50,
                transparent: false
            });
           
            container.innerHTML = '';
            container.appendChild(app.view);
           
            // 加载 Spine 资源
            app.loader
                .add('spineData', skelUrl)
                .load(function(loader, resources) {
                    try {
                        var animation = new PIXI.spine.Spine(resources.spineData.spineData);
                       
                        // 设置位置和缩放
                        animation.x = app.screen.width / 2;
                        animation.y = app.screen.height / 2;
                        animation.scale.set(0.5);
                       
                        // 播放动画
                        if (animation.state.hasAnimation(animationName)) {
                            animation.state.setAnimation(0, animationName, true);
                        }
                       
                        app.stage.addChild(animation);
                        console.log('Spine animation loaded successfully');
                    } catch(e) {
                        console.error('Error creating spine animation:', e);
                    }
                });
        });
    }
});
 
/* 卡牌 */
(function () {
    'use strict';
 
    var initialized = false;
 
    function show(el) {
        if (el) el.style.display = 'flex';
    }
    function hide(el) {
        if (el) el.style.display = 'none';
    }
 
    function resetModalView(modal) {
        var originalView = modal.querySelector('.original-card-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        var godView = modal.querySelector('.god-inspiration-view');
        var subcardsView = modal.querySelector('.subcards-view');
        var nestedSubcardsViews = modal.querySelectorAll('.nested-subcards-view');
        var inspirationNestedViews = modal.querySelectorAll('.inspiration-subcards-view');
        var inspirationDeeperNestedViews = modal.querySelectorAll('.inspiration-nested-subcards-view');
 
        if (originalView) show(originalView);
        if (inspirationView) hide(inspirationView);
        if (godView) hide(godView);
        if (subcardsView) hide(subcardsView);
 
        nestedSubcardsViews.forEach(hide);
        inspirationNestedViews.forEach(hide);
        inspirationDeeperNestedViews.forEach(hide);
    }
 
    function closeModal(modal) {
        modal.style.display = 'none';
        document.body.style.overflow = 'auto';
        resetModalView(modal);
    }
 
    function openModalFromCard(cardWrapper) {
        var cardId = cardWrapper.getAttribute('data-card-id');
        if (!cardId) return;
        var modal = document.getElementById(cardId + '-modal');
        if (!modal) return;
        resetModalView(modal);
        modal.style.display = 'block';
        document.body.style.overflow = 'hidden';
    }
 
    function handleBackToCard(button) {
        var modal = button.closest('.card-modal');
        if (modal) {
            resetModalView(modal);
        }
    }
 
    function handleBackToSubcards(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var nestedView = button.closest('.nested-subcards-view');
        var subcardsView = modal.querySelector('.subcards-view');
        if (nestedView && subcardsView) {
            hide(nestedView);
            show(subcardsView);
        }
    }
 
    function handleInspirationClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        if (!originalView || !inspirationView) return;
        hide(originalView);
        show(inspirationView);
    }
 
    function handleGodInspirationClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var godView = modal.querySelector('.god-inspiration-view');
        if (!originalView || !godView) return;
        hide(originalView);
        show(godView);
    }
 
    function handleSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var subcardsView = modal.querySelector('.subcards-view');
        if (!originalView || !subcardsView) return;
        hide(originalView);
        show(subcardsView);
    }
 
    function handleViewNestedSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var subcardIndex = button.getAttribute('data-subcard-index');
        if (!subcardIndex) return;
        var subcardsView = modal.querySelector('.subcards-view');
        var nestedView = modal.querySelector('.nested-subcards-view[data-subcard-index="' + subcardIndex + '"]');
        if (!subcardsView || !nestedView) return;
        hide(subcardsView);
        show(nestedView);
    }
 
    function handleInspirationSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var idx = button.getAttribute('data-variant-index');
        if (!idx) return;
        var inspirationView = modal.querySelector('.inspiration-view');
        var nestedView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + idx + '"]');
        if (!inspirationView || !nestedView) return;
        hide(inspirationView);
        show(nestedView);
    }
 
    function handleBackToInspiration(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var nestedView = button.closest('.inspiration-subcards-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        if (nestedView && inspirationView) {
            hide(nestedView);
            show(inspirationView);
        }
    }
 
    function handleViewInspirationNestedSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var vIdx = button.getAttribute('data-variant-index');
        var sIdx = button.getAttribute('data-subcard-index');
        if (!vIdx || !sIdx) return;
        var subcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
        var deeperView = modal.querySelector('.inspiration-nested-subcards-view[data-variant-index="' + vIdx + '"][data-subcard-index="' + sIdx + '"]');
        if (!subcardsView || !deeperView) return;
        hide(subcardsView);
        show(deeperView);
    }
 
    function handleBackToInspirationSubcards(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var deeperView = button.closest('.inspiration-nested-subcards-view');
        var vIdx = button.getAttribute('data-variant-index');
        var subcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
        if (deeperView && subcardsView) {
            hide(deeperView);
            show(subcardsView);
        }
    }
 
    function onKeydown(event) {
        if (event.key === 'Escape' || event.keyCode === 27) {
            var modals = document.querySelectorAll('.card-modal');
            modals.forEach(function (modal) {
                if (modal.style.display === 'block') {
                    var inspirationView = modal.querySelector('.inspiration-view');
                    var godView = modal.querySelector('.god-inspiration-view');
                    var subcardsView = modal.querySelector('.subcards-view');
                    var nestedSubcardsViews = modal.querySelectorAll('.nested-subcards-view');
                    var inspirationNestedViews = modal.querySelectorAll('.inspiration-subcards-view');
                    var inspirationDeeperNestedViews = modal.querySelectorAll('.inspiration-nested-subcards-view');
 
                    var inNestedView = false;
                    nestedSubcardsViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inNestedView = true;
                            hide(view);
                            if (subcardsView) show(subcardsView);
                        }
                    });
 
                    var inInspirationNested = false;
                    inspirationNestedViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inInspirationNested = true;
                            hide(view);
                            if (inspirationView) show(inspirationView);
                        }
                    });
 
                    var inInspirationDeeperNested = false;
                    inspirationDeeperNestedViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inInspirationDeeperNested = true;
                            var vIdx = view.getAttribute('data-variant-index');
                            hide(view);
                            var parentSubcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
                            if (parentSubcardsView) show(parentSubcardsView);
                        }
                    });
 
                    if (!inNestedView && !inInspirationNested && !inInspirationDeeperNested) {
                        if ((inspirationView && inspirationView.style.display !== 'none') ||
                            (subcardsView && subcardsView.style.display !== 'none') ||
                            (godView && godView.style.display !== 'none')) {
                            resetModalView(modal);
                        } else {
                            closeModal(modal);
                        }
                    }
                }
            });
        }
    }
 
    function onDocumentClick(e) {
        // 打开模态:点击卡片缩略图区域
        var cardWrapper = e.target.closest('.card-small-wrapper');
        if (cardWrapper) {
            e.preventDefault();
            e.stopPropagation();
            openModalFromCard(cardWrapper);
            return;
        }
 
        // 变体/衍生/返回/关闭
        if (e.target.classList.contains('inspiration-button')) {
            e.stopPropagation();
            handleInspirationClick(e.target);
            return;
        }
        if (e.target.classList.contains('god-inspiration-button')) {
            e.stopPropagation();
            handleGodInspirationClick(e.target);
            return;
        }
        if (e.target.classList.contains('subcards-button')) {
            e.stopPropagation();
            handleSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('view-nested-subcards-button')) {
            e.stopPropagation();
            handleViewNestedSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-card-button')) {
            e.stopPropagation();
            handleBackToCard(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-subcards-button')) {
            e.stopPropagation();
            handleBackToSubcards(e.target);
            return;
        }
        if (e.target.classList.contains('view-insp-subcards-button')) {
            e.stopPropagation();
            handleInspirationSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-inspiration-button')) {
            e.stopPropagation();
            handleBackToInspiration(e.target);
            return;
        }
        if (e.target.classList.contains('view-insp-nested-subcards-button')) {
            e.stopPropagation();
            handleViewInspirationNestedSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-insp-subcards-button')) {
            e.stopPropagation();
            handleBackToInspirationSubcards(e.target);
            return;
        }
 
        // 关闭按钮
        var closeBtn = e.target.classList.contains('modal-close-button')
            ? e.target
            : (e.target.parentElement && e.target.parentElement.classList.contains('modal-close-button') ? e.target.parentElement : null);
 
        if (closeBtn) {
            var modal = closeBtn.closest('.card-modal');
            if (modal) closeModal(modal);
        }
    }
 
    function init() {
        if (initialized) return;
        initialized = true;
 
        document.addEventListener('click', onDocumentClick);
        document.addEventListener('keydown', onKeydown);
    }
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
 
    if (typeof mw !== 'undefined' && mw.hook) {
        // 页面增量渲染时确保已初始化(事件委托只需一次)
        mw.hook('wikipage.content').add(function () { init(); });
    }
})();
 
// 卡牌悬停显示功能
(function () {
    'use strict';
 
    var hoverTimeout;
 
    function showCardPopup(linkElement) {
        // 清除之前的超时
        if (hoverTimeout) {
            clearTimeout(hoverTimeout);
        }
 
        // 检查是否已有弹出框
        var existingPopup = linkElement.querySelector('.card-hover-popup');
        if (existingPopup) {
            return;
        }
 
        // 查找紧邻的隐藏数据容器
        var dataContainer = linkElement.nextElementSibling;
        if (!dataContainer || !dataContainer.classList.contains('card-link-data')) {
            return;
        }
 
        // 在隐藏容器中查找卡牌
        var cardWrapper = dataContainer.querySelector('.card-small-wrapper');
        if (!cardWrapper) {
            return;
        }
 
        // 克隆卡牌
        var clonedCard = cardWrapper.cloneNode(true);
        clonedCard.style.cursor = 'default';
       
        // 移除可能触发模态框的属性和类
        clonedCard.removeAttribute('data-card-id');
        var originalClass = clonedCard.className;
        clonedCard.className = originalClass.replace('card-small-wrapper', 'card-hover-preview');
 
        // 创建弹出框
        var popup = document.createElement('div');
        popup.className = 'card-hover-popup';
        popup.appendChild(clonedCard);
 
        // 添加到链接中
        linkElement.appendChild(popup);
    }
 
    function hideCardPopup(linkElement) {
        hoverTimeout = setTimeout(function () {
            var popup = linkElement.querySelector('.card-hover-popup');
            if (popup) {
                popup.remove();
            }
        }, 100);
    }
 
    function initCardLinks() {
        var cardLinks = document.querySelectorAll('.card-link');
 
        cardLinks.forEach(function (link) {
            // 避免重复绑定
            if (link.hasAttribute('data-card-hover-init')) {
                return;
            }
            link.setAttribute('data-card-hover-init', 'true');
 
            // 添加事件监听器
            link.addEventListener('mouseenter', function () {
                showCardPopup(link);
            });
 
            link.addEventListener('mouseleave', function () {
                hideCardPopup(link);
            });
        });
    }
 
    // 初始化
    function init() {
        initCardLinks();
    }
 
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
 
    // MediaWiki 钩子支持
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(init);
    }
})();
 
/* 切换标签 */
(function() {
(function() {
     'use strict';
     'use strict';
第12行: 第495行:
             if (tabButtons.length === 0) return;
             if (tabButtons.length === 0) return;
              
              
            // 检测模式
             var tabContents = container.querySelectorAll('.resp-tab-content');
             var tabContents = container.querySelectorAll('.resp-tab-content');
            var portraitImages = document.querySelectorAll('.portrait-image');
              
              
             // 初始化
             // 初始化
第24行: 第505行:
                 tabContents.forEach(function(content, index) {
                 tabContents.forEach(function(content, index) {
                     content.style.display = index === 0 ? 'block' : 'none';
                     content.style.display = index === 0 ? 'block' : 'none';
                });
            }
           
            if (portraitImages.length > 0) {
                portraitImages.forEach(function(image, index) {
                    image.style.display = index === 0 ? 'block' : 'none';
                 });
                 });
             }
             }
第43行: 第518行:
                     });
                     });
                      
                      
                     // 传统模式切换
                     // 切换内容
                     if (tabContents.length > 0) {
                     if (tabContents.length > 0) {
                         tabContents.forEach(function(content, i) {
                         tabContents.forEach(function(content, i) {
                             content.style.display = i === index ? 'block' : 'none';
                             content.style.display = i === index ? 'block' : 'none';
                         });
                         });
                    }
                   
                    // 立绘模式切换
                    if (portraitImages.length > 0) {
                        portraitImages.forEach(function(image) {
                            image.style.display = 'none';
                        });
                        var targetImage = document.querySelector('.portrait-image[data-index="' + index + '"]');
                        if (targetImage) {
                            targetImage.style.display = 'block';
                        }
                     }
                     }
                 });
                 });
第73行: 第537行:
})();
})();


// 卡牌模块相关的JavaScript功能
/* 角色立绘切换 */
$(document).ready(function() {
$(document).ready(function() {
     // 全局变量,跟踪当前打开的模态窗口
     // 使用事件委托来确保动态内容也能响应
    var currentOpenModal = null;
     $(document).on('click', '.character-switch-btn', function() {
   
         // 如果点击的是已经激活的按钮,不执行任何操作
    // 处理卡牌点击事件
        if ($(this).hasClass('active')) {
     $(document).on('click', '.card-clickable', function(e) {
            return;
         e.stopPropagation();
        }
       
        var targetType = $(this).attr('data-target');
        var container = $(this).closest('#character-container');
        var imageWrapper = container.find('.character-image-wrapper');
        var allImages = imageWrapper.find('.character-image');
          
          
         var modalId = $(this).data('modal-id');
         // 先将所有图片淡出
         var modal = $('#' + modalId);
        allImages.each(function() {
            $(this).css('opacity', '0');
         });
          
          
         if (modal.length) {
         // 延迟后切换显示状态
             // 如果有其他模态窗口打开,先关闭它
        setTimeout(function() {
            if (currentOpenModal && currentOpenModal !== modalId) {
             allImages.each(function() {
                 $('#' + currentOpenModal).css('display', 'none');
                 $(this).css('display', 'none');
             }
             });
              
              
             // 检查是否有多个相同ID的模态窗口(这是问题的根源)
             // 显示目标图片
             var allModals = $('[id="' + modalId + '"]');
             imageWrapper.find('[data-image-type="' + targetType + '"]').each(function() {
            if (allModals.length > 1) {
                 $(this).css('display', 'block');
                 // 如果有重复的模态窗口,只显示第一个,移除其他的
                // 强制重绘
                allModals.slice(1).remove();
                $(this)[0].offsetHeight;
            }
                $(this).css('opacity', '1');
           
             });
            // 显示模态窗口
        }, 300);
            modal.first().css('display', 'flex');
       
            currentOpenModal = modalId;
         // 更新按钮样式
           
        container.find('.character-switch-btn').each(function() {
            // 确保主显示区域可见,变体区域隐藏
            $(this).removeClass('active');
            var mainDisplay = modal.find('[id^="main-display-"]');
            $(this).css({
            var variantsDisplay = modal.find('.variants-display');
                'background': 'rgba(0,0,0,0.5)',
            var btn = modal.find('.lingguangyishan-btn');
                'cursor': 'pointer'
           
            });
            if (mainDisplay.length) mainDisplay.css('display', 'flex');
         });
             if (variantsDisplay.length) variantsDisplay.css('display', 'none');
            if (btn.length) {
                btn.text('灵光一闪');
                btn.css('background-color', '#4a90e2');
            }
         }
    });
   
    // 处理灵光一闪按钮点击事件
    $(document).on('click', '.lingguangyishan-btn', function(e) {
        e.stopPropagation();
        var variantsId = $(this).data('variants-id');
        var modalId = $(this).data('modal-id');
        var variantsDisplay = $('#' + variantsId);
         var mainDisplay = $('#main-display-' + modalId);
          
          
         if (variantsDisplay.length && mainDisplay.length) {
         // 设置当前按钮为激活状态
            if (variantsDisplay.css('display') === 'none' || variantsDisplay.css('display') === '') {
         $(this).addClass('active');
                variantsDisplay.css('display', 'block');
        $(this).css({
                mainDisplay.css('display', 'none');
             'background': 'rgba(70, 130, 255, 0.8)',
                $(this).text('返回');
             'cursor': 'default'
                $(this).css('background-color', '#5cb85c');
         });
            } else {
                variantsDisplay.css('display', 'none');
                mainDisplay.css('display', 'flex');
                $(this).text('灵光一闪');
                $(this).css('background-color', '#4a90e2');
            }
        }
    });
   
    // 处理模态窗口关闭事件
    $(document).on('click', '.card-modal', function(e) {
         if (e.target === this) {
            $(this).css('display', 'none');
            currentOpenModal = null;
           
            // 重置显示状态
            var mainDisplay = $(this).find('[id^="main-display-"]');
            var variantsDisplay = $(this).find('.variants-display');
            var btn = $(this).find('.lingguangyishan-btn');
           
            if (mainDisplay.length) mainDisplay.css('display', 'flex');
             if (variantsDisplay.length) variantsDisplay.css('display', 'none');
            if (btn.length) {
                btn.text('灵光一闪');
                btn.css('background-color', '#4a90e2');
            }
        }
    });
   
    // 阻止模态窗口内容区域的点击事件冒泡
    $(document).on('click', '.modal-main-content', function(e) {
        e.stopPropagation();
    });
   
    // 添加按钮悬停效果
    $(document).on('mouseenter', '.lingguangyishan-btn', function() {
        if ($(this).text() === '灵光一闪') {
             $(this).css('background-color', '#357abd');
         } else {
            $(this).css('background-color', '#449d44');
        }
     });
     });
      
      
     $(document).on('mouseleave', '.lingguangyishan-btn', function() {
    // 鼠标悬停效果(仅对非激活按钮有效)
         if ($(this).text() === '灵光一闪') {
     $(document).on('mouseenter', '.character-switch-btn:not(.active)', function() {
            $(this).css('background-color', '#4a90e2');
         $(this).css('background', 'rgba(70, 130, 255, 0.5)');
        } else {
            $(this).css('background-color', '#5cb85c');
        }
     });
     });
      
      
    // 处理ESC键关闭模态窗口
     $(document).on('mouseleave', '.character-switch-btn:not(.active)', function() {
     $(document).on('keydown', function(e) {
        $(this).css('background', 'rgba(0,0,0,0.5)');
        if (e.key === 'Escape' || e.keyCode === 27) {
            if (currentOpenModal) {
                $('#' + currentOpenModal).css('display', 'none');
                currentOpenModal = null;
            }
        }
     });
     });
   
    // 页面加载完成后,清理重复的模态窗口
    setTimeout(function() {
        $('.card-modal').each(function() {
            var modalId = $(this).attr('id');
            var duplicates = $('[id="' + modalId + '"]');
            if (duplicates.length > 1) {
                duplicates.slice(1).remove();
            }
        });
    }, 100);
});
});


            $('#filter-display').text(filterText.join(' | '));
/* 悬浮目录 */
            $('#current-filters').fadeIn(300);
$(document).ready(function() {
         } else {
    // 只在有目录的页面上执行
            $('#current-filters').fadeOut(300);
    if ($('.toc').length > 0) {
         }
        // 创建侧边目录
        var $sidebar = $('<div id="toc-sidebar"><div id="toc-sidebar-trigger">展开目录</div><div id="toc-sidebar-content"></div></div>');
         $('body').append($sidebar);
          
        // 提取并修复目录内容
        var tocUl = $('<ul></ul>');
          
          
         // 更新统计
         // 避免重复的目录项
         updateStats();
         var processedItems = new Set();
          
          
         // 如果没有结果,显示提示
         // 从原始目录构建新目录
         if (visibleCount === 0) {
         $('.toc ul li').each(function() {
             if ($('#no-results').length === 0) {
             var $link = $(this).find('a').first();
                $('#character-container').append(
            var href = $link.attr('href');
                    '<div id="no-results" style="width: 100%; text-align: center; padding: 50px 20px; color: #6c757d; font-size: 16px;">' +
            var $number = $link.find('.tocnumber').first();
                    '<div style="font-size: 48px; margin-bottom: 20px;">😔</div>' +
            var $text = $link.find('.toctext').first();
                    '没有找到符合条件的战斗员<br>' +
           
                     '<small style="font-size: 14px; color: #adb5bd;">尝试修改筛选条件或减少关键词</small>' +
            // 创建唯一标识符,避免重复添加
                     '</div>'
            var itemId = $number.text() + '-' + $text.text();
                 );
           
            if (!processedItems.has(itemId)) {
                processedItems.add(itemId);
               
                // 创建新的目录项
                var $li = $('<li></li>');
                var $newLink = $('<a>>').attr('href', href);
               
                // 如果有编号,则添加编号
                if ($number.length) {
                     $newLink.append($('<span class="tocnumber"></span>').text($number.text()));
                     $newLink.append(' ');
                }
               
                $newLink.append($('<span class="toctext"></span>').text($text.text()));
                $li.append($newLink);
                 tocUl.append($li);
             }
             }
         } else {
         });
            $('#no-results').remove();
        }
    }
   
    // 更新统计信息
    function updateStats() {
        var total = $('.character-card').length;
        var visible = $('.character-card:visible').length;
          
          
         // 动画更新数字
         $('#toc-sidebar-content').append(tocUl);
        animateNumber($('#visible-count'), visible);
        animateNumber($('#total-count'), total);
          
          
         // 根据显示比例改变统计颜色
         // 点击展开/折叠事件处理
         var percentage = total > 0 ? (visible / total) * 100 : 0;
         $('#toc-sidebar-trigger').click(function() {
        var statsColor = '#28a745'; // 绿色
            $('#toc-sidebar').toggleClass('expanded');
        if (percentage < 50) statsColor = '#ffc107'; // 黄色
           
        if (percentage < 25) statsColor = '#dc3545'; // 红色
            // 根据展开/折叠状态更改按钮文字
       
            if ($('#toc-sidebar').hasClass('expanded')) {
        $('#visible-count').css('color', statsColor);
                $('#toc-sidebar-trigger').text('隐藏目录');
            } else {
                $('#toc-sidebar-trigger').text('展开目录');
            }
        });
     }
     }
});
/* 词典Tooltip */
(function() {
    var tooltipContainer = null;
    var currentTerm = null;
    var hideTimeout = null;
      
      
     // 数字动画效果
     // 初始化
     function animateNumber($element, target) {
     $(function() {
         var current = parseInt($element.text()) || 0;
         // 创建全局 tooltip 容器
        if (current === target) return;
        tooltipContainer = $('<div class="dictionary-tooltip-container"></div>');
          
         $('body').append(tooltipContainer);
        var increment = target > current ? 1 : -1;
        var steps = Math.abs(target - current);
        var duration = Math.min(500, steps * 20);
        var stepDuration = duration / steps;
          
          
         var timer = setInterval(function() {
         // 鼠标进入词条
             current += increment;
        $(document).on('mouseenter', '.dictionary-term', function(e) {
             $element.text(current);
             var $term = $(this);
             currentTerm = $term;
              
              
             if (current === target) {
            // 清除隐藏定时器
                 clearInterval(timer);
             if (hideTimeout) {
                 clearTimeout(hideTimeout);
                hideTimeout = null;
             }
             }
        }, stepDuration);
    }
   
    // 为搜索框添加清除按钮
    function addClearButton() {
        var $searchInput = $('#character-search-input');
        if ($searchInput.length > 0 && $('#clear-search').length === 0) {
            var $clearBtn = $('<span>', {
                id: 'clear-search',
                text: '✕',
                style: 'position: relative; left: -25px; cursor: pointer; color: #6c757d; display: none;'
            });
              
              
             $searchInput.after($clearBtn);
             // 获取 tooltip 内容
            var content = $term.attr('data-tooltip-content');
            if (!content) return;
           
            // 设置内容
            tooltipContainer.html(content);
              
              
             // 显示/隐藏清除按钮
             // 计算位置
             $searchInput.on('input', function() {
             updateTooltipPosition($term);
                if ($(this).val().length > 0) {
                    $clearBtn.show();
                } else {
                    $clearBtn.hide();
                }
            });
              
              
             // 清除按钮点击事件
             // 显示 tooltip
             $clearBtn.on('click', function() {
             tooltipContainer.addClass('active');
                 $searchInput.val('').trigger('input');
        });
                 currentFilters.search = '';
       
                 applyFilters();
        // 鼠标离开词条
             });
        $(document).on('mouseleave', '.dictionary-term', function() {
         }
            hideTimeout = setTimeout(function() {
     }
                 tooltipContainer.removeClass('active');
                currentTerm = null;
            }, 100);
        });
       
        // 鼠标进入 tooltip(防止快速隐藏)
        tooltipContainer.on('mouseenter', function() {
            if (hideTimeout) {
                clearTimeout(hideTimeout);
                 hideTimeout = null;
            }
        });
       
        // 鼠标离开 tooltip
        tooltipContainer.on('mouseleave', function() {
            hideTimeout = setTimeout(function() {
                tooltipContainer.removeClass('active');
                 currentTerm = null;
            }, 100);
        });
       
        // 窗口滚动时更新位置
        $(window).on('scroll resize', function() {
            if (currentTerm && tooltipContainer.hasClass('active')) {
                updateTooltipPosition(currentTerm);
             }
         });
     });
      
      
     // 初始化清除按钮
     // 更新 tooltip 位置
     addClearButton();
     function updateTooltipPosition($term) {
   
        var rect = $term[0].getBoundingClientRect();
    // 添加键盘快捷键
        var scrollTop = $(window).scrollTop();
    $(document).on('keydown', function(e) {
        var scrollLeft = $(window).scrollLeft();
         // Ctrl/Cmd + F 聚焦搜索框
       
         if ((e.ctrlKey || e.metaKey) && e.key === 'f') {
         // 基本位置:词条下方
            e.preventDefault();
        var top = rect.bottom + scrollTop + 2;
            $('#character-search-input').focus().select();
         var left = rect.left + scrollLeft;
       
        // 获取 tooltip 尺寸
        var tooltipWidth = 250; // 固定宽度
        var tooltipHeight = tooltipContainer.outerHeight();
       
        // 获取窗口尺寸
        var windowWidth = $(window).width();
        var windowHeight = $(window).height();
       
        // 检查右边界
        if (left + tooltipWidth > windowWidth + scrollLeft) {
            left = Math.max(scrollLeft, rect.right + scrollLeft - tooltipWidth);
         }
         }
          
          
         // ESC 清除搜索
         // 检查下边界
         if (e.key === 'Escape') {
         if (rect.bottom + tooltipHeight > windowHeight) {
             if ($('#character-search-input').is(':focus')) {
            // 如果下方空间不足,显示在上方
                 $('#character-search-input').val('').trigger('input');
             if (rect.top - tooltipHeight > 0) {
                currentFilters.search = '';
                 top = rect.top + scrollTop - tooltipHeight - 2;
                applyFilters();
             }
             }
         }
         }
       
        // 设置位置
        tooltipContainer.css({
            top: top + 'px',
            left: left + 'px'
        });
    }
})();
/* 轮播图 */
(function () {
  'use strict';
  function initCarousel(root) {
    if (!root || root.__inited) return;
    root.__inited = true;
    const wrapper = root.querySelector('.carousel-wrapper');
    const slides = Array.from(root.querySelectorAll('.carousel-slide'));
    const titles = Array.from(root.querySelectorAll('.carousel-title-item'));
    const btnPrev = root.querySelector('.carousel-prev');
    const btnNext = root.querySelector('.carousel-next');
    if (!wrapper || !slides.length) {
      root.style.display = 'none';
      return;
    }
    // 单张图隐藏按钮
    if (slides.length === 1) {
      root.classList.add('single');
    }
    // 标题索引与幻灯索引对齐
    titles.forEach((t, i) => {
      t.dataset.slide = String(i);
    });
    let index = 0;
    let timer = null;
    const autoplay = (root.getAttribute('data-autoplay') || '1') !== '0';
    const interval = Math.max(1500, parseInt(root.getAttribute('data-interval') || '4000', 10) || 4000);
    function update() {
      wrapper.style.transform = 'translateX(' + (-index * 100) + '%)';
      titles.forEach((t, i) => {
        if (i === index) t.classList.add('active');
        else t.classList.remove('active');
        const text = t.querySelector('.title-text');
        const ind = t.querySelector('.title-indicator');
        if (text) text.style.opacity = i === index ? '1' : '0.75';
        if (ind) ind.style.background = i === index ? '#ff6600' : 'transparent';
      });
    }
    function next() {
      index = (index + 1) % slides.length;
      update();
    }
    function prev() {
      index = (index - 1 + slides.length) % slides.length;
      update();
    }
    // 标题点击
    titles.forEach((t) => {
      t.addEventListener('click', function () {
        const i = parseInt(t.dataset.slide || '0', 10) || 0;
        index = Math.min(Math.max(i, 0), slides.length - 1);
        update();
        restartAutoplay();
      });
    });
    // 按钮点击
    if (btnPrev) {
      btnPrev.addEventListener('click', function () {
        prev();
        restartAutoplay();
      });
    }
    if (btnNext) {
      btnNext.addEventListener('click', function () {
        next();
        restartAutoplay();
      });
    }
    // 自动播放控制
    function startAutoplay() {
      if (!autoplay || slides.length <= 1) return;
      stopAutoplay();
      timer = setInterval(next, interval);
    }
    function stopAutoplay() {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    }
    function restartAutoplay() {
      stopAutoplay();
      startAutoplay();
    }
    // 悬停/聚焦暂停
    root.addEventListener('mouseenter', stopAutoplay);
    root.addEventListener('mouseleave', startAutoplay);
    root.addEventListener('focusin', stopAutoplay);
    root.addEventListener('focusout', startAutoplay);
    // 触摸滑动
    let startX = 0;
    let curX = 0;
    let dragging = false;
    const threshold = 30;
    root.addEventListener(
      'touchstart',
      function (e) {
        if (!e.touches || !e.touches.length) return;
        startX = e.touches[0].clientX;
        curX = startX;
        dragging = true;
        root.classList.add('grabbing');
        stopAutoplay();
      },
      { passive: true }
    );
    root.addEventListener(
      'touchmove',
      function (e) {
        if (!dragging || !e.touches || !e.touches.length) return;
        curX = e.touches[0].clientX;
        const dx = curX - startX;
        wrapper.style.transform = 'translateX(calc(' + (-index * 100) + '% + ' + dx + 'px))';
      },
      { passive: true }
    );
    root.addEventListener('touchend', function () {
      if (!dragging) return;
      const dx = curX - startX;
      root.classList.remove('grabbing');
      dragging = false;
      if (Math.abs(dx) > threshold) {
        if (dx < 0) next();
        else prev();
      } else {
        update();
      }
      startAutoplay();
     });
     });
   
 
     // 高亮搜索关键词(可选功能)
     // 鼠标拖动(可选)
     function highlightSearchTerm() {
    let mouseDown = false;
        if (currentFilters.search !== '') {
    let mStartX = 0;
            $('.character-card:visible').each(function() {
 
                var $card = $(this);
     root.addEventListener('mousedown', function (e) {
                var $nameElement = $card.find('.character-name');
      mouseDown = true;
                if ($nameElement.length > 0) {
      mStartX = e.clientX;
                    var originalText = $nameElement.data('original-text') || $nameElement.text();
      root.classList.add('grab');
                    $nameElement.data('original-text', originalText);
      stopAutoplay();
                   
    });
                    var regex = new RegExp('(' + currentFilters.search + ')', 'gi');
 
                    var highlightedText = originalText.replace(regex, '<span style="background-color: #ffeb3b; font-weight: bold;">$1</span>');
    window.addEventListener('mouseup', function (e) {
                    $nameElement.html(highlightedText);
      if (!mouseDown) return;
                }
      const dx = e.clientX - mStartX;
            });
      mouseDown = false;
        } else {
      root.classList.remove('grab');
            // 恢复原始文本
      if (Math.abs(dx) > threshold) {
            $('.character-name').each(function() {
        if (dx < 0) next();
                var originalText = $(this).data('original-text');
        else prev();
                if (originalText) {
      } else {
                    $(this).text(originalText);
        update();
                }
      }
            });
      startAutoplay();
         }
    });
 
    // 初始化
    update();
    startAutoplay();
  } // <- 确保此处仅关闭 initCarousel 函数
 
  function initAll(context) {
    const scope = context && context.querySelectorAll ? context : document;
    scope.querySelectorAll('.carousel-container').forEach(initCarousel);
  }
 
  // 初次加载
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () {
      initAll();
    });
  } else {
    initAll();
  }
 
  // 动态内容(如可视化编辑器或AJAX)再次初始化
  if (window.mw && mw.hook) {
    mw.hook('wikipage.content').add(function (content) {
      // content 可能是 jQuery 对象,也可能是原生节点
      if (content && content[0] && content.find) {
        // jQuery 对象
        content.find('.carousel-container').each(function () {
          initCarousel(this);
        });
      } else if (content && content.querySelectorAll) {
        // 原生节点
        initAll(content);
      } else {
        initAll();
      }
    });
  }
})();
 
/* 装备 */
$(function() {
    // 创建遮罩层
    if ($('.equipment-wrapper').length > 0 && $('#equipment-overlay').length === 0) {
         $('body').append('<div id="equipment-overlay" class="equipment-overlay"></div>');
     }
     }
      
      
     // 保存和加载用户偏好
     // 点击装备卡片显示弹窗
     var userPreferences = {
     $(document).on('click', '.equipment-card', function(e) {
        save: function() {
        e.stopPropagation();
            if (typeof(Storage) !== "undefined") {
          
                localStorage.setItem('characterFilters', JSON.stringify(currentFilters));
         var equipName = $(this).attr('data-equipment');
                localStorage.setItem('filterTimestamp', Date.now());
        var level = $(this).attr('data-level');
            }
        var popup = $(this).closest('.equipment-wrapper').find('.equipment-popup');
         },
          
         load: function() {
         if (popup.length > 0) {
            if (typeof(Storage) !== "undefined") {
             $('#equipment-overlay').fadeIn(200);
                var saved = localStorage.getItem('characterFilters');
            popup.fadeIn(200);
                var timestamp = localStorage.getItem('filterTimestamp');
               
                // 只在24小时内有效
                if (saved && timestamp) {
                    var age = Date.now() - parseInt(timestamp);
                    if (age < 24 * 60 * 60 * 1000) {
                        return JSON.parse(saved);
                    }
                }
            }
            return null;
         },
         clear: function() {
             if (typeof(Storage) !== "undefined") {
                localStorage.removeItem('characterFilters');
                localStorage.removeItem('filterTimestamp');
            }
         }
         }
     };
     });
      
      
     // 可选:加载用户上次的筛选设置
     // 防止点击装备名称链接时触发其他事件
     var savedFilters = userPreferences.load();
     $(document).on('click', '.equipment-name-link a', function(e) {
    if (savedFilters) {
        e.stopPropagation();
        currentFilters = savedFilters;
        // 允许默认的链接跳转行为
        // 应用保存的筛选
    });
        setTimeout(function() {
            applyFilters();
            // 更新UI状态
            if (currentFilters.search) {
                $('#character-search-input').val(currentFilters.search);
            }
            // 更新按钮状态
            Object.keys(currentFilters).forEach(function(filterType) {
                if (filterType !== 'search') {
                    $('.filter-btn[data-filter="' + filterType + '"][data-value="' + currentFilters[filterType] + '"]')
                        .css('background-color', colors.active);
                }
            });
        }, 100);
    }
      
      
     // 在筛选改变时保存
     // 点击关闭按钮关闭弹窗
     $(window).on('beforeunload', function() {
     $(document).on('click', '.equipment-popup-close', function(e) {
         userPreferences.save();
         e.stopPropagation();
        $(this).parent('.equipment-popup').fadeOut(200);
        $('#equipment-overlay').fadeOut(200);
     });
     });
      
      
     // 添加筛选提示
     // 点击遮罩层关闭弹窗
     function showFilterTip() {
     $(document).on('click', '#equipment-overlay', function() {
        if ($('#filter-tip').length === 0 && Math.random() < 0.1) { // 10%概率显示
        $('.equipment-popup:visible').fadeOut(200);
            var tips = [
        $(this).fadeOut(200);
                '提示:按 Ctrl+F 可以快速聚焦搜索框',
    });
                '提示:可以同时使用多个筛选条件',
                '提示:搜索支持实时预览结果',
                '提示:你的筛选设置会自动保存24小时'
            ];
            var randomTip = tips[Math.floor(Math.random() * tips.length)];
           
            $('<div>', {
                id: 'filter-tip',
                html: '<span style="color: #17a2b8;">💡 ' + randomTip + '</span>',
                style: 'padding: 10px; background-color: #d1ecf1; border: 1px solid #bee5eb; border-radius: 5px; margin-bottom: 10px;'
            }).prependTo('#filter-controls').delay(5000).fadeOut(500, function() {
                $(this).remove();
            });
        }
    }
      
      
     // 初始显示提示
     // 点击弹窗内容不关闭
     setTimeout(showFilterTip, 1000);
     $(document).on('click', '.equipment-popup', function(e) {
});
        e.stopPropagation();
 
    });
/* 添加CSS样式通过JavaScript */
$(function() {
    if ($('#character-filter-style').length === 0) {
        $('<style>', {
            id: 'character-filter-style',
            text: `
                #character-filter-system * {
                    box-sizing: border-box;
                }
               
                .filter-btn, #reset-filters, #search-button {
                    transition: all 0.3s ease;
                    user-select: none;
                }
               
                .filter-btn:active, #reset-filters:active, #search-button:active {
                    transform: scale(0.95) !important;
                }
               
                #character-search-input {
                    transition: border-color 0.3s ease;
                }
               
                #character-search-input:focus {
                    border-color: #80bdff !important;
                    outline: none;
                    box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
                }
               
                .character-card {
                    transition: all 0.3s ease;
                }
               
                .character-card:hover {
                    transform: translateY(-5px);
                    box-shadow: 0 5px 15px rgba(0,0,0,0.2);
                }
               
                #no-results {
                    animation: fadeIn 0.5s ease;
                }
               
                @keyframes fadeIn {
                    from { opacity: 0; transform: translateY(10px); }
                    to { opacity: 1; transform: translateY(0); }
                }
               
                @media (max-width: 768px) {
                    .filter-group {
                        margin-bottom: 20px !important;
                    }
                   
                    .filter-btn {
                        margin-bottom: 5px !important;
                    }
                   
                    #character-search-input {
                        width: 100% !important;
                        margin-bottom: 10px;
                    }
                   
                    #search-button, #reset-filters {
                        display: inline-block !important;
                        margin-bottom: 5px;
                    }
                }
            `
        }).appendTo('head');
    }
});
});

2025年11月5日 (三) 21:34的最新版本

/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */

// 等待 mw 对象加载完成
mw.loader.using(['mediawiki.util'], function() {
    
    // 动态加载 PIXI.js
    function loadScript(url) {
        return new Promise(function(resolve, reject) {
            var script = document.createElement('script');
            script.src = url;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }
    
    // 按顺序加载库
    loadScript('https://cdn.jsdelivr.net/npm/pixi.js@5.3.12/dist/pixi.min.js')
        .then(function() {
            return loadScript('https://cdn.jsdelivr.net/npm/pixi-spine@3.0.12/dist/pixi-spine.js');
        })
        .then(function() {
            console.log('Spine libraries loaded successfully');
            initSpinePlayers();
        })
        .catch(function(error) {
            console.error('Failed to load Spine libraries:', error);
        });
    
    function initSpinePlayers() {
        var containers = document.querySelectorAll('.spine-player-container');
        
        if (containers.length === 0) {
            console.log('No spine containers found');
            return;
        }
        
        containers.forEach(function(container) {
            var skelUrl = container.getAttribute('data-skel');
            var atlasUrl = container.getAttribute('data-atlas');
            var animationName = container.getAttribute('data-animation') || 'idle';
            var skinName = container.getAttribute('data-skin') || 'default';
            
            if (!skelUrl || !atlasUrl) {
                console.error('Missing skel or atlas URL');
                return;
            }
            
            // 创建 PIXI 应用
            var app = new PIXI.Application({
                width: container.clientWidth || 800,
                height: container.clientHeight || 600,
                backgroundColor: 0x2c3e50,
                transparent: false
            });
            
            container.innerHTML = '';
            container.appendChild(app.view);
            
            // 加载 Spine 资源
            app.loader
                .add('spineData', skelUrl)
                .load(function(loader, resources) {
                    try {
                        var animation = new PIXI.spine.Spine(resources.spineData.spineData);
                        
                        // 设置位置和缩放
                        animation.x = app.screen.width / 2;
                        animation.y = app.screen.height / 2;
                        animation.scale.set(0.5);
                        
                        // 播放动画
                        if (animation.state.hasAnimation(animationName)) {
                            animation.state.setAnimation(0, animationName, true);
                        }
                        
                        app.stage.addChild(animation);
                        console.log('Spine animation loaded successfully');
                    } catch(e) {
                        console.error('Error creating spine animation:', e);
                    }
                });
        });
    }
});

/* 卡牌 */
(function () {
    'use strict';

    var initialized = false;

    function show(el) {
        if (el) el.style.display = 'flex';
    }
    function hide(el) {
        if (el) el.style.display = 'none';
    }

    function resetModalView(modal) {
        var originalView = modal.querySelector('.original-card-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        var godView = modal.querySelector('.god-inspiration-view');
        var subcardsView = modal.querySelector('.subcards-view');
        var nestedSubcardsViews = modal.querySelectorAll('.nested-subcards-view');
        var inspirationNestedViews = modal.querySelectorAll('.inspiration-subcards-view');
        var inspirationDeeperNestedViews = modal.querySelectorAll('.inspiration-nested-subcards-view');

        if (originalView) show(originalView);
        if (inspirationView) hide(inspirationView);
        if (godView) hide(godView);
        if (subcardsView) hide(subcardsView);

        nestedSubcardsViews.forEach(hide);
        inspirationNestedViews.forEach(hide);
        inspirationDeeperNestedViews.forEach(hide);
    }

    function closeModal(modal) {
        modal.style.display = 'none';
        document.body.style.overflow = 'auto';
        resetModalView(modal);
    }

    function openModalFromCard(cardWrapper) {
        var cardId = cardWrapper.getAttribute('data-card-id');
        if (!cardId) return;
        var modal = document.getElementById(cardId + '-modal');
        if (!modal) return;
        resetModalView(modal);
        modal.style.display = 'block';
        document.body.style.overflow = 'hidden';
    }

    function handleBackToCard(button) {
        var modal = button.closest('.card-modal');
        if (modal) {
            resetModalView(modal);
        }
    }

    function handleBackToSubcards(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var nestedView = button.closest('.nested-subcards-view');
        var subcardsView = modal.querySelector('.subcards-view');
        if (nestedView && subcardsView) {
            hide(nestedView);
            show(subcardsView);
        }
    }

    function handleInspirationClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        if (!originalView || !inspirationView) return;
        hide(originalView);
        show(inspirationView);
    }

    function handleGodInspirationClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var godView = modal.querySelector('.god-inspiration-view');
        if (!originalView || !godView) return;
        hide(originalView);
        show(godView);
    }

    function handleSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var originalView = modal.querySelector('.original-card-view');
        var subcardsView = modal.querySelector('.subcards-view');
        if (!originalView || !subcardsView) return;
        hide(originalView);
        show(subcardsView);
    }

    function handleViewNestedSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var subcardIndex = button.getAttribute('data-subcard-index');
        if (!subcardIndex) return;
        var subcardsView = modal.querySelector('.subcards-view');
        var nestedView = modal.querySelector('.nested-subcards-view[data-subcard-index="' + subcardIndex + '"]');
        if (!subcardsView || !nestedView) return;
        hide(subcardsView);
        show(nestedView);
    }

    function handleInspirationSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var idx = button.getAttribute('data-variant-index');
        if (!idx) return;
        var inspirationView = modal.querySelector('.inspiration-view');
        var nestedView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + idx + '"]');
        if (!inspirationView || !nestedView) return;
        hide(inspirationView);
        show(nestedView);
    }

    function handleBackToInspiration(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var nestedView = button.closest('.inspiration-subcards-view');
        var inspirationView = modal.querySelector('.inspiration-view');
        if (nestedView && inspirationView) {
            hide(nestedView);
            show(inspirationView);
        }
    }

    function handleViewInspirationNestedSubcardsClick(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var vIdx = button.getAttribute('data-variant-index');
        var sIdx = button.getAttribute('data-subcard-index');
        if (!vIdx || !sIdx) return;
        var subcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
        var deeperView = modal.querySelector('.inspiration-nested-subcards-view[data-variant-index="' + vIdx + '"][data-subcard-index="' + sIdx + '"]');
        if (!subcardsView || !deeperView) return;
        hide(subcardsView);
        show(deeperView);
    }

    function handleBackToInspirationSubcards(button) {
        var modal = button.closest('.card-modal');
        if (!modal) return;
        var deeperView = button.closest('.inspiration-nested-subcards-view');
        var vIdx = button.getAttribute('data-variant-index');
        var subcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
        if (deeperView && subcardsView) {
            hide(deeperView);
            show(subcardsView);
        }
    }

    function onKeydown(event) {
        if (event.key === 'Escape' || event.keyCode === 27) {
            var modals = document.querySelectorAll('.card-modal');
            modals.forEach(function (modal) {
                if (modal.style.display === 'block') {
                    var inspirationView = modal.querySelector('.inspiration-view');
                    var godView = modal.querySelector('.god-inspiration-view');
                    var subcardsView = modal.querySelector('.subcards-view');
                    var nestedSubcardsViews = modal.querySelectorAll('.nested-subcards-view');
                    var inspirationNestedViews = modal.querySelectorAll('.inspiration-subcards-view');
                    var inspirationDeeperNestedViews = modal.querySelectorAll('.inspiration-nested-subcards-view');

                    var inNestedView = false;
                    nestedSubcardsViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inNestedView = true;
                            hide(view);
                            if (subcardsView) show(subcardsView);
                        }
                    });

                    var inInspirationNested = false;
                    inspirationNestedViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inInspirationNested = true;
                            hide(view);
                            if (inspirationView) show(inspirationView);
                        }
                    });

                    var inInspirationDeeperNested = false;
                    inspirationDeeperNestedViews.forEach(function (view) {
                        if (view.style.display !== 'none') {
                            inInspirationDeeperNested = true;
                            var vIdx = view.getAttribute('data-variant-index');
                            hide(view);
                            var parentSubcardsView = modal.querySelector('.inspiration-subcards-view[data-variant-index="' + vIdx + '"]');
                            if (parentSubcardsView) show(parentSubcardsView);
                        }
                    });

                    if (!inNestedView && !inInspirationNested && !inInspirationDeeperNested) {
                        if ((inspirationView && inspirationView.style.display !== 'none') ||
                            (subcardsView && subcardsView.style.display !== 'none') ||
                            (godView && godView.style.display !== 'none')) {
                            resetModalView(modal);
                        } else {
                            closeModal(modal);
                        }
                    }
                }
            });
        }
    }

    function onDocumentClick(e) {
        // 打开模态:点击卡片缩略图区域
        var cardWrapper = e.target.closest('.card-small-wrapper');
        if (cardWrapper) {
            e.preventDefault();
            e.stopPropagation();
            openModalFromCard(cardWrapper);
            return;
        }

        // 变体/衍生/返回/关闭
        if (e.target.classList.contains('inspiration-button')) {
            e.stopPropagation();
            handleInspirationClick(e.target);
            return;
        }
        if (e.target.classList.contains('god-inspiration-button')) {
            e.stopPropagation();
            handleGodInspirationClick(e.target);
            return;
        }
        if (e.target.classList.contains('subcards-button')) {
            e.stopPropagation();
            handleSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('view-nested-subcards-button')) {
            e.stopPropagation();
            handleViewNestedSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-card-button')) {
            e.stopPropagation();
            handleBackToCard(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-subcards-button')) {
            e.stopPropagation();
            handleBackToSubcards(e.target);
            return;
        }
        if (e.target.classList.contains('view-insp-subcards-button')) {
            e.stopPropagation();
            handleInspirationSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-inspiration-button')) {
            e.stopPropagation();
            handleBackToInspiration(e.target);
            return;
        }
        if (e.target.classList.contains('view-insp-nested-subcards-button')) {
            e.stopPropagation();
            handleViewInspirationNestedSubcardsClick(e.target);
            return;
        }
        if (e.target.classList.contains('back-to-insp-subcards-button')) {
            e.stopPropagation();
            handleBackToInspirationSubcards(e.target);
            return;
        }

        // 关闭按钮
        var closeBtn = e.target.classList.contains('modal-close-button')
            ? e.target
            : (e.target.parentElement && e.target.parentElement.classList.contains('modal-close-button') ? e.target.parentElement : null);

        if (closeBtn) {
            var modal = closeBtn.closest('.card-modal');
            if (modal) closeModal(modal);
        }
    }

    function init() {
        if (initialized) return;
        initialized = true;

        document.addEventListener('click', onDocumentClick);
        document.addEventListener('keydown', onKeydown);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    if (typeof mw !== 'undefined' && mw.hook) {
        // 页面增量渲染时确保已初始化(事件委托只需一次)
        mw.hook('wikipage.content').add(function () { init(); });
    }
})();

// 卡牌悬停显示功能
(function () {
    'use strict';

    var hoverTimeout;

    function showCardPopup(linkElement) {
        // 清除之前的超时
        if (hoverTimeout) {
            clearTimeout(hoverTimeout);
        }

        // 检查是否已有弹出框
        var existingPopup = linkElement.querySelector('.card-hover-popup');
        if (existingPopup) {
            return;
        }

        // 查找紧邻的隐藏数据容器
        var dataContainer = linkElement.nextElementSibling;
        if (!dataContainer || !dataContainer.classList.contains('card-link-data')) {
            return;
        }

        // 在隐藏容器中查找卡牌
        var cardWrapper = dataContainer.querySelector('.card-small-wrapper');
        if (!cardWrapper) {
            return;
        }

        // 克隆卡牌
        var clonedCard = cardWrapper.cloneNode(true);
        clonedCard.style.cursor = 'default';
        
        // 移除可能触发模态框的属性和类
        clonedCard.removeAttribute('data-card-id');
        var originalClass = clonedCard.className;
        clonedCard.className = originalClass.replace('card-small-wrapper', 'card-hover-preview');

        // 创建弹出框
        var popup = document.createElement('div');
        popup.className = 'card-hover-popup';
        popup.appendChild(clonedCard);

        // 添加到链接中
        linkElement.appendChild(popup);
    }

    function hideCardPopup(linkElement) {
        hoverTimeout = setTimeout(function () {
            var popup = linkElement.querySelector('.card-hover-popup');
            if (popup) {
                popup.remove();
            }
        }, 100);
    }

    function initCardLinks() {
        var cardLinks = document.querySelectorAll('.card-link');

        cardLinks.forEach(function (link) {
            // 避免重复绑定
            if (link.hasAttribute('data-card-hover-init')) {
                return;
            }
            link.setAttribute('data-card-hover-init', 'true');

            // 添加事件监听器
            link.addEventListener('mouseenter', function () {
                showCardPopup(link);
            });

            link.addEventListener('mouseleave', function () {
                hideCardPopup(link);
            });
        });
    }

    // 初始化
    function init() {
        initCardLinks();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // MediaWiki 钩子支持
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(init);
    }
})();

/* 切换标签 */
(function() {
    'use strict';
    
    function initTabSwitcher() {
        var tabContainers = document.querySelectorAll('.resp-tabs');
        
        tabContainers.forEach(function(container) {
            var tabButtons = container.querySelectorAll('.czn-list-style');
            if (tabButtons.length === 0) return;
            
            var tabContents = container.querySelectorAll('.resp-tab-content');
            
            // 初始化
            tabButtons.forEach(function(button, index) {
                button.classList.toggle('active', index === 0);
            });
            
            if (tabContents.length > 0) {
                tabContents.forEach(function(content, index) {
                    content.style.display = index === 0 ? 'block' : 'none';
                });
            }
            
            // 点击事件
            tabButtons.forEach(function(button, index) {
                button.addEventListener('click', function(e) {
                    e.preventDefault();
                    
                    // 更新标签状态
                    tabButtons.forEach(function(btn, i) {
                        btn.classList.toggle('active', i === index);
                    });
                    
                    // 切换内容
                    if (tabContents.length > 0) {
                        tabContents.forEach(function(content, i) {
                            content.style.display = i === index ? 'block' : 'none';
                        });
                    }
                });
            });
        });
    }
    
    // 初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTabSwitcher);
    } else {
        initTabSwitcher();
    }
})();

/* 角色立绘切换 */
$(document).ready(function() {
    // 使用事件委托来确保动态内容也能响应
    $(document).on('click', '.character-switch-btn', function() {
        // 如果点击的是已经激活的按钮,不执行任何操作
        if ($(this).hasClass('active')) {
            return;
        }
        
        var targetType = $(this).attr('data-target');
        var container = $(this).closest('#character-container');
        var imageWrapper = container.find('.character-image-wrapper');
        var allImages = imageWrapper.find('.character-image');
        
        // 先将所有图片淡出
        allImages.each(function() {
            $(this).css('opacity', '0');
        });
        
        // 延迟后切换显示状态
        setTimeout(function() {
            allImages.each(function() {
                $(this).css('display', 'none');
            });
            
            // 显示目标图片
            imageWrapper.find('[data-image-type="' + targetType + '"]').each(function() {
                $(this).css('display', 'block');
                // 强制重绘
                $(this)[0].offsetHeight;
                $(this).css('opacity', '1');
            });
        }, 300);
        
        // 更新按钮样式
        container.find('.character-switch-btn').each(function() {
            $(this).removeClass('active');
            $(this).css({
                'background': 'rgba(0,0,0,0.5)',
                'cursor': 'pointer'
            });
        });
        
        // 设置当前按钮为激活状态
        $(this).addClass('active');
        $(this).css({
            'background': 'rgba(70, 130, 255, 0.8)',
            'cursor': 'default'
        });
    });
    
    // 鼠标悬停效果(仅对非激活按钮有效)
    $(document).on('mouseenter', '.character-switch-btn:not(.active)', function() {
        $(this).css('background', 'rgba(70, 130, 255, 0.5)');
    });
    
    $(document).on('mouseleave', '.character-switch-btn:not(.active)', function() {
        $(this).css('background', 'rgba(0,0,0,0.5)');
    });
});

/* 悬浮目录 */
$(document).ready(function() {
    // 只在有目录的页面上执行
    if ($('.toc').length > 0) {
        // 创建侧边目录
        var $sidebar = $('<div id="toc-sidebar"><div id="toc-sidebar-trigger">展开目录</div><div id="toc-sidebar-content"></div></div>');
        $('body').append($sidebar);
        
        // 提取并修复目录内容
        var tocUl = $('<ul></ul>');
        
        // 避免重复的目录项
        var processedItems = new Set();
        
        // 从原始目录构建新目录
        $('.toc ul li').each(function() {
            var $link = $(this).find('a').first();
            var href = $link.attr('href');
            var $number = $link.find('.tocnumber').first();
            var $text = $link.find('.toctext').first();
            
            // 创建唯一标识符,避免重复添加
            var itemId = $number.text() + '-' + $text.text();
            
            if (!processedItems.has(itemId)) {
                processedItems.add(itemId);
                
                // 创建新的目录项
                var $li = $('<li></li>');
                var $newLink = $('').attr('href', href);
                
                // 如果有编号,则添加编号
                if ($number.length) {
                    $newLink.append($('<span class="tocnumber"></span>').text($number.text()));
                    $newLink.append(' ');
                }
                
                $newLink.append($('<span class="toctext"></span>').text($text.text()));
                $li.append($newLink);
                tocUl.append($li);
            }
        });
        
        $('#toc-sidebar-content').append(tocUl);
        
        // 点击展开/折叠事件处理
        $('#toc-sidebar-trigger').click(function() {
            $('#toc-sidebar').toggleClass('expanded');
            
            // 根据展开/折叠状态更改按钮文字
            if ($('#toc-sidebar').hasClass('expanded')) {
                $('#toc-sidebar-trigger').text('隐藏目录');
            } else {
                $('#toc-sidebar-trigger').text('展开目录');
            }
        });
    }
});

/* 词典Tooltip */
(function() {
    var tooltipContainer = null;
    var currentTerm = null;
    var hideTimeout = null;
    
    // 初始化
    $(function() {
        // 创建全局 tooltip 容器
        tooltipContainer = $('<div class="dictionary-tooltip-container"></div>');
        $('body').append(tooltipContainer);
        
        // 鼠标进入词条
        $(document).on('mouseenter', '.dictionary-term', function(e) {
            var $term = $(this);
            currentTerm = $term;
            
            // 清除隐藏定时器
            if (hideTimeout) {
                clearTimeout(hideTimeout);
                hideTimeout = null;
            }
            
            // 获取 tooltip 内容
            var content = $term.attr('data-tooltip-content');
            if (!content) return;
            
            // 设置内容
            tooltipContainer.html(content);
            
            // 计算位置
            updateTooltipPosition($term);
            
            // 显示 tooltip
            tooltipContainer.addClass('active');
        });
        
        // 鼠标离开词条
        $(document).on('mouseleave', '.dictionary-term', function() {
            hideTimeout = setTimeout(function() {
                tooltipContainer.removeClass('active');
                currentTerm = null;
            }, 100);
        });
        
        // 鼠标进入 tooltip(防止快速隐藏)
        tooltipContainer.on('mouseenter', function() {
            if (hideTimeout) {
                clearTimeout(hideTimeout);
                hideTimeout = null;
            }
        });
        
        // 鼠标离开 tooltip
        tooltipContainer.on('mouseleave', function() {
            hideTimeout = setTimeout(function() {
                tooltipContainer.removeClass('active');
                currentTerm = null;
            }, 100);
        });
        
        // 窗口滚动时更新位置
        $(window).on('scroll resize', function() {
            if (currentTerm && tooltipContainer.hasClass('active')) {
                updateTooltipPosition(currentTerm);
            }
        });
    });
    
    // 更新 tooltip 位置
    function updateTooltipPosition($term) {
        var rect = $term[0].getBoundingClientRect();
        var scrollTop = $(window).scrollTop();
        var scrollLeft = $(window).scrollLeft();
        
        // 基本位置:词条下方
        var top = rect.bottom + scrollTop + 2;
        var left = rect.left + scrollLeft;
        
        // 获取 tooltip 尺寸
        var tooltipWidth = 250; // 固定宽度
        var tooltipHeight = tooltipContainer.outerHeight();
        
        // 获取窗口尺寸
        var windowWidth = $(window).width();
        var windowHeight = $(window).height();
        
        // 检查右边界
        if (left + tooltipWidth > windowWidth + scrollLeft) {
            left = Math.max(scrollLeft, rect.right + scrollLeft - tooltipWidth);
        }
        
        // 检查下边界
        if (rect.bottom + tooltipHeight > windowHeight) {
            // 如果下方空间不足,显示在上方
            if (rect.top - tooltipHeight > 0) {
                top = rect.top + scrollTop - tooltipHeight - 2;
            }
        }
        
        // 设置位置
        tooltipContainer.css({
            top: top + 'px',
            left: left + 'px'
        });
    }
})();

/* 轮播图 */
(function () {
  'use strict';

  function initCarousel(root) {
    if (!root || root.__inited) return;
    root.__inited = true;

    const wrapper = root.querySelector('.carousel-wrapper');
    const slides = Array.from(root.querySelectorAll('.carousel-slide'));
    const titles = Array.from(root.querySelectorAll('.carousel-title-item'));
    const btnPrev = root.querySelector('.carousel-prev');
    const btnNext = root.querySelector('.carousel-next');

    if (!wrapper || !slides.length) {
      root.style.display = 'none';
      return;
    }

    // 单张图隐藏按钮
    if (slides.length === 1) {
      root.classList.add('single');
    }

    // 标题索引与幻灯索引对齐
    titles.forEach((t, i) => {
      t.dataset.slide = String(i);
    });

    let index = 0;
    let timer = null;
    const autoplay = (root.getAttribute('data-autoplay') || '1') !== '0';
    const interval = Math.max(1500, parseInt(root.getAttribute('data-interval') || '4000', 10) || 4000);

    function update() {
      wrapper.style.transform = 'translateX(' + (-index * 100) + '%)';
      titles.forEach((t, i) => {
        if (i === index) t.classList.add('active');
        else t.classList.remove('active');

        const text = t.querySelector('.title-text');
        const ind = t.querySelector('.title-indicator');
        if (text) text.style.opacity = i === index ? '1' : '0.75';
        if (ind) ind.style.background = i === index ? '#ff6600' : 'transparent';
      });
    }

    function next() {
      index = (index + 1) % slides.length;
      update();
    }

    function prev() {
      index = (index - 1 + slides.length) % slides.length;
      update();
    }

    // 标题点击
    titles.forEach((t) => {
      t.addEventListener('click', function () {
        const i = parseInt(t.dataset.slide || '0', 10) || 0;
        index = Math.min(Math.max(i, 0), slides.length - 1);
        update();
        restartAutoplay();
      });
    });

    // 按钮点击
    if (btnPrev) {
      btnPrev.addEventListener('click', function () {
        prev();
        restartAutoplay();
      });
    }
    if (btnNext) {
      btnNext.addEventListener('click', function () {
        next();
        restartAutoplay();
      });
    }

    // 自动播放控制
    function startAutoplay() {
      if (!autoplay || slides.length <= 1) return;
      stopAutoplay();
      timer = setInterval(next, interval);
    }

    function stopAutoplay() {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    }

    function restartAutoplay() {
      stopAutoplay();
      startAutoplay();
    }

    // 悬停/聚焦暂停
    root.addEventListener('mouseenter', stopAutoplay);
    root.addEventListener('mouseleave', startAutoplay);
    root.addEventListener('focusin', stopAutoplay);
    root.addEventListener('focusout', startAutoplay);

    // 触摸滑动
    let startX = 0;
    let curX = 0;
    let dragging = false;
    const threshold = 30;

    root.addEventListener(
      'touchstart',
      function (e) {
        if (!e.touches || !e.touches.length) return;
        startX = e.touches[0].clientX;
        curX = startX;
        dragging = true;
        root.classList.add('grabbing');
        stopAutoplay();
      },
      { passive: true }
    );

    root.addEventListener(
      'touchmove',
      function (e) {
        if (!dragging || !e.touches || !e.touches.length) return;
        curX = e.touches[0].clientX;
        const dx = curX - startX;
        wrapper.style.transform = 'translateX(calc(' + (-index * 100) + '% + ' + dx + 'px))';
      },
      { passive: true }
    );

    root.addEventListener('touchend', function () {
      if (!dragging) return;
      const dx = curX - startX;
      root.classList.remove('grabbing');
      dragging = false;
      if (Math.abs(dx) > threshold) {
        if (dx < 0) next();
        else prev();
      } else {
        update();
      }
      startAutoplay();
    });

    // 鼠标拖动(可选)
    let mouseDown = false;
    let mStartX = 0;

    root.addEventListener('mousedown', function (e) {
      mouseDown = true;
      mStartX = e.clientX;
      root.classList.add('grab');
      stopAutoplay();
    });

    window.addEventListener('mouseup', function (e) {
      if (!mouseDown) return;
      const dx = e.clientX - mStartX;
      mouseDown = false;
      root.classList.remove('grab');
      if (Math.abs(dx) > threshold) {
        if (dx < 0) next();
        else prev();
      } else {
        update();
      }
      startAutoplay();
    });

    // 初始化
    update();
    startAutoplay();
  } // <- 确保此处仅关闭 initCarousel 函数

  function initAll(context) {
    const scope = context && context.querySelectorAll ? context : document;
    scope.querySelectorAll('.carousel-container').forEach(initCarousel);
  }

  // 初次加载
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () {
      initAll();
    });
  } else {
    initAll();
  }

  // 动态内容(如可视化编辑器或AJAX)再次初始化
  if (window.mw && mw.hook) {
    mw.hook('wikipage.content').add(function (content) {
      // content 可能是 jQuery 对象,也可能是原生节点
      if (content && content[0] && content.find) {
        // jQuery 对象
        content.find('.carousel-container').each(function () {
          initCarousel(this);
        });
      } else if (content && content.querySelectorAll) {
        // 原生节点
        initAll(content);
      } else {
        initAll();
      }
    });
  }
})();

/* 装备 */
$(function() {
    // 创建遮罩层
    if ($('.equipment-wrapper').length > 0 && $('#equipment-overlay').length === 0) {
        $('body').append('<div id="equipment-overlay" class="equipment-overlay"></div>');
    }
    
    // 点击装备卡片显示弹窗
    $(document).on('click', '.equipment-card', function(e) {
        e.stopPropagation();
        
        var equipName = $(this).attr('data-equipment');
        var level = $(this).attr('data-level');
        var popup = $(this).closest('.equipment-wrapper').find('.equipment-popup');
        
        if (popup.length > 0) {
            $('#equipment-overlay').fadeIn(200);
            popup.fadeIn(200);
        }
    });
    
    // 防止点击装备名称链接时触发其他事件
    $(document).on('click', '.equipment-name-link a', function(e) {
        e.stopPropagation();
        // 允许默认的链接跳转行为
    });
    
    // 点击关闭按钮关闭弹窗
    $(document).on('click', '.equipment-popup-close', function(e) {
        e.stopPropagation();
        $(this).parent('.equipment-popup').fadeOut(200);
        $('#equipment-overlay').fadeOut(200);
    });
    
    // 点击遮罩层关闭弹窗
    $(document).on('click', '#equipment-overlay', function() {
        $('.equipment-popup:visible').fadeOut(200);
        $(this).fadeOut(200);
    });
    
    // 点击弹窗内容不关闭
    $(document).on('click', '.equipment-popup', function(e) {
        e.stopPropagation();
    });
});