diff --git a/extension.json b/extension.json index b8c8f6e..b132cc7 100644 --- a/extension.json +++ b/extension.json @@ -36,14 +36,14 @@ "styles": ["ext.isekai.offcanvas-toc.less"], "dependencies": [ "oojs-ui-core", - "oojs-ui-windows" + "oojs-ui.styles.icons-layout" ], "targets": [ "desktop", "mobile" ], "messages": [ - + "isekai-offcanvastoc-description-item" ] } }, diff --git a/i18n/en.json b/i18n/en.json index d0a11ff..532d38d 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2,5 +2,6 @@ "isekai-offcanvastoc-name": "Isekai Offcanvas TOC", "isekai-offcanvastoc-desc": "Show Offcanvas TOC on wiki", "prefs-offcanvas-toc": "Offcanvas TOC", - "offcanvas-toc-enabled": "Show offcanvas TOC" + "offcanvas-toc-enabled": "Show offcanvas TOC", + "isekai-offcanvastoc-description-item": "Description" } \ No newline at end of file diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json index 514ec9b..ee0e9c7 100644 --- a/i18n/zh-hans.json +++ b/i18n/zh-hans.json @@ -2,5 +2,6 @@ "isekai-offcanvastoc-name": "异世界百科 悬浮目录", "isekai-offcanvastoc-desc": "在页面上显示悬浮目录", "prefs-offcanvas-toc": "悬浮目录", - "offcanvas-toc-enabled": "显示悬浮目录" + "offcanvas-toc-enabled": "显示悬浮目录", + "isekai-offcanvastoc-description-item": "简介" } \ No newline at end of file diff --git a/includes/Hooks.php b/includes/Hooks.php index 14a85d7..f8179a6 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -2,7 +2,6 @@ namespace Isekai\OffcanvasToc; use MediaWiki\MediaWikiServices; -use Html; class Hooks { public static function onLoad(\OutputPage $outputPage) { @@ -11,23 +10,7 @@ class Hooks { $outputPage->getTitle()->isContentPage() && $service->getUserOptionsLookup()->getOption($outputPage->getUser(), 'offcanvas-toc-enabled') ) { - $outputPage->enableOOUI(); - $outputPage->addModules('ext.isekai.offcanvas-toc'); - $outputPage->addModules('oojs-ui.styles.icons-layout'); - - $outputPage->addHTML(Html::openElement('div', [ - 'id' => 'isekai-offcanvas-toc', - 'class' => 'toc-offcanvas' - ]) . Html::element('ul') . Html::closeElement('div')); - - $outputPage->addHTML(Html::openElement('button', [ - 'id' => 'iseai-offcanvas-btn', - 'class' => 'toc-offcanvas-btn' - ]) . new \OOUI\IconWidget([ - 'icon' => 'menu' - ]) . Html::closeElement('button')); - - $outputPage->addElement('div', ['id' => 'isekai-offcanvas-cover', 'class' => 'toc-offcanvas-cover']); + $outputPage->addModules(['ext.isekai.offcanvas-toc']); } } diff --git a/modules/ext.isekai.offcanvas-toc.js b/modules/ext.isekai.offcanvas-toc.js index c50297e..0e598aa 100644 --- a/modules/ext.isekai.offcanvas-toc.js +++ b/modules/ext.isekai.offcanvas-toc.js @@ -1,4 +1,13 @@ var headingList = []; +var scrollBehaviorAvaliable = (function() { + var v = navigator.userAgent.match(/Chrome\/(?\S+)/); + if (v && v.groups.version) { // 检测chrome版本 + var chromeVersion = parseInt(v.groups.version); + return chromeVersion >= 61; + } else { // 非chrome + return true; + } +})(); function getScrollOffset() { if (mw.config.get('skin') === 'timeless' && $(window).width() > 850) { @@ -22,12 +31,19 @@ function scrollToAnchor(link) { function doScroll() { var position = target.offset().top - getScrollOffset(); - $('html, body').animate({ - scrollTop: position, - }, 500); + if (scrollBehaviorAvaliable) { + window.scrollTo({ + top: position, + behavior: 'smooth' + }); + } else { + $('html, body').animate({ + scrollTop: position, + }, 500); + } } - if (mw.config.get('skin') === 'minerva') { // 手机端主体,需要检测折叠状态 + if (mw.config.get('skin') === 'minerva') { // 手机端主题,需要检测折叠状态 var collapseBlock = target.parents('.collapsible-block'); if (collapseBlock.length > 0 && !collapseBlock.hasClass('open-block')) { var h1Elem = collapseBlock.prev('.collapsible-heading'); @@ -64,7 +80,6 @@ function getScrollbarWidth() { function updateActive() { var scrollTop = $(window).scrollTop() + getAnchorOffset(); - console.log('scroll top', scrollTop); $('#isekai-offcanvas-toc ul .list-item').removeClass('active'); if (headingList.length > 0) { @@ -81,7 +96,7 @@ function updateActive() { } } if (!activedId) { - activedId = [headingList.length - 1].attr('id'); + activedId = headingList[headingList.length - 1].attr('id'); } $('#isekai-offcanvas-toc ul .list-item[data-id="' + activedId + '"]').addClass('active'); } @@ -92,6 +107,9 @@ function openOffcanvas() { $('body').addClass(['toc-offcanvas-show', 'toc-offcanvas-open']) .css('margin-right', scrollbarWidth); $('#iseai-offcanvas-btn').css('margin-right', scrollbarWidth); + if (mw.config.get('skin') === 'timeless') { + $('#mw-header-container').css('padding-right', scrollbarWidth); + } // 滚动到当前项目 let activedItem = $('#isekai-offcanvas-toc ul .list-item.active'); @@ -106,18 +124,32 @@ function closeOffcanvas() { setTimeout(function() { $('body').removeClass('toc-offcanvas-show').css('margin-right', 0); $('#iseai-offcanvas-btn').css('margin-right', 0); + if (mw.config.get('skin') === 'timeless') { + $('#mw-header-container').css('padding-right', 0); + } }, 260); } -// 生成目录 $(function() { + // 创建目录dom + $('body').append(` +
+ +
+ +
+ `); + var menuIcon = new OO.ui.IconWidget({ icon: 'menu' }); + $('#iseai-offcanvas-btn').append(menuIcon.$element); + + // 生成目录 var parserOutput = $('.mw-parser-output'); var headings = parserOutput.find('h1,h2,h3,h4,h5,h6'); var headNum = new Array(6).fill(0); var menuList = [{ number: false, - text: '简介', + text: mw.msg('isekai-offcanvastoc-description-item'), id: 'bodyContent' }]; diff --git a/modules/ext.isekai.offcanvas-toc.less b/modules/ext.isekai.offcanvas-toc.less index 182a027..cb8d3af 100644 --- a/modules/ext.isekai.offcanvas-toc.less +++ b/modules/ext.isekai.offcanvas-toc.less @@ -16,6 +16,9 @@ overflow-y: auto; background-color: #eaecf0; scrollbar-width: thin; + padding-top: env(safe-area-inset-top, 0); + padding-bottom: env(safe-area-inset-bottom, 0); + padding-right: env(safe-area-inset-right, 0); > ul { list-style: none; @@ -30,6 +33,7 @@ &:focus, &:visited { color: #54595d; + outline: none; } } @@ -109,6 +113,11 @@ color: #000; } + &:active, + &:focus { + outline: none; + } + @media screen and (min-width: 768px) { right: 24px; } @@ -116,10 +125,18 @@ @media screen and (min-width: 1340px) { right: 44px; } + + @media print { + display: none; + } +} + +.ve-activated .toc-offcanvas-btn { + display: none; } body.toc-offcanvas-show { - overflow: hidden; + overflow-y: hidden; .toc-offcanvas-cover { visibility: visible; @@ -129,6 +146,10 @@ body.toc-offcanvas-show { .toc-offcanvas { visibility: visible; } + + #mw-overscroll-bottom-cover { + display: none; + } } body.toc-offcanvas-open {