加帕里图书馆 - 兽娘动物园中文维基
动物朋友 けものフレンズ KemonoFriends百科
MediaWiki:Vector.js:修订间差异
跳转到导航
跳转到搜索
无编辑摘要 |
无编辑摘要 标签:已被回退 |
||
| 第445行: | 第445行: | ||
}); | }); | ||
} )( jQuery ); | } )( jQuery ); | ||
( function ( $, mw ) { | |||
// --- 1. 定义常量和选择器 --- | |||
const NAV_WRAPPER_ID = 'cross-page-nav-wrapper'; | |||
const TARGET_CLASS = 'spa-nav-tab'; | |||
// MediaWiki 标准的内容区域ID (用于替换主体内容) | |||
const CONTENT_AREA_ID = 'mw-content-text'; | |||
// --- 2. 条件检测 (确保模板被引用) --- | |||
const $navWrapper = $( '#' + NAV_WRAPPER_ID ); | |||
if ( $navWrapper.length === 0 ) { | |||
// 如果页面没有导航 ID,则不执行任何操作 | |||
return; | |||
} | |||
const $contentArea = $( '#' + CONTENT_AREA_ID ); | |||
// --- 3. 页面核心元素更新函数:实现“替换效果”的关键 --- | |||
function updatePageElements( newTitle ) { | |||
// 1. 更新浏览器标签页标题 | |||
document.title = newTitle + ' - ' + mw.config.get( 'wgSiteName' ); | |||
// 2. 替换页面内部主标题 (ID: firstHeading) | |||
// 确保只有在元素存在时才进行替换 | |||
$( '#firstHeading' ).text( newTitle ); | |||
// 3. 更新顶部核心标签 (如 页面/讨论/阅读/编辑) | |||
const $viewTab = $( '#ca-nstab-main' ).find( 'a' ); // 页面 | |||
const $talkTab = $( '#ca-talk' ).find( 'a' ); // 讨论 | |||
// 生成新的 URL 路径 | |||
const newUrl = mw.util.getUrl( newTitle ); | |||
const newTalkUrl = mw.util.getUrl( 'Talk:' + newTitle ); | |||
// 替换链接 (实现点击'页面'或'讨论'时,跳转到新页面) | |||
$viewTab.attr( 'href', newUrl ); | |||
$talkTab.attr( 'href', newTalkUrl ); | |||
// 更新“页面”标签的文本,使其显示新页面的标题 | |||
$viewTab.text( newTitle ); | |||
} | |||
// --- 4. 核心功能函数:加载新页面内容 --- | |||
function loadNewPageContent( targetPageTitle, $tabElement ) { | |||
// 保存原始内容,以便加载失败时恢复 | |||
const originalContent = $contentArea.html(); | |||
// 显示加载提示,实现无白屏闪烁 | |||
$contentArea.html( '<p class="loading-message">正在加载页面: ' + targetPageTitle + '...</p>' ); | |||
// 清除当前标签的选中状态 | |||
$navWrapper.find( '.current-tab' ).removeClass( 'current-tab' ); | |||
// 调用 MediaWiki API 获取目标页面的渲染后的内容 | |||
$.ajax( { | |||
url: mw.util.wikiScript( 'api' ), | |||
data: { | |||
action: 'parse', | |||
page: targetPageTitle, | |||
format: 'json', | |||
prop: 'text', // 只获取渲染后的HTML内容 | |||
disablelimitreport: 1 | |||
}, | |||
dataType: 'json', | |||
success: function ( data ) { | |||
if ( data && data.parse && data.parse.text ) { | |||
// A. 替换内容区域 | |||
$contentArea.html( data.parse.text['*'] ); | |||
// B. 更新核心页面元素 (标题、顶部标签) - 实现替换效果的关键! | |||
updatePageElements( targetPageTitle ); | |||
// C. 更新 URL (无刷新切换 URL) | |||
const newUrl = mw.util.getUrl( targetPageTitle ); | |||
history.pushState( { page: targetPageTitle }, document.title, newUrl ); | |||
// D. 更新导航栏的选中状态 | |||
if ($tabElement) { | |||
$tabElement.parent().addClass( 'current-tab' ); | |||
} | |||
// E. 触发 MediaWiki 的内容加载钩子 (重要!确保新内容中的JS/扩展能正常工作) | |||
mw.hook( 'wikipage.content' ).fire( $contentArea ); | |||
mw.notify( '已切换到页面: ' + targetPageTitle, { type: 'success' } ); | |||
} else { | |||
$contentArea.html( originalContent ); | |||
mw.notify( '页面加载失败或页面不存在: ' + targetPageTitle, { type: 'error' } ); | |||
} | |||
}, | |||
error: function () { | |||
$contentArea.html( originalContent ); | |||
mw.notify( '网络错误,无法切换页面。', { type: 'error' } ); | |||
} | |||
} ); | |||
} | |||
// --- 5. 绑定事件:拦截点击 --- | |||
$navWrapper.on( 'click', '.' + TARGET_CLASS, function ( e ) { | |||
const $tab = $( this ); | |||
const targetPage = $tab.parent().data( 'target' ); | |||
// 检查是否点击了当前页面本身 (在模板中,当前页面标签的 is-self 为 true) | |||
if ( $tab.parent().data( 'is-self' ) === true ) { | |||
e.preventDefault(); // 阻止默认跳转,但什么也不做,因为已经是当前页 | |||
return; | |||
} | |||
e.preventDefault(); // 阻止默认的页面跳转! | |||
loadNewPageContent( targetPage, $tab ); | |||
} ); | |||
// --- 6. 历史状态处理 (处理浏览器的前进/后退按钮) --- | |||
$( window ).on( 'popstate', function ( e ) { | |||
const state = e.originalEvent.state; | |||
if ( state && state.page ) { | |||
// 当用户点击后退/前进时,找到对应标签,并执行加载 | |||
const $targetTab = $navWrapper.find( '[data-target="' + state.page + '"] a' ); | |||
if ($targetTab.length) { | |||
loadNewPageContent( state.page, $targetTab ); | |||
} else { | |||
// 如果找不到标签,则执行完整页面刷新以确保状态一致性 | |||
window.location.reload(); | |||
} | |||
} else if ( window.location.pathname.indexOf( mw.config.get('wgScript') ) !== -1 ) { | |||
// 如果 popstate 发生在初始 URL 状态 (例如:从 /Test2 变回 /index.php/Test1) | |||
// 此时 URL 已经变化,也应该执行一次加载 | |||
const newTitle = mw.config.get( 'wgPageName' ); // 获取当前 URL 对应的页面标题 | |||
const $targetTab = $navWrapper.find( '[data-target="' + newTitle + '"] a' ); | |||
if ($targetTab.length) { | |||
loadNewPageContent( newTitle, $targetTab ); | |||
} | |||
} | |||
}); | |||
} )( jQuery, mediaWiki ); | |||
2025年12月10日 (三) 10:05的版本
/* 此处所有JavaScript将为使用Vector皮肤的用户加载 */
mw.loader.load( 'MediaWiki:CrossPageNav.js' );
function makeCollapsibleMwCollapsible( $content ) {
var $tables = $content
.find( 'table.collapsible:not(.mw-collapsible)' )
.addClass( 'mw-collapsible' );
$.each( $tables, function ( index, table ) {
// mw.log.warn( 'This page is using the deprecated class collapsible. Please replace it with mw-collapsible.');
if ( $( table ).hasClass( 'collapsed' ) ) {
$( table ).addClass( 'mw-collapsed' );
// mw.log.warn( 'This page is using the deprecated class collapsed. Please replace it with mw-collapsed.');
}
} );
if ( $tables.length > 0 ) {
mw.loader.using( 'jquery.makeCollapsible' ).then( function () {
$tables.makeCollapsible();
} );
}
}
mw.hook( 'wikipage.content' ).add( makeCollapsibleMwCollapsible );
function mwCollapsibleSetup( $collapsibleContent ) {
var $element,
$toggle,
autoCollapseThreshold = 2;
$.each( $collapsibleContent, function ( index, element ) {
$element = $( element );
if ( $element.hasClass( 'collapsible' ) ) {
$element.find( 'tr:first > th:first' ).prepend( $element.find( 'tr:first > * > .mw-collapsible-toggle' ) );
}
if ( $collapsibleContent.length >= autoCollapseThreshold && $element.hasClass( 'autocollapse' ) ) {
$element.data( 'mw-collapsible' ).collapse();
} else if ( $element.hasClass( 'innercollapse' ) ) {
if ( $element.parents( '.outercollapse' ).length > 0 ) {
$element.data( 'mw-collapsible' ).collapse();
}
}
// because of colored backgrounds, style the link in the text color
// to ensure accessible contrast
$toggle = $element.find( '.mw-collapsible-toggle' );
if ( $toggle.length ) {
// Make the toggle inherit text color
if ( $toggle.parent()[ 0 ].style.color ) {
$toggle.find( 'a' ).css( 'color', 'inherit' );
}
}
} );
}
mw.hook( 'wikipage.collapsibleContent' ).add( mwCollapsibleSetup );
( function ( $ ) {
var customSidebarHtml =
'<div class="portal" id="p-customnav">' +
'<div class="body">' +
'<div class="body-list">' +
// 1. 首页 (一级)
'<div class="menu-item"><a href="主馆">首页</a></div>' +
// 2. 兽娘动物园企划 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:企划介绍">兽娘动物园企划</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="Kemono Friends">Kemono Friends</a></div>' +
'<div class="menu-item"><a href="世界观">世界观</a></div>' +
'<div class="menu-item"><a href="年表">年表</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 3. Friends (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:Friends">Friends</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="哺乳纲">哺乳纲</a></div>' +
'<div class="menu-item"><a href="鸟纲">鸟纲</a></div>' +
'<div class="menu-item"><a href="爬行纲">爬行纲</a></div>' +
'<div class="menu-item"><a href="两栖纲">两栖纲</a></div>' +
'<div class="menu-item"><a href="传说生物">传说生物</a></div>' +
'<div class="menu-item"><a href="其他">其他</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 4. TV动画 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:TV动画">TV动画</a>' +
'<div class="submenu">' + // 二级菜单开始
// 4.1. 一期动画
'<div class="menu-item has-submenu">' +
'<a href="一期动画">一期动画</a>' +
'<div class="submenu">' + // 三级菜单开始
// 4.1.1. 设定集
'<div class="menu-item"><a href="一期动画设定集">一期设定集</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 4.2. 二期动画
'<div class="menu-item has-submenu">' +
'<a href="二期动画">二期动画</a>' +
'<div class="submenu">' + // 三级菜单开始
// 4.2.1. 设定集
'<div class="menu-item"><a href="二期动画设定集">二期设定集</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 4.3. 欢迎来到加帕里公园 (二级)
'<div class="menu-item"><a href="欢迎来到加帕里公园">欢迎来到加帕里公园</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 5. **书籍** (新增的一级/二级菜单)
'<div class="menu-item has-submenu">' +
'<a href="分类:书籍">书籍</a>' +
'<div class="submenu">' + // 二级菜单开始
// 5.1. 漫画 (三级 - 原来的 5.)
'<div class="menu-item has-submenu">' +
'<a href="分类:漫画">漫画</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="兽娘动物园 —欢迎来到加帕里公园!—">兽娘动物园 —欢迎来到加帕里公园!—</a></div>' +
'<div class="menu-item"><a href="兽娘动物园2">兽娘动物园2</a></div>' +
// 5.1.1. 官方同人 (四级 - 原来的 5.1.)
'<div class="menu-item has-submenu">' +
'<a href="分类:官方同人漫画">官方同人</a>' +
'<div class="submenu">' + // 四级菜单开始
'<div class="menu-item"><a href="同人漫画:加帕里公园篇">加帕里公园篇</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里咖啡篇">加帕里咖啡篇</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里馒头篇">加帕里馒头篇</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里巴士篇">加帕里巴士篇</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里公园篇2">加帕里公园篇2</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里咖啡篇2">加帕里咖啡篇2</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里巴士篇2">加帕里巴士篇2</a></div>' +
'<div class="menu-item"><a href="同人漫画:兽娘动物园 Comic × Radio Anthology 读吧 听吧 开心!!!">兽娘动物园 Comic × Radio Anthology 读吧 听吧 开心!!!</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里公园篇3">加帕里公园篇3</a></div>' +
'<div class="menu-item"><a href="同人漫画:加帕里公园篇4">加帕里公园篇4</a></div>' +
'</div>' + // 四级菜单结束
'</div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 5.2. 公式书 (三级 - 原来的 5.2.)
'<div class="menu-item has-submenu">' +
'<a href="公式书">公式书</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="兽娘动物园 Official Guide Book Project的轨迹">兽娘动物园 Official Guide Book Project的轨迹</a></div>' +
'<div class="menu-item"><a href="兽娘动物园展图鉴">兽娘动物园展图鉴</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// **5.3.小说 (三级) - 新增**
'<div class="menu-item"><a href="兽娘动物园2小说">兽娘动物园2小说</a></div>' +
'</div>' + // 二级菜单结束 (书籍)
'</div>' +
// 6. 音乐 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:音乐">音乐</a>' +
'<div class="submenu">' + // 二级菜单开始
// 6.1. 单曲 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:单曲">单曲</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="1st ようこそジャパリパークヘ">1st ようこそジャパリパークヘ</a></div>' +
'<div class="menu-item"><a href="2nd フレ!フレ!ベストフレンズ">2nd フレ!フレ!ベストフレンズ</a></div>' +
'<div class="menu-item"><a href="3rd 乗ってけ!ジャパリビート">3rd 乗ってけ!ジャパリビート</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.2. 专辑 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:专辑">专辑</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="1st 广播剧&角色曲专辑 「Japari Café」">1st 广播剧&角色曲专辑 「Japari Café」</a></div>' +
'<div class="menu-item"><a href="2nd 角色曲专辑 「Japari Café2」">2nd 角色曲专辑 「Japari Café2」</a></div>' +
'<div class="menu-item"><a href="1st PPP出道专辑 「ペパプ・イン・ザ・スカイ!」">1st PPP出道专辑 「ペパプ・イン・ザ・スカイ!」</a></div>' +
'<div class="menu-item"><a href="1st 动物饼干出道专辑 「さふぁりどらいぶ♪」">1st 动物饼干出道专辑 「さふぁりどらいぶ♪」辑</a></div>' +
'<div class="menu-item"><a href="Best けものフレンズ「ようこそジャパリパークへ 〜こんぷりーとべすと〜」">Best けものフレンズ「ようこそジャパリパークへ 〜こんぷりーとべすと〜」</a></div>' +
'<div class="menu-item"><a href="3rd 角色曲专辑「Friends Beat!」">3rd 角色曲专辑「Friends Beat!」</a></div>' +
'<div class="menu-item"><a href="1st け・も・の・だ・も・の">1st け・も・の・だ・も・の</a></div>' +
'<div class="menu-item"><a href="1st ×加帕里团出道专辑 「×・×・×(ばってん・ばってん・ばってん)」">1st ×加帕里团出道专辑 「×・×・×(ばってん・ばってん・ばってん)」</a></div>' +
'<div class="menu-item"><a href="1st MIRACLE DIALIES">1st MIRACLE DIALIES</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.3. EP (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:EP">EP</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="Starry story">Starry story</a></div>' +
'<div class="menu-item"><a href="おやすみ おはよ">おやすみ おはよ</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.4. 原声音乐 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:原声音乐">原声音乐</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="1st Original Sound Track">1st Original Sound Track</a></div>' +
'<div class="menu-item"><a href="舞台剧 舞台剧「兽娘动物园」Original Sound Track">舞台剧 舞台剧「兽娘动物园」Original Sound Track</a></div>' +
'<div class="menu-item"><a href="2nd TV动画《兽娘动物园2》Original Sound Track">2nd TV动画《兽娘动物园2》Original Sound Track</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.5. 网络音乐 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:网络音乐">网络音乐</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="桜てのひら">桜てのひら</a></div>' +
'<div class="menu-item"><a href="けもののこどう">けもののこどう</a></div>' +
'<div class="menu-item"><a href="Grayish Heaven">Grayish Heaven</a></div>' +
'<div class="menu-item"><a href="starting now!!">starting now!!</a></div>' +
'<div class="menu-item"><a href="I’m with you">I’m with you</a></div>' +
'<div class="menu-item"><a href="カラカラカラ騒ぎ">カラカラカラ騒ぎ</a></div>' +
'<div class="menu-item"><a href="Joyful">Joyful</a></div>' +
'<div class="menu-item"><a href="Dystopia World">Dystopia World</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.6. Live (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:Live">Live</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="けものフレンズ LIVE">けものフレンズ LIVE</a></div>' +
'<div class="menu-item"><a href="けものフレンズ LIVE 大阪追加公演">けものフレンズ LIVE 大阪追加公演</a></div>' +
'<div class="menu-item"><a href="けものフレンズ LIVE 〜PPP LIVE〜">けものフレンズ LIVE 〜PPP LIVE〜</a></div>' +
'<div class="menu-item"><a href="けものフレンズ LIVE 〜どうぶつビスケッツ LIVE〜">けものフレンズ LIVE 〜どうぶつビスケッツ LIVE〜</a></div>' +
'<div class="menu-item"><a href="けものフレンズ PARTY">けものフレンズ PARTY</a></div>' +
'<div class="menu-item"><a href="けものフレンズ3 LIVE">けものフレンズ3 LIVE</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck 1st Anniversary ~チャールズのかしのき~">Gothic×Luck 1st Anniversary ~チャールズのかしのき~</a></div>' +
'<div class="menu-item"><a href="けものフレンズ3 LIVE ~1st anniversary~">けものフレンズ3 LIVE ~1st anniversary~</a></div>' +
'<div class="menu-item"><a href="×ジャパリ団 LIVE ~ヘドバンの準備はできているか!?~">×ジャパリ団 LIVE ~ヘドバンの準備はできているか!?~</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck online LIVE ~オリオンの輝き~">Gothic×Luck online LIVE ~オリオンの輝き~</a></div>' +
'<div class="menu-item"><a href="PPP ONLINE LIVE ~世界ペンギンの日大感謝祭~">PPP ONLINE LIVE ~世界ペンギンの日大感謝祭~</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ユメノナカノセカイ 大阪">Gothic×Luck ユメノナカノセカイ 大阪</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ユメノナカノセカイ 仙台">Gothic×Luck ユメノナカノセカイ 仙台</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ユメノナカノセカイ 东京">Gothic×Luck ユメノナカノセカイ 东京</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ユメノナカノセカイ 东京追加">Gothic×Luck ユメノナカノセカイ 东京追加</a></div>' +
'<div class="menu-item"><a href="けものフレンズV 1st LIVE">けものフレンズV 1st LIVE</a></div>' +
'<div class="menu-item"><a href="けものフレンズV LIVE かがやきをより強く!">けものフレンズV LIVE かがやきをより強く!</a></div>' +
'<div class="menu-item"><a href="けものフレンズ LIVE はろー じゃぱん!">けものフレンズ LIVE はろー じゃぱん!</a></div>' +
'<div class="menu-item"><a href="東京コミックコンベンション2024 どうぶつビスケッツ トークショー&ミニライブ">東京コミックコンベンション2024 どうぶつビスケッツ トークショー&ミニライブ</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ただいま 大阪">Gothic×Luck ただいま 大阪</a></div>' +
'<div class="menu-item"><a href="Gothic×Luck ただいま 东京">Gothic×Luck ただいま 东京</a></div>' +
'<div class="menu-item"><a href="もうすぐ夏休み!ジャパリ歌謡祭!!">もうすぐ夏休み!ジャパリ歌謡祭!!</a></div>' +
'<div class="menu-item"><a href="ちく☆たむクルーズへようこそ!~船の上でもドッタンバッタン大騒ぎ~">ちく☆たむクルーズへようこそ!~船の上でもドッタンバッタン大騒ぎ~</a></div>' +
'<div class="menu-item"><a href="東京コミックコンベンション2025 ペパプ トークショー&ミニライブ">東京コミックコンベンション2025 ペパプ トークショー&ミニライブ</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.7 动物音乐会
'<div class="menu-item has-submenu">' +
'<a href="分类:Live">动物音乐会</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="けものフレンズ×東京フィルハーモニー交響楽団「もりのおんがくかい」">けものフレンズ×東京フィルハーモニー交響楽団「もりのおんがくかい」</a></div>' +
'<div class="menu-item"><a href="けものフレンズ×関西フィルハーモニー管弦楽団「もりのおんがくかい」">けものフレンズ×関西フィルハーモニー管弦楽団「もりのおんがくかい」</a></div>' +
'<div class="menu-item"><a href="けものフレンズ×東京フィルハーモニー交響楽団「もりのおんがくかい」 Final">けものフレンズ×東京フィルハーモニー交響楽団「もりのおんがくかい」 Final</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 6.8 参加节目(二级)
'<div class="menu-item"><a href="音乐/参加节目">参加节目</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 7. 游戏 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:游戏">游戏</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="游戏:けものフレンズ(Nexon版)">けものフレンズ(Nexon版)</a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズあらーむ">けものフレンズあらーむ</a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズぱびりおん">けものフレンズぱびりおん</a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズ FESTIVAL ">けものフレンズ FESTIVAL </a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズピクロス">けものフレンズピクロス</a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズ3 ">けものフレンズ3 </a></div>' +
'<div class="menu-item"><a href="游戏:けものフレンズ3 プラネットツアーズ ">けものフレンズ3 プラネットツアーズ </a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 8. 舞台剧 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:舞台剧">舞台剧</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="舞台「けものフレンズ」">舞台「けものフレンズ」</a></div>' +
'<div class="menu-item"><a href="あにてれ×=LOVEステージプロジェクト">あにてれ×=LOVEステージプロジェクト</a></div>' +
'<div class="menu-item"><a href="舞台「けものフレンズ」2〜ゆきふるよるのけものたち〜">舞台「けものフレンズ」2〜ゆきふるよるのけものたち〜</a></div>' +
'<div class="menu-item"><a href="JAPARI STAGE! 〜おおきなみみとちいさなきせき〜">JAPARI STAGE! 〜おおきなみみとちいさなきせき〜</a></div>' +
'<div class="menu-item"><a href="JAPARI STAGE! 〜きみのあしおとがまたきこえた〜">JAPARI STAGE! 〜きみのあしおとがまたきこえた〜</a></div>' +
'<div class="menu-item"><a href="舞台「けものフレンズ」JAPARI LIVE 〜けものたちのしんねんかい〜">舞台「けものフレンズ」JAPARI LIVE 〜けものたちのしんねんかい〜</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 9. 虚拟主播 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:虚拟主播">虚拟主播</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="虚拟主播:洪堡企鹅">洪堡企鹅</a></div>' +
'<div class="menu-item"><a href="虚拟主播:非洲企鹅">非洲企鹅</a></div>' +
'<div class="menu-item"><a href="虚拟主播:岛屿灰狐">岛屿灰狐</a></div>' +
'<div class="menu-item"><a href="虚拟主播:郊狼">郊狼</a></div>' +
'<div class="menu-item"><a href="虚拟主播:恐狮">恐狮</a></div>' +
'<div class="menu-item"><a href="虚拟主播:狞猫">狞猫</a></div>' +
'<div class="menu-item"><a href="虚拟主播:斑獛">斑獛</a></div>' +
'<div class="menu-item"><a href="虚拟主播:乔氏猫">乔氏猫</a></div>' +
'<div class="menu-item"><a href="虚拟主播:长耳蝠">长耳蝠</a></div>' +
'<div class="menu-item"><a href="虚拟主播:丛林猫">丛林猫</a></div>' +
'<div class="menu-item"><a href="虚拟主播:花栗鼠">花栗鼠</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 10. 联动 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:联动">联动</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="联动:けものフレンズDIARY">けものフレンズDIARY</a></div>' +
// 联动:游戏
'<div class="menu-item has-submenu">' +
'<a href="联动:游戏">游戏</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="联动:言灵战士">言灵战士</a></div>' +
'<div class="menu-item"><a href="联动:命运之子">命运之子</a></div>' +
'<div class="menu-item"><a href="联动:锁链战记3">锁链战记3</a></div>' +
'<div class="menu-item"><a href="联动:dragon_nest_m">dragon_nest_m</a></div>' +
'<div class="menu-item"><a href="联动:hangame">hangame</a></div>' +
'<div class="menu-item"><a href="联动:魔物地下城">魔物地下城</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
'<div class="menu-item"><a href="联动:动物园&水族馆">动物园&水族馆</a></div>' +
'<div class="menu-item"><a href="联动:饮食店">饮食店</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 11. 美术展 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:美术展">美术展</a>' +
'<div class="submenu">' + // 二级菜单开始
// 11.1. 吉崎观音概念设计展 (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:吉崎观音概念设计展">吉崎观音概念设计展</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="吉崎观音概念设计展:东京">东京</a></div>' +
'<div class="menu-item"><a href="吉崎观音概念设计展:广岛">广岛</a></div>' +
'<div class="menu-item"><a href="吉崎观音概念设计展:名古屋">名古屋</a></div>' +
'<div class="menu-item"><a href="吉崎观音概念设计展:北海道">北海道</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
'<div class="menu-item"><a href="けものフレンズわーるど">けものフレンズわーるど</a></div>' +
'<div class="menu-item"><a href="けものフレンズ展">けものフレンズ展</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 12. 直播 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:直播">直播</a>' +
'<div class="submenu">' + // 二级菜单开始
'<div class="menu-item"><a href="けものフレンズRADIO!!">けものフレンズRADIO!!</a></div>' +
'<div class="menu-item"><a href="けものフレンズアワー">けものフレンズアワー</a></div>' +
'<div class="menu-item"><a href="けものフレンズ presents フレンズ探検隊">けものフレンズ presents フレンズ探検隊</a></div>' +
'<div class="menu-item"><a href="「けものフレンズ」presentsどうぶつ図鑑">「けものフレンズ」presentsどうぶつ図鑑</a></div>' +
'<div class="menu-item"><a href="PPPのゆるぺぱ!">PPPのゆるぺぱ!</a></div>' +
'<div class="menu-item"><a href="PPPのなぞぺぱ!">PPPのなぞぺぱ!</a></div>' +
'<div class="menu-item"><a href="あにてれ presents フレンズ探検隊2">あにてれ presents フレンズ探検隊2</a></div>' +
'<div class="menu-item"><a href="Gothic×LuckのGothic×Radio">Gothic×LuckのGothic×Radio</a></div>' +
'<div class="menu-item"><a href="舞台剧直播">舞台剧直播</a></div>' +
'<div class="menu-item"><a href="けものフレンズ3 わくわくどきどき探検レポート">けものフレンズ3 わくわくどきどき探検レポート</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 13. 同人作品 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:同人作品">同人作品</a>' +
'<div class="submenu">' + // 二级菜单开始
// 13.1. 漫画 (三级)
'<div class="menu-item has-submenu">' +
'<a href="同人作品:漫画">漫画</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="贿派">贿派</a></div>' +
'<div class="menu-item"><a href="ころは">ころは</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
'<div class="menu-item"><a href="同人作品:游戏">游戏</a></div>' +
'</div>' + // 二级菜单结束
'</div>' +
// 14. 其他 (二级)
'<div class="menu-item has-submenu">' +
'<a href="分类:其他作品">其他</a>' +
'<div class="submenu">' + // 二级菜单开始
// 14.1. 快闪店
'<div class="menu-item has-submenu">' +
'<a href="分类:快闪店">快闪店</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="快闪店:新宿">新宿</a></div>' +
'<div class="menu-item"><a href="秋叶原Gamers">秋叶原Gamers</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
'<div class="menu-item"><a href="VR阿莱桑">VR阿莱桑</a></div>' +
// 14.2. 官方FC (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:官方FC">官方FC</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="官方FC:旧">旧</a></div>' +
'<div class="menu-item"><a href="官方FC:新">新</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
// 14.3. AI Chat Japari Talk (三级)
'<div class="menu-item has-submenu">' +
'<a href="分类:AI_Chat_Japari_Talk">AI Chat Japari Talk</a>' +
'<div class="submenu">' + // 三级菜单开始
'<div class="menu-item"><a href="./ACJT:薮猫">薮猫</a></div>' +
'<div class="menu-item"><a href="./ACJT:阿莱桑">阿莱桑</a></div>' +
'<div class="menu-item"><a href="./ACJT:耳廓狐">耳廓狐</a></div>' +
'<div class="menu-item"><a href="./ACJT:小爪水獭">小爪水獭</a></div>' +
'<div class="menu-item"><a href="./ACJT:朱鹮">朱鹮</a></div>' +
'<div class="menu-item"><a href="./ACJT:霍加狓">霍加狓</a></div>' +
'<div class="menu-item"><a href="./ACJT:白脸角鸮">白脸角鸮</a></div>' +
'<div class="menu-item"><a href="./ACJT:雕鸮">雕鸮</a></div>' +
'<div class="menu-item"><a href="./ACJT:狞猫">狞猫</a></div>' +
'<div class="menu-item"><a href="./ACJT:长尾虎猫">长尾虎猫</a></div>' +
'<div class="menu-item"><a href="./ACJT:墨西哥钝口螈">墨西哥钝口螈</a></div>' +
'<div class="menu-item"><a href="./ACJT:日本狗獾">日本狗獾</a></div>' +
'<div class="menu-item"><a href="./ACJT:貉">貉</a></div>' +
'<div class="menu-item"><a href="./ACJT:黄斑岩蹄兔">黄斑岩蹄兔</a></div>' +
'</div>' + // 三级菜单结束
'</div>' +
'</div>' + // 二级菜单结束 (其他)
'</div>' +
'</div>' + // .body-list 结束
'</div>' +
'</div>';
$( document ).ready( function () {
var $sidebarPanel = $( '#mw-panel' );
// 1. 替换默认的“导航”区块 (#p-navigation)
var $defaultNav = $sidebarPanel.find( '#p-navigation' );
if ( $defaultNav.length ) {
$defaultNav.replaceWith( customSidebarHtml );
}
// 2. 绑定悬停逻辑到所有 .has-submenu 元素上 (支持多级)
$sidebarPanel.on( {
'mouseenter': function() {
// 添加类名,让 CSS 弹出子菜单
$( this ).addClass( 'submenu-open' );
},
'mouseleave': function() {
// 移除类名,隐藏子菜单
$( this ).removeClass( 'submenu-open' );
}
}, '.menu-item.has-submenu');
});
} )( jQuery );
( function ( $, mw ) {
// --- 1. 定义常量和选择器 ---
const NAV_WRAPPER_ID = 'cross-page-nav-wrapper';
const TARGET_CLASS = 'spa-nav-tab';
// MediaWiki 标准的内容区域ID (用于替换主体内容)
const CONTENT_AREA_ID = 'mw-content-text';
// --- 2. 条件检测 (确保模板被引用) ---
const $navWrapper = $( '#' + NAV_WRAPPER_ID );
if ( $navWrapper.length === 0 ) {
// 如果页面没有导航 ID,则不执行任何操作
return;
}
const $contentArea = $( '#' + CONTENT_AREA_ID );
// --- 3. 页面核心元素更新函数:实现“替换效果”的关键 ---
function updatePageElements( newTitle ) {
// 1. 更新浏览器标签页标题
document.title = newTitle + ' - ' + mw.config.get( 'wgSiteName' );
// 2. 替换页面内部主标题 (ID: firstHeading)
// 确保只有在元素存在时才进行替换
$( '#firstHeading' ).text( newTitle );
// 3. 更新顶部核心标签 (如 页面/讨论/阅读/编辑)
const $viewTab = $( '#ca-nstab-main' ).find( 'a' ); // 页面
const $talkTab = $( '#ca-talk' ).find( 'a' ); // 讨论
// 生成新的 URL 路径
const newUrl = mw.util.getUrl( newTitle );
const newTalkUrl = mw.util.getUrl( 'Talk:' + newTitle );
// 替换链接 (实现点击'页面'或'讨论'时,跳转到新页面)
$viewTab.attr( 'href', newUrl );
$talkTab.attr( 'href', newTalkUrl );
// 更新“页面”标签的文本,使其显示新页面的标题
$viewTab.text( newTitle );
}
// --- 4. 核心功能函数:加载新页面内容 ---
function loadNewPageContent( targetPageTitle, $tabElement ) {
// 保存原始内容,以便加载失败时恢复
const originalContent = $contentArea.html();
// 显示加载提示,实现无白屏闪烁
$contentArea.html( '<p class="loading-message">正在加载页面: ' + targetPageTitle + '...</p>' );
// 清除当前标签的选中状态
$navWrapper.find( '.current-tab' ).removeClass( 'current-tab' );
// 调用 MediaWiki API 获取目标页面的渲染后的内容
$.ajax( {
url: mw.util.wikiScript( 'api' ),
data: {
action: 'parse',
page: targetPageTitle,
format: 'json',
prop: 'text', // 只获取渲染后的HTML内容
disablelimitreport: 1
},
dataType: 'json',
success: function ( data ) {
if ( data && data.parse && data.parse.text ) {
// A. 替换内容区域
$contentArea.html( data.parse.text['*'] );
// B. 更新核心页面元素 (标题、顶部标签) - 实现替换效果的关键!
updatePageElements( targetPageTitle );
// C. 更新 URL (无刷新切换 URL)
const newUrl = mw.util.getUrl( targetPageTitle );
history.pushState( { page: targetPageTitle }, document.title, newUrl );
// D. 更新导航栏的选中状态
if ($tabElement) {
$tabElement.parent().addClass( 'current-tab' );
}
// E. 触发 MediaWiki 的内容加载钩子 (重要!确保新内容中的JS/扩展能正常工作)
mw.hook( 'wikipage.content' ).fire( $contentArea );
mw.notify( '已切换到页面: ' + targetPageTitle, { type: 'success' } );
} else {
$contentArea.html( originalContent );
mw.notify( '页面加载失败或页面不存在: ' + targetPageTitle, { type: 'error' } );
}
},
error: function () {
$contentArea.html( originalContent );
mw.notify( '网络错误,无法切换页面。', { type: 'error' } );
}
} );
}
// --- 5. 绑定事件:拦截点击 ---
$navWrapper.on( 'click', '.' + TARGET_CLASS, function ( e ) {
const $tab = $( this );
const targetPage = $tab.parent().data( 'target' );
// 检查是否点击了当前页面本身 (在模板中,当前页面标签的 is-self 为 true)
if ( $tab.parent().data( 'is-self' ) === true ) {
e.preventDefault(); // 阻止默认跳转,但什么也不做,因为已经是当前页
return;
}
e.preventDefault(); // 阻止默认的页面跳转!
loadNewPageContent( targetPage, $tab );
} );
// --- 6. 历史状态处理 (处理浏览器的前进/后退按钮) ---
$( window ).on( 'popstate', function ( e ) {
const state = e.originalEvent.state;
if ( state && state.page ) {
// 当用户点击后退/前进时,找到对应标签,并执行加载
const $targetTab = $navWrapper.find( '[data-target="' + state.page + '"] a' );
if ($targetTab.length) {
loadNewPageContent( state.page, $targetTab );
} else {
// 如果找不到标签,则执行完整页面刷新以确保状态一致性
window.location.reload();
}
} else if ( window.location.pathname.indexOf( mw.config.get('wgScript') ) !== -1 ) {
// 如果 popstate 发生在初始 URL 状态 (例如:从 /Test2 变回 /index.php/Test1)
// 此时 URL 已经变化,也应该执行一次加载
const newTitle = mw.config.get( 'wgPageName' ); // 获取当前 URL 对应的页面标题
const $targetTab = $navWrapper.find( '[data-target="' + newTitle + '"] a' );
if ($targetTab.length) {
loadNewPageContent( newTitle, $targetTab );
}
}
});
} )( jQuery, mediaWiki );