You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
11 KiB
JavaScript

5 years ago
/**
* Created by Xiaotao.Nie on 09/04/2018.
* All right reserved
* IF you have any question please email onlythen@yeah.net
*/
// Global functions and listeners
window.onresize = () => {
// when window resize , we show remove some class that me be added
// often for debug
if(window.document.documentElement.clientWidth > 680){
let aboutContent = document.getElementById('nav-content')
aboutContent.classList.remove('hide-block')
aboutContent.classList.remove('show-block');
}
// if(window.isPost){
// reLayout()
// }
reHeightToc();
};
// Nav switch function on mobile
/*****************************************************************************/
const navToggle = document.getElementById('site-nav-toggle');
navToggle.addEventListener('click', () => {
let aboutContent = document.getElementById('nav-content')
if (!aboutContent.classList.contains('show-block')) {
aboutContent.classList.add('show-block');
aboutContent.classList.remove('hide-block')
} else {
aboutContent.classList.add('hide-block')
aboutContent.classList.remove('show-block');
}
})
// global search
/*****************************************************************************/
const searchButton = document.getElementById('search')
const searchField = document.getElementById('search-field')
const searchInput = document.getElementById('search-input')
const searchResultContainer = document.getElementById('search-result-container')
const escSearch = document.getElementById('esc-search')
const beginSearch = document.getElementById('begin-search')
searchField.addEventListener('mousewheel',(e) => {
// e.preventDefault()
e.stopPropagation()
return false
}, false)
var searchJson;
var caseSensitive = false
searchButton.addEventListener('click', () => {
search()
});
escSearch.addEventListener('click',() => {
hideSearchField()
})
beginSearch.addEventListener('click',() => {
let keyword = searchInput.value;
if(keyword){
searchFromKeyWord(keyword)
}
})
function toggleSeachField(){
if (!searchField.classList.contains('show-flex-fade')) {
showSearchField()
} else {
hideSearchField()
}
}
function showSearchField() {
searchInput.focus()
searchField.classList.add('show-flex-fade');
searchField.classList.remove('hide-flex-fade');
}
function hideSearchField(){
window.onkeydown = null;
searchField.classList.add('hide-flex-fade');
searchField.classList.remove('show-flex-fade');
}
function searchFromKeyWord(keyword = ""){
let result = [];
let sildeWindowSize = 100;
let handleKeyword = keyword
if(!caseSensitive){
handleKeyword = keyword.toLowerCase()
}
if(!searchJson) return -1;
else {
searchJson.forEach((item) => {
if(!item.title || !item.content) return 0; // break
let title = item.title
let content = item.content.trim().replace(/<[^>]+>/g,"").replace(/[`#\n]/g,"");
let lowerTitle = title,lowerContent = content;
if(!caseSensitive){
lowerTitle = title.toLowerCase();
lowerContent = content.toLowerCase();
}
if(lowerTitle.indexOf(handleKeyword) !== -1 || lowerContent.indexOf(handleKeyword) !== -1){
let resultItem = {}
resultItem.title = title.replace(keyword, "<span class='red'>" + keyword + '</span>');
resultItem.url = item.url;
resultItem.content = [];
let lastend = 0
while(lowerContent.indexOf(handleKeyword) !== -1){
let begin = lowerContent.indexOf(handleKeyword) - sildeWindowSize / 2 < 0 ? 0 : lowerContent.indexOf(handleKeyword) - sildeWindowSize / 2
let end = begin + sildeWindowSize;
let reg = caseSensitive ? new RegExp('('+keyword+')','g') : new RegExp('('+keyword+')','ig')
resultItem.content.push("..." + content.slice(lastend + begin, lastend + end).replace(reg, "<span class='red'>$1</span>") + "...")
lowerContent = lowerContent.slice(end, lowerContent.length)
lastend = end
}
// resultItem.title = title.replace(keyword, "<span class='red'>" + keyword + '</span>');
result.push(resultItem)
}
})
}
if(!result.length){
searchResultContainer.innerHTML = `
<div class="no-search-result">No Result</div>
`
return;
}
let searchFragment = document.createElement('ul')
for(let item of result){
let searchItem = document.createElement('li');
let searchTitle = document.createElement('a');
searchTitle.href = item.url
searchTitle.innerHTML = item.title;
searchItem.appendChild(searchTitle)
if(item.content.length) {
let searchContentLiContainer = document.createElement('ul')
for (let citem of item.content) {
let searchContentFragment = document.createElement('li')
searchContentFragment.innerHTML = citem;
searchContentLiContainer.appendChild(searchContentFragment)
}
searchItem.appendChild(searchContentLiContainer)
}
searchFragment.appendChild(searchItem)
}
while(searchResultContainer.firstChild){
searchResultContainer.removeChild(searchResultContainer.firstChild)
}
searchResultContainer.appendChild(searchFragment)
}
function search(){
toggleSeachField()
window.onkeydown = (e) => {
if (e.which === 27) {
/** 这里编写当ESC按下时的处理逻辑 */
toggleSeachField()
} else if(e.which === 13){
// 回车按下
let keyword = searchInput.value;
if(keyword){
searchFromKeyWord(keyword)
}
}
}
if(!searchJson){
let isXml;
let search_path = window.hexo_search_path;
if (search_path.length === 0) {
search_path = "search.json";
} else if (/json$/i.test(search_path)) {
isXml = false;
}
let path = window.hexo_root+ search_path;
$.ajax({
url: path,
dataType: isXml ? "xml" : "json",
async: true,
success: function (res) {
searchJson = isXml ? $("entry", res).map(function() {
return {
title: $("title", this).text(),
content: $("content",this).text(),
url: $("url" , this).text()
};
}).get() : res;
}
});
}
}
// directory function in post pages
/*****************************************************************************/
function getDistanceOfLeft(obj) {
let left = 0;
let top = 0;
while (obj) {
left += obj.offsetLeft;
top += obj.offsetTop;
obj = obj.offsetParent;
}
return {
left:left,
top:top
};
}
var toc = document.getElementById('toc')
var tocToTop = getDistanceOfLeft(toc).top;
function reHeightToc(){
if(toc) { // resize toc height
toc.style.height = ( document.documentElement.clientHeight - 10 ) + 'px';
toc.style.overflowY = 'scroll';
}
}
reHeightToc();
if(window.isPost){
var result = []
var nameSet = new Set();
if(!toc || !toc.children || !toc.children[0]){
// do nothing
}
else {
if (toc.children[0].nodeName === "OL") {
let ol = Array.from(toc.children[0].children)
function getArrayFromOl(ol) {
let result = []
// let escape = function (item) {
// return item.replace(/<[^>]+>/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/[\. _]/g, '-')
// }
ol.forEach((item) => {
if (item.children.length === 1) {
// TODO: need change
let value = item.children[0].getAttribute('href').replace(/^#/,"")
result.push({
value: [value],
dom: item
})
nameSet.add(value)
}
else {
let concatArray = getArrayFromOl(Array.from(item.children[1].children))
nameSet.add(item.children[0].getAttribute('href').replace(/^#/,""))
result.push({
value: [item.children[0].getAttribute('href').replace(/^#/,"")].concat(concatArray.reduce((p, n) => {
p = p.concat(n.value)
return p;
}, [])),
dom: item
})
result = result.concat(concatArray)
}
})
return result
}
result = getArrayFromOl(ol)
}
var nameArray = Array.from(nameSet)
function reLayout() {
let scrollToTop = document.documentElement.scrollTop || window.pageYOffset // Safari is special
if(tocToTop === 0) {
// Fix bug that when resize window the toc layout may be wrong
toc = document.getElementById('toc')
toc.classList.remove('toc-fixed')
tocToTop = getDistanceOfLeft(toc).top;
}
if (tocToTop <= scrollToTop + 10) {
if (!toc.classList.contains('toc-fixed'))
toc.classList.add('toc-fixed')
} else {
if (toc.classList.contains('toc-fixed'))
toc.classList.remove('toc-fixed')
}
let minTop = 9999;
let minTopsValue = ""
for (let item of nameArray) {
let dom = document.getElementById(item) || document.getElementById(item.replace(/\s/g, ''))
if (!dom) continue
let toTop = getDistanceOfLeft(dom).top - scrollToTop;
if (Math.abs(toTop) < minTop) {
minTop = Math.abs(toTop)
minTopsValue = item
}
// console.log(minTopsValue, minTop)
}
if (minTopsValue) {
for (let item of result) {
if (item.value.indexOf(minTopsValue) !== -1) {
item.dom.classList.add("active")
} else {
item.dom.classList.remove("active")
}
}
}
}
reLayout()
window.addEventListener('scroll', (e) => {
reLayout()
})
}
}