HFish/docs/blog/media/gridea-search/gridea-search.js

231 lines
7.9 KiB
JavaScript
Raw Normal View History

2021-08-02 17:56:47 +08:00
/**
* 宝硕(https://github.com/renbaoshuo) 修改自 https://github.com/tangkaichuan/gridea-search
*/
(function () {
//获取url参数
function getParam(url, param) {
if (url.indexOf('?') > -1) {
var urlSearch = url.split('?');
var paramList = urlSearch[1].split('&');
for (var i = paramList.length - 1; i >= 0; i--) {
var temp = paramList[i].split('=');
if (temp[0] === param) {
return temp[1];
}
}
} else {
return "";
}
}
//获取解码后的搜索词
function getQueryPhrase() {
if(window.location.href.indexOf('?') == -1) return "";
var phrase = getParam(window.location.href, 'q');
var queryPhrase = decodeURIComponent(phrase.replace(/\+/g, ' '));
return queryPhrase;
}
//填充搜索输入框
function fillSearchInput() {
var searchForm = document.getElementById('gridea-search-form');
var searchInput = searchForm.getElementsByTagName('input')[0];
searchInput.value = getQueryPhrase();
}
//Ajax异步GET请求
function ajax(obj) {
var xhr = new XMLHttpRequest();
xhr.open('get', obj.url, true);
xhr.send(null);
xhr.onreadystatechange = function () {
//异步请求响应状态为4数据加载完毕
if (xhr.readyState === 4) {
if (xhr.status === 200) {
obj.success(xhr.responseText);
} else {
obj.error(xhr.status);
}
}
}
}
//模糊搜索 https://github.com/krisk/fuse
function fuzzySearch(data, phrase) {
var options = {
includeMatches: true,
ignoreLocation: true,
keys: [
'title',
'content'
]
};
var fuse = new Fuse(data, options);
var fuzzyResult = fuse.search(phrase);
return fuzzyResult;
}
//检查缓存是否最新
function checkCache() {
var caches = {};
caches.infos = JSON.parse(localStorage.getItem('InfosCache'));
caches.contents = JSON.parse(localStorage.getItem('ContentsCache'));
if (caches.infos && caches.contents) {
var cachedTime = caches.infos.utils.now.toString();
var updateTime = document.getElementById('gridea-search-result').getAttribute('data-update');
if (cachedTime === updateTime) {
return caches;
}
}
localStorage.removeItem('InfosCache');
localStorage.removeItem('ContentsCache');
return false;
}
//获取博客全文api
function getContents(callback) {
var caches = checkCache();
if (caches) {
callback(caches.contents);
}
else {
ajax({
url: '../api-content/index.html' + "?_=" + Date.now(),
success: function (data) {
callback(JSON.parse(data));
localStorage.setItem('ContentsCache', data);
}
});
}
}
//获取博客信息api
function getInfos(callback) {
var caches = checkCache();
if (caches) {
callback(caches.infos);
}
else {
ajax({
url: '../api-info/index.html' + "?_=" + Date.now(),
success: function (data) {
callback(JSON.parse(data));
localStorage.setItem('InfosCache', data);
}
});
}
}
//根据一段文本调用模糊搜索
function searchBy(phrase, callback) {
var result = '';
var getFuzzyResult = function (data) {
result = fuzzySearch(data.posts, phrase);
callback(result);
}
//根据全文内容获取搜索结果
getContents(getFuzzyResult);
}
//显示无搜索结果
function showNoResult() {
var resultDIV = document.getElementById('gridea-search-result');
var noResult = resultDIV.getElementsByClassName('no-result')[0];
noResult.style.display = 'block';
resultDIV.innerHTML = noResult.outerHTML;
}
//根据解码后的搜索词执行搜索
function searchByPhrase(resultHandler) {
var queryPhrase = getQueryPhrase();
if (queryPhrase === '' || typeof (queryPhrase) === 'undefined') {
showNoResult();
} else {
searchBy(queryPhrase, resultHandler);
}
}
//获取搜索结果列表模板的URL
function getTemplateURL() {
var scripts = document.getElementsByTagName('script');
var templateURL = '';
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].type === 'text/ejs') {
templateURL = scripts[i].src;
return templateURL;
}
}
}
//渲染搜索结果列表ejs https://github.com/mde/ejs
function renderResult(searchedInfos) {
if (searchedInfos.posts.length > 0) {
ajax({
url: getTemplateURL(),
success: function (data) {
var resultDIV = document.getElementById('gridea-search-result');
resultDIV.innerHTML = ejs.compile(data)(searchedInfos);
}
});
} else {
showNoResult();
}
}
//搜索结果关键字高亮
function keywordHighlight(searchedContent) {
var searchedPostContent = searchedContent.item.content;//搜索结果内容预览
var preview = '... ';
for (var i = 0; i < searchedContent.matches.length; i++) {
if (searchedContent.matches[i].key === 'content') {//如果匹配到文章内容,截取关键字
var indices = searchedContent.matches[i].indices[0];
var beforeKeyword = searchedPostContent.substring(indices[0] - 20, indices[0]);//关键字前10字
var keyword = searchedPostContent.substring(indices[0], indices[1] + 1);//关键字
var afterKeyword = searchedPostContent.substring(indices[1] + 1, indices[1] + 120);//关键字后70字
preview = beforeKeyword + '<span class="searched-keyword">'
+ keyword + '</span>' + afterKeyword;
} else {//没有匹配到文章内容则是标题直接截取前80字
preview = searchedPostContent.substring(0, 80);
}
}
return preview + ' ...';
}
//循环匹配搜索到的内容与展示信息
function getResult(infos, searchedContents) {
var searchedInfos = JSON.parse(JSON.stringify(infos));//对象深拷贝
searchedInfos.posts = [];
for (var i = 0; i < searchedContents.length; i++) {
for (var j = 0; j < infos.posts.length; j++) {
if (searchedContents[i].item.link === infos.posts[j].link) {
infos.posts[j].searchedPreview = keywordHighlight(searchedContents[i]);// 预览关键字高亮
infos.posts[j].content = searchedContents[i].item.content;// content注入
searchedInfos.posts.push(infos.posts[j]);// push到所需结果中
}
}
}
return searchedInfos;
}
//主方法
function grideaSearch() {
//搜索结果回调
var resultHandler = function (searchedContents) {
getInfos(function (infos) {
// console.log(infos);
// console.log(searchedContents);
var searchedInfos = getResult(infos, searchedContents);
renderResult(searchedInfos);
});
}
searchByPhrase(resultHandler);
}
//页面加载完执行
window.onload = function () {
fillSearchInput();
grideaSearch();
}
})();