MediaWiki:Common.js:修订间差异
来自勿忘草与永远的少女
跳到导航跳到搜索
标签:撤销 已被回退 |
无编辑摘要 标签:已被回退 |
||
| 第86行: | 第86行: | ||
$(window).resize(adjustSidebarHeight); | $(window).resize(adjustSidebarHeight); | ||
}); | }); | ||
/* | |||
/* 棋子筛选器(原有的锚点筛选) */ | |||
$(function() { | $(function() { | ||
$('a[href^="#"]').click(function(e) { | $('a[href^="#"]').click(function(e) { | ||
| 第107行: | 第108行: | ||
}); | }); | ||
}); | }); | ||
/* ========== 装备/棋子图鉴高级筛选器(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 ); | |||
2026年4月17日 (五) 21:52的版本
/* 这里的任何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 );