UNPKG

hexo-theme-essence

Version:

A Simple Clean Theme for Hexo with user-friendly Navigation System.

157 lines (137 loc) 4.9 kB
import { postSearch } from './parser'; import { throttle } from '../../../../module/utils'; const dq = document.querySelector.bind(document); const headerDiv = dq('.header-inner'), searchInput = dq('.header-inner .search input'), searchBox = dq('.search-box'), searchContainer = dq('.search-container'), searchCounter = dq('.search-count'), searchResult = dq('.search-result'), searchShadow = dq('.search-shadow'), mobileSearchInput = dq('.mobile-search input'); function escapeRegExp (s) { return s.replace(/[(){}[\]|.*+?^$\\]/g, '\\$&'); } function renderSearchData (keyword, counterNode, resultNode) { keyword = keyword.trim(); let rkey = new RegExp(escapeRegExp(keyword), 'gi'); if (!keyword.trim()) { const counter = 0, html = ''; counterNode.innerHTML = `一共搜索到 ${counter} 个结果`; resultNode.innerHTML = html; } else { const data = { posts: window.searchData.posts.map(post => postSearch(post, rkey)).filter(data => data !== null), pages: window.searchData.pages.map(post => postSearch(post, rkey)).filter(data => data !== null), }; const html = [...data.pages, ...data.posts] .sort((a, b) => b.weight - a.weight).map(o => o.output).join(''); const counter = data.posts.length + data.pages.length; counterNode.innerHTML = `一共搜索到 ${counter} 个结果`; resultNode.innerHTML = html; } } var initializing_search_data = false; var search_status = 'none'; function initializeSearchData () { if (initializing_search_data) return; initializing_search_data = true; if (window.searchData === undefined) { fetch('/search.json') .then(res => res.json()) .then(function (data) { console.log('Search data initialize succeed!'); window.searchData = data; document.getElementsByClassName('search-data-status')[0].innerHTML = ''; }) .catch(function (reason) { console.error('Search data initialize failed!'); console.log(reason); document.getElementsByClassName('search-data-status')[0].innerHTML = '<span>Failed!</span>'; }); } } function bindEvent () { searchInput.addEventListener('focus', () => searchOpen('desktop'), false); searchInput.addEventListener('keyup', throttle(searchSubmit, 500), false); mobileSearchInput.addEventListener('focus', () => searchOpen('mobile'), false); mobileSearchInput.addEventListener('keyup', throttle(mobileSearchSubmit, 500), false); const searchCloseBtn = document.querySelector('.header-inner .search .search-close-icon'); searchCloseBtn.addEventListener('click', () => searchClose('desktop', true), false); const mobileSearchCloseBtn = document.querySelector('.header-inner .mobile-search .search-close-icon'); mobileSearchCloseBtn.addEventListener('click', () => searchClose('mobile', true), false); searchBox.addEventListener('click', () => searchClose(false), false); searchContainer.addEventListener('click', (e) => { e.stopPropagation(); }); } function searchOpen (type) { search_status = type; if (type === 'mobile') { headerDiv.classList.add('mobile-search-active'); searchBox.classList.add('active', 'mobile'); } else { headerDiv.classList.add('header-input-shadow'); searchBox.classList.add('active'); } searchShadow.classList.add('active'); if (!window.searchData) initializeSearchData(); } function searchClose (type, clearAll) { search_status = 'none'; if (type === 'mobile') { headerDiv.classList.remove('mobile-search-active'); searchBox.classList.remove('active', 'mobile'); if (clearAll) { mobileSearchInput.value = ''; } } else { headerDiv.classList.remove('header-input-shadow'); searchBox.classList.remove('active'); if (clearAll) { searchInput.value = ''; } } searchShadow.classList.remove('active'); if (clearAll) { searchResult.innerHTML = ''; searchCounter.innerHTML = ''; } } function searchSubmit (e) { if (search_status === 'none') searchOpen('desktop'); if (e && e.keyCode === 27) { searchClose('desktop', false); e.target.blur(); } const str = searchInput.value; if (window.searchData) { renderSearchData(str, searchCounter, searchResult); } else { initializeSearchData(); } } function mobileSearchSubmit (e) { if (search_status === 'none') searchOpen('mobile'); if (e && e.keyCode === 27) { searchClose('mobile', false); e.target.blur(); } const str = mobileSearchInput.value; if (window.searchData) { renderSearchData(str, searchCounter, searchResult); } else { initializeSearchData(); } } export function searchInit () { bindEvent(); } export function mobileSearchControl (method) { if (method === 'open') { headerDiv.classList.add('mobile-search-active'); mobileSearchInput.focus(); } else { searchClose('mobile', true); } }