更新
This commit is contained in:
1 parent
522abb824b
commit
63389e016a
168 files changed
+11220
No files matched your search
@@ -0,0 +1,723 @@
|
||||
$(function () {
|
||||
const blogNameWidth = $('#site-name').width()
|
||||
const menusWidth = $('#menus').width()
|
||||
|
||||
const adjustMenu = () => {
|
||||
const $nav = $('#nav')
|
||||
let t
|
||||
if (window.innerWidth < 768) t = true
|
||||
else t = blogNameWidth + menusWidth > $nav.width() - 30
|
||||
|
||||
if (t) {
|
||||
$nav.addClass('hide-menu')
|
||||
} else {
|
||||
$nav.removeClass('hide-menu')
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化header
|
||||
const initAdjust = () => {
|
||||
adjustMenu()
|
||||
$('#nav').addClass('show')
|
||||
}
|
||||
|
||||
// sidebar menus
|
||||
const sidebarFn = () => {
|
||||
const $toggleMenu = $('#toggle-menu')
|
||||
const $mobileSidebarMenus = $('#sidebar-menus')
|
||||
const $menuMask = $('#menu-mask')
|
||||
const $body = $('body')
|
||||
|
||||
function openMobileSidebar () {
|
||||
btf.sidebarPaddingR()
|
||||
$body.css('overflow', 'hidden')
|
||||
$menuMask.fadeIn()
|
||||
$toggleMenu.removeClass('close').addClass('open')
|
||||
$mobileSidebarMenus.addClass('open')
|
||||
}
|
||||
|
||||
function closeMobileSidebar () {
|
||||
$body.css({ overflow: '', 'padding-right': '' })
|
||||
$menuMask.fadeOut()
|
||||
$toggleMenu.removeClass('open').addClass('close')
|
||||
$mobileSidebarMenus.removeClass('open')
|
||||
}
|
||||
|
||||
$toggleMenu.on('click', function () {
|
||||
openMobileSidebar()
|
||||
})
|
||||
|
||||
$menuMask.on('click touchstart', function (e) {
|
||||
if ($toggleMenu.hasClass('open')) {
|
||||
closeMobileSidebar()
|
||||
}
|
||||
})
|
||||
|
||||
$(window).on('resize', function (e) {
|
||||
if (!$toggleMenu.is(':visible')) {
|
||||
if ($toggleMenu.hasClass('open')) closeMobileSidebar()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 首頁top_img底下的箭頭
|
||||
*/
|
||||
const scrollDownInIndex = () => {
|
||||
$('#scroll-down').on('click', function () {
|
||||
btf.scrollToDest('#content-inner')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 代碼
|
||||
* 只適用於Hexo默認的代碼渲染
|
||||
*/
|
||||
const addHighlightTool = function () {
|
||||
const isHighlightCopy = GLOBAL_CONFIG.highlight.highlightCopy
|
||||
const isHighlightLang = GLOBAL_CONFIG.highlight.highlightLang
|
||||
const isHighlightShrink = GLOBAL_CONFIG_SITE.isHighlightShrink
|
||||
const isShowTool = isHighlightCopy || isHighlightLang || isHighlightShrink !== undefined
|
||||
const $figureHighlight = GLOBAL_CONFIG.highlight.plugin === 'highlighjs' ? $('figure.highlight') : $('pre[class*="language-"]')
|
||||
|
||||
if (isShowTool && $figureHighlight.length) {
|
||||
const isPrismjs = GLOBAL_CONFIG.highlight.plugin === 'prismjs'
|
||||
|
||||
let highlightShrinkEle = ''
|
||||
let highlightCopyEle = ''
|
||||
const highlightShrinkClass = isHighlightShrink === true ? 'closed' : ''
|
||||
|
||||
if (isHighlightShrink !== undefined) {
|
||||
highlightShrinkEle = `<i class="fas fa-angle-down expand ${highlightShrinkClass}"></i>`
|
||||
}
|
||||
|
||||
if (isHighlightCopy) {
|
||||
highlightCopyEle = '<div class="copy-notice"></div><i class="fas fa-paste copy-button"></i>'
|
||||
}
|
||||
|
||||
if (isHighlightLang) {
|
||||
if (isPrismjs) {
|
||||
$figureHighlight.each(function () {
|
||||
const $this = $(this)
|
||||
const langName = $this.attr('data-language') !== undefined ? $this.attr('data-language') : 'Code'
|
||||
const highlightLangEle = `<div class="code-lang">${langName}</div>`
|
||||
$this.wrap('<figure class="highlight"></figure>').before(`<div class="highlight-tools ${highlightShrinkClass}">${highlightShrinkEle + highlightLangEle + highlightCopyEle}</div>`)
|
||||
})
|
||||
} else {
|
||||
$figureHighlight.each(function (i, o) {
|
||||
const $this = $(this)
|
||||
let langName = $this.attr('class').split(' ')[1]
|
||||
if (langName === 'plain' || langName === undefined) langName = 'Code'
|
||||
const highlightLangEle = `<div class="code-lang">${langName}</div>`
|
||||
$this.prepend(`<div class="highlight-tools ${highlightShrinkClass}">${highlightShrinkEle + highlightLangEle + highlightCopyEle}</div>`)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const ele = `<div class="highlight-tools ${highlightShrinkClass}">${highlightShrinkEle + highlightCopyEle}</div>`
|
||||
if (isPrismjs) $figureHighlight.wrap('<figure class="highlight"></figure>').before(ele)
|
||||
else $figureHighlight.prepend(ele)
|
||||
}
|
||||
|
||||
/**
|
||||
* 代碼收縮
|
||||
*/
|
||||
|
||||
if (isHighlightShrink !== undefined) {
|
||||
$('.highlight-tools >.expand').on('click', function () {
|
||||
const $this = $(this)
|
||||
const $table = $this.parent().nextAll()
|
||||
$this.toggleClass('closed')
|
||||
$table.is(':visible') ? $table.css('display', 'none') : $table.css('display', 'block')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 代碼copy
|
||||
*/
|
||||
if (isHighlightCopy) {
|
||||
const copy = function (text, ctx) {
|
||||
if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
|
||||
document.execCommand('copy')
|
||||
if (GLOBAL_CONFIG.Snackbar !== undefined) {
|
||||
btf.snackbarShow(GLOBAL_CONFIG.copy.success)
|
||||
} else {
|
||||
$(ctx).prev('.copy-notice')
|
||||
.text(GLOBAL_CONFIG.copy.success)
|
||||
.animate({
|
||||
opacity: 1
|
||||
}, 450, function () {
|
||||
setTimeout(function () {
|
||||
$(ctx).prev('.copy-notice').animate({
|
||||
opacity: 0
|
||||
}, 650)
|
||||
}, 400)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (GLOBAL_CONFIG.Snackbar !== undefined) {
|
||||
btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport)
|
||||
} else {
|
||||
$(ctx).prev('.copy-notice').text(GLOBAL_CONFIG.copy.noSupport)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// click events
|
||||
$('.highlight-tools >.copy-button').on('click', function () {
|
||||
const $buttonParent = $(this).parents('figure.highlight')
|
||||
$buttonParent.addClass('copy-true')
|
||||
const selection = window.getSelection()
|
||||
const range = document.createRange()
|
||||
if (isPrismjs) range.selectNodeContents($buttonParent.find('> pre code')[0])
|
||||
else range.selectNodeContents($buttonParent.find('table .code pre')[0])
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
const text = selection.toString()
|
||||
copy(text, this)
|
||||
selection.removeAllRanges()
|
||||
$buttonParent.removeClass('copy-true')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PhotoFigcaption
|
||||
*/
|
||||
function addPhotoFigcaption () {
|
||||
const images = $('#article-container img').not('.justified-gallery img')
|
||||
images.each(function (i, o) {
|
||||
const $this = $(o)
|
||||
if ($this.attr('alt')) {
|
||||
const t = $('<div class="img-alt is-center">' + $this.attr('alt') + '</div>')
|
||||
$this.after(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* justified-gallery 圖庫排版
|
||||
*/
|
||||
|
||||
let detectJgJsLoad = false
|
||||
const runJustifiedGallery = function () {
|
||||
const $justifiedGallery = $('.justified-gallery')
|
||||
if ($justifiedGallery.length) {
|
||||
const $imgList = $justifiedGallery.find('img')
|
||||
$imgList.unwrap()
|
||||
if ($imgList.length) {
|
||||
$imgList.each(function (i, o) {
|
||||
if ($(o).attr('data-lazy-src')) $(o).attr('src', $(o).attr('data-lazy-src'))
|
||||
$(o).wrap('<div></div>')
|
||||
})
|
||||
}
|
||||
|
||||
if (detectJgJsLoad) btf.initJustifiedGallery($justifiedGallery)
|
||||
else {
|
||||
$('head').append(`<link rel="stylesheet" type="text/css" href="${GLOBAL_CONFIG.justifiedGallery.css}">`)
|
||||
$.getScript(`${GLOBAL_CONFIG.justifiedGallery.js}`, function () {
|
||||
btf.initJustifiedGallery($justifiedGallery)
|
||||
})
|
||||
detectJgJsLoad = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fancybox和 mediumZoom
|
||||
*/
|
||||
const addLightBox = function () {
|
||||
if (GLOBAL_CONFIG.lightbox === 'fancybox') {
|
||||
const images = $('#article-container img:not(.gallery-group-img)').not($('a>img'))
|
||||
images.each(function (i, o) {
|
||||
const lazyloadSrc = $(o).attr('data-lazy-src') ? $(o).attr('data-lazy-src') : $(o).attr('src')
|
||||
const dataCaption = $(o).attr('alt') ? $(o).attr('alt') : ''
|
||||
$(o).wrap(`<a href="${lazyloadSrc}" data-fancybox="group" data-caption="${dataCaption}" class="fancybox"></a>`)
|
||||
})
|
||||
|
||||
$().fancybox({
|
||||
selector: '[data-fancybox]',
|
||||
loop: true,
|
||||
transitionEffect: 'slide',
|
||||
protect: true,
|
||||
buttons: ['slideShow', 'fullScreen', 'thumbs', 'close'],
|
||||
hash: false
|
||||
})
|
||||
} else {
|
||||
const zoom = mediumZoom(document.querySelectorAll('#article-container :not(a)>img'))
|
||||
zoom.on('open', function (event) {
|
||||
const photoBg = $(document.documentElement).attr('data-theme') === 'dark' ? '#121212' : '#fff'
|
||||
zoom.update({
|
||||
background: photoBg
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 滾動處理
|
||||
*/
|
||||
const scrollFn = function () {
|
||||
let initTop = 0
|
||||
let isChatShow = true
|
||||
const $rightside = $('#rightside')
|
||||
const $nav = $('#nav')
|
||||
const isChatBtnHide = typeof chatBtnHide === 'function'
|
||||
const isChatBtnShow = typeof chatBtnShow === 'function'
|
||||
$(window).scroll(btf.throttle(function (event) {
|
||||
const currentTop = $(this).scrollTop()
|
||||
const isDown = scrollDirection(currentTop)
|
||||
if (currentTop > 56) {
|
||||
if (isDown) {
|
||||
if ($nav.hasClass('visible')) $nav.removeClass('visible')
|
||||
if (isChatBtnShow && isChatShow === true) {
|
||||
chatBtnHide()
|
||||
isChatShow = false
|
||||
}
|
||||
} else {
|
||||
if (!$nav.hasClass('visible')) $nav.addClass('visible')
|
||||
if (isChatBtnHide && isChatShow === false) {
|
||||
window.chatBtnShow()
|
||||
isChatShow = true
|
||||
}
|
||||
}
|
||||
$nav.addClass('fixed')
|
||||
if ($rightside.css('opacity') === '0') {
|
||||
$rightside.css({ opacity: '1', transform: 'translateX(-38px)' })
|
||||
}
|
||||
} else {
|
||||
if (currentTop === 0) {
|
||||
$nav.removeClass('fixed').removeClass('visible')
|
||||
}
|
||||
$rightside.css({ opacity: '', transform: '' })
|
||||
}
|
||||
}, 200))
|
||||
|
||||
// find the scroll direction
|
||||
function scrollDirection (currentTop) {
|
||||
const result = currentTop > initTop // true is down & false is up
|
||||
initTop = currentTop
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toc
|
||||
*/
|
||||
const tocFn = function () {
|
||||
const $cardTocLayout = $('#card-toc')
|
||||
const $cardToc = $cardTocLayout.find('.toc-content')
|
||||
const $tocChild = $cardToc.find('.toc-child')
|
||||
const $tocLink = $cardToc.find('.toc-link')
|
||||
const $article = $('#article-container')
|
||||
|
||||
$tocChild.hide()
|
||||
|
||||
// main of scroll
|
||||
$(window).scroll(btf.throttle(function (event) {
|
||||
const currentTop = $(this).scrollTop()
|
||||
scrollPercent(currentTop)
|
||||
findHeadPosition(currentTop)
|
||||
}, 100))
|
||||
|
||||
// expand toc-item
|
||||
const expandToc = function ($item) {
|
||||
if ($item.is(':visible')) {
|
||||
return
|
||||
}
|
||||
$item.fadeIn(400)
|
||||
}
|
||||
|
||||
const scrollPercent = function (currentTop) {
|
||||
const docHeight = $article.height()
|
||||
const winHeight = $(window).height()
|
||||
const headerHeight = $article.offset().top
|
||||
const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : ($(document).height() - winHeight)
|
||||
const scrollPercent = (currentTop - headerHeight) / (contentMath)
|
||||
const scrollPercentRounded = Math.round(scrollPercent * 100)
|
||||
const percentage = (scrollPercentRounded > 100) ? 100
|
||||
: (scrollPercentRounded <= 0) ? 0
|
||||
: scrollPercentRounded
|
||||
$cardToc.attr('progress-percentage', percentage)
|
||||
}
|
||||
|
||||
// anchor
|
||||
const isAnchor = GLOBAL_CONFIG.isanchor
|
||||
const updateAnchor = function (anchor) {
|
||||
if (window.history.replaceState && anchor !== window.location.hash) {
|
||||
window.history.replaceState(undefined, undefined, anchor)
|
||||
}
|
||||
}
|
||||
|
||||
const mobileToc = {
|
||||
open: () => {
|
||||
$cardTocLayout.css('display', 'block')
|
||||
},
|
||||
|
||||
close: () => {
|
||||
$cardTocLayout.css('animation', 'toc-close .2s')
|
||||
setTimeout(() => {
|
||||
$cardTocLayout.css({ display: '', animation: '' })
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
$('#mobile-toc-button').on('click', () => {
|
||||
if ($cardTocLayout.is(':visible')) {
|
||||
mobileToc.close()
|
||||
} else {
|
||||
mobileToc.open()
|
||||
}
|
||||
})
|
||||
|
||||
// toc元素點擊
|
||||
$tocLink.on('click', function (e) {
|
||||
e.preventDefault()
|
||||
btf.scrollToDest(decodeURI($(this).attr('href')))
|
||||
if (window.innerWidth < 900) {
|
||||
mobileToc.close()
|
||||
}
|
||||
})
|
||||
|
||||
const autoScrollToc = function (currentTop, item) {
|
||||
const activePosition = item.offset().top
|
||||
const $tocContent = $cardToc
|
||||
const sidebarScrollTop = $tocContent.scrollTop()
|
||||
if (activePosition > (currentTop + $(window).height() - 100)) {
|
||||
$tocContent.scrollTop(sidebarScrollTop + 100)
|
||||
}
|
||||
if (activePosition < currentTop + 100) {
|
||||
$tocContent.scrollTop(sidebarScrollTop - 100)
|
||||
}
|
||||
}
|
||||
|
||||
// find head position & add active class
|
||||
// DOM Hierarchy:
|
||||
// ol.toc > (li.toc-item, ...)
|
||||
// li.toc-item > (a.toc-link, ol.toc-2child > (li.toc-item, ...))
|
||||
const list = $article.find('h1,h2,h3,h4,h5,h6')
|
||||
|
||||
const findHeadPosition = function (top) {
|
||||
// assume that we are not in the post page if no TOC link be found,
|
||||
// thus no need to update the status
|
||||
if ($tocLink.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
let currentId = ''
|
||||
list.each(function () {
|
||||
const head = $(this)
|
||||
if (top > head.offset().top - 70) {
|
||||
currentId = '#' + encodeURI($(this).attr('id'))
|
||||
}
|
||||
})
|
||||
|
||||
if (currentId === '') {
|
||||
$tocLink.removeClass('active')
|
||||
$tocChild.hide()
|
||||
}
|
||||
|
||||
const currentActive = $tocLink.filter('.active')
|
||||
if (currentId && currentActive.attr('href') !== currentId) {
|
||||
if (isAnchor) updateAnchor(currentId)
|
||||
|
||||
$tocLink.removeClass('active')
|
||||
|
||||
const _this = $tocLink.filter('[href="' + currentId + '"]')
|
||||
_this.addClass('active')
|
||||
autoScrollToc(top, _this)
|
||||
|
||||
const parents = _this.parents('.toc-child')
|
||||
// Returned list is in reverse order of the DOM elements
|
||||
// Thus `parents.last()` is the outermost .toc-child container
|
||||
// i.e. list of subsections
|
||||
const topLink = (parents.length > 0) ? parents.last() : _this
|
||||
expandToc(topLink.closest('.toc-item').find('.toc-child'))
|
||||
topLink
|
||||
// Find all top-level .toc-item containers, i.e. sections
|
||||
// excluding the currently active one
|
||||
.closest('.toc-item').siblings('.toc-item')
|
||||
// Hide their respective list of subsections
|
||||
.find('.toc-child').hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rightside
|
||||
*/
|
||||
|
||||
const $rightsideEle = $('#rightside')
|
||||
|
||||
// read-mode
|
||||
$rightsideEle.on('click', '#readmode', function () {
|
||||
$('body').toggleClass('read-mode')
|
||||
})
|
||||
|
||||
// Switch Between Light And Dark Mode
|
||||
if ($('#darkmode').length) {
|
||||
const switchReadMode = function () {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
$rightsideEle.on('click', '#darkmode', () => {
|
||||
switchReadMode()
|
||||
typeof utterancesTheme === 'function' && utterancesTheme()
|
||||
typeof FB === 'object' && window.loadFBComment()
|
||||
window.DISQUS && $('#disqus_thread').children().length && setTimeout(() => window.disqusReset(), 200)
|
||||
})
|
||||
}
|
||||
|
||||
// rightside 點擊設置 按鈕 展開
|
||||
$rightsideEle.on('click', '#rightside_config', () => $('#rightside-config-hide').toggleClass('show'))
|
||||
|
||||
// Back to top
|
||||
$rightsideEle.on('click', '#go-up', () => btf.scrollToDest('body'))
|
||||
|
||||
$rightsideEle.on('click', '#hide-aside-btn', () => {
|
||||
const $htmlDom = $(document.documentElement)
|
||||
if ($htmlDom.hasClass('hide-aside')) {
|
||||
$htmlDom.removeClass('hide-aside')
|
||||
saveToLocal.set('aside-status', 'show', 2)
|
||||
} else {
|
||||
$htmlDom.addClass('hide-aside')
|
||||
saveToLocal.set('aside-status', 'hide', 2)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* menu
|
||||
* 側邊欄sub-menu 展開/收縮
|
||||
* 解決menus在觸摸屏下,滑動屏幕menus_item_child不消失的問題(手機hover的bug)
|
||||
*/
|
||||
const clickFnOfSubMenu = function () {
|
||||
$('#sidebar-menus .expand').on('click', function () {
|
||||
$(this).parents('.menus_item').find('> .menus_item_child').slideToggle()
|
||||
$(this).toggleClass('hide')
|
||||
})
|
||||
|
||||
$(window).on('touchmove', function (e) {
|
||||
const $menusChild = $('#nav .menus_item_child')
|
||||
if ($menusChild.is(':visible')) {
|
||||
$menusChild.css('display', 'none')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 複製時加上版權信息
|
||||
*/
|
||||
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 = $('#runtimeshow')
|
||||
if ($runtimeCount.length) {
|
||||
const publishDate = $runtimeCount.attr('data-publishDate')
|
||||
$runtimeCount.text(btf.diffDate(publishDate) + ' ' + GLOBAL_CONFIG.runtime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 最後一次更新時間
|
||||
*/
|
||||
const addLastPushDate = () => {
|
||||
const $lastPushDateItem = $('#last-push-date')
|
||||
if ($lastPushDateItem.length) {
|
||||
const lastPushDate = $lastPushDateItem.attr('data-lastPushDate')
|
||||
const diffDay = btf.diffDate(lastPushDate, true)
|
||||
$lastPushDateItem.text(diffDay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* table overflow
|
||||
*/
|
||||
const addTableWrap = function () {
|
||||
const $table = $('#article-container table').not($('figure.highlight > table'))
|
||||
$table.each(function () {
|
||||
$(this).wrap('<div class="table-wrap"></div>')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* tag-hide
|
||||
*/
|
||||
const clickFnOfTagHide = function () {
|
||||
const $hideInline = $('.hide-button')
|
||||
if ($hideInline.length) {
|
||||
$hideInline.on('click', function (e) {
|
||||
const $this = $(this)
|
||||
const $hideContent = $(this).next('.hide-content')
|
||||
$this.toggleClass('open')
|
||||
$hideContent.toggle()
|
||||
if ($this.hasClass('open')) {
|
||||
if ($hideContent.find('.justified-gallery').length > 0) {
|
||||
btf.initJustifiedGallery($hideContent.find('.justified-gallery'))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const tabsFn = {
|
||||
clickFnOfTabs: function () {
|
||||
const $tab = $('#article-container .tabs')
|
||||
$tab.find('.tab > button:not(.tab-to-top)').on('click', function (e) {
|
||||
const $this = $(this)
|
||||
const $tabItem = $this.parent()
|
||||
|
||||
if (!$tabItem.hasClass('active')) {
|
||||
const $tabContent = $this.parents('.nav-tabs').next()
|
||||
$tabItem.siblings('.active').removeClass('active')
|
||||
$tabItem.addClass('active')
|
||||
const tabId = $this.attr('data-href')
|
||||
$tabContent.find('> .tab-item-content').removeClass('active')
|
||||
$tabContent.find(`> ${tabId}`).addClass('active')
|
||||
const $isTabJustifiedGallery = $tabContent.find(tabId).find('.justified-gallery')
|
||||
if ($isTabJustifiedGallery.length > 0) {
|
||||
btf.initJustifiedGallery($isTabJustifiedGallery)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
backToTop: () => {
|
||||
const backToTopBtn = $('#article-container .tabs .tab-to-top')
|
||||
backToTopBtn.on('click', function () {
|
||||
btf.scrollToDest($(this).parents('.tabs'))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const toggleCardCategory = function () {
|
||||
const $cardCategory = $('#aside-cat-list .card-category-list-item.parent i')
|
||||
$cardCategory.on('click', function (e) {
|
||||
e.preventDefault()
|
||||
$(this).toggleClass('expand').parents('.parent').next().slideToggle(300)
|
||||
})
|
||||
}
|
||||
|
||||
const switchComments = function () {
|
||||
let switchDone = false
|
||||
$('#comment-switch > .switch-btn').on('click', function () {
|
||||
const $btn = $(this)
|
||||
$btn.hasClass('move') ? $btn.removeClass('move') : $btn.addClass('move')
|
||||
$('#post-comment > .comment-wrap > div').each(function (i, o) {
|
||||
const $this = $(o)
|
||||
if ($this.is(':visible')) {
|
||||
$this.hide()
|
||||
} else {
|
||||
$this.css({
|
||||
display: 'block',
|
||||
animation: 'tabshow .5s'
|
||||
})
|
||||
}
|
||||
})
|
||||
if (!switchDone && typeof loadOtherComment === 'function') {
|
||||
switchDone = true
|
||||
loadOtherComment()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addPostOutdateNotice = function () {
|
||||
const data = GLOBAL_CONFIG.noticeOutdate
|
||||
var diffDay = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)
|
||||
if (diffDay >= data.limitDay) {
|
||||
const code = `<div class="post-outdate-notice">${data.messagePrev + ' ' + diffDay + ' ' + data.messageNext}</div>`
|
||||
if (data.position === 'top') {
|
||||
$('#article-container').prepend(code)
|
||||
} else {
|
||||
$('#article-container').append(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lazyloadImg = () => {
|
||||
window.lazyLoadInstance = new LazyLoad({
|
||||
elements_selector: 'img',
|
||||
threshold: 0,
|
||||
data_src: 'lazy-src'
|
||||
})
|
||||
}
|
||||
|
||||
const relativeDate = function (selector) {
|
||||
selector.each((i, o) => {
|
||||
const $this = $(o)
|
||||
const timeVal = $this.attr('datetime')
|
||||
$this.text(btf.diffDate(timeVal, true)).css('display', 'inline')
|
||||
})
|
||||
}
|
||||
|
||||
const unRefreshFn = function () {
|
||||
$(window).on('resize', function () {
|
||||
adjustMenu()
|
||||
})
|
||||
|
||||
clickFnOfSubMenu()
|
||||
GLOBAL_CONFIG.islazyload && lazyloadImg()
|
||||
GLOBAL_CONFIG.copyright !== undefined && addCopyright()
|
||||
}
|
||||
|
||||
window.refreshFn = function () {
|
||||
initAdjust()
|
||||
|
||||
if (GLOBAL_CONFIG_SITE.isPost) {
|
||||
GLOBAL_CONFIG_SITE.isToc && tocFn()
|
||||
GLOBAL_CONFIG.noticeOutdate !== undefined && addPostOutdateNotice()
|
||||
GLOBAL_CONFIG.relativeDate.post && relativeDate($('#post-meta time'))
|
||||
} else {
|
||||
GLOBAL_CONFIG.relativeDate.homepage && relativeDate($('#recent-posts time'))
|
||||
GLOBAL_CONFIG.runtime && addRuntime()
|
||||
addLastPushDate()
|
||||
toggleCardCategory()
|
||||
}
|
||||
|
||||
sidebarFn()
|
||||
GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex()
|
||||
GLOBAL_CONFIG.highlight && addHighlightTool()
|
||||
GLOBAL_CONFIG.isPhotoFigcaption && addPhotoFigcaption()
|
||||
runJustifiedGallery()
|
||||
GLOBAL_CONFIG.lightbox !== 'null' && addLightBox()
|
||||
scrollFn()
|
||||
addTableWrap()
|
||||
clickFnOfTagHide()
|
||||
tabsFn.clickFnOfTabs()
|
||||
tabsFn.backToTop()
|
||||
switchComments()
|
||||
}
|
||||
|
||||
refreshFn()
|
||||
unRefreshFn()
|
||||
})
|
||||
@@ -0,0 +1,145 @@
|
||||
$(function () {
|
||||
const openSearch = () => {
|
||||
$('body').css({ width: '100%', overflow: 'hidden' })
|
||||
$('#algolia-search .search-dialog').css('display', 'block')
|
||||
$('.ais-search-box--input').focus()
|
||||
$('#search-mask').fadeIn()
|
||||
// shortcut: ESC
|
||||
document.addEventListener('keydown', function f (event) {
|
||||
if (event.code === 'Escape') {
|
||||
closeSearch()
|
||||
document.removeEventListener('keydown', f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const closeSearch = () => {
|
||||
$('body').css({ width: '', overflow: '' })
|
||||
$('#algolia-search .search-dialog').css({
|
||||
animation: 'search_close .5s'
|
||||
})
|
||||
|
||||
setTimeout(function () {
|
||||
$('#algolia-search .search-dialog').css({
|
||||
animation: '',
|
||||
display: 'none'
|
||||
})
|
||||
}, 500)
|
||||
|
||||
$('#search-mask').fadeOut()
|
||||
}
|
||||
|
||||
const searchClickFn = () => {
|
||||
$('a.social-icon.search').on('click', openSearch)
|
||||
$('#search-mask, .search-close-button').on('click touchstart', closeSearch)
|
||||
}
|
||||
|
||||
searchClickFn()
|
||||
|
||||
window.addEventListener('pjax:complete', function () {
|
||||
closeSearch()
|
||||
searchClickFn()
|
||||
})
|
||||
|
||||
const algolia = GLOBAL_CONFIG.algolia
|
||||
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName
|
||||
if (!isAlgoliaValid) {
|
||||
return console.error('Algolia setting is invalid!')
|
||||
}
|
||||
|
||||
const search = instantsearch({
|
||||
appId: algolia.appId,
|
||||
apiKey: algolia.apiKey,
|
||||
indexName: algolia.indexName,
|
||||
searchParameters: {
|
||||
hitsPerPage: algolia.hits.per_page || 10
|
||||
},
|
||||
searchFunction: function (helper) {
|
||||
const searchInput = $('#algolia-search-input').find('input')
|
||||
|
||||
if (searchInput.val()) {
|
||||
helper.search()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
search.addWidget(
|
||||
instantsearch.widgets.searchBox({
|
||||
container: '#algolia-search-input',
|
||||
reset: false,
|
||||
magnifier: false,
|
||||
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder
|
||||
})
|
||||
)
|
||||
search.addWidget(
|
||||
instantsearch.widgets.hits({
|
||||
container: '#algolia-hits',
|
||||
templates: {
|
||||
item: function (data) {
|
||||
const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
|
||||
return (
|
||||
'<a href="' + link + '" class="algolia-hit-item-link">' +
|
||||
data._highlightResult.title.value +
|
||||
'</a>'
|
||||
)
|
||||
},
|
||||
empty: function (data) {
|
||||
return (
|
||||
'<div id="algolia-hits-empty">' +
|
||||
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) +
|
||||
'</div>'
|
||||
)
|
||||
}
|
||||
},
|
||||
cssClasses: {
|
||||
item: 'algolia-hit-item'
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
search.addWidget(
|
||||
instantsearch.widgets.stats({
|
||||
container: '#algolia-stats',
|
||||
templates: {
|
||||
body: function (data) {
|
||||
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
|
||||
.replace(/\$\{hits}/, data.nbHits)
|
||||
.replace(/\$\{time}/, data.processingTimeMS)
|
||||
return (
|
||||
'<hr>' +
|
||||
stats +
|
||||
'<span class="algolia-logo pull-right">' +
|
||||
' <img src="' + GLOBAL_CONFIG.root + 'img/algolia.svg" alt="Algolia" />' +
|
||||
'</span>'
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
search.addWidget(
|
||||
instantsearch.widgets.pagination({
|
||||
container: '#algolia-pagination',
|
||||
scrollTo: false,
|
||||
showFirstLast: false,
|
||||
labels: {
|
||||
first: '<i class="fas fa-angle-double-left"></i>',
|
||||
last: '<i class="fas fa-angle-double-right"></i>',
|
||||
previous: '<i class="fas fa-angle-left"></i>',
|
||||
next: '<i class="fas fa-angle-right"></i>'
|
||||
},
|
||||
cssClasses: {
|
||||
root: 'pagination',
|
||||
item: 'pagination-item',
|
||||
link: 'page-number',
|
||||
active: 'current',
|
||||
disabled: 'disabled-item'
|
||||
}
|
||||
})
|
||||
)
|
||||
search.start()
|
||||
|
||||
window.pjax && search.on('render', () => {
|
||||
window.pjax.refresh(document.getElementById('algolia-hits'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,164 @@
|
||||
$(function () {
|
||||
let loadFlag = false
|
||||
const openSearch = function () {
|
||||
$('body').css({
|
||||
width: '100%',
|
||||
overflow: 'hidden'
|
||||
})
|
||||
$('#local-search .search-dialog').css('display', 'block')
|
||||
$('#local-search-input input').focus()
|
||||
$('#search-mask').fadeIn()
|
||||
if (!loadFlag) {
|
||||
search(GLOBAL_CONFIG.localSearch.path)
|
||||
loadFlag = true
|
||||
}
|
||||
|
||||
// shortcut: ESC
|
||||
document.addEventListener('keydown', function f (event) {
|
||||
if (event.code === 'Escape') {
|
||||
closeSearch()
|
||||
document.removeEventListener('keydown', f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const closeSearch = function () {
|
||||
$('body').css({
|
||||
width: '',
|
||||
overflow: ''
|
||||
})
|
||||
$('#local-search .search-dialog').css({
|
||||
animation: 'search_close .5s'
|
||||
})
|
||||
|
||||
setTimeout(function () {
|
||||
$('#local-search .search-dialog').css({
|
||||
animation: '',
|
||||
display: 'none'
|
||||
})
|
||||
}, 500)
|
||||
|
||||
$('#search-mask').fadeOut()
|
||||
}
|
||||
|
||||
const searchClickFn = () => {
|
||||
$('a.social-icon.search').on('click', openSearch)
|
||||
$('#search-mask, .search-close-button').on('click', closeSearch)
|
||||
}
|
||||
|
||||
searchClickFn()
|
||||
|
||||
window.addEventListener('pjax:complete', function () {
|
||||
$('#local-search .search-dialog').is(':visible') && closeSearch()
|
||||
searchClickFn()
|
||||
})
|
||||
|
||||
function search (path) {
|
||||
$.ajax({
|
||||
url: GLOBAL_CONFIG.root + path,
|
||||
dataType: 'xml',
|
||||
success: function (xmlResponse) {
|
||||
// get the contents from search data
|
||||
const datas = $('entry', xmlResponse).map(function () {
|
||||
return {
|
||||
title: $('title', this).text(),
|
||||
content: $('content', this).text(),
|
||||
url: $('url', this).text()
|
||||
}
|
||||
}).get()
|
||||
|
||||
const $input = $('#local-search-input input')[0]
|
||||
const $resultContent = $('#local-hits')[0]
|
||||
$input.addEventListener('input', function () {
|
||||
let str = '<div class="search-result-list">'
|
||||
const keywords = this.value.trim().toLowerCase().split(/[\s]+/)
|
||||
$resultContent.innerHTML = ''
|
||||
if (this.value.trim().length <= 0) {
|
||||
$('.local-search-stats__hr').hide()
|
||||
return
|
||||
}
|
||||
let count = 0
|
||||
// perform local searching
|
||||
datas.forEach(function (data) {
|
||||
let isMatch = true
|
||||
if (!data.title || data.title.trim() === '') {
|
||||
data.title = 'Untitled'
|
||||
}
|
||||
let dataTitle = data.title.trim().toLowerCase()
|
||||
const dataContent = data.content.trim().replace(/<[^>]+>/g, '').toLowerCase()
|
||||
const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url
|
||||
let indexTitle = -1
|
||||
let indexContent = -1
|
||||
let firstOccur = -1
|
||||
// only match artiles with not empty titles and contents
|
||||
if (dataTitle !== '' || dataContent !== '') {
|
||||
keywords.forEach(function (keyword, i) {
|
||||
indexTitle = dataTitle.indexOf(keyword)
|
||||
indexContent = dataContent.indexOf(keyword)
|
||||
if (indexTitle < 0 && indexContent < 0) {
|
||||
isMatch = false
|
||||
} else {
|
||||
if (indexContent < 0) {
|
||||
indexContent = 0
|
||||
}
|
||||
if (i === 0) {
|
||||
firstOccur = indexContent
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
isMatch = false
|
||||
}
|
||||
|
||||
// show search results
|
||||
if (isMatch) {
|
||||
const content = data.content.trim().replace(/<[^>]+>/g, '')
|
||||
if (firstOccur >= 0) {
|
||||
// cut out 130 characters
|
||||
let start = firstOccur - 30
|
||||
let end = firstOccur + 100
|
||||
|
||||
if (start < 0) {
|
||||
start = 0
|
||||
}
|
||||
|
||||
if (start === 0) {
|
||||
end = 100
|
||||
}
|
||||
|
||||
if (end > content.length) {
|
||||
end = content.length
|
||||
}
|
||||
|
||||
let matchContent = content.substring(start, end)
|
||||
|
||||
// highlight all keywords
|
||||
keywords.forEach(function (keyword) {
|
||||
const regS = new RegExp(keyword, 'gi')
|
||||
matchContent = matchContent.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
|
||||
dataTitle = dataTitle.replace(regS, '<span class="search-keyword">' + keyword + '</span>')
|
||||
})
|
||||
|
||||
str += '<div class="local-search__hit-item"><a href="' + dataUrl + '" class="search-result-title">' + dataTitle + '</a>'
|
||||
count += 1
|
||||
$('.local-search-stats__hr').show()
|
||||
|
||||
if (dataContent !== '') {
|
||||
str += '<p class="search-result">' + matchContent + '...</p>'
|
||||
}
|
||||
}
|
||||
str += '</div>'
|
||||
}
|
||||
})
|
||||
if (count === 0) {
|
||||
str += '<div id="local-search__hits-empty">' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) +
|
||||
'</div>'
|
||||
}
|
||||
str += '</div>'
|
||||
$resultContent.innerHTML = str
|
||||
window.pjax && window.pjax.refresh($resultContent)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,99 @@
|
||||
/* eslint-disable no-undef */
|
||||
(function () {
|
||||
const translate = GLOBAL_CONFIG.translate
|
||||
const snackbarData = GLOBAL_CONFIG.Snackbar
|
||||
const defaultEncoding = translate.defaultEncoding // 網站默認語言,1: 繁體中文, 2: 簡體中文
|
||||
const translateDelay = translate.translateDelay // 延遲時間,若不在前, 要設定延遲翻譯時間, 如100表示100ms,默認為0
|
||||
const msgToTraditionalChinese = translate.msgToTraditionalChinese // 此處可以更改為你想要顯示的文字
|
||||
const msgToSimplifiedChinese = translate.msgToSimplifiedChinese // 同上,但兩處均不建議更改
|
||||
let currentEncoding = defaultEncoding
|
||||
const targetEncodingCookie = 'translate-chn-cht'
|
||||
let targetEncoding =
|
||||
saveToLocal.get(targetEncodingCookie) === undefined
|
||||
? defaultEncoding
|
||||
: Number(saveToLocal.get('translate-chn-cht'))
|
||||
let translateButtonObject
|
||||
const isSnackbar = GLOBAL_CONFIG.Snackbar !== undefined
|
||||
|
||||
function translateText (txt) {
|
||||
if (txt === '' || txt == null) return ''
|
||||
if (currentEncoding === 1 && targetEncoding === 2) return Simplized(txt)
|
||||
else if (currentEncoding === 2 && targetEncoding === 1) { return Traditionalized(txt) } else return txt
|
||||
}
|
||||
function translateBody (fobj) {
|
||||
let objs
|
||||
if (typeof fobj === 'object') objs = fobj.childNodes
|
||||
else objs = document.body.childNodes
|
||||
for (let i = 0; i < objs.length; i++) {
|
||||
const obj = objs.item(i)
|
||||
if (
|
||||
'||BR|HR|'.indexOf('|' + obj.tagName + '|') > 0 ||
|
||||
obj === translateButtonObject
|
||||
) { continue }
|
||||
if (obj.title !== '' && obj.title != null) { obj.title = translateText(obj.title) }
|
||||
if (obj.alt !== '' && obj.alt != null) obj.alt = translateText(obj.alt)
|
||||
if (obj.placeholder !== '' && obj.placeholder != null) obj.placeholder = translateText(obj.placeholder)
|
||||
if (
|
||||
obj.tagName === 'INPUT' &&
|
||||
obj.value !== '' &&
|
||||
obj.type !== 'text' &&
|
||||
obj.type !== 'hidden'
|
||||
) { obj.value = translateText(obj.value) }
|
||||
if (obj.nodeType === 3) obj.data = translateText(obj.data)
|
||||
else translateBody(obj)
|
||||
}
|
||||
}
|
||||
function translatePage () {
|
||||
if (targetEncoding === 1) {
|
||||
currentEncoding = 1
|
||||
targetEncoding = 2
|
||||
translateButtonObject.innerHTML = msgToTraditionalChinese
|
||||
saveToLocal.set(targetEncodingCookie, targetEncoding, 2)
|
||||
translateBody()
|
||||
if (isSnackbar) btf.snackbarShow(snackbarData.cht_to_chs)
|
||||
} else if (targetEncoding === 2) {
|
||||
currentEncoding = 2
|
||||
targetEncoding = 1
|
||||
translateButtonObject.innerHTML = msgToSimplifiedChinese
|
||||
saveToLocal.set(targetEncodingCookie, targetEncoding, 2)
|
||||
translateBody()
|
||||
if (isSnackbar) btf.snackbarShow(snackbarData.chs_to_cht)
|
||||
}
|
||||
}
|
||||
function JTPYStr () {
|
||||
return '万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖Line truncated
|
||||
}
|
||||
function FTPYStr () {
|
||||
return '萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備複夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴Line truncated
|
||||
}
|
||||
function Traditionalized (cc) {
|
||||
let str = ''
|
||||
const ss = JTPYStr()
|
||||
const tt = FTPYStr()
|
||||
for (let i = 0; i < cc.length; i++) {
|
||||
if (cc.charCodeAt(i) > 10000 && ss.indexOf(cc.charAt(i)) !== -1) { str += tt.charAt(ss.indexOf(cc.charAt(i))) } else str += cc.charAt(i)
|
||||
}
|
||||
return str
|
||||
}
|
||||
function Simplized (cc) {
|
||||
let str = ''
|
||||
const ss = JTPYStr()
|
||||
const tt = FTPYStr()
|
||||
for (let i = 0; i < cc.length; i++) {
|
||||
if (cc.charCodeAt(i) > 10000 && tt.indexOf(cc.charAt(i)) !== -1) { str += ss.charAt(tt.indexOf(cc.charAt(i))) } else str += cc.charAt(i)
|
||||
}
|
||||
return str
|
||||
}
|
||||
function translateInitialization () {
|
||||
translateButtonObject = document.getElementById('translateLink')
|
||||
if (translateButtonObject) {
|
||||
if (currentEncoding !== targetEncoding) {
|
||||
setTimeout(function () { translateBody() }, translateDelay)
|
||||
if (targetEncoding === 1) { translateButtonObject.innerHTML = msgToSimplifiedChinese } else translateButtonObject.innerHTML = msgToTraditionalChinese
|
||||
}
|
||||
translateButtonObject.addEventListener('click', translatePage, false)
|
||||
}
|
||||
}
|
||||
translateInitialization()
|
||||
document.addEventListener('pjax:complete', translateInitialization)
|
||||
})()
|
||||
@@ -0,0 +1,149 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
var btf = {
|
||||
debounce: function (func, wait, immediate) {
|
||||
let timeout
|
||||
return function () {
|
||||
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 (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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
return throttled
|
||||
},
|
||||
|
||||
sidebarPaddingR: () => {
|
||||
const innerWidth = window.innerWidth
|
||||
const clientWidth = document.body.clientWidth
|
||||
const paddingRight = innerWidth - clientWidth
|
||||
if (innerWidth !== clientWidth) {
|
||||
$('body').css('padding-right', paddingRight)
|
||||
}
|
||||
},
|
||||
|
||||
scrollToDest: name => {
|
||||
const scrollOffset = $(name).offset().top
|
||||
let offset
|
||||
if ($(window).scrollTop() > scrollOffset) {
|
||||
offset = 65
|
||||
} else {
|
||||
offset = 0
|
||||
}
|
||||
$('body,html').animate({
|
||||
scrollTop: scrollOffset - offset
|
||||
})
|
||||
},
|
||||
|
||||
snackbarShow: (text, showAction, duration) => {
|
||||
const sa = (typeof showAction !== 'undefined') ? showAction : false
|
||||
const dur = (typeof duration !== 'undefined') ? duration : 2000
|
||||
const position = GLOBAL_CONFIG.Snackbar.position
|
||||
const bg = document.documentElement.getAttribute('data-theme') === 'light' ? GLOBAL_CONFIG.Snackbar.bgLight : GLOBAL_CONFIG.Snackbar.bgDark
|
||||
Snackbar.show({
|
||||
text: text,
|
||||
backgroundColor: bg,
|
||||
showAction: sa,
|
||||
duration: dur,
|
||||
pos: position
|
||||
})
|
||||
},
|
||||
|
||||
initJustifiedGallery: function (selector) {
|
||||
selector.each(function (i, o) {
|
||||
if ($(this).is(':visible')) {
|
||||
$(this).justifiedGallery({
|
||||
rowHeight: 220,
|
||||
margins: 4
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
diffDate: (d, more = false) => {
|
||||
const dateNow = new Date()
|
||||
const datePost = new Date(d)
|
||||
const dateDiff = dateNow.getTime() - datePost.getTime()
|
||||
const minute = 1000 * 60
|
||||
const hour = minute * 60
|
||||
const day = hour * 24
|
||||
const month = day * 30
|
||||
|
||||
let result
|
||||
if (more) {
|
||||
const monthCount = dateDiff / month
|
||||
const dayCount = dateDiff / day
|
||||
const hourCount = dateDiff / hour
|
||||
const minuteCount = dateDiff / minute
|
||||
|
||||
if (monthCount > 12) {
|
||||
result = datePost.toLocaleDateString().replace(/\//g, '-')
|
||||
} else if (monthCount >= 1) {
|
||||
result = parseInt(monthCount) + ' ' + GLOBAL_CONFIG.date_suffix.month
|
||||
} else if (dayCount >= 1) {
|
||||
result = parseInt(dayCount) + ' ' + GLOBAL_CONFIG.date_suffix.day
|
||||
} else if (hourCount >= 1) {
|
||||
result = parseInt(hourCount) + ' ' + GLOBAL_CONFIG.date_suffix.hour
|
||||
} else if (minuteCount >= 1) {
|
||||
result = parseInt(minuteCount) + ' ' + GLOBAL_CONFIG.date_suffix.min
|
||||
} else {
|
||||
result = GLOBAL_CONFIG.date_suffix.just
|
||||
}
|
||||
} else {
|
||||
result = parseInt(dateDiff / day)
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
loadComment: (dom, callback) => {
|
||||
if ('IntersectionObserver' in window) {
|
||||
const observerItem = new IntersectionObserver((entries) => {
|
||||
if (entries[0].isIntersecting) {
|
||||
callback()
|
||||
observerItem.disconnect()
|
||||
}
|
||||
}, { threshold: [0] })
|
||||
observerItem.observe(dom)
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user