refactor: partial code refactoring && optimization TOC

This commit is contained in:
XPoet 2020-10-21 19:36:38 +08:00
parent 72bb6ac530
commit b3a397f7dd
16 changed files with 408 additions and 364 deletions

View File

@ -86,7 +86,7 @@ website_count:
# See: https://github.com/theme-next/hexo-generator-searchdb # See: https://github.com/theme-next/hexo-generator-searchdb
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
local_search: local_search:
enable: true enable: false
# If auto, trigger search by changing input. # If auto, trigger search by changing input.
# If manual, trigger search by pressing enter key or search button. # If manual, trigger search by pressing enter key or search button.
@ -141,7 +141,7 @@ side_tools:
# Back to top # Back to top
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
back2top: back2top:
enable: false enable: true
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------

View File

@ -15,10 +15,14 @@
title = __('tag') + ': ' + page.tag; title = __('tag') + ': ' + page.tag;
} else if (page.title === 'about') { } else if (page.title === 'about') {
title = __('about'); title = __('about');
} else if (page.title === 'links') {
title = __('links');
} }
%> %>
<title> <title>
<% if (title){ %><%= title %> | <% } %><%= config.title %> <% if (title){ %><%= title %> |
<% } %>
<%= config.title %>
</title> </title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<% if (theme.style.favicon){ %> <% if (theme.style.favicon){ %>

View File

@ -1,21 +1,24 @@
<%- js([ <%- js([
'js/main.js', 'js/utils.js',
'js/header-shrink.js', 'js/header-shrink.js',
'js/toggle-mode.js' 'js/dark-light-toggle.js',
'js/main.js'
]) %> ]) %>
<% if (theme.back2top.enable) { %> <% if (theme.back2top.enable) { %>
<%- js('js/scroll-to-top.js') %> <%- js('js/back2top.js') %>
<% } %> <% } %>
<% if (is_post()) { %> <% if (is_post()) { %>
<%- js('js/left-side-toggle.js') %>
<% if (theme.code_copy.enable) { %> <% if (theme.code_copy.enable) { %>
<%- js('js/code-copy.js') %> <%- js('js/code-copy.js') %>
<% } %> <% } %>
<% if (theme.toc.enable) { %> <% if (theme.toc.enable) { %>
<%- js(['lib/anime.min.js', 'js/toc.js', 'js/post-toc.js']) %> <%- js(['lib/anime.min.js', 'js/toc.js']) %>
<% } %> <% } %>
<% } %> <% } %>

View File

@ -8,18 +8,21 @@ const url = require('url');
* Export theme config to js * Export theme config to js
*/ */
hexo.extend.helper.register('export_config', function () { hexo.extend.helper.register('export_config', function () {
let {config, theme} = this; let {config, theme} = this;
let exportConfig = { let exportConfig = {
hostname: url.parse(config.url).hostname || config.url, hostname: url.parse(config.url).hostname || config.url,
root: config.root, root: config.root,
localsearch: theme.local_search, localsearch: theme.local_search,
themeInfo: theme.theme_info, themeInfo: theme.theme_info,
codeblock: theme.codeblock codeblock: theme.codeblock,
}; toc: theme.toc,
if (config.search) { back2top: theme.back2top
exportConfig.path = config.search.path; };
} if (config.search) {
return `<script id="hexo-configurations"> exportConfig.path = config.search.path;
}
return `<script id="hexo-configurations">
let ILS = window.ILS || {};
let CONFIG = ${JSON.stringify(exportConfig)}; let CONFIG = ${JSON.stringify(exportConfig)};
</script>`; </script>`;
}); });

View File

@ -69,15 +69,14 @@
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
// TODO: ...
} }
h1 { h1 {
color: var(--second-text-color); color: var(--second-text-color);
font-size: 2em; font-size: 2em;
font-weight: 600; font-weight: 600;
margin-block-start: 1.1em; margin-block-start: 1.4em;
margin-block-end: 1.1em; margin-block-end: 1.0em;
} }
@ -85,16 +84,16 @@
color: var(--second-text-color); color: var(--second-text-color);
font-size: 1.8em; font-size: 1.8em;
font-weight: 600; font-weight: 600;
margin-block-start: 1.1em; margin-block-start: 1.4em;
margin-block-end: 1.1em; margin-block-end: 1.0em;
} }
h3 { h3 {
color: var(--second-text-color); color: var(--second-text-color);
font-size: 1.6em; font-size: 1.6em;
font-weight: 550; font-weight: 550;
margin-block-start: 1em; margin-block-start: 1.2em;
margin-block-end: 1em; margin-block-end: 0.8em;
} }
@ -102,16 +101,16 @@
color: var(--second-text-color); color: var(--second-text-color);
font-size: 1.4em; font-size: 1.4em;
font-weight: 550; font-weight: 550;
margin-block-start: 1em; margin-block-start: 1.2em;
margin-block-end: 1em; margin-block-end: 0.8em;
} }
h5 { h5 {
color: var(--second-text-color); color: var(--second-text-color);
font-size: 1.2em; font-size: 1.2em;
font-weight: 500; font-weight: 500;
margin-block-start: 0.9em; margin-block-start: 1.0em;
margin-block-end: 0.9em; margin-block-end: 0.6em;
} }
@ -119,8 +118,8 @@
color: var(--second-text-color); color: var(--second-text-color);
font-size: 1.2em; font-size: 1.2em;
font-weight: 500; font-weight: 500;
margin-block-start: 0.9em; margin-block-start: 1.0em;
margin-block-end: 0.9em; margin-block-end: 0.6em;
} }

35
source/js/back2top.js Normal file
View File

@ -0,0 +1,35 @@
window.addEventListener('DOMContentLoaded', () => {
ILS.utils = {
...ILS.utils,
back2TopButton_dom: document.querySelector('.scroll-to-top'),
back2top() {
const scrollTopTimer = setInterval(function () {
let top = document.body.scrollTop || document.documentElement.scrollTop;
let speed = top / 2;
if (document.body.scrollTop !== 0) {
document.body.scrollTop -= speed;
} else {
document.documentElement.scrollTop -= speed;
}
if (top === 0) {
clearInterval(scrollTopTimer);
}
}, 30);
},
initBack2TopButton() {
if (ILS.utils.back2TopButton_dom) {
ILS.utils.back2TopButton_dom.addEventListener('click', () => {
this.back2top();
});
}
},
}
ILS.utils.initBack2TopButton();
});

View File

@ -1,45 +1,45 @@
HTMLElement.prototype.wrap = function (wrapper) { HTMLElement.prototype.wrap = function (wrapper) {
this.parentNode.insertBefore(wrapper, this); this.parentNode.insertBefore(wrapper, this);
this.parentNode.removeChild(this); this.parentNode.removeChild(this);
wrapper.appendChild(this); wrapper.appendChild(this);
}; };
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('figure.highlight').forEach(element => { document.querySelectorAll('figure.highlight').forEach(element => {
const box = document.createElement('div'); const box = document.createElement('div');
element.wrap(box); element.wrap(box);
box.classList.add('highlight-container'); box.classList.add('highlight-container');
box.insertAdjacentHTML('beforeend', '<div class="copy-btn"><i class="fa fa-clipboard"></i></div>'); box.insertAdjacentHTML('beforeend', '<div class="copy-btn"><i class="fa fa-clipboard"></i></div>');
var button = element.parentNode.querySelector('.copy-btn'); var button = element.parentNode.querySelector('.copy-btn');
button.addEventListener('click', event => { button.addEventListener('click', event => {
var target = event.currentTarget; var target = event.currentTarget;
var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n');
var ta = document.createElement('textarea'); var ta = document.createElement('textarea');
ta.style.top = window.scrollY + 'px'; // Prevent page scrolling ta.style.top = window.scrollY + 'px'; // Prevent page scrolling
ta.style.position = 'absolute'; ta.style.position = 'absolute';
ta.style.opacity = '0'; ta.style.opacity = '0';
ta.readOnly = true; ta.readOnly = true;
ta.value = code; ta.value = code;
document.body.append(ta); document.body.append(ta);
const selection = document.getSelection(); const selection = document.getSelection();
const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false; const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
ta.select(); ta.select();
ta.setSelectionRange(0, code.length); ta.setSelectionRange(0, code.length);
ta.readOnly = false; ta.readOnly = false;
var result = document.execCommand('copy'); var result = document.execCommand('copy');
target.querySelector('i').className = result ? 'fa fa-check' : 'fa fa-times'; target.querySelector('i').className = result ? 'fa fa-check' : 'fa fa-times';
ta.blur(); // For iOS ta.blur(); // For iOS
target.blur(); target.blur();
if (selected) { if (selected) {
selection.removeAllRanges(); selection.removeAllRanges();
selection.addRange(selected); selection.addRange(selected);
} }
document.body.removeChild(ta); document.body.removeChild(ta);
});
button.addEventListener('mouseleave', event => {
setTimeout(() => {
event.target.querySelector('i').className = 'fa fa-clipboard';
}, 300);
});
}); });
button.addEventListener('mouseleave', event => {
setTimeout(() => {
event.target.querySelector('i').className = 'fa fa-clipboard';
}, 300);
});
});
}); });

View File

@ -0,0 +1,72 @@
window.addEventListener('DOMContentLoaded', () => {
ILS.utils.modeToggle = {
localStorageKey: 'MAGIC',
modeToggleButton_dom: document.querySelector('.mode-toggle'),
iconDom: document.querySelector('.mode-toggle i'),
articleContent: document.querySelector('.main-content'),
setItemUtil(modeClass, prefersColorScheme) {
document.body.classList.toggle(modeClass);
const isDark = document.body.className.indexOf(modeClass) === -1;
if (isDark) {
this.iconDom.className = 'fa fa-moon-o';
this.articleContent.classList.remove('night-code-theme');
} else {
this.iconDom.className = 'fa fa-lightbulb-o';
this.articleContent.classList.add('night-code-theme');
}
localStorage.setItem(this.localStorageKey, JSON.stringify(
{
prefersColorScheme: prefersColorScheme,
isDark: isDark
}
));
},
initModeStatus() {
this.modeConfig = JSON.parse(localStorage.getItem(this.localStorageKey));
if (this.modeConfig) {
if (this.modeConfig.prefersColorScheme === 'dark') {
if (this.modeConfig.isDark) {
document.body.classList.remove('light-mode');
this.articleContent.classList.remove('night-code-theme');
this.iconDom.className = 'fa fa-lightbulb-o';
} else {
document.body.classList.add('light-mode');
this.articleContent.classList.add('night-code-theme');
this.iconDom.className = 'fa fa-moon-o';
}
} else {
if (this.modeConfig.isDark) {
document.body.classList.remove('dark-mode');
this.articleContent.classList.remove('night-code-theme');
this.iconDom.className = 'fa fa-moon-o';
} else {
document.body.classList.add('dark-mode');
this.articleContent.classList.add('night-code-theme');
this.iconDom.className = 'fa fa-lightbulb-o';
}
}
}
},
initModeToggleButton() {
this.modeToggleButton_dom.addEventListener('click', () => {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
this.setItemUtil('light-mode', 'dark');
} else {
this.setItemUtil('dark-mode', 'light');
}
});
}
}
ILS.utils.modeToggle.initModeStatus();
ILS.utils.modeToggle.initModeToggleButton();
});

View File

@ -1,36 +1,50 @@
const pageTemplateDom = document.querySelector('.page-main-content'); window.addEventListener('DOMContentLoaded', () => {
const sidebarToolsDom = document.querySelector('.sidebar-tools'); ILS.utils.headerShrink = {
const headerDom = document.querySelector('.header-wrapper');
const menuBarDom = document.querySelector('.menu-bar');
const windowMaskDom = document.querySelector('.window-mask');
pageTemplateDom: document.querySelector('.page-main-content'),
sidebarToolsDom: document.querySelector('.sidebar-tools'),
headerDom: document.querySelector('.header-wrapper'),
menuBarDom: document.querySelector('.menu-bar'),
windowMaskDom: document.querySelector('.window-mask'),
let isHeaderShrink = false; isHeaderShrink: false,
const headerHeight = headerDom.getBoundingClientRect().height;
window.addEventListener('scroll', function (_e) { init() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; this.headerHeight = this.headerDom.getBoundingClientRect().height;
if (!isHeaderShrink && scrollTop > headerHeight) { },
isHeaderShrink = true;
headerDom.classList.add('header-wrapper-shrink');
pageTemplateDom.classList.add('page-main-content-top-shrink');
sidebarToolsDom.classList.add('sidebar-tools-shrink');
} else if (isHeaderShrink && scrollTop <= headerHeight) { headerShrink() {
isHeaderShrink = false;
headerDom.classList.remove('header-wrapper-shrink'); const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
pageTemplateDom.classList.remove('page-main-content-top-shrink');
sidebarToolsDom.classList.remove('sidebar-tools-shrink'); if (!this.isHeaderShrink && scrollTop > this.headerHeight) {
this.isHeaderShrink = true;
this.headerDom.classList.add('header-wrapper-shrink');
this.pageTemplateDom.classList.add('page-main-content-top-shrink');
this.sidebarToolsDom.classList.add('sidebar-tools-shrink');
} else if (this.isHeaderShrink && scrollTop <= this.headerHeight) {
this.isHeaderShrink = false;
this.headerDom.classList.remove('header-wrapper-shrink');
this.pageTemplateDom.classList.remove('page-main-content-top-shrink');
this.sidebarToolsDom.classList.remove('sidebar-tools-shrink');
}
},
initMenuBarButton() {
this.menuBarDom.addEventListener('click', () => {
this.headerDom.classList.toggle('header-drawer-show');
});
},
initWindowMask() {
this.windowMaskDom.addEventListener('click', () => {
this.headerDom.classList.toggle('header-drawer-show');
});
},
} }
ILS.utils.headerShrink.init();
ILS.utils.headerShrink.initMenuBarButton();
ILS.utils.headerShrink.initWindowMask();
}); });
menuBarDom.addEventListener('click', function (_e) {
headerDom.classList.toggle('header-drawer-show');
});
windowMaskDom.addEventListener('click', function (_e) {
headerDom.classList.toggle('header-drawer-show');
});

View File

@ -0,0 +1,38 @@
window.addEventListener('DOMContentLoaded', () => {
ILS.utils.leftSideToggle = {
init() {
this.toggleBar = document.querySelector('.page-aside-toggle');
this.pageTopDom = document.querySelector('.page-main-content-top');
this.containerDom = document.querySelector('.page-container');
this.leftAsideDom = document.querySelector('.page-aside');
this.headerContentDom = document.querySelector('.header-wrapper .header-content');
this.mainContentDom = document.querySelector('.page-main-content-middle .main-content');
this.isOpenPageAside = false;
},
initToggleBarButton() {
if (this.toggleBar) {
this.toggleBar.addEventListener('click', () => {
this.isOpenPageAside = !this.isOpenPageAside;
this.changePageLayoutWhenOpenToggle(this.isOpenPageAside);
})
}
},
changePageLayoutWhenOpenToggle(isOpen) {
const pageAsideWidth = '258px';
this.containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
this.pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`;
this.headerContentDom.style.width = isOpen ? '76%' : '62%';
this.mainContentDom.style.width = isOpen ? '76%' : '62%';
},
}
ILS.utils.leftSideToggle.init();
ILS.utils.leftSideToggle.initToggleBarButton();
});

View File

@ -1,47 +1,8 @@
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
console.log(`${CONFIG.themeInfo.name} v${CONFIG.themeInfo.version}`); // print theme info
ILS.utils.printThemeInfo();
pageAsideOpenToggle(); // init scroll
ILS.utils.initWindowScroll();
}); });
const pageAsideOpenToggle = () => {
const toggleDom = document.querySelector('.page-aside-toggle');
const pageTopDom = document.querySelector('.page-main-content-top');
const containerDom = document.querySelector('.page-container');
const leftAsideDom = document.querySelector('.page-aside');
const headerContentDom = document.querySelector('.header-wrapper .header-content');
const mainContentDom = document.querySelector('.page-main-content-middle .main-content');
let isOpen = false;
const openToggle = (isOpen) => {
const pageAsideWidth = '258px';
containerDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
pageTopDom.style.paddingLeft = isOpen ? pageAsideWidth : '0';
leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`;
headerContentDom.style.width = isOpen ? '76%' : '62%';
mainContentDom.style.width = isOpen ? '76%' : '62%';
}
toggleDom.addEventListener('click', () => {
isOpen = !isOpen;
openToggle(isOpen);
})
window.utils = {
openToggle: () => {
isOpen = true;
openToggle(isOpen);
}
}
}

View File

@ -1,10 +0,0 @@
window.addEventListener('DOMContentLoaded', () => {
const navItems = document.querySelectorAll('.post-toc-wrap .post-toc li');
const toggleDom = document.querySelector('.page-aside-toggle');
if (navItems.length) {
toggleDom.style.display = 'flex';
window.utils.openToggle();
}
});

View File

@ -1,53 +0,0 @@
(function () {
const scrollToTopDom = document.querySelector('.scroll-to-top');
const headerProgressDom = document.querySelector('.header-progress');
const headerWrapper = document.querySelector('.header-wrapper');
const backToTop = () => {
let scrollTopTimer = setInterval(function () {
let top = document.body.scrollTop || document.documentElement.scrollTop;
let speed = top / 2;
if (document.body.scrollTop !== 0) {
document.body.scrollTop -= speed;
} else {
document.documentElement.scrollTop -= speed;
}
if (top === 0) {
clearInterval(scrollTopTimer);
}
}, 30);
};
scrollToTopDom.addEventListener('click', () => {
backToTop();
});
let prevScroll = 0;
window.addEventListener('scroll', function (_e) {
// back to top & show scroll percent
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
const clientHeight = window.innerHeight || document.documentElement.clientHeight;
const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100).toFixed(0);
const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3);
if (percent === '0') {
scrollToTopDom.style.display = 'none';
headerProgressDom.style.display = 'none';
} else {
scrollToTopDom.style.display = 'flex';
headerProgressDom.style.display = 'block';
headerProgressDom.style.width = `${ProgressPercent}%`;
}
// hide header handle
const opacity = headerWrapper.style.opacity
if (scrollTop > prevScroll && scrollTop > 360) {
if (opacity > 0) headerWrapper.style.opacity = '0';
} else {
if (opacity < 1) headerWrapper.style.opacity = '1';
}
prevScroll = scrollTop
});
})();

View File

@ -1,107 +1,95 @@
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
const articleToc = document.querySelector('.article-toc'); ILS.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li');
const postTocWrap = document.querySelector('.post-toc-wrap'); ILS.utils.articleToc_dom = document.querySelector('.article-toc');
const navItems = postTocWrap.querySelectorAll('.post-toc li'); ILS.utils.postTocWrap_dom = document.querySelector('.post-toc-wrap');
const headerWrapper = document.querySelector('.header-wrapper'); ILS.utils.headerWrapper_dom = document.querySelector('.header-wrapper');
if (navItems.length > 0) { if (ILS.utils.navItems.length > 0) {
const sections = [...navItems].map(element => { ILS.utils = {
let link = element.querySelector('a.nav-link');
// TOC item animation navigate. ...ILS.utils,
link.addEventListener('click', event => {
event.preventDefault(); findActiveIndexByTOC() {
let target = document.getElementById(event.currentTarget.getAttribute('href').replace('#', '')); if (!Array.isArray(ILS.utils.sections)) return;
let offset = target.getBoundingClientRect().top + window.scrollY - 18; let index = ILS.utils.sections.findIndex(element => {
window.anime({ return element && element.getBoundingClientRect().top - 20 > 0;
targets: document.scrollingElement,
duration: 500,
easing: 'linear',
scrollTop: offset,
complete: function () {
setTimeout(() => {
if (headerWrapper.style.opacity !== '0') headerWrapper.style.opacity = '0'
}, 100)
}
}); });
}); if (index === -1) {
return document.getElementById(link.getAttribute('href').replace('#', '')); index = ILS.utils.sections.length - 1;
}); } else if (index > 0) {
index--;
function activateNavByIndex(target) {
if (target.classList.contains('active-current')) return;
document.querySelectorAll('.post-toc .active').forEach(element => {
element.classList.remove('active', 'active-current');
});
target.classList.add('active', 'active-current');
let parent = target.parentNode;
while (!parent.matches('.post-toc')) {
if (parent.matches('li')) parent.classList.add('active');
parent = parent.parentNode;
}
// Scrolling to center active TOC element if TOC content is taller then viewport.
window.anime({
targets: postTocWrap,
duration: 200,
easing: 'linear',
scrollTop: postTocWrap.scrollTop - (postTocWrap.offsetHeight / 2) + target.getBoundingClientRect().top - postTocWrap.getBoundingClientRect().top
});
}
function findIndex(entries) {
let index = 0;
let entry = entries[index];
if (entry.boundingClientRect.top > 0) {
index = sections.indexOf(entry.target);
return index === 0 ? 0 : index - 1;
}
for (; index < entries.length; index++) {
if (entries[index].boundingClientRect.top <= 0) {
entry = entries[index];
} else {
return sections.indexOf(entry.target);
} }
} ILS.utils.activateNavByIndex(index);
return sections.indexOf(entry.target); },
}
function createIntersectionObserver(marginTop) { registerSidebarTOC() {
ILS.utils.sections = [...document.querySelectorAll('.post-toc li a.nav-link')].map(element => {
const target = document.getElementById(decodeURI(element.getAttribute('href')).replace('#', ''));
element.addEventListener('click', event => {
event.preventDefault();
const offset = target.getBoundingClientRect().top + window.scrollY;
window.anime({
targets: document.scrollingElement,
duration: 500,
easing: 'linear',
scrollTop: offset - 10,
complete: function () {
setTimeout(() => {
if (ILS.utils.headerWrapper_dom.style.opacity !== '0') ILS.utils.headerWrapper_dom.style.opacity = '0'
}, 100)
}
});
});
return target;
});
},
marginTop = Math.floor(marginTop + 10000); activateNavByIndex: function (index) {
let intersectionObserver = new IntersectionObserver((entries, observe) => { const target = document.querySelectorAll('.post-toc li a.nav-link')[index];
let scrollHeight = document.documentElement.scrollHeight + 100; if (!target || target.classList.contains('active-current')) return;
if (scrollHeight > marginTop) {
observe.disconnect(); document.querySelectorAll('.post-toc .active').forEach(element => {
createIntersectionObserver(scrollHeight); element.classList.remove('active', 'active-current');
return; });
target.classList.add('active', 'active-current');
let parent = target.parentNode;
while (!parent.matches('.post-toc')) {
if (parent.matches('li')) parent.classList.add('active');
parent = parent.parentNode;
} }
let index = findIndex(entries); // Scrolling to center active TOC element if TOC content is taller then viewport.
activateNavByIndex(navItems[index]); const tocElement = document.querySelector('.post-toc-wrap');
}, { window.anime({
rootMargin: marginTop + 'px 0px -100% 0px', targets: tocElement,
threshold: 0 duration: 200,
}); easing: 'linear',
sections.forEach(element => { scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top
element && intersectionObserver.observe(element); });
}); },
showPageAsideWhenHasTOC() {
ILS.utils.leftSideToggle.toggleBar.style.display = 'flex';
ILS.utils.leftSideToggle.isOpenPageAside = true;
ILS.utils.leftSideToggle.changePageLayoutWhenOpenToggle(ILS.utils.leftSideToggle.isOpenPageAside);
}
} }
createIntersectionObserver(document.documentElement.scrollHeight); ILS.utils.showPageAsideWhenHasTOC();
ILS.utils.registerSidebarTOC();
} else { } else {
if (postTocWrap) { if (ILS.utils.postTocWrap_dom) {
postTocWrap.innerHTML = ''; ILS.utils.postTocWrap_dom.innerHTML = '';
postTocWrap.style.display = 'none'; ILS.utils.postTocWrap_dom.style.display = 'none';
} }
if (articleToc) { if (ILS.utils.articleToc_dom) {
articleToc.style.display = 'none'; ILS.utils.articleToc_dom.style.display = 'none';
} }
} }
}); });

View File

@ -1,70 +0,0 @@
/**
* 日间/夜间 模式切换
*/
const localStorageKey = 'MAGIC'
const modeToggleBtn = document.querySelector('.mode-toggle');
const iconDom = modeToggleBtn.querySelector('i');
const articleContent = document.querySelector('.main-content');
const modeConfig = JSON.parse(localStorage.getItem(localStorageKey));
if (modeConfig) {
if (modeConfig.prefersColorScheme === 'dark') {
if (modeConfig.isDark) {
document.body.classList.remove('light-mode');
articleContent.classList.remove('night-code-theme');
iconDom.className = 'fa fa-lightbulb-o';
} else {
iconDom.className = 'fa fa-moon-o';
document.body.classList.add('light-mode');
articleContent.classList.add('night-code-theme');
}
} else {
if (modeConfig.isDark) {
document.body.classList.remove('dark-mode');
articleContent.classList.remove('night-code-theme');
iconDom.className = 'fa fa-moon-o';
} else {
document.body.classList.add('dark-mode');
iconDom.className = 'fa fa-lightbulb-o';
articleContent.classList.add('night-code-theme');
}
}
}
const setItemUtil = (modeClass, prefersColorScheme) => {
document.body.classList.toggle(modeClass);
const isDark = document.body.className.indexOf(modeClass) === -1;
if (isDark) {
iconDom.className = 'fa fa-moon-o';
articleContent.classList.remove('night-code-theme');
} else {
iconDom.className = 'fa fa-lightbulb-o';
articleContent.classList.add('night-code-theme');
}
localStorage.setItem(localStorageKey, JSON.stringify(
{
prefersColorScheme: prefersColorScheme,
isDark: isDark
}
));
};
modeToggleBtn.addEventListener('click', function (e) {
if (
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
) {
setItemUtil('light-mode', 'dark');
} else {
setItemUtil('dark-mode', 'light');
}
});

60
source/js/utils.js Normal file
View File

@ -0,0 +1,60 @@
ILS.utils = {
printThemeInfo() {
console.log(`${CONFIG.themeInfo.name} v${CONFIG.themeInfo.version}`);
}
}
ILS.utils = {
...ILS.utils,
headerProgress_dom: document.querySelector('.header-progress'),
headerWrapper_dom: document.querySelector('.header-wrapper'),
// Scroll Style Handle
prevScrollValue: 0,
styleHandleWhenScroll() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
const clientHeight = window.innerHeight || document.documentElement.clientHeight;
const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100).toFixed(0);
const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3);
if (CONFIG.back2top.enable && ILS.utils.back2TopButton_dom) {
ILS.utils.back2TopButton_dom.style.display = percent === '0' ? 'none' : 'flex';
}
if (ILS.utils.headerProgress_dom) {
ILS.utils.headerProgress_dom.style.display = percent === '0' ? 'none' : 'block';
ILS.utils.headerProgress_dom.style.width = `${ProgressPercent}%`;
}
// hide header handle
const opacity = ILS.utils.headerWrapper_dom.style.opacity;
if (scrollTop > ILS.utils.prevScrollValue && scrollTop > 500) {
if (opacity !== '0') ILS.utils.headerWrapper_dom.style.opacity = '0';
} else {
if (opacity !== '1') ILS.utils.headerWrapper_dom.style.opacity = '1';
}
ILS.utils.prevScrollValue = scrollTop;
},
// 初始 window scroll 事件
initWindowScroll() {
window.addEventListener('scroll', function (_e) {
// style handle when scroll
ILS.utils.styleHandleWhenScroll();
// TOC scroll handle
if (CONFIG.toc.enable && ILS.utils.hasOwnProperty('findActiveIndexByTOC')) {
ILS.utils.findActiveIndexByTOC();
}
// header shrink
ILS.utils.headerShrink.headerShrink();
});
},
}