/**
* 对数组进行排序,作为 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 = '<p></p>'
const replaceHTML = `<i class="kw">$1</i>`
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 = `<a href="${rootp}/c$url$.html"><strong>$name$</strong> - $des$</a>${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