From 0abad9b9a82920bd8a44e4cb344d2784ef675a70 Mon Sep 17 00:00:00 2001 From: XPoet Date: Wed, 30 Dec 2020 18:11:46 +0800 Subject: [PATCH] refactor: enhance the user experience with PJAX --- _config.yml | 23 +- layout/_partial/comment/gitalk.ejs | 46 +-- layout/_partial/comment/valine.ejs | 73 +++-- layout/_partial/footer.ejs | 4 +- layout/_partial/pjax/pjax.ejs | 21 ++ layout/_partial/scripts.ejs | 27 +- layout/index.ejs | 2 +- layout/layout.ejs | 2 +- scripts/helpers/export-config.js | 11 +- source/js/back2top.js | 6 +- source/js/code-copy.js | 25 +- source/js/dark-light-toggle.js | 8 +- source/js/header-shrink.js | 4 +- source/js/left-side-toggle.js | 11 +- source/js/libs/pjax.min.js | 1 + source/js/local-search.js | 9 +- source/js/main.js | 36 +-- source/js/toc.js | 26 +- source/js/utils.js | 471 ++++++++++++++++------------- 19 files changed, 444 insertions(+), 362 deletions(-) create mode 100644 layout/_partial/pjax/pjax.ejs create mode 100644 source/js/libs/pjax.min.js diff --git a/_config.yml b/_config.yml index 0e4c051..9237cff 100644 --- a/_config.yml +++ b/_config.yml @@ -49,7 +49,9 @@ social_contact: links: github: # your GitHub URL weixin: # your WeChat QR-Code URL + qq: # your QQ QR-Code URL weibo: # your WeiBo URL + zhihu: # your ZhiHu URL twitter: # your twitter URL facebook: # your facebook URL email: # your email @@ -193,6 +195,20 @@ copyright_info: enable: true +# --------------------------------------------------------------------------------------- +# CDN +# --------------------------------------------------------------------------------------- +cdn: + enable: false + + +# --------------------------------------------------------------------------------------- +# PJAX +# --------------------------------------------------------------------------------------- +pjax: + enable: false + + # --------------------------------------------------------------------------------------- # Footer settings # --------------------------------------------------------------------------------------- @@ -200,13 +216,6 @@ footer: since: 2020 -# --------------------------------------------------------------------------------------- -# CDN -# --------------------------------------------------------------------------------------- -cdn: - enable: true - - # --------------------------------------------------------------------------------------- # Keep version (Please don't modify) # --------------------------------------------------------------------------------------- diff --git a/layout/_partial/comment/gitalk.ejs b/layout/_partial/comment/gitalk.ejs index 048922d..d3136c8 100644 --- a/layout/_partial/comment/gitalk.ejs +++ b/layout/_partial/comment/gitalk.ejs @@ -5,24 +5,36 @@ && theme.comment.gitalk.github_id && theme.comment.gitalk.repository ) { %> - +
- <% } %> diff --git a/layout/_partial/comment/valine.ejs b/layout/_partial/comment/valine.ejs index d12b6f4..b8f18bb 100755 --- a/layout/_partial/comment/valine.ejs +++ b/layout/_partial/comment/valine.ejs @@ -4,42 +4,55 @@ && theme.comment.valine.appkey ) { %>
- +
-
<% } %> diff --git a/layout/_partial/footer.ejs b/layout/_partial/footer.ejs index dc478c4..5483ecf 100644 --- a/layout/_partial/footer.ejs +++ b/layout/_partial/footer.ejs @@ -7,8 +7,8 @@ <% } %> <%= date(new Date(), 'YYYY') %> <%= theme.base_info.author || config.author %> - <% if (theme.website_count.busuanzi_count.enable) { %> - + <% if (theme.website_count.busuanzi_count.enable === true) { %> +
<% if (theme.website_count.busuanzi_count.site_uv) { %> diff --git a/layout/_partial/pjax/pjax.ejs b/layout/_partial/pjax/pjax.ejs new file mode 100644 index 0000000..11a9e59 --- /dev/null +++ b/layout/_partial/pjax/pjax.ejs @@ -0,0 +1,21 @@ +<%- __js('js/libs/pjax.min.js') %> + diff --git a/layout/_partial/scripts.ejs b/layout/_partial/scripts.ejs index eb63ec2..f519a39 100644 --- a/layout/_partial/scripts.ejs +++ b/layout/_partial/scripts.ejs @@ -10,15 +10,20 @@ <%- __js('js/local-search.js') %> <% } %> -<% if (is_post()) { %> - - <%- __js('js/left-side-toggle.js') %> - - <% if (theme.code_copy.enable ) { %> - <%- __js('js/code-copy.js') %> - <% } %> - - <% if (theme.toc.enable) { %> - <%- __js(['js/libs/anime.min.js', 'js/toc.js']) %> - <% } %> +<% if (theme.code_copy.enable) { %> + <%- __js('js/code-copy.js') %> +<% } %> + +
+ <% if (theme.toc.enable && is_post()) { %> + <%- __js([ + 'js/left-side-toggle.js', + 'js/libs/anime.min.js', + 'js/toc.js' + ]) %> + <% } %> +
+ +<% if (theme.pjax.enable === true) { %> + <%- partial('pjax/pjax') %> <% } %> diff --git a/layout/index.ejs b/layout/index.ejs index da62077..907e0ab 100644 --- a/layout/index.ejs +++ b/layout/index.ejs @@ -1 +1 @@ -<%- partial('page') %> \ No newline at end of file +<%- partial('page') %> diff --git a/layout/layout.ejs b/layout/layout.ejs index 0a626dc..c4d7925 100644 --- a/layout/layout.ejs +++ b/layout/layout.ejs @@ -5,4 +5,4 @@ <%- body %> <%- partial('_partial/scripts') %> - \ No newline at end of file + diff --git a/scripts/helpers/export-config.js b/scripts/helpers/export-config.js index 9fd967b..9f36161 100644 --- a/scripts/helpers/export-config.js +++ b/scripts/helpers/export-config.js @@ -12,9 +12,9 @@ const yaml = require('js-yaml'); */ 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'); let file = fs.readdirSync(languageDir).find(v => v === `${config.language}.yml`); file = languageDir + '/' + (file ? file : 'en.yml'); @@ -24,14 +24,14 @@ hexo.extend.helper.register('export_config', function () { } catch (e) { console.log(e); } - // --------------------------------- - + // ----------------------------------------------- let hexo_config = { hostname: url.parse(config.url).hostname || config.url, root: config.root }; + if (config.search) { hexo_config.path = config.search.path; } @@ -41,6 +41,7 @@ hexo.extend.helper.register('export_config', function () { style: theme.style, local_search: theme.local_search, side_tools: theme.side_tools, + pjax: theme.pjax, version: theme.version, } @@ -48,6 +49,6 @@ hexo.extend.helper.register('export_config', function () { let KEEP = window.KEEP || {}; KEEP.hexo_config = ${JSON.stringify(hexo_config)}; KEEP.theme_config = ${JSON.stringify(theme_config)}; - KEEP.language = ${JSON.stringify(languageContent)}; + KEEP.language_ago = ${JSON.stringify(languageContent['ago'])}; `; }); diff --git a/source/js/back2top.js b/source/js/back2top.js index 87a13ce..e93be65 100644 --- a/source/js/back2top.js +++ b/source/js/back2top.js @@ -1,4 +1,5 @@ -window.addEventListener('DOMContentLoaded', () => { +KEEP.initBack2Top = () => { + KEEP.utils = { ...KEEP.utils, @@ -49,4 +50,5 @@ window.addEventListener('DOMContentLoaded', () => { KEEP.utils.initBack2Top(); KEEP.utils.initBack2Bottom(); -}); + +} diff --git a/source/js/code-copy.js b/source/js/code-copy.js index 0c7a19d..9f528b4 100644 --- a/source/js/code-copy.js +++ b/source/js/code-copy.js @@ -1,20 +1,21 @@ -HTMLElement.prototype.wrap = function (wrapper) { - this.parentNode.insertBefore(wrapper, this); - this.parentNode.removeChild(this); - wrapper.appendChild(this); -}; +KEEP.initCodeCopy = () => { + + HTMLElement.prototype.wrap = function (wrapper) { + this.parentNode.insertBefore(wrapper, this); + this.parentNode.removeChild(this); + wrapper.appendChild(this); + }; -window.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('figure.highlight').forEach(element => { const box = document.createElement('div'); element.wrap(box); box.classList.add('highlight-container'); box.insertAdjacentHTML('beforeend', '
'); - var button = element.parentNode.querySelector('.copy-btn'); + const button = element.parentNode.querySelector('.copy-btn'); button.addEventListener('click', event => { - var target = event.currentTarget; - var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); - var ta = document.createElement('textarea'); + const target = event.currentTarget; + const code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); + const ta = document.createElement('textarea'); ta.style.top = window.scrollY + 'px'; // Prevent page scrolling ta.style.position = 'absolute'; ta.style.opacity = '0'; @@ -26,7 +27,7 @@ window.addEventListener('DOMContentLoaded', () => { ta.select(); ta.setSelectionRange(0, code.length); ta.readOnly = false; - var result = document.execCommand('copy'); + const result = document.execCommand('copy'); target.querySelector('i').className = result ? 'fas fa-check' : 'fas fa-times'; ta.blur(); // For iOS target.blur(); @@ -42,4 +43,4 @@ window.addEventListener('DOMContentLoaded', () => { }, 300); }); }); -}); +} diff --git a/source/js/dark-light-toggle.js b/source/js/dark-light-toggle.js index 63f4eee..8b6749e 100644 --- a/source/js/dark-light-toggle.js +++ b/source/js/dark-light-toggle.js @@ -1,4 +1,5 @@ -window.addEventListener('DOMContentLoaded', () => { +KEEP.initModeToggle = () => { + KEEP.utils.modeToggle = { localStorageKey: 'KEEP', @@ -56,7 +57,7 @@ window.addEventListener('DOMContentLoaded', () => { }, initModeToggleButton() { - this.modeToggleButton_dom.addEventListener('click', () => { + this.modeToggleButton_dom.addEventListener('click', () => { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { this.setItemUtil('light-mode', 'dark'); } else { @@ -68,4 +69,5 @@ window.addEventListener('DOMContentLoaded', () => { KEEP.utils.modeToggle.initModeStatus(); KEEP.utils.modeToggle.initModeToggleButton(); -}); + +}; diff --git a/source/js/header-shrink.js b/source/js/header-shrink.js index 65e54e0..f6f61e0 100644 --- a/source/js/header-shrink.js +++ b/source/js/header-shrink.js @@ -1,4 +1,4 @@ -window.addEventListener('DOMContentLoaded', () => { +KEEP.initHeaderShrink = () => { KEEP.utils.headerShrink = { pageTemplateDom: document.querySelector('.page-main-content'), @@ -45,4 +45,4 @@ window.addEventListener('DOMContentLoaded', () => { KEEP.utils.headerShrink.init(); KEEP.utils.headerShrink.initMenuBarButton(); KEEP.utils.headerShrink.initWindowMask(); -}); +} diff --git a/source/js/left-side-toggle.js b/source/js/left-side-toggle.js index bbf719a..80770b0 100644 --- a/source/js/left-side-toggle.js +++ b/source/js/left-side-toggle.js @@ -1,5 +1,4 @@ -window.addEventListener('DOMContentLoaded', () => { - +function initLeftSideToggle() { KEEP.utils.leftSideToggle = { init() { @@ -34,8 +33,12 @@ window.addEventListener('DOMContentLoaded', () => { this.leftAsideDom.style.left = isOpen ? '0' : `-${pageAsideWidth}`; }, } - KEEP.utils.leftSideToggle.init(); KEEP.utils.leftSideToggle.initToggleBarButton(); +} -}); +if (KEEP.theme_config.pjax && KEEP.utils) { + initLeftSideToggle(); +} else { + window.addEventListener('DOMContentLoaded', initLeftSideToggle); +} diff --git a/source/js/libs/pjax.min.js b/source/js/libs/pjax.min.js new file mode 100644 index 0000000..0666821 --- /dev/null +++ b/source/js/libs/pjax.min.js @@ -0,0 +1 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Pjax=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i]+>/gi;var htmlAttribsRegex=/\s?[a-z:]+(?:=['"][^'">]+['"])*/gi;var matches=html.match(htmlRegex);if(matches&&matches.length){matches=matches[0].match(htmlAttribsRegex);if(matches.length){matches.shift();matches.forEach(function(htmlAttrib){var attr=htmlAttrib.trim().split("=");if(attr.length===1){tmpEl.documentElement.setAttribute(attr[0],true)}else{tmpEl.documentElement.setAttribute(attr[0],attr[1].slice(1,-1))}})}}tmpEl.documentElement.innerHTML=html;this.log("load content",tmpEl.documentElement.attributes,tmpEl.documentElement.innerHTML.length);if(document.activeElement&&contains(document,this.options.selectors,document.activeElement)){try{document.activeElement.blur()}catch(e){}}this.switchSelectors(this.options.selectors,tmpEl,document,options)},abortRequest:require("./lib/abort-request"),doRequest:require("./lib/send-request"),handleResponse:require("./lib/proto/handle-response"),loadUrl:function(href,options){options=typeof options==="object"?extend({},this.options,options):clone(this.options);this.log("load href",href,options);this.abortRequest(this.request);trigger(document,"pjax:send",options);this.request=this.doRequest(href,options,this.handleResponse.bind(this))},executeScripts:function(elements){elements.forEach(function(element){var code=element.text||element.textContent||element.innerHTML||"";var script=document.createElement("script");if(element.id){script.id=element.id}if(element.className){script.className=element.className}if(element.type){script.type=element.type}if(element.src){script.src=element.src;script.async=false}if(element.dataset.pjax!==undefined){script.dataset.pjax=""}if(code!==""){script.appendChild(document.createTextNode(code))}element.parentNode.replaceChild(script,element)})},afterAllSwitches:function(){var autofocusEl=Array.prototype.slice.call(document.querySelectorAll("[autofocus]")).pop();if(autofocusEl&&document.activeElement!==autofocusEl){autofocusEl.focus()}this.options.selectors.forEach(function(selector){forEachEls(document.querySelectorAll(selector),function(el){if(el===0);})});var state=this.state;if(state.options.history){if(!window.history.state){this.lastUid=this.maxUid=newUid();window.history.replaceState({url:window.location.href,title:document.title,uid:this.maxUid,scrollPos:[0,0]},document.title)}this.lastUid=this.maxUid=newUid();window.history.pushState({url:state.href,title:state.options.title,uid:this.maxUid,scrollPos:[0,0]},state.options.title,state.href)}this.forEachSelectors(function(el){this.parseDOM(el)},this);trigger(document,"pjax:complete pjax:success",state.options);if(typeof state.options.analytics==="function"){state.options.analytics()}if(state.options.history){var a=document.createElement("a");a.href=this.state.href;if(a.hash){var name=a.hash.slice(1);name=decodeURIComponent(name);var curtop=0;var target=document.getElementById(name)||document.getElementsByName(name)[0];if(target){if(target.offsetParent){do{curtop+=target.offsetTop;target=target.offsetParent}while(target)}}window.scrollTo(0,curtop)}else if(state.options.scrollTo!==false){if(state.options.scrollTo.length>1){window.scrollTo(state.options.scrollTo[0],state.options.scrollTo[1])}else{window.scrollTo(0,state.options.scrollTo)}}}else if(state.options.scrollRestoration&&state.options.scrollPos){window.scrollTo(state.options.scrollPos[0],state.options.scrollPos[1])}this.state={numPendingSwitches:0,href:null,options:null}}};Pjax.isSupported=require("./lib/is-supported");if(Pjax.isSupported()){module.exports=Pjax}else{var stupidPjax=noop;for(var key in Pjax.prototype){if(Pjax.prototype.hasOwnProperty(key)&&typeof Pjax.prototype[key]==="function"){stupidPjax[key]=noop}}module.exports=stupidPjax}},{"./lib/abort-request":2,"./lib/events/on":3,"./lib/events/trigger":4,"./lib/foreach-els":5,"./lib/foreach-selectors":6,"./lib/is-supported":7,"./lib/parse-options":8,"./lib/proto/attach-form":9,"./lib/proto/attach-link":10,"./lib/proto/handle-response":11,"./lib/proto/log":12,"./lib/proto/parse-element":13,"./lib/send-request":14,"./lib/switches":16,"./lib/switches-selectors":15,"./lib/uniqueid":17,"./lib/util/clone":18,"./lib/util/contains":19,"./lib/util/extend":20,"./lib/util/noop":21}],2:[function(require,module,exports){var noop=require("./util/noop");module.exports=function(request){if(request&&request.readyState<4){request.onreadystatechange=noop;request.abort()}}},{"./util/noop":21}],3:[function(require,module,exports){var forEachEls=require("../foreach-els");module.exports=function(els,events,listener,useCapture){events=typeof events==="string"?events.split(" "):events;events.forEach(function(e){forEachEls(els,function(el){el.addEventListener(e,listener,useCapture)})})}},{"../foreach-els":5}],4:[function(require,module,exports){var forEachEls=require("../foreach-els");module.exports=function(els,events,opts){events=typeof events==="string"?events.split(" "):events;events.forEach(function(e){var event;event=document.createEvent("HTMLEvents");event.initEvent(e,true,true);event.eventName=e;if(opts){Object.keys(opts).forEach(function(key){event[key]=opts[key]})}forEachEls(els,function(el){var domFix=false;if(!el.parentNode&&el!==document&&el!==window){domFix=true;document.body.appendChild(el)}el.dispatchEvent(event);if(domFix){el.parentNode.removeChild(el)}})})}},{"../foreach-els":5}],5:[function(require,module,exports){module.exports=function(els,fn,context){if(els instanceof HTMLCollection||els instanceof NodeList||els instanceof Array){return Array.prototype.forEach.call(els,fn,context)}return fn.call(context,els)}},{}],6:[function(require,module,exports){var forEachEls=require("./foreach-els");module.exports=function(selectors,cb,context,DOMcontext){DOMcontext=DOMcontext||document;selectors.forEach(function(selector){forEachEls(DOMcontext.querySelectorAll(selector),cb,context)})}},{"./foreach-els":5}],7:[function(require,module,exports){module.exports=function(){return window.history&&window.history.pushState&&window.history.replaceState&&!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/)}},{}],8:[function(require,module,exports){var defaultSwitches=require("./switches");module.exports=function(options){options=options||{};options.elements=options.elements||"a[href], form[action]";options.selectors=options.selectors||["title",".js-Pjax"];options.switches=options.switches||{};options.switchesOptions=options.switchesOptions||{};options.history=typeof options.history==="undefined"?true:options.history;options.analytics=typeof options.analytics==="function"||options.analytics===false?options.analytics:defaultAnalytics;options.scrollTo=typeof options.scrollTo==="undefined"?0:options.scrollTo;options.scrollRestoration=typeof options.scrollRestoration!=="undefined"?options.scrollRestoration:true;options.cacheBust=typeof options.cacheBust==="undefined"?true:options.cacheBust;options.debug=options.debug||false;options.timeout=options.timeout||0;options.currentUrlFullReload=typeof options.currentUrlFullReload==="undefined"?false:options.currentUrlFullReload;if(!options.switches.head){options.switches.head=defaultSwitches.switchElementsAlt}if(!options.switches.body){options.switches.body=defaultSwitches.switchElementsAlt}return options};function defaultAnalytics(){if(window._gaq){_gaq.push(["_trackPageview"])}if(window.ga){ga("send","pageview",{page:location.pathname,title:document.title})}}},{"./switches":16}],9:[function(require,module,exports){var on=require("../events/on");var clone=require("../util/clone");var attrState="data-pjax-state";var formAction=function(el,event){if(isDefaultPrevented(event)){return}var options=clone(this.options);options.requestOptions={requestUrl:el.getAttribute("action")||window.location.href,requestMethod:el.getAttribute("method")||"GET"};var virtLinkElement=document.createElement("a");virtLinkElement.setAttribute("href",options.requestOptions.requestUrl);var attrValue=checkIfShouldAbort(virtLinkElement,options);if(attrValue){el.setAttribute(attrState,attrValue);return}event.preventDefault();if(el.enctype==="multipart/form-data"){options.requestOptions.formData=new FormData(el)}else{options.requestOptions.requestParams=parseFormElements(el)}el.setAttribute(attrState,"submit");options.triggerElement=el;this.loadUrl(virtLinkElement.href,options)};function parseFormElements(el){var requestParams=[];var formElements=el.elements;for(var i=0;i1||event.metaKey||event.ctrlKey||event.shiftKey||event.altKey){return"modifier"}if(el.protocol!==window.location.protocol||el.host!==window.location.host){return"external"}if(el.hash&&el.href.replace(el.hash,"")===window.location.href.replace(location.hash,"")){return"anchor"}if(el.href===window.location.href.split("#")[0]+"#"){return"anchor-empty"}}var isDefaultPrevented=function(event){return event.defaultPrevented||event.returnValue===false};module.exports=function(el){var that=this;el.setAttribute(attrState,"");on(el,"click",function(event){linkAction.call(that,el,event)});on(el,"keyup",function(event){if(event.keyCode===13){linkAction.call(that,el,event)}}.bind(this))}},{"../events/on":3,"../util/clone":18}],11:[function(require,module,exports){var clone=require("../util/clone");var newUid=require("../uniqueid");var trigger=require("../events/trigger");module.exports=function(responseText,request,href,options){options=clone(options||this.options);options.request=request;if(responseText===false){trigger(document,"pjax:complete pjax:error",options);return}var currentState=window.history.state||{};window.history.replaceState({url:currentState.url||window.location.href,title:currentState.title||document.title,uid:currentState.uid||newUid(),scrollPos:[document.documentElement.scrollLeft||document.body.scrollLeft,document.documentElement.scrollTop||document.body.scrollTop]},document.title,window.location.href);var oldHref=href;if(request.responseURL){if(href!==request.responseURL){href=request.responseURL}}else if(request.getResponseHeader("X-PJAX-URL")){href=request.getResponseHeader("X-PJAX-URL")}else if(request.getResponseHeader("X-XHR-Redirected-To")){href=request.getResponseHeader("X-XHR-Redirected-To")}var a=document.createElement("a");a.href=oldHref;var oldHash=a.hash;a.href=href;if(oldHash&&!a.hash){a.hash=oldHash;href=a.href}this.state.href=href;this.state.options=options;try{this.loadContent(responseText,options)}catch(e){trigger(document,"pjax:error",options);if(!this.options.debug){if(console&&console.error){console.error("Pjax switch fail: ",e)}return this.latestChance(href)}else{throw e}}}},{"../events/trigger":4,"../uniqueid":17,"../util/clone":18}],12:[function(require,module,exports){module.exports=function(){if(this.options.debug&&console){if(typeof console.log==="function"){console.log.apply(console,arguments)}else if(console.log){console.log(arguments)}}}},{}],13:[function(require,module,exports){var attrState="data-pjax-state";module.exports=function(el){switch(el.tagName.toLowerCase()){case"a":if(!el.hasAttribute(attrState)){this.attachLink(el)}break;case"form":if(!el.hasAttribute(attrState)){this.attachForm(el)}break;default:throw"Pjax can only be applied on or
submit"}}},{}],14:[function(require,module,exports){var updateQueryString=require("./util/update-query-string");module.exports=function(location,options,callback){options=options||{};var queryString;var requestOptions=options.requestOptions||{};var requestMethod=(requestOptions.requestMethod||"GET").toUpperCase();var requestParams=requestOptions.requestParams||null;var formData=requestOptions.formData||null;var requestPayload=null;var request=new XMLHttpRequest;var timeout=options.timeout||0;request.onreadystatechange=function(){if(request.readyState===4){if(request.status===200){callback(request.responseText,request,location,options)}else if(request.status!==0){callback(null,request,location,options)}}};request.onerror=function(e){console.log(e);callback(null,request,location,options)};request.ontimeout=function(){callback(null,request,location,options)};if(requestParams&&requestParams.length){queryString=requestParams.map(function(param){return param.name+"="+param.value}).join("&");switch(requestMethod){case"GET":location=location.split("?")[0];location+="?"+queryString;break;case"POST":requestPayload=queryString;break}}else if(formData){requestPayload=formData}if(options.cacheBust){location=updateQueryString(location,"t",Date.now())}request.open(requestMethod,location,true);request.timeout=timeout;request.setRequestHeader("X-Requested-With","XMLHttpRequest");request.setRequestHeader("X-PJAX","true");request.setRequestHeader("X-PJAX-Selectors",JSON.stringify(options.selectors));if(requestPayload&&requestMethod==="POST"&&!formData){request.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}request.send(requestPayload);return request}},{"./util/update-query-string":22}],15:[function(require,module,exports){var forEachEls=require("./foreach-els");var defaultSwitches=require("./switches");module.exports=function(switches,switchesOptions,selectors,fromEl,toEl,options){var switchesQueue=[];selectors.forEach(function(selector){var newEls=fromEl.querySelectorAll(selector);var oldEls=toEl.querySelectorAll(selector);if(this.log){this.log("Pjax switch",selector,newEls,oldEls)}if(newEls.length!==oldEls.length){throw"DOM doesn’t look the same on new loaded page: ’"+selector+"’ - new "+newEls.length+", old "+oldEls.length}forEachEls(newEls,function(newEl,i){var oldEl=oldEls[i];if(this.log){this.log("newEl",newEl,"oldEl",oldEl)}var callback=switches[selector]?switches[selector].bind(this,oldEl,newEl,options,switchesOptions[selector]):defaultSwitches.outerHTML.bind(this,oldEl,newEl,options);switchesQueue.push(callback)},this)},this);this.state.numPendingSwitches=switchesQueue.length;switchesQueue.forEach(function(queuedSwitch){queuedSwitch()})}},{"./foreach-els":5,"./switches":16}],16:[function(require,module,exports){var on=require("./events/on");module.exports={outerHTML:function(oldEl,newEl){oldEl.outerHTML=newEl.outerHTML;this.onSwitch()},innerHTML:function(oldEl,newEl){oldEl.innerHTML=newEl.innerHTML;if(newEl.className===""){oldEl.removeAttribute("class")}else{oldEl.className=newEl.className}this.onSwitch()},switchElementsAlt:function(oldEl,newEl){oldEl.innerHTML=newEl.innerHTML;if(newEl.hasAttributes()){var attrs=newEl.attributes;for(var i=0;i'; + const noResultDom = document.querySelector('#no-result'); + noResultDom && (noResultDom.innerHTML = ''); }); }; @@ -301,4 +301,5 @@ window.addEventListener('DOMContentLoaded', () => { onPopupClose(); } }); -}); + +} diff --git a/source/js/main.js b/source/js/main.js index 44f879f..1d7df8f 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -7,32 +7,14 @@ window.addEventListener('DOMContentLoaded', () => { repository: 'https://github.com/XPoet/hexo-theme-keep' } - // print theme info - KEEP.utils.printThemeInfo(); + KEEP.refresh = () => { + KEEP.initUtils(); + KEEP.initHeaderShrink(); + KEEP.initModeToggle(); + KEEP.initLocalSearch(); + KEEP.initBack2Top(); + KEEP.initCodeCopy(); + } - // init scroll - 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(); + KEEP.refresh(); }); diff --git a/source/js/toc.js b/source/js/toc.js index 23b6024..bd4357b 100644 --- a/source/js/toc.js +++ b/source/js/toc.js @@ -1,11 +1,7 @@ -window.addEventListener('DOMContentLoaded', () => { - +function initTOC() { 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) { - KEEP.utils = { ...KEEP.utils, @@ -74,21 +70,15 @@ window.addEventListener('DOMContentLoaded', () => { KEEP.utils.leftSideToggle.changePageLayoutWhenOpenToggle(KEEP.utils.leftSideToggle.isOpenPageAside); } } - KEEP.utils.showPageAsideWhenHasTOC(); KEEP.utils.registerSidebarTOC(); - - } else { - - 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'; - } + KEEP.utils.pageContainer_dom.removeChild(document.querySelector('.page-aside')); } -}); +} +if (KEEP.theme_config.pjax && KEEP.utils) { + initTOC(); +} else { + window.addEventListener('DOMContentLoaded', initTOC); +} diff --git a/source/js/utils.js b/source/js/utils.js index 1629ede..8452b1a 100644 --- a/source/js/utils.js +++ b/source/js/utils.js @@ -1,238 +1,277 @@ -KEEP.utils = { +KEEP.initUtils = () => { - headerProgress_dom: document.querySelector('.header-progress'), - pageTop_dom: document.querySelector('.page-main-content-top'), - firstScreen_dom: document.querySelector('.first-screen-container'), - html_root_dom: document.querySelector('html'), + KEEP.utils = { - innerHeight: window.innerHeight, - prevScrollValue: 0, - defaultFontSize: 0, + html_root_dom: document.querySelector('html'), + pageContainer_dom: document.querySelector('.page-container'), + 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 - printThemeInfo() { - const themeInfo = `${KEEP.themeInfo.name} v${KEEP.themeInfo.version}`; - 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; - } - }, + innerHeight: window.innerHeight, + prevScrollValue: 0, + defaultFontSize: 0, - // Scroll Style Handle - 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); + // print theme base info + printThemeInfo() { + const themeInfo = `${KEEP.themeInfo.name} v${KEEP.themeInfo.version}`; + 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; + } + }, - if (this.headerProgress_dom) { - this.headerProgress_dom.style.visibility = percent === '0' ? 'hidden' : 'visible'; - this.headerProgress_dom.style.width = `${ProgressPercent}%`; - } + // Scroll Style Handle + 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); - // hide header handle - 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(); + if (this.headerProgress_dom) { + this.headerProgress_dom.style.visibility = percent === '0' ? 'hidden' : 'visible'; + this.headerProgress_dom.style.width = `${ProgressPercent}%`; } - // header shrink - KEEP.utils.headerShrink.headerShrink(); - }); - }, + // hide header handle + 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 - toggleShowToolsList() { - document.querySelector('.tool-toggle-show').addEventListener('click', () => { - document.querySelector('.side-tools-list').classList.toggle('show'); - }); - }, + KEEP.utils.toggleShowToolsList(); // global font adjust - globalFontAdjust() { - const initFontSize = document.defaultView.getComputedStyle(document.body).fontSize; - const fs = Number(initFontSize.substring(0, initFontSize.length - 2)); + KEEP.utils.globalFontAdjust(); - 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; - } - - }); - }, + // adjust content area width + KEEP.utils.contentAreaWidthAdjust(); // 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'); - }, + KEEP.utils.goComment(); // init page height handle - initPageHeightHandle() { - if (this.firstScreen_dom) return; + KEEP.utils.initPageHeightHandle(); - 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'; - } - }, + // init first screen height + KEEP.utils.initFirstScreenHeight(); - // big image viewer - imageViewer() { - let isBigImage = false; + // big image viewer handle + KEEP.utils.imageViewer(); - const showHandle = (dom, isShow) => { - document.body.style.overflow = isShow ? 'hidden' : 'auto'; - dom.style.display = isShow ? 'flex' : 'none'; - } + // set how long age in home article block + KEEP.utils.setHowLongAgoInHome(); - 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()) - }) - } }