/** * 对数组进行排序,作为 Array.sort() 回调函数使用 */ const sortArray = function (a, b) { return a.nIdx - b.nIdx; } /** * 判断 indexOf() 是否捕获到了搜索词 * @returns {boolean} 是否捕获 */ function indexOfCatch(a) { return a > -1 } (function () { class Commands { query = '' query_size = 5 //搜索框结果显示5条 page_size = 50 //每页显示20条 $$(id) { return document.getElementById(id) } constructor() { function $$(id) { return document.getElementById(id) } this.commands = linux_commands || []; this.elm_query = $$('query'); this.elm_btn = $$('search_btn'); this.elm_result = $$('result'); this.elm_search_result = $$('search_list_result'); // 获取根路径 this.root_path = (function () { let elm_path = $$('current_path'); let url = window.location.origin + window.location.pathname; return elm_path ? url.replace(/\/(c\/)?(\w|-)+\.html/, '').replace(/\/$/, '') : ''; })(); this.init(); this.goToIndex(); } /** * 前往主页 * @memberof Commands */ goToIndex() { let elma = document.getElementsByTagName('A'); for (let i = 0; i < elma.length; i++) { if (elma[i].pathname === '/' && !/^https?:/i.test(elma[i].protocol)) { elma[i].href = this.root_path + '/'; } } } /** * 绑定事件 * 该函数有兼容性处理 * @param {HTMLElement} element 需要绑定事件的元素 * @param {*} type 需要绑定的类型 * @param {*} callback 事件触发回调 * @memberof Commands */ bindEvent(element, type, callback) { if (element.addEventListener) { element.addEventListener(type, callback, false); } else if (element.attachEvent) { element.attachEvent('on' + type, callback); } } isSreachIndexOF(oldstr, kw) { if (!oldstr || !kw) return -1; return oldstr.toLowerCase().indexOf(kw.toLowerCase()); } //获取URL上面的参数 getQueryString(name) { let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); let r = decodeURIComponent(window.location.hash.replace(/^(\#\!|\#)/, '')).match(reg); if (r != null) return unescape(r[2]); return null; } /** * 通过 window.history 设置地址栏的地址 * @memberof Commands */ pushState() { if (window.history && window.history.pushState) if (this.query) { history.pushState({}, "linux_commands", `#!kw=${this.query}`) } else { history.pushState({}, "linux_commands", window.location.pathname); } } /** * 一个简单的模板函数 * * @param {string} str 传入的 HTML 模板 * @param {object} obj 一个对象,用于放置在 HTML 模板中 * @return {string} 经过处理的 HTML 模板 * @memberof Commands */ simple(str, obj) { return str.replace(/\$\w+\$/gi, function (matchs) { let returns = obj[matchs.replace(/\$/g, "")]; return typeof returns === "undefined" ? "" : returns; }) } /**创建 keyworlds HTML * @param {*} json 根据这段 JSON 生成 * @param {*} keywolds 关键字 * @param {*} islist 表示这是否是一个列表 * @return {*} 返回一个 HTML 字符串 */ createKeyworldsHTML(json, keywolds, islist) { const listHTML = '

' const replaceHTML = `$1` let name = json.n let des = json.d let reg = new RegExp(`(${keywolds})`, "ig") if (keywolds) { name = json.n.replace(reg, replaceHTML); des = json.d.replace(reg, replaceHTML) || ''; } let rootp = this.root_path.replace(/\/$/, ''); const str = `$name$ - $des$${islist ? listHTML : ''}` return this.simple(str, { name, url: json.p, des }); } /**搜索结果 * @param {boolean} islist 是否为列表*/ searchResult(islist = false) { let arr = this.commands const self = this let page_size = arr.length let arrResultHTML = [] const show_list_count = islist ? this.page_size : this.query_size; let nameArr = [], desArr = []; if (indexOfCatch(arr && arr.length && toString.call(arr).indexOf('Array'))) { for (let i = 0; i < page_size; i++) { if (!arr[i]) break; const nIdx = self.isSreachIndexOF(arr[i].n, self.query); const dIdx = self.isSreachIndexOF(arr[i].d, self.query); let json = arr[i]; if (indexOfCatch(nIdx)) { json.nIdx = nIdx; nameArr.push(json); } else if (indexOfCatch(dIdx)) { json.dIdx = dIdx; desArr.push(json); } } } nameArr.sort(sortArray); desArr.sort(sortArray); const resultData = nameArr.concat(desArr).slice(0, show_list_count); resultData.forEach(a => { arrResultHTML.push(self.createKeyworldsHTML(a, self.query, islist)); }) /** @type {HTMLElement} */ let elm = islist ? this.elm_search_result : this.elm_result; elm.innerHTML = '' arrResultHTML.forEach((result, i) => { const el = document.createElement('li') el.innerHTML = result elm.appendChild(el); }) if (!arrResultHTML.length) { const noResultTipHTML = document.createElement("LI"); const tipSpan = document.createElement("span") const nullQueryStringTips = `请尝试输入一些字符,进行搜索!` const undefinedQueryTips = `没有搜索到任何内容,请尝试输入其它字符!` tipSpan.innerText = this.query ? undefinedQueryTips : nullQueryStringTips noResultTipHTML.appendChild(tipSpan); elm.appendChild(noResultTipHTML); } } /** * 移动搜索结果的光标 * @param {"up"|"down"} type 触发事件类型 * @memberof Commands */ selectedResult(type) { /** @type {Array} */ let items = this.elm_result.children; let index = 0; for (var i = 0; i < items.length; i++) { if (items[i].className == 'ok') { items[i].className = ''; if (type == 'up') index = i - 1; else index = i + 1; break; }; }; if (items[index]) items[index].className = 'ok'; } // 是否选中搜索结果 isSelectedResult() { let items = this.elm_result.children; let isSel = false; for (let i = 0; i < items.length; i++) { if (items[i].className == 'ok') { isSel = items[i]; break; }; }; return isSel; } init() { /** * 设定搜索结果的 CSS display 属性 * * @param {string} [inputDisplay='none'] */ function setdisplay(inputDisplay) { self.elm_result.style.display = inputDisplay || 'none' } let self = this; let kw = self.getQueryString('kw'); this.elm_query.value = kw; this.query = kw || ''; if (this.elm_search_result) self.searchResult(true); this.bindEvent(this.elm_query, 'input', function (e) { self.query = e.target.value; self.pushState() if (self.query) { self.searchResult(); } else { setdisplay() } if (!self.elm_search_result) { setdisplay(self.query ? 'block' : 'none') } else { self.elm_btn.click(); } }) this.bindEvent(this.elm_btn, 'click', function (e) { setdisplay(); if (self.elm_search_result) self.searchResult(true); else window.location.href = self.root_path + '/list.html#!kw=' + self.query; }) this.bindEvent(this.elm_query, 'focus', function (e) { self.searchResult(); if (self.query) setdisplay('block'); }) this.bindEvent(this.elm_query, 'blur', function (e) { setTimeout(function () { setdisplay(); }, 300) }) // 输入Enter键 this.bindEvent(document, 'keyup', function (e) { if (e.keyCode === 40) self.selectedResult("down"); if (e.keyCode === 38) self.selectedResult("up"); if (e.key == 'Enter') { let item = self.isSelectedResult(); if (!item) return self.elm_btn.click(); if (item.children[0]) item.children[0].click(); } }) if (kw) self.searchResult(); } } new Commands() })()