From 305ba8a9d4d4ff0d7e5f76b6165d4df65c2a7724 Mon Sep 17 00:00:00 2001 From: liuzhihang Date: Thu, 27 Oct 2022 23:24:22 +0800 Subject: [PATCH] =?UTF-8?q?utils=20js=20=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.yaml | 4 +- templates/assets/js/main.btf.js | 797 ++++++++++++++++++++++++++++++++ templates/assets/js/main.js | 233 +++++----- templates/assets/js/man.heo.js | 327 +++++++++++++ templates/assets/js/utils.js | 269 +++++++---- 5 files changed, 1400 insertions(+), 230 deletions(-) create mode 100644 templates/assets/js/main.btf.js create mode 100644 templates/assets/js/man.heo.js diff --git a/settings.yaml b/settings.yaml index 9baf1197..d4a1a1d2 100644 --- a/settings.yaml +++ b/settings.yaml @@ -78,7 +78,7 @@ spec: - $formkit: select name: cols label: 文章列表布局 - value: col1 + value: col2 options: - label: 单列 value: col1 @@ -88,7 +88,7 @@ spec: value: col3 - label: 四列 value: col4 - help: "选择单列时,文章卡片的图片将位于左侧" + help: "建议单列时,将图片放在左右" - $formkit: select name: post_location label: 封面位置 diff --git a/templates/assets/js/main.btf.js b/templates/assets/js/main.btf.js new file mode 100644 index 00000000..ab868b47 --- /dev/null +++ b/templates/assets/js/main.btf.js @@ -0,0 +1,797 @@ +document.addEventListener('DOMContentLoaded', function () { + let blogNameWidth, menusWidth, searchWidth, $nav + let mobileSidebarOpen = false + + const adjustMenu = (init) => { + if (init) { + blogNameWidth = document.getElementById('site-name').offsetWidth + const $menusEle = document.querySelectorAll('#menus .menus_item') + menusWidth = 0 + $menusEle.length && $menusEle.forEach(i => { + menusWidth += i.offsetWidth + }) + const $searchEle = document.querySelector('#search-button') + searchWidth = $searchEle ? $searchEle.offsetWidth : 0 + $nav = document.getElementById('nav') + } + + let hideMenuIndex = '' + if (window.innerWidth <= 768) hideMenuIndex = true + else hideMenuIndex = blogNameWidth + menusWidth + searchWidth > $nav.offsetWidth - 120 + + if (hideMenuIndex) { + $nav.classList.add('hide-menu') + } else { + $nav.classList.remove('hide-menu') + } + } + + // 初始化header + const initAdjust = () => { + adjustMenu(true) + $nav.classList.add('show') + } + + // sidebar menus + const sidebarFn = { + open: () => { + btf.sidebarPaddingR() + document.body.style.overflow = 'hidden' + btf.animateIn(document.getElementById('menu-mask'), 'to_show 0.5s') + document.getElementById('sidebar-menus').classList.add('open') + mobileSidebarOpen = true + }, + close: () => { + const $body = document.body + $body.style.overflow = '' + $body.style.paddingRight = '' + btf.animateOut(document.getElementById('menu-mask'), 'to_hide 0.5s') + document.getElementById('sidebar-menus').classList.remove('open') + mobileSidebarOpen = false + } + } + + /** + * 首頁top_img底下的箭頭 + */ + const scrollDownInIndex = () => { + const $scrollDownEle = document.getElementById('scroll-down') + $scrollDownEle && $scrollDownEle.addEventListener('click', function () { + btf.scrollToDest(document.getElementById('content-inner').offsetTop, 300) + }) + } + + /** + * 代碼 + * 只適用於Hexo默認的代碼渲染 + */ + const addHighlightTool = function () { + const highLight = GLOBAL_CONFIG.highlight + if (!highLight) return + + const isHighlightCopy = highLight.highlightCopy + const isHighlightLang = highLight.highlightLang + const isHighlightShrink = GLOBAL_CONFIG_SITE.isHighlightShrink + const highlightHeightLimit = highLight.highlightHeightLimit + const isShowTool = isHighlightCopy || isHighlightLang || isHighlightShrink !== undefined + const $figureHighlight = highLight.plugin === 'highlighjs' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]') + + if (!((isShowTool || highlightHeightLimit) && $figureHighlight.length)) return + + const isPrismjs = highLight.plugin === 'prismjs' + + let highlightShrinkEle = '' + let highlightCopyEle = '' + const highlightShrinkClass = isHighlightShrink === true ? 'closed' : '' + + if (isHighlightShrink !== undefined) { + highlightShrinkEle = `` + } + + if (isHighlightCopy) { + highlightCopyEle = '
' + } + + const copy = (text, ctx) => { + if (document.queryCommandSupported && document.queryCommandSupported('copy')) { + document.execCommand('copy') + if (GLOBAL_CONFIG.Snackbar !== undefined) { + btf.snackbarShow(GLOBAL_CONFIG.copy.success) + } else { + const prevEle = ctx.previousElementSibling + prevEle.innerText = GLOBAL_CONFIG.copy.success + prevEle.style.opacity = 1 + setTimeout(() => { + prevEle.style.opacity = 0 + }, 700) + } + } else { + if (GLOBAL_CONFIG.Snackbar !== undefined) { + btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport) + } else { + ctx.previousElementSibling.innerText = GLOBAL_CONFIG.copy.noSupport + } + } + } + + // click events + const highlightCopyFn = (ele) => { + const $buttonParent = ele.parentNode + $buttonParent.classList.add('copy-true') + const selection = window.getSelection() + const range = document.createRange() + if (isPrismjs) range.selectNodeContents($buttonParent.querySelectorAll('pre code')[0]) + else range.selectNodeContents($buttonParent.querySelectorAll('table .code pre')[0]) + selection.removeAllRanges() + selection.addRange(range) + const text = selection.toString() + copy(text, ele.lastChild) + selection.removeAllRanges() + $buttonParent.classList.remove('copy-true') + } + + const highlightShrinkFn = (ele) => { + const $nextEle = [...ele.parentNode.children].slice(1) + ele.firstChild.classList.toggle('closed') + if (btf.isHidden($nextEle[$nextEle.length - 1])) { + $nextEle.forEach(e => { + e.style.display = 'block' + }) + } else { + $nextEle.forEach(e => { + e.style.display = 'none' + }) + } + } + + const highlightToolsFn = function (e) { + const $target = e.target.classList + if ($target.contains('expand')) highlightShrinkFn(this) + else if ($target.contains('copy-button')) highlightCopyFn(this) + } + + const expandCode = function () { + this.classList.toggle('expand-done') + } + + function createEle(lang, item, service) { + const fragment = document.createDocumentFragment() + + if (isShowTool) { + const hlTools = document.createElement('div') + hlTools.className = `highlight-tools ${highlightShrinkClass}` + hlTools.innerHTML = highlightShrinkEle + lang + highlightCopyEle + hlTools.addEventListener('click', highlightToolsFn) + fragment.appendChild(hlTools) + } + + if (highlightHeightLimit && item.offsetHeight > highlightHeightLimit + 30) { + const ele = document.createElement('div') + ele.className = 'code-expand-btn' + ele.innerHTML = '' + ele.addEventListener('click', expandCode) + fragment.appendChild(ele) + } + + if (service === 'hl') { + item.insertBefore(fragment, item.firstChild) + } else { + item.parentNode.insertBefore(fragment, item) + } + } + + if (isHighlightLang) { + if (isPrismjs) { + $figureHighlight.forEach(function (item) { + const langName = item.getAttribute('data-language') ? item.getAttribute('data-language') : 'Code' + const highlightLangEle = `
${langName}
` + btf.wrap(item, 'figure', {class: 'highlight'}) + createEle(highlightLangEle, item) + }) + } else { + $figureHighlight.forEach(function (item) { + let langName = item.getAttribute('class').split(' ')[1] + if (langName === 'plain' || langName === undefined) langName = 'Code' + const highlightLangEle = `
${langName}
` + createEle(highlightLangEle, item, 'hl') + }) + } + } else { + if (isPrismjs) { + $figureHighlight.forEach(function (item) { + btf.wrap(item, 'figure', {class: 'highlight'}) + createEle('', item) + }) + } else { + $figureHighlight.forEach(function (item) { + createEle('', item, 'hl') + }) + } + } + } + + /** + * PhotoFigcaption + */ + function addPhotoFigcaption() { + document.querySelectorAll('#article-container img').forEach(function (item) { + const parentEle = item.parentNode + const altValue = item.title || item.alt + if (altValue && !parentEle.parentNode.classList.contains('justified-gallery')) { + const ele = document.createElement('div') + ele.className = 'img-alt is-center' + ele.textContent = altValue + parentEle.insertBefore(ele, item.nextSibling) + } + }) + } + + /** + * Lightbox + */ + const runLightbox = () => { + btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)')) + } + + /** + * justified-gallery 圖庫排版 + */ + const runJustifiedGallery = function (ele) { + ele.forEach(item => { + const $imgList = item.querySelectorAll('img') + + $imgList.forEach(i => { + const dataLazySrc = i.getAttribute('data-lazy-src') + if (dataLazySrc) i.src = dataLazySrc + btf.wrap(i, 'div', {class: 'fj-gallery-item'}) + }) + }) + + if (window.fjGallery) { + setTimeout(() => { + btf.initJustifiedGallery(ele) + }, 100) + return + } + + const newEle = document.createElement('link') + newEle.rel = 'stylesheet' + newEle.href = GLOBAL_CONFIG.source.justifiedGallery.css + document.body.appendChild(newEle) + getScript(`${GLOBAL_CONFIG.source.justifiedGallery.js}`).then(() => { + btf.initJustifiedGallery(ele) + }) + } + + /** + * 滾動處理 + */ + const scrollFn = function () { + const $rightside = document.getElementById('rightside') + const innerHeight = window.innerHeight + 56 + + // 當滾動條小于 56 的時候 + if (document.body.scrollHeight <= innerHeight) { + $rightside.style.cssText = 'opacity: 1; transform: translateX(-58px)' + return + } + + // find the scroll direction + function scrollDirection(currentTop) { + const result = currentTop > initTop // true is down & false is up + initTop = currentTop + return result + } + + let initTop = 0 + let isChatShow = true + const $header = document.getElementById('page-header') + const isChatBtnHide = typeof chatBtnHide === 'function' + const isChatBtnShow = typeof chatBtnShow === 'function' + + const scrollTask = btf.throttle(() => { + const currentTop = window.scrollY || document.documentElement.scrollTop + const isDown = scrollDirection(currentTop) + if (currentTop > 56) { + if (isDown) { + if ($header.classList.contains('nav-visible')) $header.classList.remove('nav-visible') + if (isChatBtnShow && isChatShow === true) { + chatBtnHide() + isChatShow = false + } + } else { + if (!$header.classList.contains('nav-visible')) $header.classList.add('nav-visible') + if (isChatBtnHide && isChatShow === false) { + chatBtnShow() + isChatShow = true + } + } + $header.classList.add('nav-fixed') + if (window.getComputedStyle($rightside).getPropertyValue('opacity') === '0') { + $rightside.style.cssText = 'opacity: 0.8; transform: translateX(-58px)' + } + } else { + if (currentTop === 0) { + $header.classList.remove('nav-fixed', 'nav-visible') + } + $rightside.style.cssText = "opacity: ''; transform: ''" + } + + if (document.body.scrollHeight <= innerHeight) { + $rightside.style.cssText = 'opacity: 0.8; transform: translateX(-58px)' + } + }, 200) + + window.scrollCollect = scrollTask + + window.addEventListener('scroll', scrollCollect) + } + + /** + * toc,anchor + */ + const scrollFnToDo = function () { + const isToc = GLOBAL_CONFIG_SITE.isToc + const isAnchor = GLOBAL_CONFIG.isAnchor + const $article = document.getElementById('article-container') + + if (!($article && (isToc || isAnchor))) return + + let $tocLink, $cardToc, scrollPercent, autoScrollToc, isExpand + + if (isToc) { + const $cardTocLayout = document.getElementById('card-toc') + $cardToc = $cardTocLayout.getElementsByClassName('toc-content')[0] + $tocLink = $cardToc.querySelectorAll('.toc-link') + const $tocPercentage = $cardTocLayout.querySelector('.toc-percentage') + isExpand = $cardToc.classList.contains('is-expand') + + scrollPercent = currentTop => { + const docHeight = $article.clientHeight + const winHeight = document.documentElement.clientHeight + const headerHeight = $article.offsetTop + const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : (document.documentElement.scrollHeight - winHeight) + const scrollPercent = (currentTop - headerHeight) / (contentMath) + const scrollPercentRounded = Math.round(scrollPercent * 100) + const percentage = (scrollPercentRounded > 100) ? 100 : (scrollPercentRounded <= 0) ? 0 : scrollPercentRounded + $tocPercentage.textContent = percentage + } + + window.mobileToc = { + open: () => { + $cardTocLayout.style.cssText = 'animation: toc-open .3s; opacity: 1; right: 55px' + }, + + close: () => { + $cardTocLayout.style.animation = 'toc-close .2s' + setTimeout(() => { + $cardTocLayout.style.cssText = "opacity:''; animation: ''; right: ''" + }, 100) + } + } + + // toc元素點擊 + $cardToc.addEventListener('click', e => { + e.preventDefault() + const target = e.target.classList + if (target.contains('toc-content')) return + const $target = target.contains('toc-link') + ? e.target + : e.target.parentElement + btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI($target.getAttribute('href')).replace('#', ''))), 300) + if (window.innerWidth < 900) { + window.mobileToc.close() + } + }) + + autoScrollToc = item => { + const activePosition = item.getBoundingClientRect().top + const sidebarScrollTop = $cardToc.scrollTop + if (activePosition > (document.documentElement.clientHeight - 100)) { + $cardToc.scrollTop = sidebarScrollTop + 150 + } + if (activePosition < 100) { + $cardToc.scrollTop = sidebarScrollTop - 150 + } + } + } + + // find head position & add active class + const list = $article.querySelectorAll('h1,h2,h3,h4,h5,h6') + let detectItem = '' + const findHeadPosition = function (top) { + if (top === 0) { + return false + } + + let currentId = '' + let currentIndex = '' + + list.forEach(function (ele, index) { + if (top > btf.getEleTop(ele) - 80) { + const id = ele.id + currentId = id ? '#' + encodeURI(id) : '' + currentIndex = index + } + }) + + if (detectItem === currentIndex) return + + if (isAnchor) btf.updateAnchor(currentId) + + detectItem = currentIndex + + if (isToc) { + $cardToc.querySelectorAll('.active').forEach(i => { + i.classList.remove('active') + }) + + if (currentId === '') { + return + } + + const currentActive = $tocLink[currentIndex] + currentActive.classList.add('active') + + setTimeout(() => { + autoScrollToc(currentActive) + }, 0) + + if (isExpand) return + let parent = currentActive.parentNode + + for (; !parent.matches('.toc'); parent = parent.parentNode) { + if (parent.matches('li')) parent.classList.add('active') + } + } + } + + // main of scroll + window.tocScrollFn = function () { + return btf.throttle(function () { + const currentTop = window.scrollY || document.documentElement.scrollTop + isToc && scrollPercent(currentTop) + findHeadPosition(currentTop) + }, 100)() + } + window.addEventListener('scroll', tocScrollFn) + } + + /** + * Rightside + */ + const rightSideFn = { + switchReadMode: () => { // read-mode + const $body = document.body + $body.classList.add('read-mode') + const newEle = document.createElement('button') + newEle.type = 'button' + newEle.className = 'fas fa-sign-out-alt exit-readmode' + $body.appendChild(newEle) + + function clickFn() { + $body.classList.remove('read-mode') + newEle.remove() + newEle.removeEventListener('click', clickFn) + } + + newEle.addEventListener('click', clickFn) + }, + switchDarkMode: () => { // Switch Between Light And Dark Mode + const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light' + if (nowMode === 'light') { + activateDarkMode() + saveToLocal.set('theme', 'dark', 2) + GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night) + } else { + activateLightMode() + saveToLocal.set('theme', 'light', 2) + GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day) + } + // handle some cases + typeof utterancesTheme === 'function' && utterancesTheme() + typeof changeGiscusTheme === 'function' && changeGiscusTheme() + typeof FB === 'object' && window.loadFBComment && window.loadFBComment() + typeof runMermaid === 'function' && window.runMermaid() + }, + showOrHideBtn: (e) => { // rightside 點擊設置 按鈕 展開 + const rightsideHideClassList = document.getElementById('rightside-config-hide').classList + rightsideHideClassList.toggle('show') + if (e.classList.contains('show')) { + rightsideHideClassList.add('status') + setTimeout(() => { + rightsideHideClassList.remove('status') + }, 300) + } + e.classList.toggle('show') + }, + scrollToTop: () => { // Back to top + btf.scrollToDest(0, 500) + }, + hideAsideBtn: () => { // Hide aside + const $htmlDom = document.documentElement.classList + $htmlDom.contains('hide-aside') + ? saveToLocal.set('aside-status', 'show', 2) + : saveToLocal.set('aside-status', 'hide', 2) + $htmlDom.toggle('hide-aside') + }, + + runMobileToc: () => { + if (window.getComputedStyle(document.getElementById('card-toc')).getPropertyValue('opacity') === '0') window.mobileToc.open() + else window.mobileToc.close() + } + } + + document.getElementById('rightside').addEventListener('click', function (e) { + const $target = e.target.id ? e.target : e.target.parentNode + switch ($target.id) { + case 'go-up': + rightSideFn.scrollToTop() + break + case 'rightside_config': + rightSideFn.showOrHideBtn($target) + break + case 'mobile-toc-button': + rightSideFn.runMobileToc() + break + case 'readmode': + rightSideFn.switchReadMode() + break + case 'darkmode': + rightSideFn.switchDarkMode() + break + case 'hide-aside-btn': + rightSideFn.hideAsideBtn() + break + default: + break + } + }) + + /** + * menu + * 側邊欄sub-menu 展開/收縮 + */ + const clickFnOfSubMenu = () => { + document.querySelectorAll('#sidebar-menus .site-page.group').forEach(function (item) { + item.addEventListener('click', function () { + this.classList.toggle('hide') + }) + }) + } + + /** + * 複製時加上版權信息 + */ + const addCopyright = () => { + const copyright = GLOBAL_CONFIG.copyright + document.body.oncopy = (e) => { + e.preventDefault() + let textFont; + const copyFont = window.getSelection(0).toString() + if (copyFont.length > copyright.limitCount) { + textFont = copyFont + '\n' + '\n' + '\n' + + copyright.languages.author + '\n' + + copyright.languages.link + window.location.href + '\n' + + copyright.languages.source + '\n' + + copyright.languages.info + } else { + textFont = copyFont + } + if (e.clipboardData) { + return e.clipboardData.setData('text', textFont) + } else { + return window.clipboardData.setData('text', textFont) + } + } + } + + /** + * 網頁運行時間 + */ + const addRuntime = () => { + const $runtimeCount = document.getElementById('runtimeshow') + if ($runtimeCount) { + const publishDate = $runtimeCount.getAttribute('data-publishDate') + $runtimeCount.innerText = btf.diffDate(publishDate) + ' ' + GLOBAL_CONFIG.runtime + } + } + + /** + * 最後一次更新時間 + */ + const addLastPushDate = () => { + const $lastPushDateItem = document.getElementById('last-push-date') + if ($lastPushDateItem) { + const lastPushDate = $lastPushDateItem.getAttribute('data-lastPushDate') + $lastPushDateItem.innerText = btf.diffDate(lastPushDate, true) + } + } + + /** + * table overflow + */ + const addTableWrap = () => { + const $table = document.querySelectorAll('#article-container :not(.highlight) > table, #article-container > table') + if ($table.length) { + $table.forEach(item => { + btf.wrap(item, 'div', {class: 'table-wrap'}) + }) + } + } + + /** + * tag-hide + */ + const clickFnOfTagHide = function () { + const $hideInline = document.querySelectorAll('#article-container .hide-button') + if ($hideInline.length) { + $hideInline.forEach(function (item) { + item.addEventListener('click', function (e) { + const $this = this + $this.classList.add('open') + const $fjGallery = $this.nextElementSibling.querySelectorAll('.fj-gallery') + $fjGallery.length && btf.initJustifiedGallery($fjGallery) + }) + }) + } + } + + const tabsFn = { + clickFnOfTabs: function () { + document.querySelectorAll('#article-container .tab > button').forEach(function (item) { + item.addEventListener('click', function (e) { + const $this = this + const $tabItem = $this.parentNode + + if (!$tabItem.classList.contains('active')) { + const $tabContent = $tabItem.parentNode.nextElementSibling + const $siblings = btf.siblings($tabItem, '.active')[0] + $siblings && $siblings.classList.remove('active') + $tabItem.classList.add('active') + const tabId = $this.getAttribute('data-href').replace('#', '') + const childList = [...$tabContent.children] + childList.forEach(item => { + if (item.id === tabId) item.classList.add('active') + else item.classList.remove('active') + }) + const $isTabJustifiedGallery = $tabContent.querySelectorAll(`#${tabId} .fj-gallery`) + if ($isTabJustifiedGallery.length > 0) { + btf.initJustifiedGallery($isTabJustifiedGallery) + } + } + }) + }) + }, + backToTop: () => { + document.querySelectorAll('#article-container .tabs .tab-to-top').forEach(function (item) { + item.addEventListener('click', function () { + btf.scrollToDest(btf.getEleTop(btf.getParents(this, '.tabs')), 300) + }) + }) + } + } + + const toggleCardCategory = function () { + const $cardCategory = document.querySelectorAll('#aside-cat-list .card-category-list-item.parent i') + if ($cardCategory.length) { + $cardCategory.forEach(function (item) { + item.addEventListener('click', function (e) { + e.preventDefault() + const $this = this + $this.classList.toggle('expand') + const $parentEle = $this.parentNode.nextElementSibling + if (btf.isHidden($parentEle)) { + $parentEle.style.display = 'block' + } else { + $parentEle.style.display = 'none' + } + }) + }) + } + } + + const switchComments = function () { + let switchDone = false + const $switchBtn = document.querySelector('#comment-switch > .switch-btn') + $switchBtn && $switchBtn.addEventListener('click', function () { + this.classList.toggle('move') + document.querySelectorAll('#post-comment > .comment-wrap > div').forEach(function (item) { + if (btf.isHidden(item)) { + item.style.cssText = 'display: block;animation: tabshow .5s' + } else { + item.style.cssText = "display: none;animation: ''" + } + }) + + if (!switchDone && typeof loadOtherComment === 'function') { + switchDone = true + loadOtherComment() + } + }) + } + + const addPostOutdateNotice = function () { + const data = GLOBAL_CONFIG.noticeOutdate + const diffDay = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate) + if (diffDay >= data.limitDay) { + const ele = document.createElement('div') + ele.className = 'post-outdate-notice' + ele.textContent = data.messagePrev + ' ' + diffDay + ' ' + data.messageNext + const $targetEle = document.getElementById('article-container') + if (data.position === 'top') { + $targetEle.insertBefore(ele, $targetEle.firstChild) + } else { + $targetEle.appendChild(ele) + } + } + } + + const lazyloadImg = () => { + window.lazyLoadInstance = new LazyLoad({ + elements_selector: 'img', + threshold: 0, + data_src: 'lazy-src' + }) + } + + const relativeDate = function (selector) { + selector.forEach(item => { + const $this = item + const timeVal = $this.getAttribute('datetime') + $this.innerText = btf.diffDate(timeVal, true) + $this.style.display = 'inline' + }) + } + + const unRefreshFn = function () { + window.addEventListener('resize', () => { + adjustMenu(false) + btf.isHidden(document.getElementById('toggle-menu')) && mobileSidebarOpen && sidebarFn.close() + }) + + document.getElementById('menu-mask').addEventListener('click', e => { + sidebarFn.close() + }) + + clickFnOfSubMenu() + GLOBAL_CONFIG.islazyload && lazyloadImg() + GLOBAL_CONFIG.copyright !== undefined && addCopyright() + } + + window.refreshFn = function () { + initAdjust() + + if (GLOBAL_CONFIG_SITE.isPost) { + GLOBAL_CONFIG.noticeOutdate !== undefined && addPostOutdateNotice() + GLOBAL_CONFIG.relativeDate.post && relativeDate(document.querySelectorAll('#post-meta time')) + } else { + GLOBAL_CONFIG.relativeDate.homepage && relativeDate(document.querySelectorAll('#recent-posts time')) + GLOBAL_CONFIG.runtime && addRuntime() + addLastPushDate() + toggleCardCategory() + } + + scrollFnToDo() + GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex() + addHighlightTool() + GLOBAL_CONFIG.isPhotoFigcaption && addPhotoFigcaption() + scrollFn() + + const $jgEle = document.querySelectorAll('#article-container .fj-gallery') + $jgEle.length && runJustifiedGallery($jgEle) + + runLightbox() + addTableWrap() + clickFnOfTagHide() + tabsFn.clickFnOfTabs() + tabsFn.backToTop() + switchComments() + document.getElementById('toggle-menu').addEventListener('click', () => { + sidebarFn.open() + }) + } + + refreshFn() + unRefreshFn() +}) diff --git a/templates/assets/js/main.js b/templates/assets/js/main.js index c46edd9f..866c9bfe 100644 --- a/templates/assets/js/main.js +++ b/templates/assets/js/main.js @@ -9,12 +9,12 @@ document.addEventListener("DOMContentLoaded", function () { let menusWidth = $menusEle && $menusEle.offsetWidth; let $search = document.querySelector("#search-button"); let searchWidth = $search && $search.offsetWidth; + let $nav = document.getElementById("nav"); // 菜单栏调整 function adjustMenu(init) { 0 < arguments.length && void 0 !== init && init && (blogNameWidth = $siteName && $siteName.offsetWidth, menusWidth = $menusEle && $menusEle.offsetWidth, searchWidth = $search && $search.offsetWidth); - const $nav = document.getElementById("nav"); if (window.innerWidth < 768 || blogNameWidth + menusWidth + searchWidth > $nav.offsetWidth - 120) { $nav.classList.add("hide-menu") @@ -23,6 +23,12 @@ document.addEventListener("DOMContentLoaded", function () { } } + // 初始化header + const initAdjust = () => { + adjustMenu(true); + $nav.classList.add("show"); + }; + function scrollFnToDo() { const $cardTocLayout = document.getElementById("card-toc"); const $cardToc = $cardTocLayout.getElementsByClassName("toc-content")[0]; @@ -41,15 +47,12 @@ document.addEventListener("DOMContentLoaded", function () { const docHeight = $article.clientHeight; const winHeight = document.documentElement.clientHeight; const headerHeight = $article.offsetTop; - const scrollPercent = (currentTop - headerHeight) / - (winHeight < docHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight); + const scrollPercent = (currentTop - headerHeight) / (winHeight < docHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight); const scrollPercentRounded = Math.round(100 * scrollPercent); const percentage = 100 < scrollPercentRounded ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded; $cardToc.setAttribute("progress-percentage", percentage); } - var l = GLOBAL_CONFIG.isanchor - function close() { $cardTocLayout.style.animation = "toc-close .2s"; setTimeout(function () { @@ -64,9 +67,7 @@ document.addEventListener("DOMContentLoaded", function () { // document.getElementById("mobile-toc-button") .addEventListener("click", function () { - ("0" === window.getComputedStyle($cardTocLayout).getPropertyValue("opacity") - ? open() - : close())(); + ("0" === window.getComputedStyle($cardTocLayout).getPropertyValue("opacity") ? open() : close())(); }); // toc 元素点击 $cardToc.addEventListener("click", e => { @@ -80,139 +81,117 @@ document.addEventListener("DOMContentLoaded", function () { const list = $article.querySelectorAll("h1,h2,h3,h4,h5,h6"); let detectItem = ""; const findHeadPosition = function (top) { - if (0 === $tocLink.length || 0 === top) return !1; - var t, - e, - o = "", - i = ""; - if ((list.forEach(function (ele, index) { - top > btf.getEleTop(ele) - 80 && - ((o = "#" + encodeURI(ele.getAttribute("id"))), (i = index)); - }), detectItem !== i) - ) { - if ( - (l && - ((t = o), - window.history.replaceState && - t !== window.location.hash && - ((t = t || location.pathname), - (e = GLOBAL_CONFIG_SITE.title), - window.history.replaceState( - {url: location.href, title: e}, - e, - t - ))), - "" === o) - ) - return ( - $cardToc.querySelectorAll(".active").forEach(function (t) { - t.classList.remove("active"); - }), - void (detectItem = i) - ); - (detectItem = i), - $cardToc.querySelectorAll(".active").forEach(function (t) { - t.classList.remove("active"); - }); - var a = $tocLink[i]; - a.classList.add("active"), - setTimeout(function () { - var t, e; - (t = a.getBoundingClientRect().top), - (e = $cardToc.scrollTop), - t > document.documentElement.clientHeight - 100 && - ($cardToc.scrollTop = e + 150), - t < 100 && ($cardToc.scrollTop = e - 150); - }, 0); - for (var c = a.parentNode; !c.matches(".toc"); c = c.parentNode) - c.matches("li") && c.classList.add("active"); + if (0 === $tocLink.length || 0 === top) { + return false; + } + + let currentId = ""; + let currentIndex = ""; + + list.forEach(function (ele, index) { + if (top > btf.getEleTop(ele) - 80) { + currentId = "#" + encodeURI(ele.getAttribute("id")); + currentIndex = index; + } + + }); + if (detectItem === currentIndex) { + return; + } + + $cardToc.querySelectorAll(".active").forEach(function (i) { + i.classList.remove("active"); + }); + + if ("" === currentId) { + return + } + + detectItem = currentIndex; + + const currentActive = $tocLink[currentIndex]; + currentActive.classList.add("active"); + + setTimeout(function () { + autoScrollToc(currentActive); + }, 0); + + for (; !parent.matches(".toc"); parent = parent.parentNode) { + if (parent.matches("li")) parent.classList.add("active") } }; - } - var d = !1, n = function () { - "light" == ("dark" === document.documentElement.getAttribute("data-theme") ? "dark" : "light") ? (activateDarkMode(), saveToLocal.set("theme", "dark", 2), void 0 !== GLOBAL_CONFIG.Snackbar && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night, !1, 2e3)) : (activateLightMode(), saveToLocal.set("theme", "light", 2), void 0 !== GLOBAL_CONFIG.Snackbar && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day, !1, 2e3)), "function" == typeof utterancesTheme && utterancesTheme(), "object" === ("undefined" == typeof FB ? "undefined" : _typeof(FB)) && window.loadFBComment(), window.DISQUS && document.getElementById("disqus_thread").children.length && setTimeout(function () { - return window.disqusReset() - }, 200) - }; - function I(t) { - t.forEach(function (t) { - var e = t, n = e.getAttribute("datetime"); - e.innerText = btf.diffDate(n, !0), e.style.display = "inline" - }) - } - - var g, O = function () { - document.querySelectorAll("#article-container .tab > button").forEach(function (t) { - t.addEventListener("click", function (t) { - var e, n, o, i, a = this.parentNode; - a.classList.contains("active") || (e = a.parentNode.nextElementSibling, (n = btf.siblings(a, ".active")[0]) && n.classList.remove("active"), a.classList.add("active"), o = this.getAttribute("data-href").replace("#", ""), _toConsumableArray(e.children).forEach(function (t) { - t.id === o ? t.classList.add("active") : t.classList.remove("active") - }), 0 < (i = e.querySelectorAll("#".concat(o, " .justified-gallery"))).length && btf.initJustifiedGallery(i)) - }) - }) - }, G = function () { - document.querySelectorAll("#article-container .tabs .tab-to-top").forEach(function (t) { - t.addEventListener("click", function () { - btf.scrollToDest(btf.getEleTop(btf.getParents(this, ".tabs")), 300) - }) - }) - }; - window.refreshFn = function () { - var t, e, n, o, i, a, c, r, s, l, d, u, f, m, h, g, y, p, b; - - function v() { - f.style.overflow = "", f.style.paddingRight = "", btf.fadeOut(u, .5), d.classList.remove("open") + function autoScrollToc(item) { + const activePosition = item.getBoundingClientRect().top + const sidebarScrollTop = $cardToc.scrollTop + if (activePosition > (document.documentElement.clientHeight - 100)) { + $cardToc.scrollTop = sidebarScrollTop + 150 + } + if (activePosition < 100) { + $cardToc.scrollTop = sidebarScrollTop - 150 + } } - adjustMenu(), document.getElementById("nav").classList.add("show"), GLOBAL_CONFIG_SITE.isPost ? (GLOBAL_CONFIG_SITE.isToc && scrollFnToDo(), void 0 !== GLOBAL_CONFIG.noticeOutdate && (r = GLOBAL_CONFIG.noticeOutdate, (s = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)) >= r.limitDay && ((a = document.createElement("div")).className = "post-outdate-notice", a.textContent = r.messagePrev + " " + s + " " + r.messageNext, c = document.getElementById("article-container"), "top" === r.position ? c.insertBefore(a, c.firstChild) : c.appendChild(a))), GLOBAL_CONFIG.relativeDate.post && I(document.querySelectorAll("#post-meta time"))) : (GLOBAL_CONFIG.relativeDate.homepage && I(document.querySelectorAll("#recent-posts time")), !GLOBAL_CONFIG.runtime || (i = document.getElementById("runtimeshow")) && (o = i.getAttribute("data-publishDate"), i.innerText = btf.diffDate(o) + " " + GLOBAL_CONFIG.runtime), (n = document.getElementById("last-push-date")) && (e = n.getAttribute("data-lastPushDate"), n.innerText = btf.diffDate(e, !0)), (t = document.querySelectorAll("#aside-cat-list .card-category-list-item.parent i")).length && t.forEach(function (t) { - t.addEventListener("click", function (t) { - t.preventDefault(); - this.classList.toggle("expand"); - var e = this.parentNode.nextElementSibling; - btf.isHidden(e) ? e.style.display = "block" : e.style.display = "none" - }) - })), l = document.getElementById("toggle-menu"), d = document.getElementById("sidebar-menus"), u = document.getElementById("menu-mask"), f = document.body, l.addEventListener("click", function () { - btf.sidebarPaddingR(), f.style.overflow = "hidden", btf.fadeIn(u, .5), d.classList.add("open") - }); - window.addEventListener("resize", function (t) { - btf.isHidden(l) && v() - }); + } - w(); + function scrollFn() { + var a, + c, + r, + s, + l, + d, + u = document.getElementById("rightside"), + f = window.innerHeight + 56; + document.body.scrollHeight <= f + ? (u.style.cssText = "opacity: 1; transform: translateX(-38px)") + : ((c = !(a = 0)), + (r = document.getElementById("page-header")), + document.getElementById("guli_top"), + (s = document.getElementById("cookies-window")), + (l = "function" == typeof chatBtnHide), + (d = "function" == typeof chatBtnShow), + window.addEventListener( + "scroll", + btf.throttle(function (t) { + var e, + n, + o = window.scrollY || document.documentElement.scrollTop, + i = ((n = a < (e = o)), (a = e), n); + 56 < o + ? (i + ? (r.classList.contains("nav-visible") && + r.classList.remove("nav-visible"), + d && !0 === c && (chatBtnHide(), (c = !1))) + : (r.classList.contains("nav-visible") || + r.classList.add("nav-visible"), + l && !1 === c && (chatBtnShow(), (c = !0))), + r.classList.add("nav-fixed"), + s.classList.add("cw-hide"), + "0" === + window.getComputedStyle(u).getPropertyValue("opacity") && + (u.style.cssText = + "opacity: 1; transform: translateX(-38px)")) + : (0 === o && r.classList.remove("nav-fixed", "nav-visible"), + (u.style.cssText = "opacity: ''; transform: ''")), + document.body.scrollHeight <= f && + (u.style.cssText = "opacity: 1; transform: translateX(-38px)"); + }, 200) + )); + } - "mediumZoom" === GLOBAL_CONFIG.lightbox && (h = mediumZoom(document.querySelectorAll("#article-container :not(a)>img"))).on("open", function (t) { - var e = "dark" === document.documentElement.getAttribute("data-theme") ? "#121212" : "#fff"; - h.update({background: e}) - }); - - (g = document.querySelectorAll("#article-container :not(.highlight) > table, #article-container > table")).length && g.forEach(function (t) { - btf.wrap(t, "div", "", "table-wrap") - }); - - (y = document.querySelectorAll("#article-container .hide-button")).length && y.forEach(function (t) { - t.addEventListener("click", function (t) { - var e = this.nextElementSibling; - this.classList.toggle("open"), this.classList.contains("open") && 0 < e.querySelectorAll(".justified-gallery").length && btf.initJustifiedGallery(e.querySelectorAll(".justified-gallery")) - }) - }); - O(); - G(); - p = !1; - (b = document.querySelector("#comment-switch > .switch-btn")) && b.addEventListener("click", function () { - this.classList.toggle("move"), document.querySelectorAll("#post-comment > .comment-wrap > div").forEach(function (t) { - btf.isHidden(t) ? t.style.cssText = "display: block;animation: tabshow .5s" : t.style.cssText = "display: none;animation: ''" - }); - p || "function" != typeof loadOtherComment || (p = !0, loadOtherComment()) - }); + window.refreshFn = function () { + initAdjust(); + scrollFnToDo(); + scrollFn(); }; refreshFn(); window.addEventListener("resize", adjustMenu); window.addEventListener("orientationchange", function () { - setTimeout(adjustMenu(!0), 100) + setTimeout(adjustMenu, 100) }); document.querySelectorAll("#sidebar-menus .expand").forEach(function (t) { diff --git a/templates/assets/js/man.heo.js b/templates/assets/js/man.heo.js new file mode 100644 index 00000000..9df470ff --- /dev/null +++ b/templates/assets/js/man.heo.js @@ -0,0 +1,327 @@ +"use strict"; + +function _typeof(t) { + return (_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (t) { + return typeof t + } : function (t) { + return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t + })(t) +} + +function _toConsumableArray(t) { + return _arrayWithoutHoles(t) || _iterableToArray(t) || _unsupportedIterableToArray(t) || _nonIterableSpread() +} + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") +} + +function _unsupportedIterableToArray(t, e) { + if (t) { + if ("string" == typeof t) return _arrayLikeToArray(t, e); + var n = Object.prototype.toString.call(t).slice(8, -1); + return "Object" === n && t.constructor && (n = t.constructor.name), "Map" === n || "Set" === n ? Array.from(t) : "Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n) ? _arrayLikeToArray(t, e) : void 0 + } +} + +function _iterableToArray(t) { + if ("undefined" != typeof Symbol && null != t[Symbol.iterator] || null != t["@@iterator"]) return Array.from(t) +} + +function _arrayWithoutHoles(t) { + if (Array.isArray(t)) return _arrayLikeToArray(t) +} + +function _arrayLikeToArray(t, e) { + (null == e || e > t.length) && (e = t.length); + for (var n = 0, o = new Array(e); n < e; n++) o[n] = t[n]; + return o +} + +document.addEventListener("DOMContentLoaded", function () { + function L(t) { + 0 < arguments.length && void 0 !== t && t && (i = o && o.offsetWidth, c = a && a.offsetWidth, s = r && r.offsetWidth); + var e = document.getElementById("nav"), n = window.innerWidth < 768 || i + c + s > e.offsetWidth - 120; + n ? e.classList.add("hide-menu") : e.classList.remove("hide-menu") + } + + function E() { + var t, e, n, c, r, o, s, l, d, u, i, f, m, a = GLOBAL_CONFIG.highlight; + + function h(t, e, n) { + var o, i, a = document.createDocumentFragment(); + r && ((o = document.createElement("div")).className = "highlight-tools ".concat(u), o.innerHTML = l + t + d, o.addEventListener("click", f), a.appendChild(o)), c && e.offsetHeight > c + 30 && ((i = document.createElement("div")).className = "code-expand-btn", i.innerHTML = '', i.addEventListener("click", m), a.appendChild(i)), "hl" === n ? e.insertBefore(a, e.firstChild) : e.parentNode.insertBefore(a, e) + } + + a && (t = a.highlightCopy, e = a.highlightLang, n = GLOBAL_CONFIG_SITE.isHighlightShrink, c = a.highlightHeightLimit, r = t || e || void 0 !== n, o = "highlighjs" === a.plugin ? document.querySelectorAll("figure.highlight") : document.querySelectorAll('pre[class*="language-"]'), (r || c) && o.length && (s = "prismjs" === a.plugin, u = !(d = l = "") === n ? "closed" : "", void 0 !== n && (l = '')), t && (d = '
'), i = function (t) { + var e = t.parentNode; + e.classList.add("copy-true"); + var n = window.getSelection(), o = document.createRange(); + s ? o.selectNodeContents(e.querySelectorAll("pre code")[0]) : o.selectNodeContents(e.querySelectorAll("table .code pre")[0]), n.removeAllRanges(), n.addRange(o); + var i, a; + n.toString(); + i = t.lastChild, document.queryCommandSupported && document.queryCommandSupported("copy") ? (document.execCommand("copy"), void 0 !== GLOBAL_CONFIG.Snackbar ? btf.snackbarShow(GLOBAL_CONFIG.copy.success) : ((a = i.previousElementSibling).innerText = GLOBAL_CONFIG.copy.success, a.style.opacity = 1, setTimeout(function () { + a.style.opacity = 0 + }, 700))) : void 0 !== GLOBAL_CONFIG.Snackbar ? btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport) : i.previousElementSibling.innerText = GLOBAL_CONFIG.copy.noSupport, n.removeAllRanges(), e.classList.remove("copy-true") + }, f = function (t) { + var e, n, o = t.target.classList; + o.contains("expand") ? (n = _toConsumableArray((e = this).parentNode.children).slice(1), e.firstChild.classList.toggle("closed"), btf.isHidden(n[n.length - 1]) ? n.forEach(function (t) { + t.style.display = "block" + }) : n.forEach(function (t) { + t.style.display = "none" + })) : o.contains("copy-button") && i(this) + }, m = function () { + this.classList.toggle("expand-done") + }, e ? s ? o.forEach(function (t) { + var e = t.getAttribute("data-language") ? t.getAttribute("data-language") : "Code", + n = '
'.concat(e, "
"); + btf.wrap(t, "figure", "", "highlight"), h(n, t) + }) : o.forEach(function (t) { + var e = t.getAttribute("class").split(" ")[1]; + "plain" !== e && void 0 !== e || (e = "Code"), h('
'.concat(e, "
"), t, "hl") + }) : s ? o.forEach(function (t) { + btf.wrap(t, "figure", "", "highlight"), h("", t) + }) : o.forEach(function (t) { + h("", t, "hl") + }))) + } + + var o = document.getElementById("site-name"), i = o && o.offsetWidth, + a = document.querySelector("#menus .menus_items"), c = a && a.offsetWidth, + r = document.querySelector("#search-button"), s = r && r.offsetWidth; + + function l(t) { + function e(t) { + t.each(function (t, e) { + var n = $(e), o = n.attr("data-lazy-src") || n.attr("src"), i = o + "_1600w", a = n.attr("alt") || ""; + -1 != o.indexOf("!blogimg") ? n.wrap('')) : n.wrap('')) + }), $().fancybox({ + selector: "[data-fancybox]", + loop: !0, + transitionEffect: "slide", + protect: !0, + buttons: ["slideShow", "fullScreen", "thumbs", "close"], + hash: !1 + }) + } + + void 0 === $.fancybox ? ($("head").append('')), $.getScript("".concat(GLOBAL_CONFIG.source.fancybox.js), function () { + e($(t)) + })) : e($(t)) + } + + function w() { + var n = "fancybox" === GLOBAL_CONFIG.lightbox ? document.querySelectorAll("#article-container :not(a):not(.gallery-group) > img, #article-container > img,.bber-content-img > img") : [], + o = 0 < n.length, i = document.querySelectorAll("#article-container .justified-gallery"), a = 0 < i.length; + (a || o) && btf.isJqueryLoad(function () { + var t, e; + a && (t = $(i), (e = t.find("img")).unwrap(), e.length && e.each(function (t, e) { + $(e).attr("data-lazy-src") && $(e).attr("src", $(e).attr("data-lazy-src")), $(e).wrap("
") + }), d ? btf.initJustifiedGallery(t) : ($("head").append('')), $.getScript("".concat(GLOBAL_CONFIG.source.justifiedGallery.js), function () { + btf.initJustifiedGallery(t) + }), d = !0)), o && l(n) + }) + } + + function A() { + var a, c, r, s, l, d, u = document.getElementById("rightside"), f = window.innerHeight + 56; + document.body.scrollHeight <= f ? u.style.cssText = "opacity: 1; transform: translateX(-38px)" : (c = !(a = 0), r = document.getElementById("page-header"), document.getElementById("guli_top"), s = document.getElementById("cookies-window"), l = "function" == typeof chatBtnHide, d = "function" == typeof chatBtnShow, window.addEventListener("scroll", btf.throttle(function (t) { + var e, n, o = window.scrollY || document.documentElement.scrollTop, i = (n = a < (e = o), a = e, n); + 56 < o ? (i ? (r.classList.contains("nav-visible") && r.classList.remove("nav-visible"), d && !0 === c && (chatBtnHide(), c = !1)) : (r.classList.contains("nav-visible") || r.classList.add("nav-visible"), l && !1 === c && (chatBtnShow(), c = !0)), r.classList.add("nav-fixed"), s.classList.add("cw-hide"), "0" === window.getComputedStyle(u).getPropertyValue("opacity") && (u.style.cssText = "opacity: 1; transform: translateX(-38px)")) : (0 === o && r.classList.remove("nav-fixed", "nav-visible"), u.style.cssText = "opacity: ''; transform: ''"), document.body.scrollHeight <= f && (u.style.cssText = "opacity: 1; transform: translateX(-38px)") + }, 200))) + } + + function S() { + var t = document.getElementById("card-toc"), r = t.getElementsByClassName("toc-content")[0], + s = r.querySelectorAll(".toc-link"), c = document.getElementById("article-container"); + window.tocScrollFn = function () { + return btf.throttle(function () { + var t = window.scrollY || document.documentElement.scrollTop; + e(t), i(t) + }, 100)() + }, window.addEventListener("scroll", tocScrollFn); + var e = function (t) { + var e = c.clientHeight, n = document.documentElement.clientHeight, + o = (t - c.offsetTop) / (n < e ? e - n : document.documentElement.scrollHeight - n), + i = Math.round(100 * o), a = 100 < i ? 100 : i <= 0 ? 0 : i; + r.setAttribute("progress-percentage", a) + }, l = GLOBAL_CONFIG.isanchor, n = function () { + t.style.cssText = "animation: toc-open .3s; opacity: 1; right: 45px" + }, o = function () { + t.style.animation = "toc-close .2s", setTimeout(function () { + t.style.cssText = "opacity:''; animation: ''; right: ''" + }, 100) + }; + document.getElementById("mobile-toc-button").addEventListener("click", function () { + ("0" === window.getComputedStyle(t).getPropertyValue("opacity") ? n : o)() + }), r.addEventListener("click", function (t) { + t.preventDefault(); + var e = t.target.classList.contains("toc-link") ? t.target : t.target.parentElement; + btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI(e.getAttribute("href")).replace("#", ""))), 300), window.innerWidth < 900 && o() + }); + var d = c.querySelectorAll("h1,h2,h3,h4,h5,h6"), u = "", i = function (n) { + if (0 === s.length || 0 === n) return !1; + var t, e, o = "", i = ""; + if (d.forEach(function (t, e) { + n > btf.getEleTop(t) - 80 && (o = "#" + encodeURI(t.getAttribute("id")), i = e) + }), u !== i) { + if (l && (t = o, window.history.replaceState && t !== window.location.hash && (t = t || location.pathname, e = GLOBAL_CONFIG_SITE.title, window.history.replaceState({ + url: location.href, + title: e + }, e, t))), "" === o) return r.querySelectorAll(".active").forEach(function (t) { + t.classList.remove("active") + }), void (u = i); + u = i, r.querySelectorAll(".active").forEach(function (t) { + t.classList.remove("active") + }); + var a = s[i]; + a.classList.add("active"), setTimeout(function () { + var t, e; + t = a.getBoundingClientRect().top, e = r.scrollTop, t > document.documentElement.clientHeight - 100 && (r.scrollTop = e + 150), t < 100 && (r.scrollTop = e - 150) + }, 0); + for (var c = a.parentNode; !c.matches(".toc"); c = c.parentNode) c.matches("li") && c.classList.add("active") + } + } + } + + var d = !1, e = function () { + var e = document.body; + e.classList.add("read-mode"); + var n = document.createElement("button"); + n.type = "button", n.className = "fas fa-sign-out-alt exit-readmode", e.appendChild(n), n.addEventListener("click", function t() { + e.classList.remove("read-mode"), n.remove(), n.removeEventListener("click", t) + }) + }, n = function () { + "light" == ("dark" === document.documentElement.getAttribute("data-theme") ? "dark" : "light") ? (activateDarkMode(), saveToLocal.set("theme", "dark", 2), void 0 !== GLOBAL_CONFIG.Snackbar && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night, !1, 2e3)) : (activateLightMode(), saveToLocal.set("theme", "light", 2), void 0 !== GLOBAL_CONFIG.Snackbar && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day, !1, 2e3)), "function" == typeof utterancesTheme && utterancesTheme(), "object" === ("undefined" == typeof FB ? "undefined" : _typeof(FB)) && window.loadFBComment(), window.DISQUS && document.getElementById("disqus_thread").children.length && setTimeout(function () { + return window.disqusReset() + }, 200) + }, u = function () { + document.getElementById("rightside-config-hide").classList.toggle("show") + }, f = function () { + btf.scrollToDest(0, 500) + }, m = function () { + var t = document.documentElement.classList; + t.contains("hide-aside") ? saveToLocal.set("aside-status", "show", 2) : saveToLocal.set("aside-status", "hide", 2), t.toggle("hide-aside") + }, h = function (t) { + var e = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue("--global-font-size")), + n = ""; + if (t) { + if (20 <= e) return; + n = e + 1, document.documentElement.style.setProperty("--global-font-size", n + "px"), document.getElementById("nav").classList.contains("hide-menu") || L(!0) + } else { + if (e <= 10) return; + n = e - 1, document.documentElement.style.setProperty("--global-font-size", n + "px"), document.getElementById("nav").classList.contains("hide-menu") && L(!0) + } + saveToLocal.set("global-font-size", n, 2) + }; + document.getElementById("rightside").addEventListener("click", function (t) { + switch (t.target.id || t.target.parentNode.id) { + case"go-up": + f(); + break; + case"rightside_config": + u(); + break; + case"readmode": + e(); + break; + case"darkmode": + n(); + break; + case"hide-aside-btn": + m(); + break; + case"font-plus": + h(!0); + break; + case"font-minus": + h() + } + }); + + function I(t) { + t.forEach(function (t) { + var e = t, n = e.getAttribute("datetime"); + e.innerText = btf.diffDate(n, !0), e.style.display = "inline" + }) + } + + var g, O = function () { + document.querySelectorAll("#article-container .tab > button").forEach(function (t) { + t.addEventListener("click", function (t) { + var e, n, o, i, a = this.parentNode; + a.classList.contains("active") || (e = a.parentNode.nextElementSibling, (n = btf.siblings(a, ".active")[0]) && n.classList.remove("active"), a.classList.add("active"), o = this.getAttribute("data-href").replace("#", ""), _toConsumableArray(e.children).forEach(function (t) { + t.id === o ? t.classList.add("active") : t.classList.remove("active") + }), 0 < (i = e.querySelectorAll("#".concat(o, " .justified-gallery"))).length && btf.initJustifiedGallery(i)) + }) + }) + }, G = function () { + document.querySelectorAll("#article-container .tabs .tab-to-top").forEach(function (t) { + t.addEventListener("click", function () { + btf.scrollToDest(btf.getEleTop(btf.getParents(this, ".tabs")), 300) + }) + }) + }; + window.refreshFn = function () { + var t, e, n, o, i, a, c, r, s, l, d, u, f, m, h, g, y, p, b; + + function v() { + f.style.overflow = "", f.style.paddingRight = "", btf.fadeOut(u, .5), d.classList.remove("open") + } + + L(), document.getElementById("nav").classList.add("show"), GLOBAL_CONFIG_SITE.isPost ? (GLOBAL_CONFIG_SITE.isToc && S(), void 0 !== GLOBAL_CONFIG.noticeOutdate && (r = GLOBAL_CONFIG.noticeOutdate, (s = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)) >= r.limitDay && ((a = document.createElement("div")).className = "post-outdate-notice", a.textContent = r.messagePrev + " " + s + " " + r.messageNext, c = document.getElementById("article-container"), "top" === r.position ? c.insertBefore(a, c.firstChild) : c.appendChild(a))), GLOBAL_CONFIG.relativeDate.post && I(document.querySelectorAll("#post-meta time"))) : (GLOBAL_CONFIG.relativeDate.homepage && I(document.querySelectorAll("#recent-posts time")), !GLOBAL_CONFIG.runtime || (i = document.getElementById("runtimeshow")) && (o = i.getAttribute("data-publishDate"), i.innerText = btf.diffDate(o) + " " + GLOBAL_CONFIG.runtime), (n = document.getElementById("last-push-date")) && (e = n.getAttribute("data-lastPushDate"), n.innerText = btf.diffDate(e, !0)), (t = document.querySelectorAll("#aside-cat-list .card-category-list-item.parent i")).length && t.forEach(function (t) { + t.addEventListener("click", function (t) { + t.preventDefault(); + this.classList.toggle("expand"); + var e = this.parentNode.nextElementSibling; + btf.isHidden(e) ? e.style.display = "block" : e.style.display = "none" + }) + })), l = document.getElementById("toggle-menu"), d = document.getElementById("sidebar-menus"), u = document.getElementById("menu-mask"), f = document.body, l.addEventListener("click", function () { + btf.sidebarPaddingR(), f.style.overflow = "hidden", btf.fadeIn(u, .5), d.classList.add("open") + }), u.addEventListener("click", function (t) { + d.classList.contains("open") && v() + }), window.addEventListener("resize", function (t) { + btf.isHidden(l) && d.classList.contains("open") && v() + }), !GLOBAL_CONFIG_SITE.isHome || (m = document.getElementById("scroll-down")) && m.addEventListener("click", function () { + btf.scrollToDest(document.getElementById("content-inner").offsetTop, 300) + }), E(), GLOBAL_CONFIG.isPhotoFigcaption && document.querySelectorAll("#article-container img").forEach(function (t) { + var e, n = t.parentNode; + n.parentNode.classList.contains("justified-gallery") || ((e = document.createElement("div")).className = "img-alt is-center", e.textContent = t.getAttribute("alt"), n.insertBefore(e, t.nextSibling)) + }), w(), "mediumZoom" === GLOBAL_CONFIG.lightbox && (h = mediumZoom(document.querySelectorAll("#article-container :not(a)>img"))).on("open", function (t) { + var e = "dark" === document.documentElement.getAttribute("data-theme") ? "#121212" : "#fff"; + h.update({background: e}) + }), A(), (g = document.querySelectorAll("#article-container :not(.highlight) > table, #article-container > table")).length && g.forEach(function (t) { + btf.wrap(t, "div", "", "table-wrap") + }), (y = document.querySelectorAll("#article-container .hide-button")).length && y.forEach(function (t) { + t.addEventListener("click", function (t) { + var e = this.nextElementSibling; + this.classList.toggle("open"), this.classList.contains("open") && 0 < e.querySelectorAll(".justified-gallery").length && btf.initJustifiedGallery(e.querySelectorAll(".justified-gallery")) + }) + }), O(), G(), p = !1, (b = document.querySelector("#comment-switch > .switch-btn")) && b.addEventListener("click", function () { + this.classList.toggle("move"), document.querySelectorAll("#post-comment > .comment-wrap > div").forEach(function (t) { + btf.isHidden(t) ? t.style.cssText = "display: block;animation: tabshow .5s" : t.style.cssText = "display: none;animation: ''" + }), p || "function" != typeof loadOtherComment || (p = !0, loadOtherComment()) + }) + }, refreshFn(), window.addEventListener("resize", L), window.addEventListener("orientationchange", function () { + setTimeout(L(!0), 100) + }), document.querySelectorAll("#sidebar-menus .expand").forEach(function (t) { + t.addEventListener("click", function () { + this.classList.toggle("hide"); + var t = this.parentNode.nextElementSibling; + btf.isHidden(t) ? t.style.display = "block" : t.style.display = "none" + }) + }), window.addEventListener("touchmove", function (t) { + document.querySelectorAll("#nav .menus_item_child").forEach(function (t) { + btf.isHidden(t) || (t.style.display = "none") + }) + }), GLOBAL_CONFIG.islazyload && (window.lazyLoadInstance = new LazyLoad({ + elements_selector: "img", + threshold: 0, + data_src: "lazy-src" + })), void 0 !== GLOBAL_CONFIG.copyright && (g = GLOBAL_CONFIG.copyright, document.body.oncopy = function (t) { + t.preventDefault(); + var e = window.getSelection(0).toString(), + n = e.length > g.limitCount ? e + "\n\n\n" + g.languages.author + "\n" + g.languages.link + window.location.href + "\n" + g.languages.source + "\n" + g.languages.info : e; + return t.clipboardData ? t.clipboardData.setData("text", n) : window.clipboardData.setData("text", n) + }) +}); \ No newline at end of file diff --git a/templates/assets/js/utils.js b/templates/assets/js/utils.js index a2ee41cb..7046eb00 100644 --- a/templates/assets/js/utils.js +++ b/templates/assets/js/utils.js @@ -1,119 +1,186 @@ "use strict"; -function _toConsumableArray(e) { - return _arrayWithoutHoles(e) || _iterableToArray(e) || _unsupportedIterableToArray(e) || _nonIterableSpread() -} - -function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") -} - -function _unsupportedIterableToArray(e, t) { - if (e) { - if ("string" == typeof e) return _arrayLikeToArray(e, t); - var n = Object.prototype.toString.call(e).slice(8, -1); - return "Object" === n && e.constructor && (n = e.constructor.name), "Map" === n || "Set" === n ? Array.from(e) : "Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n) ? _arrayLikeToArray(e, t) : void 0 - } -} - -function _iterableToArray(e) { - if ("undefined" != typeof Symbol && null != e[Symbol.iterator] || null != e["@@iterator"]) return Array.from(e) -} - -function _arrayWithoutHoles(e) { - if (Array.isArray(e)) return _arrayLikeToArray(e) -} - -function _arrayLikeToArray(e, t) { - (null == t || t > e.length) && (t = e.length); - for (var n = 0, r = new Array(t); n < t; n++) r[n] = e[n]; - return r -} - -var btf = { - debounce: function (r, o, i) { - var a; +const btf = { + debounce: function (func, wait, immediate) { + let timeout return function () { - var e = this, t = arguments, n = i && !a; - clearTimeout(a), a = setTimeout(function () { - a = null, i || r.apply(e, t) - }, o), n && r.apply(e, t) + const context = this + const args = arguments + const later = function () { + timeout = null + if (!immediate) func.apply(context, args) + } + const callNow = immediate && !timeout + clearTimeout(timeout) + timeout = setTimeout(later, wait) + if (callNow) func.apply(context, args) } - }, throttle: function (n, r, o) { - var i, a, s, u = 0; - o = o || {}; + }, - function l() { - u = !1 === o.leading ? 0 : (new Date).getTime(), i = null, n.apply(a, s), i || (a = s = null) + throttle: function (func, wait, options) { + let timeout, context, args + let previous = 0 + if (!options) options = {} + + const later = function () { + previous = options.leading === false ? 0 : new Date().getTime() + timeout = null + func.apply(context, args) + if (!timeout) context = args = null } - return function () { - var e = (new Date).getTime(); - u || !1 !== o.leading || (u = e); - var t = r - (e - u); - a = this, s = arguments, t <= 0 || r < t ? (i && (clearTimeout(i), i = null), u = e, n.apply(a, s), i || (a = s = null)) : i || !1 === o.trailing || (i = setTimeout(l, t)) + const throttled = function () { + const now = new Date().getTime() + if (!previous && options.leading === false) previous = now + const remaining = wait - (now - previous) + context = this + args = arguments + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout) + timeout = null + } + previous = now + func.apply(context, args) + if (!timeout) context = args = null + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining) + } } - }, sidebarPaddingR: function () { - var e = window.innerWidth, t = document.body.clientWidth, n = e - t; - e !== t && (document.body.style.paddingRight = n + "px") - }, snackbarShow: function (e, t, n) { - var r = void 0 !== t && t, o = void 0 !== n ? n : 5e3, i = GLOBAL_CONFIG.Snackbar.position, - a = "light" === document.documentElement.getAttribute("data-theme") ? GLOBAL_CONFIG.Snackbar.bgLight : GLOBAL_CONFIG.Snackbar.bgDark; - document.styleSheets[0].addRule(":root", "--heo-snackbar-time:" + o + "ms!important"), Snackbar.show({ - text: e, - backgroundColor: a, - showAction: r, - duration: o, - pos: i + + return throttled + }, + + sidebarPaddingR: () => { + const innerWidth = window.innerWidth + const clientWidth = document.body.clientWidth + const paddingRight = innerWidth - clientWidth + if (innerWidth !== clientWidth) { + document.body.style.paddingRight = paddingRight + 'px' + } + }, + + snackbarShow: (text, showAction = false, duration = 2000) => { + const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar + const bg = document.documentElement.getAttribute('data-theme') === 'light' ? bgLight : bgDark + Snackbar.show({ + text: text, + backgroundColor: bg, + showAction: showAction, + duration: duration, + pos: position, + customClass: 'snackbar-css' }) - }, initJustifiedGallery: function (e) { - e instanceof jQuery || (e = $(e)), e.each(function (e, t) { - $(this).is(":visible") && $(this).justifiedGallery({rowHeight: 220, margins: 4}) + }, + + initJustifiedGallery: function (selector) { + selector.forEach(function (i) { + if (!btf.isHidden(i)) { + fjGallery(i, { + itemSelector: '.fj-gallery-item', + rowHeight: 220, + gutter: 4, + onJustify: function () { + this.$container.style.opacity = '1' + } + }) + } }) - }, diffDate: function (e, t) { - var n, r, o, i = 1 < arguments.length && void 0 !== t && t, a = new Date, s = new Date(e), - u = a.getTime() - s.getTime(); - return i ? (n = u / 864e5, r = u / 36e5, o = u / 6e4, 12 < u / 2592e6 ? s.toLocaleDateString() : 7 <= n ? s.toLocaleDateString().substr(5) : 1 <= n ? parseInt(n) + "" + GLOBAL_CONFIG.date_suffix.day : 1 <= r || 1 <= o ? "最近" : GLOBAL_CONFIG.date_suffix.just) : parseInt(u / 864e5) - }, loadComment: function (e, t) { - var n; - "IntersectionObserver" in window ? (n = new IntersectionObserver(function (e) { - e[0].isIntersecting && (t(), n.disconnect()) - }, {threshold: [0]})).observe(e) : t() - }, scrollToDest: function (o, i) { - var a, s; - o < 0 || i < 0 || (a = window.scrollY || window.screenTop, o -= 70, "CSS" in window && CSS.supports("scroll-behavior", "smooth") ? window.scrollTo({ - top: o, - behavior: "smooth" - }) : (s = null, i = i || 500, window.requestAnimationFrame(function e(t) { - var n, r; - s = s || t, a < o ? (n = t - s, window.scrollTo(0, (o - a) * n / i + a), n < i ? window.requestAnimationFrame(e) : window.scrollTo(0, o)) : (r = t - s, window.scrollTo(0, a - (a - o) * r / i), r < i ? window.requestAnimationFrame(e) : window.scrollTo(0, o)) - }))) - }, fadeIn: function (e, t) { + }, + + scrollToDest: (pos, time = 500) => { + const currentPos = window.pageYOffset + if (currentPos > pos) pos = pos - 70 + + if ('scrollBehavior' in document.documentElement.style) { + window.scrollTo({ + top: pos, + behavior: 'smooth' + }) + return + } + + let start = null + pos = +pos + window.requestAnimationFrame(function step (currentTime) { + start = !start ? currentTime : start + const progress = currentTime - start + if (currentPos < pos) { + window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos) + } else { + window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time)) + } + if (progress < time) { + window.requestAnimationFrame(step) + } else { + window.scrollTo(0, pos) + } + }) + }, + + fadeIn: function (e, t) { e.style.cssText = "display:block;animation: to_show ".concat(t, "s") - }, fadeOut: function (t, e) { + }, + + fadeOut: function (t, e) { t.addEventListener("animationend", function e() { t.style.cssText = "display: none; animation: '' ", t.removeEventListener("animationend", e) }), t.style.animation = "to_hide ".concat(e, "s") - }, getParents: function (e, t) { - for (; e && e !== document; e = e.parentNode) if (e.matches(t)) return e; + }, + + getParents: (elem, selector) => { + for (; elem && elem !== document; elem = elem.parentNode) { + if (elem.matches(selector)) return elem + } return null - }, siblings: function (t, n) { - return _toConsumableArray(t.parentNode.children).filter(function (e) { - return n ? e !== t && e.matches(n) : e !== t + }, + + siblings: (ele, selector) => { + return [...ele.parentNode.children].filter((child) => { + if (selector) { + return child !== ele && child.matches(selector) + } + return child !== ele }) - }, wrap: function (e, t, n, r) { - var o = 2 < arguments.length && void 0 !== n ? n : "", i = 3 < arguments.length && void 0 !== r ? r : "", - a = document.createElement(t); - o && (a.id = o), i && (a.className = i), e.parentNode.insertBefore(a, e), a.appendChild(e) - }, unwrap: function (e) { - var t = e.parentNode; - t !== document.body && (t.parentNode.insertBefore(e, t), t.parentNode.removeChild(t)) - }, isJqueryLoad: function (e) { + }, + + /** + * @param {*} selector + * @param {*} eleType the type of create element + * @param {*} options object key: value + */ + wrap: (selector, eleType, options) => { + const creatEle = document.createElement(eleType) + for (const [key, value] of Object.entries(options)) { + creatEle.setAttribute(key, value) + } + selector.parentNode.insertBefore(creatEle, selector) + creatEle.appendChild(selector) + }, + + unwrap: el => { + const elParentNode = el.parentNode + if (elParentNode !== document.body) { + elParentNode.parentNode.insertBefore(el, elParentNode) + elParentNode.parentNode.removeChild(elParentNode) + } + }, + + isJqueryLoad: function (e) { "undefined" == typeof jQuery ? getScript(GLOBAL_CONFIG.source.jQuery).then(e) : e() - }, isHidden: function (e) { - return 0 === e.offsetHeight && 0 === e.offsetWidth - }, getEleTop: function (e) { - for (var t = e.offsetTop, n = e.offsetParent; null !== n;) t += n.offsetTop, n = n.offsetParent; - return t - } + }, + + isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0, + + getEleTop: ele => { + let actualTop = ele.offsetTop + let current = ele.offsetParent + + while (current !== null) { + actualTop += current.offsetTop + current = current.offsetParent + } + + return actualTop + }, }; \ No newline at end of file