MediaWiki:Common.js

来自勿忘草与永远的少女
Admin留言 | 贡献2026年4月17日 (五) 21:52的版本
跳到导航跳到搜索

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5
/* 这里的任何JavaScript将为所有用户在每次页面加载时加载。 */
$(function() {
    // 检查是否已存在导航栏,避免重复添加
    if ($('.fixed-top-nav').length === 0) {
        
        // 导航栏 HTML 结构
        var navHtml = `
            <div class="fixed-top-nav">
                <a href="首页" class="nav-logo">
                    <img src="/wikibg/logo.jpg" alt="网站Logo">
                    <span>万华镜</span>
                </a>
                <div class="nav-links">
                    <a href="首页" class="nav-link">
                        📚 首页
                    </a>
                    <a href="游戏攻略" class="nav-link">
                        📖 游戏攻略
                    </a>
                    <a href="棋子" class="nav-link">
                        ⚔️ 棋子图鉴
                    </a>
                    <a href="天赋图鉴" class="nav-link">
                        🗺️ 天赋图鉴
                    </a>
                    <a href="装备图鉴" class="nav-link">
                        📊 装备图鉴
                    </a>
                    <a href="https://www.war3whj.top/war3wiki/moniqi/moniqi.html" class="nav-link">
                        📊 阵容模拟器
                    </a>
                </div>
            </div>
        `;
        
        // 将导航栏插入到 body 开头
        $('body').prepend(navHtml);
        
        // 滚动时添加效果(可选)
        $(window).scroll(function() {
            if ($(window).scrollTop() > 50) {
                $('.fixed-top-nav').addClass('scrolled');
            } else {
                $('.fixed-top-nav').removeClass('scrolled');
            }
        });
    }
});


$(function() {
    // 确保页脚固定在底部
    var footer = $('#footer, .mw-footer');
    
    if (footer.length > 0) {
        // 设置底部内边距避免内容被遮挡
        var footerHeight = footer.outerHeight();
        $('body').css('padding-bottom', footerHeight + 20 + 'px');
        
        // 窗口大小改变时重新计算
        $(window).resize(function() {
            var newHeight = footer.outerHeight();
            $('body').css('padding-bottom', newHeight + 20 + 'px');
        });
    }
});

$(function() {
    // 为角色卡片添加悬停效果(可选,纯CSS已有,这里作为备用)
    $('.character-card').hover(
        function() { $(this).addClass('hover'); },
        function() { $(this).removeClass('hover'); }
    );
    
    // 动态计算右侧边栏高度(可选,用于对齐)
    function adjustSidebarHeight() {
        var leftHeight = $('.custom-homepage .left-column').outerHeight();
        var rightHeight = $('.custom-homepage .right-column').outerHeight();
        if (rightHeight < leftHeight && $(window).width() > 768) {
            $('.custom-homepage .right-column').css('min-height', leftHeight);
        }
    }
    
    // 延迟执行,等待图片加载完成
    setTimeout(adjustSidebarHeight, 500);
    $(window).resize(adjustSidebarHeight);
});

/* 棋子筛选器(原有的锚点筛选) */
$(function() {
    $('a[href^="#"]').click(function(e) {
        e.preventDefault();
        var filter = $(this).attr('href').substring(1);

        if (filter === '全部') {
            $('.role-card').show();
            return;
        }

        $('.role-card').each(function() {
            var text = $(this).text();
            if (text.includes(filter)) {
                $(this).show();
            } else {
                $(this).hide();
            }
        });
    });
});

/* ========== 装备/棋子图鉴高级筛选器(TableFilter 类) ========== */
( function ( $, mw ) {
    'use strict';

    /**
     * 表格筛选器类
     */
    class TableFilter {
        /**
         * 创建一个新的 TableFilter 实例。
         * @param {jQuery} $table - 要筛选的表格元素(jQuery 对象)。
         * @param {Object} options - 配置选项。
         * @param {string[]} options.columns - 要为其创建筛选器的列索引数组(从0开始)。
         * @param {Object} options.labels - 筛选器列的显示名称。
         * @param {number} options.headerRowIndex - 表头所在的行索引(默认为0)。
         */
        constructor( $table, options ) {
            this.$table = $table;
            this.options = $.extend( {
                columns: [],
                labels: {},
                headerRowIndex: 0
            }, options );

            // 存储每列的所有可能值
            this.columnValues = {};
            // 存储当前的筛选状态 { 列索引: 选中的值 }
            this.currentFilters = {};

            this.init();
        }

        /**
         * 初始化筛选器:构建UI,解析表格数据,绑定事件。
         */
        init() {
            // 如果表格不存在或不是jQuery对象,则退出
            if ( !this.$table || !this.$table.length ) {
                return;
            }

            this.parseTableData();
            this.buildUI();
            this.bindEvents();
            this.updateStats();
        }

        /**
         * 解析表格数据,获取每列的所有唯一值。
         */
        parseTableData() {
            const self = this;
            const $rows = this.$table.find( 'tr' ).slice( this.options.headerRowIndex + 1 ); // 跳过表头

            this.options.columns.forEach( function( colIndex ) {
                self.columnValues[ colIndex ] = new Set();

                $rows.each( function() {
                    const $cell = $( this ).find( 'td, th' ).eq( colIndex );
                    if ( $cell.length ) {
                        const value = $.trim( $cell.text() );
                        if ( value ) {
                            self.columnValues[ colIndex ].add( value );
                        }
                    }
                } );

                // 将Set转换为数组,并按自然顺序排序
                self.columnValues[ colIndex ] = Array.from( self.columnValues[ colIndex ] ).sort();
            } );
        }

        /**
         * 构建筛选器的UI界面。
         */
        buildUI() {
            const self = this;
            const $container = $( '<div>' ).addClass( 'equipment-filter-container' );

            this.options.columns.forEach( function( colIndex ) {
                const $group = $( '<div>' ).addClass( 'equipment-filter-group' );
                const labelText = self.options.labels[ colIndex ] || '筛选';
                const $label = $( '<span>' ).addClass( 'equipment-filter-label' ).text( labelText + ':' );

                $group.append( $label );

                // 创建"全部"按钮
                const $allBtn = $( '<span>' )
                    .addClass( 'equipment-filter-btn active' )
                    .attr( 'data-filter-col', colIndex )
                    .attr( 'data-filter-val', '' )
                    .text( '全部' );

                $group.append( $allBtn );

                // 为每个唯一值创建按钮
                const values = self.columnValues[ colIndex ] || [];
                values.forEach( function( val ) {
                    const $btn = $( '<span>' )
                        .addClass( 'equipment-filter-btn' )
                        .attr( 'data-filter-col', colIndex )
                        .attr( 'data-filter-val', val )
                        .text( val );

                    $group.append( $btn );
                } );

                $container.append( $group );
            } );

            // 创建底部工具栏(清除按钮 + 统计信息)
            const $toolbar = $( '<div>' ).addClass( 'equipment-filter-group' );
            const $resetBtn = $( '<span>' ).addClass( 'equipment-filter-reset' ).text( '清除所有筛选' );
            const $stats = $( '<span>' ).addClass( 'equipment-filter-stat' );

            $toolbar.append( $resetBtn, $stats );
            $container.append( $toolbar );

            // 将筛选器容器插入到表格之前
            this.$table.before( $container );

            // 保存UI元素的引用
            this.$container = $container;
            this.$stats = $stats;
            this.$resetBtn = $resetBtn;
        }

        /**
         * 绑定UI元素的事件。
         */
        bindEvents() {
            const self = this;

            // 筛选按钮点击事件
            this.$container.on( 'click', '.equipment-filter-btn', function() {
                const $btn = $( this );
                const col = $btn.data( 'filter-col' );
                const val = $btn.data( 'filter-val' );

                // 切换active类
                $btn.closest( '.equipment-filter-group' ).find( '.equipment-filter-btn' ).removeClass( 'active' );
                $btn.addClass( 'active' );

                // 更新筛选状态
                if ( val === '' ) {
                    delete self.currentFilters[ col ];
                } else {
                    self.currentFilters[ col ] = val;
                }

                self.applyFilters();
            } );

            // 清除筛选按钮点击事件
            this.$resetBtn.on( 'click', function() {
                self.clearFilters();
            } );
        }

        /**
         * 应用当前的筛选条件,更新表格显示。
         */
        applyFilters() {
            const self = this;
            const $rows = this.$table.find( 'tr' ).slice( this.options.headerRowIndex + 1 );
            let visibleCount = 0;

            $rows.each( function() {
                const $row = $( this );
                let showRow = true;

                // 遍历当前所有的筛选条件
                $.each( self.currentFilters, function( col, val ) {
                    const $cell = $row.find( 'td, th' ).eq( parseInt( col ) );
                    const cellValue = $.trim( $cell.text() );

                    if ( cellValue !== val ) {
                        showRow = false;
                        return false; // 跳出 each 循环
                    }
                } );

                if ( showRow ) {
                    $row.show();
                    visibleCount++;
                } else {
                    $row.hide();
                }
            } );

            this.updateStats( visibleCount );
        }

        /**
         * 清除所有筛选条件,显示所有行。
         */
        clearFilters() {
            this.currentFilters = {};
            this.$container.find( '.equipment-filter-btn' ).removeClass( 'active' );
            // 激活"全部"按钮
            this.$container.find( '.equipment-filter-btn[data-filter-val=""]' ).addClass( 'active' );

            const $rows = this.$table.find( 'tr' ).slice( this.options.headerRowIndex + 1 );
            $rows.show();
            this.updateStats( $rows.length );
        }

        /**
         * 更新统计信息(显示匹配行数)。
         * @param {number} visibleCount - 当前可见的行数。
         */
        updateStats( visibleCount ) {
            if ( this.$stats ) {
                const totalRows = this.$table.find( 'tr' ).length - ( this.options.headerRowIndex + 1 );
                this.$stats.text( `显示 ${visibleCount} / ${totalRows} 项` );
            }
        }
    }

    /**
     * 当页面加载完成后,初始化筛选器。
     */
    $( document ).ready( function() {
        // 检查当前页面是否包含需要筛选的表格
        const $table = $( '.equipment-filter-target' );
        if ( !$table.length ) {
            return;
        }

        // ========== 筛选器配置(请根据你的表格列顺序修改) ==========
        // 棋子图鉴表格字段顺序:图片, 图片文件名, 名称, _pageName, 稀有度, 费用, 定位, 羁绊
        // 对应的列索引(从0开始):
        // 0:图片   1:图片文件名   2:名称   3:_pageName   4:稀有度   5:费用   6:定位   7:羁绊
        const filterConfig = {
            columns: [ 4, 5, 6, 7 ], // 对稀有度(4)、费用(5)、定位(6)、羁绊(7)进行筛选
            labels: {
                4: '稀有度',
                5: '费用',
                6: '定位',
                7: '羁绊'
            },
            headerRowIndex: 0 // 表头在第0行
        };

        // 实例化 TableFilter
        new TableFilter( $table, filterConfig );
    } );

} )( jQuery, mediaWiki );