feat: 替換 Justified Gallery 為 flickr-justified-gallery

feat: 完全移除 jquery
feat: 清除配置文件的CDN, 默認 CDN 不再顯示在 config
feat: 切換夜間模式後, mermaid 也會切換夜間主題
feat: 移除騰訊分析
feat: 移除右下角字體調整按鈕
feat: 本地搜索可處理 json
feat: 右下角按鈕自定義順序
feat: 右小角按鈕 UI 微調
improvement: 手機端更改閲讀模式退出按鈕到右下角
improvement: photofigcaption 和 fancybox 的 figcaption 優先顯示 圖片的title屬性,然後是 alt 屬性
improvement: 首頁ui微調
improvement: 禁止一些瀏覽器會出現點擊左下角按鈕出現放大網頁的行為
improvement: js 優化
fix: 修復窗口大小改變時,導航欄的ui 可能會錯亂的 bug
fix: 修復 pjax 下, twikoo 評論獲取是上一篇評論的 bug
fix: 壓縮 html 代碼後, mermaid 顯示正常
This commit is contained in:
Jerry
2021-10-12 23:27:56 +08:00
parent 7e729cff79
commit cb82bfb7b6
34 changed files with 611 additions and 570 deletions

View File

@@ -240,4 +240,4 @@ if hexo-config('avatar.effect') == true
transform: translateX(200px)
100%
transform: translateX(0)
transform: translateX(0)

View File

@@ -246,8 +246,8 @@
max-height: calc(100% - 60px)
width: $toc-mobile-width
opacity: 0
transition: initial
transform-origin: right bottom
transition: none
.toc-percentage
float: right
@@ -317,8 +317,9 @@
border-radius: 70px
img
width: 100%
height: 100%
transition: filter 375ms ease-in 0.2s, transform .3s
transition: filter 375ms ease-in .2s, transform .3s
object-fit: cover
&:hover

View File

@@ -239,7 +239,6 @@
top: 0
z-index: 90
display: flex
flex-wrap: wrap
align-items: center
padding: 0 36px
width: 100%
@@ -335,13 +334,10 @@
font-size: inherit
.menus_items
position: absolute
left: 0
visibility: hidden
opacity: 0
display: none
#search-button span
display: none !important
display: none
#search-button
display: inline

View File

@@ -1,6 +1,6 @@
#rightside
position: fixed
right: -38px
right: -48px
bottom: $rightside-bottom
z-index: 100
opacity: 0
@@ -8,7 +8,7 @@
#rightside-config-hide
transition: transform .4s
transform: translate(35px, 0)
transform: translate(48px, 0)
&.show
transform: translate(0, 0) !important
@@ -17,17 +17,25 @@
& > button,
& > a
display: block
margin-bottom: 2px
width: 30px
height: 30px
margin-bottom: 5px
width: w = 38px
height: w
border-radius: 5px
background-color: var(--btn-bg)
color: var(--btn-color)
text-align: center
font-size: 16px
line-height: w
touch-action: manipulation
&:hover
background-color: var(--btn-hover-color)
+maxWidth768()
width: w = 34px
height: w
line-height: w
#mobile-toc-button
display: none

View File

@@ -61,16 +61,9 @@ if hexo-config('waline.bg')
.medium-zoom-overlay
z-index: 99999 !important
.mermaid
overflow: auto
.mermaid-wrap
margin: 0 0 20px
background: $white
text-align: center
opacity: 0
transition: all .3s
&[data-processed]
opacity: 1
.utterances,
.fb-comments iframe

View File

@@ -91,7 +91,6 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
// hide-tags
.hide-button,
.btn-beautify,
.mermaid,
.hl-label,
.post-outdate-notice,
.error-img,

View File

@@ -36,6 +36,7 @@ if hexo-config('readmode')
position: fixed
top: 30px
right: 30px
z-index: 100
width: 40px
height: 40px
border-radius: 8px
@@ -44,6 +45,10 @@ if hexo-config('readmode')
font-size: 16px
transition: background .3s
+maxWidth768()
top: initial
bottom: 30px
&:hover
background: var(--exit-btn-hover)

View File

@@ -54,5 +54,7 @@
#page-header.full_page
background-attachment: scroll !important
.recent-post-item
.recent-post-item,
.avatar-img,
.flink-item-icon
transform: translateZ(0)

View File

@@ -8,7 +8,7 @@
flex-direction: row
align-items: center
overflow: hidden
height: 20em
height: 18em
+maxWidth768()
flex-direction: column
@@ -24,7 +24,7 @@
.post_cover
overflow: hidden
width: 45%
width: 44%
height: 100%
+maxWidth768()
@@ -42,7 +42,7 @@
& >.recent-post-info
padding: 0 40px
width: 55%
width: 57%
+maxWidth768()
padding: 20px 20px 30px
@@ -88,13 +88,10 @@
else
display: none
.article-meta__separator
.article-meta-separator
margin: 0 6px
.article-meta__link
margin: 0 4px
.fa-angle-right
.article-meta-link
margin: 0 4px
if hexo-config('post_meta.page.date_format') == 'relative'
@@ -110,4 +107,4 @@
& > .content
@extend .limit-more-line
-webkit-line-clamp: 3
-webkit-line-clamp: 2

View File

@@ -1,107 +1,102 @@
figure.gallery-group
position: relative
float: left
overflow: hidden
margin: 6px 4px
width: calc(50% - 8px)
height: 250px
border-radius: 8px
background: $dark-black
-webkit-transform: translate3d(0, 0, 0)
+maxWidth600()
width: calc(100% - 8px)
&:hover
img
opacity: .4
transform: translate3d(0, 0, 0)
.gallery-group-name::after
transform: translate3d(0, 0, 0)
p
opacity: 1
transform: translate3d(0, 0, 0)
img
#article-container
figure.gallery-group
position: relative
margin: 0 !important
max-width: none !important
width: calc(100% + 20px)
float: left
overflow: hidden
margin: 6px 4px
width: calc(50% - 8px)
height: 250px
backface-visibility: hidden
opacity: .8
transition: all .3s, filter 375ms ease-in 0.2s !important
transform: translate3d(-10px, 0, 0)
object-fit: cover
border-radius: 8px
background: $dark-black
-webkit-transform: translate3d(0, 0, 0)
figcaption
position: absolute
top: 0
left: 0
padding: 30px
width: 100%
height: 100%
color: $gallery-color
text-transform: uppercase
backface-visibility: hidden
+maxWidth600()
width: calc(100% - 8px)
& > a
&:hover
img
opacity: .4
transform: translate3d(0, 0, 0)
.gallery-group-name::after
transform: translate3d(0, 0, 0)
p
opacity: 1
transform: translate3d(0, 0, 0)
img
position: relative
margin: 0
max-width: none
width: calc(100% + 20px)
height: 250px
backface-visibility: hidden
opacity: .8
transition: all .3s, filter 375ms ease-in .2s
transform: translate3d(-10px, 0, 0)
object-fit: cover
figcaption
position: absolute
top: 0
right: 0
bottom: 0
left: 0
z-index: 1000
opacity: 0
p
@extend .limit-more-line
margin: 0
padding: 8px 0 0
letter-spacing: 1px
font-size: 1.1em
line-height: 1.5
opacity: 0
transition: opacity .35s, transform .35s
transform: translate3d(100%, 0, 0)
-webkit-line-clamp: 4
.gallery-group-name
@extend .limit-more-line
position: relative
margin: 0
padding: 8px 0
font-weight: bold
font-size: 1.65em
line-height: 1.5
-webkit-line-clamp: 2
&:after
position: absolute
bottom: 0
left: 0
padding: 30px
width: 100%
height: 2px
background: $gallery-color
content: ''
transition: transform .35s
transform: translate3d(-100%, 0, 0)
height: 100%
color: $gallery-color
text-transform: uppercase
backface-visibility: hidden
.gallery-group-main
overflow: auto
padding: 0 0 16px
& > a
position: absolute
top: 0
right: 0
bottom: 0
left: 0
z-index: 1000
opacity: 0
.justified-gallery
margin: 0 0 16px
p
@extend .limit-more-line
margin: 0
padding: 8px 0 0
letter-spacing: 1px
font-size: 1.1em
line-height: 1.5
opacity: 0
transition: opacity .35s, transform .35s
transform: translate3d(100%, 0, 0)
-webkit-line-clamp: 4
img
.gallery-group-name
@extend .limit-more-line
position: relative
margin: 0
padding: 8px 0
font-weight: bold
font-size: 1.65em
line-height: 1.5
-webkit-line-clamp: 2
&:after
position: absolute
bottom: 0
left: 0
width: 100%
height: 2px
background: $gallery-color
content: ''
transition: transform .35s
transform: translate3d(-100%, 0, 0)
.gallery-group-main
overflow: auto
padding: 0 0 16px
.fj-gallery
margin: 0 0 16px
opacity: 0
.img-alt
display: none
.fancybox
width: auto
text-align: inherit
.img-alt
display: none

View File

@@ -1,23 +1,21 @@
document.addEventListener('DOMContentLoaded', function () {
const $blogName = document.getElementById('site-name')
let blogNameWidth = $blogName && $blogName.offsetWidth
const $menusEle = document.querySelector('#menus .menus_items')
let menusWidth = $menusEle && $menusEle.offsetWidth
const $searchEle = document.querySelector('#search-button')
let searchWidth = $searchEle && $searchEle.offsetWidth
let blogNameWidth, menusWidth, searchWidth, $nav, hideMenuIndex, mobileSidebarOpen
const adjustMenu = (change = false) => {
if (change) {
blogNameWidth = $blogName && $blogName.offsetWidth
menusWidth = $menusEle && $menusEle.offsetWidth
searchWidth = $searchEle && $searchEle.offsetWidth
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')
}
const $nav = document.getElementById('nav')
let t
if (window.innerWidth < 768) t = true
else t = blogNameWidth + menusWidth + searchWidth > $nav.offsetWidth - 120
if (t) {
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')
@@ -26,44 +24,26 @@ document.addEventListener('DOMContentLoaded', function () {
// 初始化header
const initAdjust = () => {
adjustMenu()
document.getElementById('nav').classList.add('show')
adjustMenu(true)
$nav.classList.add('show')
}
// sidebar menus
const sidebarFn = () => {
const $toggleMenu = document.getElementById('toggle-menu')
const $mobileSidebarMenus = document.getElementById('sidebar-menus')
const $menuMask = document.getElementById('menu-mask')
const $body = document.body
function openMobileSidebar () {
const sidebarFn = {
open: () => {
btf.sidebarPaddingR()
$body.style.overflow = 'hidden'
btf.fadeIn($menuMask, 0.5)
$mobileSidebarMenus.classList.add('open')
}
function closeMobileSidebar () {
document.body.style.overflow = 'hidden'
btf.fadeIn(document.getElementById('menu-mask'), 0.5)
document.getElementById('sidebar-menus').classList.add('open')
mobileSidebarOpen = true
},
close: () => {
const $body = document.body
$body.style.overflow = ''
$body.style.paddingRight = ''
btf.fadeOut($menuMask, 0.5)
$mobileSidebarMenus.classList.remove('open')
btf.fadeOut(document.getElementById('menu-mask'), 0.5)
document.getElementById('sidebar-menus').classList.remove('open')
}
$toggleMenu.addEventListener('click', openMobileSidebar)
$menuMask.addEventListener('click', e => {
if ($mobileSidebarMenus.classList.contains('open')) {
closeMobileSidebar()
}
})
window.addEventListener('resize', e => {
if (btf.isHidden($toggleMenu)) {
if ($mobileSidebarMenus.classList.contains('open')) closeMobileSidebar()
}
})
}
/**
@@ -225,7 +205,7 @@ document.addEventListener('DOMContentLoaded', function () {
function addPhotoFigcaption () {
document.querySelectorAll('#article-container img').forEach(function (item) {
const parentEle = item.parentNode
const altValue = item.alt
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'
@@ -237,7 +217,6 @@ document.addEventListener('DOMContentLoaded', function () {
/**
* Lightbox
* It needs to call it after the Justified Gallery done, or the fancybox maybe not work
*/
const runLightbox = () => {
btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)'))
@@ -245,41 +224,28 @@ document.addEventListener('DOMContentLoaded', function () {
/**
* justified-gallery 圖庫排版
* 需要 jQuery
*/
let detectJgJsLoad = false
const runJustifiedGallery = function (ele) {
const $justifiedGallery = $(ele)
const $imgList = $justifiedGallery.find('img')
$imgList.unwrap() // remove <p> tag
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>')
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' })
})
}
})
runLightbox()
if (detectJgJsLoad) {
btf.initJustifiedGallery($justifiedGallery)
if (window.fjGallery) {
btf.initJustifiedGallery(ele)
return
}
$('head').append(`<link rel="stylesheet" type="text/css" href="${GLOBAL_CONFIG.source.justifiedGallery.css}">`)
$.getScript(`${GLOBAL_CONFIG.source.justifiedGallery.js}`, () => { btf.initJustifiedGallery($justifiedGallery) })
detectJgJsLoad = true
}
const jqLoadAndRun = () => {
const $jgEle = document.querySelectorAll('#article-container .justified-gallery')
if ($jgEle.length) {
btf.isJqueryLoad(() => {
runJustifiedGallery($jgEle)
})
return
}
runLightbox()
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) })
}
/**
@@ -328,7 +294,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
$header.classList.add('nav-fixed')
if (window.getComputedStyle($rightside).getPropertyValue('opacity') === '0') {
$rightside.style.cssText = 'opacity: 1; transform: translateX(-38px)'
$rightside.style.cssText = 'opacity: 0.7; transform: translateX(-58px)'
}
} else {
if (currentTop === 0) {
@@ -338,7 +304,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
if (document.body.scrollHeight <= innerHeight) {
$rightside.style.cssText = 'opacity: 1; transform: translateX(-38px)'
$rightside.style.cssText = 'opacity: 0.7; transform: translateX(-58px)'
}
}, 200)()
}
@@ -390,9 +356,9 @@ document.addEventListener('DOMContentLoaded', function () {
}
}
const mobileToc = {
window.mobileToc = {
open: () => {
$cardTocLayout.style.cssText = 'animation: toc-open .3s; opacity: 1; right: 45px'
$cardTocLayout.style.cssText = 'animation: toc-open .3s; opacity: 1; right: 55px'
},
close: () => {
@@ -403,11 +369,6 @@ document.addEventListener('DOMContentLoaded', function () {
}
}
document.getElementById('mobile-toc-button').addEventListener('click', () => {
if (window.getComputedStyle($cardTocLayout).getPropertyValue('opacity') === '0') mobileToc.open()
else mobileToc.close()
})
// toc元素點擊
$cardToc.addEventListener('click', (e) => {
e.preventDefault()
@@ -416,7 +377,7 @@ document.addEventListener('DOMContentLoaded', function () {
: e.target.parentElement
btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI($target.getAttribute('href')).replace('#', ''))), 300)
if (window.innerWidth < 900) {
mobileToc.close()
window.mobileToc.close()
}
})
@@ -512,6 +473,7 @@ document.addEventListener('DOMContentLoaded', function () {
typeof utterancesTheme === 'function' && utterancesTheme()
typeof FB === 'object' && window.loadFBComment()
window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
typeof runMermaid === 'function' && window.runMermaid()
},
showOrHideBtn: () => { // rightside 點擊設置 按鈕 展開
document.getElementById('rightside-config-hide').classList.toggle('show')
@@ -527,22 +489,9 @@ document.addEventListener('DOMContentLoaded', function () {
$htmlDom.toggle('hide-aside')
},
adjustFontSize: (plus) => {
const fontSizeVal = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--global-font-size'))
let newValue = ''
if (plus) {
if (fontSizeVal >= 20) return
newValue = fontSizeVal + 1
document.documentElement.style.setProperty('--global-font-size', newValue + 'px')
!document.getElementById('nav').classList.contains('hide-menu') && adjustMenu(true)
} else {
if (fontSizeVal <= 10) return
newValue = fontSizeVal - 1
document.documentElement.style.setProperty('--global-font-size', newValue + 'px')
document.getElementById('nav').classList.contains('hide-menu') && adjustMenu(true)
}
saveToLocal.set('global-font-size', newValue, 2)
runMobileToc: () => {
if (window.getComputedStyle(document.getElementById('card-toc')).getPropertyValue('opacity') === '0') window.mobileToc.open()
else window.mobileToc.close()
}
}
@@ -555,6 +504,9 @@ document.addEventListener('DOMContentLoaded', function () {
case 'rightside_config':
rightSideFn.showOrHideBtn()
break
case 'mobile-toc-button':
rightSideFn.runMobileToc()
break
case 'readmode':
rightSideFn.switchReadMode()
break
@@ -564,12 +516,6 @@ document.addEventListener('DOMContentLoaded', function () {
case 'hide-aside-btn':
rightSideFn.hideAsideBtn()
break
case 'font-plus':
rightSideFn.adjustFontSize(true)
break
case 'font-minus':
rightSideFn.adjustFontSize()
break
default:
break
}
@@ -659,8 +605,8 @@ document.addEventListener('DOMContentLoaded', function () {
const $hideContent = $this.nextElementSibling
$this.classList.toggle('open')
if ($this.classList.contains('open')) {
if ($hideContent.querySelectorAll('.justified-gallery').length > 0) {
btf.initJustifiedGallery($hideContent.querySelectorAll('.justified-gallery'))
if ($hideContent.querySelectorAll('.fj-gallery').length > 0) {
btf.initJustifiedGallery($hideContent.querySelectorAll('.fj-gallery'))
}
}
})
@@ -686,7 +632,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (item.id === tabId) item.classList.add('active')
else item.classList.remove('active')
})
const $isTabJustifiedGallery = $tabContent.querySelectorAll(`#${tabId} .justified-gallery`)
const $isTabJustifiedGallery = $tabContent.querySelectorAll(`#${tabId} .fj-gallery`)
if ($isTabJustifiedGallery.length > 0) {
btf.initJustifiedGallery($isTabJustifiedGallery)
}
@@ -776,8 +722,12 @@ document.addEventListener('DOMContentLoaded', function () {
}
const unRefreshFn = function () {
window.addEventListener('resize', adjustMenu)
window.addEventListener('orientationchange', () => { setTimeout(adjustMenu(true), 100) })
window.addEventListener('resize', () => {
adjustMenu(false)
hideMenuIndex && mobileSidebarOpen && sidebarFn.close()
})
document.getElementById('menu-mask').addEventListener('click', e => { sidebarFn.close() })
clickFnOfSubMenu()
GLOBAL_CONFIG.islazyload && lazyloadImg()
@@ -798,17 +748,21 @@ document.addEventListener('DOMContentLoaded', function () {
}
GLOBAL_CONFIG_SITE.isToc && tocFn()
sidebarFn()
GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex()
addHighlightTool()
GLOBAL_CONFIG.isPhotoFigcaption && addPhotoFigcaption()
jqLoadAndRun()
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()

View File

@@ -41,107 +41,112 @@ window.addEventListener('load', () => {
searchClickFn()
})
function search (path) {
fetch(GLOBAL_CONFIG.root + path)
.then(response => response.text())
.then(str => new window.DOMParser().parseFromString(str, 'text/xml'))
.then(data => {
const datas = [...data.querySelectorAll('entry')].map(function (item) {
const content = item.querySelector('content')
return {
title: item.querySelector('title').textContent,
content: content ? content.textContent : '',
url: item.querySelector('url').textContent
}
})
const $input = document.querySelector('#local-search-input input')
const $resultContent = document.getElementById('local-search-results')
$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) 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 {
async function search (path) {
let datas = []
const typeF = path.split('.')[1]
const response = await fetch(GLOBAL_CONFIG.root + path)
if (typeF === 'json') {
datas = await response.json()
} else if (typeF === 'xml') {
const res = await response.text()
const t = await new window.DOMParser().parseFromString(res, 'text/xml')
const a = await t
datas = [...a.querySelectorAll('entry')].map(function (item) {
return {
title: item.querySelector('title').textContent,
content: item.querySelector('content').textContent,
url: item.querySelector('url').textContent
}
})
}
const $input = document.querySelector('#local-search-input input')
const $resultContent = document.getElementById('local-search-results')
$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) 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
}
// 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
if (dataContent !== '') {
str += '<p class="search-result">' + matchContent + '...</p>'
}
} else {
if (indexContent < 0) {
indexContent = 0
}
if (i === 0) {
firstOccur = indexContent
}
str += '</div>'
}
})
if (count === 0) {
str += '<div id="local-search__hits-empty">' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) +
'</div>'
} 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 < 0 ? 0 : firstOccur - 30
// let end = firstOccur + 50 > content.length ? content.length : firstOccur + 50
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
if (dataContent !== '') {
str += '<p class="search-result">' + matchContent + '...</p>'
}
}
str += '</div>'
$resultContent.innerHTML = str
window.pjax && window.pjax.refresh($resultContent)
})
}
})
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)
})
}
})

View File

@@ -72,20 +72,6 @@ const btf = {
})
},
initJustifiedGallery: function (selector) {
if (!(selector instanceof jQuery)) {
selector = $(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)
@@ -135,15 +121,11 @@ const btf = {
}
},
scrollToDest: (pos, time) => {
if (pos < 0 || time < 0) {
return
}
const currentPos = window.scrollY || window.screenTop
scrollToDest: (pos, time = 500) => {
const currentPos = window.pageYOffset
if (currentPos > pos) pos = pos - 70
if ('CSS' in window && CSS.supports('scroll-behavior', 'smooth')) {
if ('scrollBehavior' in document.documentElement.style) {
window.scrollTo({
top: pos,
behavior: 'smooth'
@@ -152,25 +134,19 @@ const btf = {
}
let start = null
time = time || 500
pos = +pos
window.requestAnimationFrame(function step (currentTime) {
start = !start ? currentTime : start
const progress = currentTime - start
if (currentPos < pos) {
const progress = currentTime - start
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos)
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
}
} else {
const progress = currentTime - start
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time))
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
}
}
if (progress < time) {
window.requestAnimationFrame(step)
} else {
window.scrollTo(0, pos)
}
})
},
@@ -226,14 +202,6 @@ const btf = {
}
},
isJqueryLoad: fn => {
if (typeof jQuery === 'undefined') {
getScript(GLOBAL_CONFIG.source.jQuery).then(fn)
} else {
fn()
}
},
isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
getEleTop: ele => {
@@ -265,14 +233,35 @@ const btf = {
ele.forEach(i => {
if (i.parentNode.tagName !== 'A') {
const dataSrc = i.dataset.lazySrc || i.src
const dataCaption = i.alt || ''
const dataCaption = i.title || i.alt || ''
btf.wrap(i, 'a', { href: dataSrc, 'data-fancybox': 'gallery', 'data-caption': dataCaption, 'data-thumb': dataSrc })
}
})
Fancybox.bind('[data-fancybox]', {
Hash: false
})
if (!window.fancyboxRun) {
Fancybox.bind('[data-fancybox]', {
Hash: false,
Thumbs: {
autoStart: false
}
})
window.fancyboxRun = true
}
}
},
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'
}
})
}
})
}
}