vendor: 3,572 bytes, lines 1-98
1/* global CONFIG, NexT, pjax, LocalSearch */ 2 3document.addEventListener('DOMContentLoaded', () => { 4 if (!CONFIG.path) { 5 // Search DB path 6 console.warn('`hexo-generator-searchdb` plugin is not installed!'); 7 return; 8 } 9 const localSearch = new LocalSearch({ 10 path : CONFIG.path, 11 top_n_per_article: CONFIG.localsearch.top_n_per_article, 12 unescape : CONFIG.localsearch.unescape 13 }); 14 15 const input = document.querySelector('.search-input'); 16 const container = document.querySelector('.search-result-container'); 17 18 const inputEventFunction = () => { 19 if (!localSearch.isfetched) return; 20 const searchText = input.value.trim().toLowerCase(); 21 const keywords = searchText.split(/[-\s]+/); 22 let resultItems = []; 23 if (searchText.length > 0) { 24 // Perform local searching 25 resultItems = localSearch.getResultItems(keywords); 26 } 27 if (keywords.length === 1 && keywords[0] === '') { 28 container.innerHTML = '<div class="search-result-icon"><i class="fa fa-search fa-5x"></i></div>'; 29 } else if (resultItems.length === 0) { 30 container.innerHTML = '<div class="search-result-icon"><i class="far fa-frown fa-5x"></i></div>'; 31 } else { 32 resultItems.sort((left, right) => { 33 if (left.includedCount !== right.includedCount) { 34 return right.includedCount - left.includedCount; 35 } else if (left.hitCount !== right.hitCount) { 36 return right.hitCount - left.hitCount; 37 } 38 return right.id - left.id; 39 }); 40 const stats = CONFIG.i18n.hits.replace('${hits}', resultItems.length); 41 42 container.innerHTML = `<div class="search-stats">${stats}</div> 43 <hr> 44 <ul class="search-result-list">${resultItems.map(result => result.item).join('')}</ul>`; 45 if (typeof pjax === 'object') pjax.refresh(container); 46 } 47 }; 48 49 localSearch.highlightSearchWords(document.querySelector('.post-body')); 50 if (CONFIG.localsearch.preload) { 51 localSearch.fetchData(); 52 } 53 54 input.addEventListener('input', inputEventFunction); 55 window.addEventListener('search:loaded', inputEventFunction); 56 57 // Handle and trigger popup window 58 document.querySelectorAll('.popup-trigger').forEach(element => { 59 element.addEventListener('click', () => { 60 NexT.utils.setGutter(); 61 document.body.classList.add('search-active'); 62 // Wait for search-popup animation to complete 63 setTimeout(() => input.focus(), 500); 64 if (!localSearch.isfetched) localSearch.fetchData(); 65 }); 66 }); 67 68 // Monitor main search box 69 const onPopupClose = () => { 70 NexT.utils.setGutter('0'); 71 document.body.classList.remove('search-active'); 72 }; 73 74 document.querySelector('.search-pop-overlay').addEventListener('click', event => { 75 if (event.target === document.querySelector('.search-pop-overlay')) { 76 onPopupClose(); 77 } 78 }); 79 document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); 80 document.addEventListener('pjax:success', () => { 81 localSearch.highlightSearchWords(document.querySelector('.post-body')); 82 onPopupClose(); 83 }); 84 window.addEventListener('keydown', event => { 85 if ((event.ctrlKey || event.metaKey) && event.key === 'k') { 86 event.preventDefault(); 87 NexT.utils.setGutter(); 88 document.body.classList.add('search-active'); 89 setTimeout(() => input.focus(), 500); 90 if (!localSearch.isfetched) localSearch.fetchData(); 91 } 92 }); 93 window.addEventListener('keyup', event => { 94 if (event.key === 'Escape') { 95 onPopupClose(); 96 } 97 }); 98});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.