refactor: enhance the user experience with PJAX

This commit is contained in:
XPoet 2020-12-30 18:11:46 +08:00
parent 141adcb1d3
commit 0abad9b9a8
19 changed files with 444 additions and 362 deletions

View File

@ -49,7 +49,9 @@ social_contact:
links: links:
github: # your GitHub URL github: # your GitHub URL
weixin: # your WeChat QR-Code URL weixin: # your WeChat QR-Code URL
qq: # your QQ QR-Code URL
weibo: # your WeiBo URL weibo: # your WeiBo URL
zhihu: # your ZhiHu URL
twitter: # your twitter URL twitter: # your twitter URL
facebook: # your facebook URL facebook: # your facebook URL
email: # your email email: # your email
@ -193,6 +195,20 @@ copyright_info:
enable: true enable: true
# ---------------------------------------------------------------------------------------
# CDN
# ---------------------------------------------------------------------------------------
cdn:
enable: false
# ---------------------------------------------------------------------------------------
# PJAX
# ---------------------------------------------------------------------------------------
pjax:
enable: false
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
# Footer settings # Footer settings
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
@ -200,13 +216,6 @@ footer:
since: 2020 since: 2020
# ---------------------------------------------------------------------------------------
# CDN
# ---------------------------------------------------------------------------------------
cdn:
enable: true
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
# Keep version (Please don't modify) # Keep version (Please don't modify)
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------

View File

@ -5,24 +5,36 @@
&& theme.comment.gitalk.github_id && theme.comment.gitalk.github_id
&& theme.comment.gitalk.repository && theme.comment.gitalk.repository
) { %> ) { %>
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script> <script <%= theme.pjax.enable === true ? 'data-pjax' : '' %>
src="//cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.js"></script>
<div id="gitalk-container"></div> <div id="gitalk-container"></div>
<script> <script <%= theme.pjax.enable === true ? 'data-pjax' : '' %>>
let __gitalk__pathname = decodeURI(location.pathname);
const __gitalk__pathnameLength = __gitalk__pathname.length; function loadGitalk() {
const __gitalk__pathnameMaxLength = 50; let __gitalk__pathname = decodeURI(location.pathname);
if (__gitalk__pathnameLength > __gitalk__pathnameMaxLength) { const __gitalk__pathnameLength = __gitalk__pathname.length;
__gitalk__pathname = __gitalk__pathname.substring(0, __gitalk__pathnameMaxLength - 3) + '...'; const __gitalk__pathnameMaxLength = 50;
if (__gitalk__pathnameLength > __gitalk__pathnameMaxLength) {
__gitalk__pathname = __gitalk__pathname.substring(0, __gitalk__pathnameMaxLength - 3) + '...';
}
new Gitalk({
clientID: '<%= theme.comment.gitalk.client_id %>',
clientSecret: '<%= theme.comment.gitalk.client_secret %>',
repo: '<%= theme.comment.gitalk.repository %>',
owner: '<%= theme.comment.gitalk.github_id %>',
admin: ['<%= theme.comment.gitalk.github_id %>'],
id: __gitalk__pathname,
language: '<%= config.language %>'
}).render('gitalk-container');
}
if ('<%= theme.pjax.enable %>') {
const loadGitalkTimeout = setTimeout(() => {
loadGitalk();
clearTimeout(loadGitalkTimeout);
}, 1000);
} else {
window.addEventListener('DOMContentLoaded', loadGitalk);
} }
const gitalk = new Gitalk({
clientID: '<%= theme.comment.gitalk.client_id %>',
clientSecret: '<%= theme.comment.gitalk.client_secret %>',
repo: '<%= theme.comment.gitalk.repository %>',
owner: '<%= theme.comment.gitalk.github_id %>',
admin: ['<%= theme.comment.gitalk.github_id %>'],
id: __gitalk__pathname,
language: '<%= config.language %>'
})
gitalk.render('gitalk-container')
</script> </script>
<% } %> <% } %>

View File

@ -4,42 +4,55 @@
&& theme.comment.valine.appkey && theme.comment.valine.appkey
) { %> ) { %>
<div class="valine-container"> <div class="valine-container">
<script src='//unpkg.com/valine/dist/Valine.min.js'></script> <script <%= theme.pjax.enable === true ? 'data-pjax' : '' %>
src="//cdn.jsdelivr.net/npm/valine@latest/dist/Valine.min.js"></script>
<div id="vcomments"></div> <div id="vcomments"></div>
<script> <script <%= theme.pjax.enable === true ? 'data-pjax' : '' %>>
const temp_valine_input_meta = '<%= theme.comment.valine.meta %>';
new Valine({
el: '#vcomments',
appId: '<%= theme.comment.valine.appid %>',
appKey: '<%= theme.comment.valine.appkey %>',
meta: temp_valine_input_meta ? temp_valine_input_meta.split(',') : ['nick', 'mail', 'link'],
avatar: 'wavatar',
enableQQ: true,
placeholder: '<%= theme.comment.valine.placeholder %>',
lang: '<%= config.language %>'.toLowerCase()
});
// Add "Author" identify function loadValine() {
const getValineDomTimer = setInterval(() => { const temp_valine_input_meta = '<%= theme.comment.valine.meta %>';
const vcards = document.querySelectorAll('#vcomments .vcards .vcard'); new Valine({
if (vcards.length > 0) { el: '#vcomments',
appId: '<%= theme.comment.valine.appid %>',
appKey: '<%= theme.comment.valine.appkey %>',
meta: temp_valine_input_meta ? temp_valine_input_meta.split(',') : ['nick', 'mail', 'link'],
avatar: 'wavatar',
enableQQ: true,
placeholder: '<%= theme.comment.valine.placeholder %>',
lang: '<%= config.language %>'.toLowerCase()
});
let author = '<%= theme.base_info.author || config.author %>'; // Add "Author" identify
if (author) { const getValineDomTimer = setInterval(() => {
author = author.toLocaleLowerCase(); const vcards = document.querySelectorAll('#vcomments .vcards .vcard');
} if (vcards.length > 0) {
for (let vcard of vcards) { let author = '<%= theme.base_info.author || config.author %>';
const vnick = vcard.querySelector('.vhead .vnick'); if (author) {
if (vnick.innerHTML.toLocaleLowerCase() === author) { author = author.toLocaleLowerCase();
vcard.classList.add('author');
} }
for (let vcard of vcards) {
const vnick = vcard.querySelector('.vhead .vnick');
if (vnick.innerHTML.toLocaleLowerCase() === author) {
vcard.classList.add('author');
}
}
clearInterval(getValineDomTimer);
} else {
clearInterval(getValineDomTimer);
} }
clearInterval(getValineDomTimer); }, 2000);
} else { }
clearInterval(getValineDomTimer);
} if ('<%= theme.pjax.enable %>') {
}, 2000); const loadValineTimeout = setTimeout(() => {
loadValine();
clearTimeout(loadValineTimeout);
}, 1000);
} else {
window.addEventListener('DOMContentLoaded', loadValine);
}
</script> </script>
</div> </div>
<% } %> <% } %>

View File

@ -7,8 +7,8 @@
<% } %> <% } %>
<%= date(new Date(), 'YYYY') %> <i class="fas fa-heart icon-animate"></i> <a href="/"><%= theme.base_info.author || config.author %></a> <%= date(new Date(), 'YYYY') %> <i class="fas fa-heart icon-animate"></i> <a href="/"><%= theme.base_info.author || config.author %></a>
</div> </div>
<% if (theme.website_count.busuanzi_count.enable) { %> <% if (theme.website_count.busuanzi_count.enable === true) { %>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script> <script async <%= theme.pjax.enable === true ? 'data-pjax' : '' %> src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<div class="website-count info-item"> <div class="website-count info-item">
<% if (theme.website_count.busuanzi_count.site_uv) { %> <% if (theme.website_count.busuanzi_count.site_uv) { %>
<span id="busuanzi_container_site_uv"> <span id="busuanzi_container_site_uv">

View File

@ -0,0 +1,21 @@
<%- __js('js/libs/pjax.min.js') %>
<script>
window.addEventListener('DOMContentLoaded', () => {
const pjax = new Pjax({
selectors: [
'head title',
'.page-container',
'.pjax',
],
cacheBust: false,
currentUrlFullReload: false,
timeout: 0
});
window.addEventListener('pjax:complete', () => {
KEEP.refresh();
pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
});
});
</script>

View File

@ -10,15 +10,20 @@
<%- __js('js/local-search.js') %> <%- __js('js/local-search.js') %>
<% } %> <% } %>
<% if (is_post()) { %> <% if (theme.code_copy.enable) { %>
<%- __js('js/code-copy.js') %>
<%- __js('js/left-side-toggle.js') %> <% } %>
<% if (theme.code_copy.enable ) { %> <div class="post-scripts <%= theme.pjax.enable === true ? 'pjax' : '' %>">
<%- __js('js/code-copy.js') %> <% if (theme.toc.enable && is_post()) { %>
<% } %> <%- __js([
'js/left-side-toggle.js',
<% if (theme.toc.enable) { %> 'js/libs/anime.min.js',
<%- __js(['js/libs/anime.min.js', 'js/toc.js']) %> 'js/toc.js'
<% } %> ]) %>
<% } %>
</div>
<% if (theme.pjax.enable === true) { %>
<%- partial('pjax/pjax') %>
<% } %> <% } %>

View File

@ -1 +1 @@
<%- partial('page') %> <%- partial('page') %>

View File

@ -5,4 +5,4 @@
<%- body %> <%- body %>
<%- partial('_partial/scripts') %> <%- partial('_partial/scripts') %>
</body> </body>
</html> </html>

View File

@ -12,9 +12,9 @@ const yaml = require('js-yaml');
*/ */
hexo.extend.helper.register('export_config', function () { hexo.extend.helper.register('export_config', function () {
let { config, theme } = this; let {config, theme} = this;
// ------ export language to js ------ // ------------ export language to js ------------
const languageDir = path.join(__dirname, '../../languages'); const languageDir = path.join(__dirname, '../../languages');
let file = fs.readdirSync(languageDir).find(v => v === `${config.language}.yml`); let file = fs.readdirSync(languageDir).find(v => v === `${config.language}.yml`);
file = languageDir + '/' + (file ? file : 'en.yml'); file = languageDir + '/' + (file ? file : 'en.yml');
@ -24,14 +24,14 @@ hexo.extend.helper.register('export_config', function () {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
// --------------------------------- // -----------------------------------------------
let hexo_config = { let hexo_config = {
hostname: url.parse(config.url).hostname || config.url, hostname: url.parse(config.url).hostname || config.url,
root: config.root root: config.root
}; };
if (config.search) { if (config.search) {
hexo_config.path = config.search.path; hexo_config.path = config.search.path;
} }
@ -41,6 +41,7 @@ hexo.extend.helper.register('export_config', function () {
style: theme.style, style: theme.style,
local_search: theme.local_search, local_search: theme.local_search,
side_tools: theme.side_tools, side_tools: theme.side_tools,
pjax: theme.pjax,
version: theme.version, version: theme.version,
} }
@ -48,6 +49,6 @@ hexo.extend.helper.register('export_config', function () {
let KEEP = window.KEEP || {}; let KEEP = window.KEEP || {};
KEEP.hexo_config = ${JSON.stringify(hexo_config)}; KEEP.hexo_config = ${JSON.stringify(hexo_config)};
KEEP.theme_config = ${JSON.stringify(theme_config)}; KEEP.theme_config = ${JSON.stringify(theme_config)};
KEEP.language = ${JSON.stringify(languageContent)}; KEEP.language_ago = ${JSON.stringify(languageContent['ago'])};
</script>`; </script>`;
}); });

View File

@ -1,4 +1,5 @@
window.addEventListener('DOMContentLoaded', () => { KEEP.initBack2Top = () => {
KEEP.utils = { KEEP.utils = {
...KEEP.utils, ...KEEP.utils,
@ -49,4 +50,5 @@ window.addEventListener('DOMContentLoaded', () => {
KEEP.utils.initBack2Top(); KEEP.utils.initBack2Top();
KEEP.utils.initBack2Bottom(); KEEP.utils.initBack2Bottom();
});
}

View File

@ -1,20 +1,21 @@
HTMLElement.prototype.wrap = function (wrapper) { KEEP.initCodeCopy = () => {
this.parentNode.insertBefore(wrapper, this);
this.parentNode.removeChild(this); HTMLElement.prototype.wrap = function (wrapper) {
wrapper.appendChild(this); this.parentNode.insertBefore(wrapper, this);
}; this.parentNode.removeChild(this);
wrapper.appendChild(this);
};
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="fas fa-copy"></i></div>'); box.insertAdjacentHTML('beforeend', '<div class="copy-btn"><i class="fas fa-copy"></i></div>');
var button = element.parentNode.querySelector('.copy-btn'); const button = element.parentNode.querySelector('.copy-btn');
button.addEventListener('click', event => { button.addEventListener('click', event => {
var target = event.currentTarget; const target = event.currentTarget;
var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); const code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n');
var ta = document.createElement('textarea'); const 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';
@ -26,7 +27,7 @@ window.addEventListener('DOMContentLoaded', () => {
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'); const result = document.execCommand('copy');
target.querySelector('i').className = result ? 'fas fa-check' : 'fas fa-times'; target.querySelector('i').className = result ? 'fas fa-check' : 'fas fa-times';
ta.blur(); // For iOS ta.blur(); // For iOS
target.blur(); target.blur();
@ -42,4 +43,4 @@ window.addEventListener('DOMContentLoaded', () => {
}, 300); }, 300);
}); });
}); });
}); }

View File

@ -1,4 +1,5 @@
window.addEventListener('DOMContentLoaded', () => { KEEP.initModeToggle = () => {
KEEP.utils.modeToggle = { KEEP.utils.modeToggle = {
localStorageKey: 'KEEP', localStorageKey: 'KEEP',
@ -56,7 +57,7 @@ window.addEventListener('DOMContentLoaded', () => {
}, },
initModeToggleButton() { initModeToggleButton() {
this.modeToggleButton_dom.addEventListener('click', () => { this.modeToggleButton_dom.addEventListener('click', () => {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
this.setItemUtil('light-mode', 'dark'); this.setItemUtil('light-mode', 'dark');
} else { } else {
@ -68,4 +69,5 @@ window.addEventListener('DOMContentLoaded', () => {
KEEP.utils.modeToggle.initModeStatus(); KEEP.utils.modeToggle.initModeStatus();
KEEP.utils.modeToggle.initModeToggleButton(); KEEP.utils.modeToggle.initModeToggleButton();
});
};

View File

@ -1,4 +1,4 @@
window.addEventListener('DOMContentLoaded', () => { KEEP.initHeaderShrink = () => {
KEEP.utils.headerShrink = { KEEP.utils.headerShrink = {
pageTemplateDom: document.querySelector('.page-main-content'), pageTemplateDom: document.querySelector('.page-main-content'),
@ -45,4 +45,4 @@ window.addEventListener('DOMContentLoaded', () => {
KEEP.utils.headerShrink.init(); KEEP.utils.headerShrink.init();
KEEP.utils.headerShrink.initMenuBarButton(); KEEP.utils.headerShrink.initMenuBarButton();
KEEP.utils.headerShrink.initWindowMask(); KEEP.utils.headerShrink.initWindowMask();
}); }

View File

@ -1,5 +1,4 @@
window.addEventListener('DOMContentLoaded', () => { function initLeftSideToggle() {
KEEP.utils.leftSideToggle = { KEEP.utils.leftSideToggle = {
init() { init() {
@ -34,8 +33,12 @@ window.addEventListener('DOMContentLoaded', () => {
this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`; this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`;
}, },
} }
KEEP.utils.leftSideToggle.init(); KEEP.utils.leftSideToggle.init();
KEEP.utils.leftSideToggle.initToggleBarButton(); KEEP.utils.leftSideToggle.initToggleBarButton();
}
}); if (KEEP.theme_config.pjax && KEEP.utils) {
initLeftSideToggle();
} else {
window.addEventListener('DOMContentLoaded', initLeftSideToggle);
}

1
source/js/libs/pjax.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,4 @@
/* global CONFIG */ KEEP.initLocalSearch = () => {
window.addEventListener('DOMContentLoaded', () => {
// Search DB path // Search DB path
let searchPath = KEEP.hexo_config.path; let searchPath = KEEP.hexo_config.path;
@ -251,7 +250,8 @@ window.addEventListener('DOMContentLoaded', () => {
return data; return data;
}); });
// Remove loading animation // Remove loading animation
document.getElementById('no-result').innerHTML = '<i class="fas fa-search fa-5x"></i>'; const noResultDom = document.querySelector('#no-result');
noResultDom && (noResultDom.innerHTML = '<i class="fas fa-search fa-5x"></i>');
}); });
}; };
@ -301,4 +301,5 @@ window.addEventListener('DOMContentLoaded', () => {
onPopupClose(); onPopupClose();
} }
}); });
});
}

View File

@ -7,32 +7,14 @@ window.addEventListener('DOMContentLoaded', () => {
repository: 'https://github.com/XPoet/hexo-theme-keep' repository: 'https://github.com/XPoet/hexo-theme-keep'
} }
// print theme info KEEP.refresh = () => {
KEEP.utils.printThemeInfo(); KEEP.initUtils();
KEEP.initHeaderShrink();
KEEP.initModeToggle();
KEEP.initLocalSearch();
KEEP.initBack2Top();
KEEP.initCodeCopy();
}
// init scroll KEEP.refresh();
KEEP.utils.registerWindowScroll();
// toggle show tools list
KEEP.utils.toggleShowToolsList();
// global font adjust
KEEP.utils.globalFontAdjust();
KEEP.utils.contentAreaWidthAdjust();
// comment
KEEP.utils.goComment();
// init page height handle
KEEP.utils.initPageHeightHandle();
// init first screen height
KEEP.utils.initFirstScreenHeight();
// big image viewer handle
KEEP.utils.imageViewer();
// set how long age in home article block
KEEP.utils.setHowLongAgoInHome();
}); });

View File

@ -1,11 +1,7 @@
window.addEventListener('DOMContentLoaded', () => { function initTOC() {
KEEP.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li'); KEEP.utils.navItems = document.querySelectorAll('.post-toc-wrap .post-toc li');
KEEP.utils.articleToc_dom = document.querySelector('.article-toc');
KEEP.utils.postTocWrap_dom = document.querySelector('.post-toc-wrap');
if (KEEP.utils.navItems.length > 0) { if (KEEP.utils.navItems.length > 0) {
KEEP.utils = { KEEP.utils = {
...KEEP.utils, ...KEEP.utils,
@ -74,21 +70,15 @@ window.addEventListener('DOMContentLoaded', () => {
KEEP.utils.leftSideToggle.changePageLayoutWhenOpenToggle(KEEP.utils.leftSideToggle.isOpenPageAside); KEEP.utils.leftSideToggle.changePageLayoutWhenOpenToggle(KEEP.utils.leftSideToggle.isOpenPageAside);
} }
} }
KEEP.utils.showPageAsideWhenHasTOC(); KEEP.utils.showPageAsideWhenHasTOC();
KEEP.utils.registerSidebarTOC(); KEEP.utils.registerSidebarTOC();
} else { } else {
KEEP.utils.pageContainer_dom.removeChild(document.querySelector('.page-aside'));
if (KEEP.utils.postTocWrap_dom) {
KEEP.utils.postTocWrap_dom.innerHTML = '';
KEEP.utils.postTocWrap_dom.style.display = 'none';
}
if (KEEP.utils.articleToc_dom) {
KEEP.utils.articleToc_dom.style.display = 'none';
}
} }
}); }
if (KEEP.theme_config.pjax && KEEP.utils) {
initTOC();
} else {
window.addEventListener('DOMContentLoaded', initTOC);
}

View File

@ -1,238 +1,277 @@
KEEP.utils = { KEEP.initUtils = () => {
headerProgress_dom: document.querySelector('.header-progress'), KEEP.utils = {
pageTop_dom: document.querySelector('.page-main-content-top'),
firstScreen_dom: document.querySelector('.first-screen-container'),
html_root_dom: document.querySelector('html'),
innerHeight: window.innerHeight, html_root_dom: document.querySelector('html'),
prevScrollValue: 0, pageContainer_dom: document.querySelector('.page-container'),
defaultFontSize: 0, headerProgress_dom: document.querySelector('.header-progress'),
pageTop_dom: document.querySelector('.page-main-content-top'),
firstScreen_dom: document.querySelector('.first-screen-container'),
// print theme base info innerHeight: window.innerHeight,
printThemeInfo() { prevScrollValue: 0,
const themeInfo = `${KEEP.themeInfo.name} v${KEEP.themeInfo.version}`; defaultFontSize: 0,
console.log(`\n %c ${themeInfo} %c ${KEEP.themeInfo.repository} \n`, `color: #fadfa3; background: #333; padding: 5px 0;`, `background: #fadfa3; padding: 5px 0;`);
const footThemeInfoDom = document.querySelector('.footer .info-container .theme-info a.theme-version');
if (footThemeInfoDom) {
footThemeInfoDom.setAttribute('href', KEEP.themeInfo.repository);
footThemeInfoDom.innerHTML = themeInfo;
}
},
// Scroll Style Handle // print theme base info
styleHandleWhenScroll() { printThemeInfo() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; const themeInfo = `${KEEP.themeInfo.name} v${KEEP.themeInfo.version}`;
const scrollHeight = document.body.scrollHeight || document.documentElement.scrollHeight; console.log(`\n %c ${themeInfo} %c ${KEEP.themeInfo.repository} \n`, `color: #fadfa3; background: #333; padding: 5px 0;`, `background: #fadfa3; padding: 5px 0;`);
const clientHeight = window.innerHeight || document.documentElement.clientHeight; const footThemeInfoDom = document.querySelector('.footer .info-container .theme-info a.theme-version');
const percent = Math.round(scrollTop / (scrollHeight - clientHeight) * 100).toFixed(0); if (footThemeInfoDom) {
const ProgressPercent = (scrollTop / (scrollHeight - clientHeight) * 100).toFixed(3); footThemeInfoDom.setAttribute('href', KEEP.themeInfo.repository);
footThemeInfoDom.innerHTML = themeInfo;
}
},
if (this.headerProgress_dom) { // Scroll Style Handle
this.headerProgress_dom.style.visibility = percent === '0' ? 'hidden' : 'visible'; styleHandleWhenScroll() {
this.headerProgress_dom.style.width = `${ProgressPercent}%`; 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);
// hide header handle if (this.headerProgress_dom) {
if (scrollTop > this.prevScrollValue && scrollTop > this.innerHeight) { this.headerProgress_dom.style.visibility = percent === '0' ? 'hidden' : 'visible';
this.pageTop_dom.style.transform = 'translateY(-100%)'; this.headerProgress_dom.style.width = `${ProgressPercent}%`;
} else {
this.pageTop_dom.style.transform = 'translateY(0)';
}
this.prevScrollValue = scrollTop;
},
// register window scroll event
registerWindowScroll() {
window.addEventListener('scroll', () => {
// style handle when scroll
this.styleHandleWhenScroll();
// TOC scroll handle
if (KEEP.theme_config.toc.enable && KEEP.utils.hasOwnProperty('findActiveIndexByTOC')) {
KEEP.utils.findActiveIndexByTOC();
} }
// header shrink // hide header handle
KEEP.utils.headerShrink.headerShrink(); if (scrollTop > this.prevScrollValue && scrollTop > this.innerHeight) {
}); this.pageTop_dom.style.transform = 'translateY(-100%)';
}, } else {
this.pageTop_dom.style.transform = 'translateY(0)';
}
this.prevScrollValue = scrollTop;
},
// register window scroll event
registerWindowScroll() {
window.addEventListener('scroll', () => {
// style handle when scroll
this.styleHandleWhenScroll();
// TOC scroll handle
if (KEEP.theme_config.toc.enable && KEEP.utils.hasOwnProperty('findActiveIndexByTOC')) {
KEEP.utils.findActiveIndexByTOC();
}
// header shrink
KEEP.utils.headerShrink.headerShrink();
});
},
// toggle show tools list
toggleShowToolsList() {
document.querySelector('.tool-toggle-show').addEventListener('click', () => {
document.querySelector('.side-tools-list').classList.toggle('show');
});
},
// global font adjust
globalFontAdjust() {
const initFontSize = document.defaultView.getComputedStyle(document.body).fontSize;
const fs = Number(initFontSize.substring(0, initFontSize.length - 2));
const setFontSize = (defaultFontSize) => {
this.html_root_dom.style.fontSize = `${fs * (1 + defaultFontSize * 0.05)}px`;
}
document.querySelector('.tool-font-adjust-plus').addEventListener('click', () => {
if (this.defaultFontSize >= 5) return;
this.defaultFontSize++;
setFontSize(this.defaultFontSize);
});
document.querySelector('.tool-font-adjust-minus').addEventListener('click', () => {
if (this.defaultFontSize <= 0) return;
this.defaultFontSize--;
setFontSize(this.defaultFontSize);
});
},
// toggle content area width
contentAreaWidthAdjust() {
const toolExpandDom = document.querySelector('.tool-expand-width');
const headerContentDom = document.querySelector('.header-content');
const mainContentDom = document.querySelector('.main-content');
const iconDom = toolExpandDom.querySelector('i');
const defaultMaxWidth = KEEP.theme_config.style.content_max_width || '1000px';
const expandMaxWidth = '90%';
let headerMaxWidth = defaultMaxWidth;
let isExpand = false;
if (KEEP.theme_config.style.first_screen.enable === true) {
headerMaxWidth = parseInt(defaultMaxWidth) * 1.2 + 'px';
}
toolExpandDom.addEventListener('click', () => {
isExpand = !isExpand;
if (isExpand) {
iconDom.classList.remove('fa-arrows-alt-h');
iconDom.classList.add('fa-compress-arrows-alt');
headerContentDom.style.maxWidth = expandMaxWidth;
mainContentDom.style.maxWidth = expandMaxWidth;
} else {
iconDom.classList.remove('fa-compress-arrows-alt');
iconDom.classList.add('fa-arrows-alt-h');
headerContentDom.style.maxWidth = headerMaxWidth;
mainContentDom.style.maxWidth = defaultMaxWidth;
}
});
},
// go comment
goComment() {
this.goComment_dom = document.querySelector('.go-comment');
if (this.goComment_dom) {
this.goComment_dom.addEventListener('click', () => {
document.querySelector('#comment-anchor').scrollIntoView();
});
}
},
// get dom element height
getElementHeight(selectors) {
const dom = document.querySelector(selectors);
return dom ? dom.getBoundingClientRect().height : 0;
},
// init first screen height
initFirstScreenHeight() {
this.firstScreen_dom && (this.firstScreen_dom.style.height = this.innerHeight + 'px');
},
// init page height handle
initPageHeightHandle() {
if (this.firstScreen_dom) return;
const temp_h1 = this.getElementHeight('.header-progress');
const temp_h2 = this.getElementHeight('.page-main-content-top');
const temp_h3 = this.getElementHeight('.page-main-content-middle');
const temp_h4 = this.getElementHeight('.page-main-content-bottom');
const allDomHeight = temp_h1 + temp_h2 + temp_h3 + temp_h4;
const innerHeight = window.innerHeight;
const pb_dom = document.querySelector('.page-main-content-bottom');
if (allDomHeight < innerHeight) {
pb_dom.style.marginTop = (innerHeight - allDomHeight) + 'px';
}
},
// big image viewer
imageViewer() {
let isBigImage = false;
const showHandle = (dom, isShow) => {
document.body.style.overflow = isShow ? 'hidden' : 'auto';
dom.style.display = isShow ? 'flex' : 'none';
}
const imageViewerDom = document.querySelector('.image-viewer-container');
const targetImg = document.querySelector('.image-viewer-container img');
imageViewerDom && imageViewerDom.addEventListener('click', () => {
isBigImage = false;
showHandle(imageViewerDom, isBigImage);
});
const imgDoms = document.querySelectorAll('.markdown-body img');
if (imgDoms.length) {
imgDoms.forEach(img => {
img.addEventListener('click', () => {
isBigImage = true;
showHandle(imageViewerDom, isBigImage);
targetImg.setAttribute('src', img.getAttribute('src'))
});
});
} else {
this.pageContainer_dom.removeChild(imageViewerDom)
}
},
// set how long ago language
setHowLongAgoLanguage(p1, p2) {
return p2.replace(/%s/g, p1)
},
getHowLongAgo(timestamp) {
let l = KEEP.language_ago;
timestamp /= 1000;
const __Y = Math.floor(timestamp / (60 * 60 * 24 * 30) / 12)
const __M = Math.floor(timestamp / (60 * 60 * 24 * 30))
const __W = Math.floor(timestamp / (60 * 60 * 24) / 7)
const __d = Math.floor(timestamp / (60 * 60 * 24))
const __h = Math.floor(timestamp / (60 * 60) % 24)
const __m = Math.floor(timestamp / 60 % 60)
const __s = Math.floor(timestamp % 60)
if (__Y > 0) {
return this.setHowLongAgoLanguage(__Y, l.year)
} else if (__M > 0) {
return this.setHowLongAgoLanguage(__M, l.month)
} else if (__W > 0) {
return this.setHowLongAgoLanguage(__W, l.week)
} else if (__d > 0) {
return this.setHowLongAgoLanguage(__d, l.day)
} else if (__h > 0) {
return this.setHowLongAgoLanguage(__h, l.hour)
} else if (__m > 0) {
return this.setHowLongAgoLanguage(__m, l.minute)
} else if (__s > 0) {
return this.setHowLongAgoLanguage(__s, l.second)
}
},
setHowLongAgoInHome() {
const post = document.querySelectorAll('.home-article-meta-info .home-article-date');
post && post.forEach(v => {
v.innerHTML = this.getHowLongAgo(Date.now() - new Date(v.dataset.date).getTime())
})
}
}
// print theme info
KEEP.utils.printThemeInfo();
// init scroll
KEEP.utils.registerWindowScroll();
// toggle show tools list // toggle show tools list
toggleShowToolsList() { KEEP.utils.toggleShowToolsList();
document.querySelector('.tool-toggle-show').addEventListener('click', () => {
document.querySelector('.side-tools-list').classList.toggle('show');
});
},
// global font adjust // global font adjust
globalFontAdjust() { KEEP.utils.globalFontAdjust();
const initFontSize = document.defaultView.getComputedStyle(document.body).fontSize;
const fs = Number(initFontSize.substring(0, initFontSize.length - 2));
const setFontSize = (defaultFontSize) => { // adjust content area width
this.html_root_dom.style.fontSize = `${fs * (1 + defaultFontSize * 0.05)}px`; KEEP.utils.contentAreaWidthAdjust();
}
document.querySelector('.tool-font-adjust-plus').addEventListener('click', () => {
if (this.defaultFontSize >= 5) return;
this.defaultFontSize++;
setFontSize(this.defaultFontSize);
});
document.querySelector('.tool-font-adjust-minus').addEventListener('click', () => {
if (this.defaultFontSize <= 0) return;
this.defaultFontSize--;
setFontSize(this.defaultFontSize);
});
},
// toggle content area width
contentAreaWidthAdjust() {
const toolExpandDom = document.querySelector('.tool-expand-width');
const headerContentDom = document.querySelector('.header-content');
const mainContentDom = document.querySelector('.main-content');
const iconDom = toolExpandDom.querySelector('i');
const defaultMaxWidth = KEEP.theme_config.style.content_max_width || '1000px';
const expandMaxWidth = '90%';
let headerMaxWidth = defaultMaxWidth;
let isExpand = false;
if (KEEP.theme_config.style.first_screen.enable === true) {
headerMaxWidth = parseInt(defaultMaxWidth) * 1.2 + 'px';
}
toolExpandDom.addEventListener('click', () => {
isExpand = !isExpand;
if (isExpand) {
iconDom.classList.remove('fa-arrows-alt-h');
iconDom.classList.add('fa-compress-arrows-alt');
headerContentDom.style.maxWidth = expandMaxWidth;
mainContentDom.style.maxWidth = expandMaxWidth;
} else {
iconDom.classList.remove('fa-compress-arrows-alt');
iconDom.classList.add('fa-arrows-alt-h');
headerContentDom.style.maxWidth = headerMaxWidth;
mainContentDom.style.maxWidth = defaultMaxWidth;
}
});
},
// go comment // go comment
goComment() { KEEP.utils.goComment();
this.goComment_dom = document.querySelector('.go-comment');
if (this.goComment_dom) {
this.goComment_dom.addEventListener('click', () => {
document.querySelector('#comment-anchor').scrollIntoView();
});
}
},
// get dom element height
getElementHeight(selectors) {
const dom = document.querySelector(selectors);
return dom ? dom.getBoundingClientRect().height : 0;
},
// init first screen height
initFirstScreenHeight() {
this.firstScreen_dom && (this.firstScreen_dom.style.height = this.innerHeight + 'px');
},
// init page height handle // init page height handle
initPageHeightHandle() { KEEP.utils.initPageHeightHandle();
if (this.firstScreen_dom) return;
const temp_h1 = this.getElementHeight('.header-progress'); // init first screen height
const temp_h2 = this.getElementHeight('.page-main-content-top'); KEEP.utils.initFirstScreenHeight();
const temp_h3 = this.getElementHeight('.page-main-content-middle');
const temp_h4 = this.getElementHeight('.page-main-content-bottom');
const allDomHeight = temp_h1 + temp_h2 + temp_h3 + temp_h4;
const innerHeight = window.innerHeight;
const pb_dom = document.querySelector('.page-main-content-bottom');
if (allDomHeight < innerHeight) {
pb_dom.style.marginTop = (innerHeight - allDomHeight) + 'px';
}
},
// big image viewer // big image viewer handle
imageViewer() { KEEP.utils.imageViewer();
let isBigImage = false;
const showHandle = (dom, isShow) => { // set how long age in home article block
document.body.style.overflow = isShow ? 'hidden' : 'auto'; KEEP.utils.setHowLongAgoInHome();
dom.style.display = isShow ? 'flex' : 'none';
}
const imageViewerDom = document.querySelector('.image-viewer-container');
const targetImg = document.querySelector('.image-viewer-container img');
imageViewerDom && imageViewerDom.addEventListener('click', () => {
isBigImage = false;
showHandle(imageViewerDom, isBigImage);
});
const imgDoms = document.querySelectorAll('.markdown-body img');
imgDoms && imgDoms.forEach(img => {
img.addEventListener('click', () => {
isBigImage = true;
showHandle(imageViewerDom, isBigImage);
targetImg.setAttribute('src', img.getAttribute('src'))
});
});
},
// set how long ago language
setHowLongAgoLanguage(p1, p2) {
return p2.replace(/%s/g, p1)
},
getHowLongAgo(timestamp) {
let l = KEEP.language
timestamp /= 1000;
const __Y = Math.floor(timestamp / (60 * 60 * 24 * 30) / 12)
const __M = Math.floor(timestamp / (60 * 60 * 24 * 30))
const __W = Math.floor(timestamp / (60 * 60 * 24) / 7)
const __d = Math.floor(timestamp / (60 * 60 * 24))
const __h = Math.floor(timestamp / (60 * 60) % 24)
const __m = Math.floor(timestamp / 60 % 60)
const __s = Math.floor(timestamp % 60)
if (__Y > 0) {
return this.setHowLongAgoLanguage(__Y, l.ago.year)
} else if (__M > 0) {
return this.setHowLongAgoLanguage(__M, l.ago.month)
} else if (__W > 0) {
return this.setHowLongAgoLanguage(__W, l.ago.week)
} else if (__d > 0) {
return this.setHowLongAgoLanguage(__d, l.ago.day)
} else if (__h > 0) {
return this.setHowLongAgoLanguage(__h, l.ago.hour)
} else if (__m > 0) {
return this.setHowLongAgoLanguage(__m, l.ago.minute)
} else if (__s > 0) {
return this.setHowLongAgoLanguage(__s, l.ago.second)
}
},
setHowLongAgoInHome() {
const post = document.querySelectorAll('.home-article-meta-info .home-article-date');
post && post.forEach(v => {
v.innerHTML = this.getHowLongAgo(Date.now() - new Date(v.dataset.date).getTime())
})
}
} }