UNPKG

dobo-redis

Version:
266 lines (209 loc) 6.67 kB
/* global document */ const searchId = 'LiBfqbJVcV' const searchHash = '#' + searchId const searchContainer = document.querySelector('#PkfLWpAbet') const searchWrapper = document.querySelector('#iCxFxjkHbP') const searchCloseButton = document.querySelector('#VjLlGakifb') const searchInput = document.querySelector('#vpcKVYIppa') const resultBox = document.querySelector('#fWwVHRuDuN') function showResultText (text) { resultBox.innerHTML = `<span class="search-result-c-text">${text}</span>` } function hideSearch () { // eslint-disable-next-line no-undef if (window.location.hash === searchHash) { // eslint-disable-next-line no-undef history.go(-1) } // eslint-disable-next-line no-undef window.onhashchange = null if (searchContainer) { searchContainer.style.display = 'none' } } function listenCloseKey (event) { if (event.key === 'Escape') { hideSearch() // eslint-disable-next-line no-undef window.removeEventListener('keyup', listenCloseKey) } } function showSearch () { try { // Closing mobile menu before opening // search box. // It is defined in core.js // eslint-disable-next-line no-undef hideMobileMenu() } catch (error) { console.error(error) } // eslint-disable-next-line no-undef window.onhashchange = hideSearch // eslint-disable-next-line no-undef if (window.location.hash !== searchHash) { // eslint-disable-next-line no-undef history.pushState(null, null, searchHash) } if (searchContainer) { searchContainer.style.display = 'flex' // eslint-disable-next-line no-undef window.addEventListener('keyup', listenCloseKey) } if (searchInput) { searchInput.focus() } } async function fetchAllData () { // eslint-disable-next-line no-undef const { hostname, protocol, port } = location // eslint-disable-next-line no-undef const base = protocol + '//' + hostname + (port !== '' ? ':' + port : '') + baseURL // eslint-disable-next-line no-undef const url = new URL('data/search.json', base) const result = await fetch(url) const { list } = await result.json() return list } // eslint-disable-next-line no-unused-vars function onClickSearchItem (event) { const target = event.currentTarget if (target) { const href = target.getAttribute('href') || '' let elementId = href.split('#')[1] || '' let element = document.getElementById(elementId) if (!element) { elementId = decodeURI(elementId) element = document.getElementById(elementId) } if (element) { setTimeout(function () { // eslint-disable-next-line no-undef bringElementIntoView(element) // defined in core.js }, 100) } } } function buildSearchResult (result) { let output = '' const removeHTMLTagsRegExp = /(<([^>]+)>)/ig for (const res of result) { const { title = '', description = '' } = res.item const _link = res.item.link.replace('<a href="', '').replace(/">.*/, '') const _title = title.replace(removeHTMLTagsRegExp, '') const _description = description.replace(removeHTMLTagsRegExp, '') output += ` <a onclick="onClickSearchItem(event)" href="${_link}" class="search-result-item"> <div class="search-result-item-title">${_title}</div> <div class="search-result-item-p">${_description || 'No description available.'}</div> </a> ` } return output } function getSearchResult (list, keys, searchKey) { const defaultOptions = { shouldSort: true, threshold: 0.4, location: 0, distance: 100, maxPatternLength: 32, minMatchCharLength: 1, keys } const options = { ...defaultOptions } // eslint-disable-next-line no-undef const searchIndex = Fuse.createIndex(options.keys, list) // eslint-disable-next-line no-undef const fuse = new Fuse(list, options, searchIndex) const result = fuse.search(searchKey) if (result.length > 20) { return result.slice(0, 20) } return result } function debounce (func, wait, immediate) { let timeout return function () { const args = arguments clearTimeout(timeout) timeout = setTimeout(() => { timeout = null if (!immediate) { // eslint-disable-next-line consistent-this, no-invalid-this func.apply(this, args) } }, wait) if (immediate && !timeout) { // eslint-disable-next-line consistent-this, no-invalid-this func.apply(this, args) } } } let searchData async function search (event) { const value = event.target.value const keys = ['title', 'description'] if (!resultBox) { console.error('Search result container not found') return } if (!value) { showResultText('Type anything to view search result') return } if (!searchData) { showResultText('Loading...') try { // eslint-disable-next-line require-atomic-updates searchData = await fetchAllData() } catch (e) { console.log(e) showResultText('Failed to load result.') return } } const result = getSearchResult(searchData, keys, value) if (!result.length) { showResultText('No result found! Try some different combination.') return } // eslint-disable-next-line require-atomic-updates resultBox.innerHTML = buildSearchResult(result) } function onDomContentLoaded () { const searchButton = document.querySelectorAll('.search-button') const debouncedSearch = debounce(search, 300) if (searchCloseButton) { searchCloseButton.addEventListener('click', hideSearch) } if (searchButton) { searchButton.forEach(function (item) { item.addEventListener('click', showSearch) }) } if (searchContainer) { searchContainer.addEventListener('click', hideSearch) } if (searchWrapper) { searchWrapper.addEventListener('click', function (event) { event.stopPropagation() }) } if (searchInput) { searchInput.addEventListener('keyup', debouncedSearch) } // eslint-disable-next-line no-undef if (window.location.hash === searchHash) { showSearch() } } // eslint-disable-next-line no-undef window.addEventListener('DOMContentLoaded', onDomContentLoaded) // eslint-disable-next-line no-undef window.addEventListener('hashchange', function () { // eslint-disable-next-line no-undef if (window.location.hash === searchHash) { showSearch() } })