robot_wiki/amWiki/js/amWiki.search.js

297 lines
9.4 KiB
JavaScript
Raw Permalink Normal View History

2024-09-12 11:24:29 +08:00
/**
* amWiki Web端 - 全库搜索模块
* @author Tevin
*/
;
(function (win) {
'use strict';
/**
* 全局搜索
* @param {Storage} _storage
* @constructor
*/
var Search = function (_storage) {
this._storage = _storage;
this.$e = {
//显示搜索面板按钮
searchShow: $('#searchShow'),
//更新全部缓存按钮
searchUpdate: this._storage.$e.searchUpdate,
//搜索面板
searchBox: $('#searchBox'),
//搜索结果列表
results: $('#results'),
//搜索结果信息提示
resultMsg: $('#resultMsg'),
//搜素结果显示更多
resultMore: $('#resultMore'),
//搜索按钮
search: $('#search'),
//搜索文本
searchText: $('#searchText')
};
this._data = {
//搜素结果
result: [],
//单条结果的模板
template: $('#template\\:searchResult').text(),
//每页结果数
pageSize: 15,
//当前页码
pagination: 0
};
this._bindCtrl();
//用户执行重建缓存的回调
this.onNeedRebuildStorage = null;
};
/**
* 绑定用户操作
* @private
*/
Search.prototype._bindCtrl = function () {
var that = this;
//展开折叠搜索面板
this.$e.searchShow.on('click', function () {
if (that.$e.searchBox.hasClass('on')) {
that.displayBox('off');
that.$e.searchShow.trigger('searchoff');
} else {
that.displayBox('on', function () {
resetResHeight();
});
that.$e.searchShow.trigger('searchon');
}
});
//设置结果区域高度
var resetResHeight = function () {
var hOut = that.$e.searchBox.height();
var dt = that.$e.results.offset().top - that.$e.searchUpdate.offset().top;
that.$e.results.height(hOut - dt);
};
$(win).on('resize', function () {
if (that.$e.searchBox.hasClass('on')) {
resetResHeight();
}
});
//当本地浏览且存在页面挂载数据时,隐藏重建缓存按钮
if (location.protocol == 'file:' && typeof AWPageMounts != 'undefined') {
this.$e.searchUpdate.parent().addClass('off');
}
//重建缓存
this.$e.searchUpdate.on('click', function () {
//开启重建缓存时,如果存在搜索子进程,则干掉子进程
if (that._worker) {
that._worker.terminate();
that._worker = null;
that.$e.resultMsg.hide();
}
that.$e.search.prop('disabled', true);
that.$e.searchUpdate.prop('disabled', true);
that.onNeedRebuildStorage(function () {
that.$e.search.prop('disabled', false);
that.$e.searchUpdate.val('请勿频繁使用');
});
});
//更新全部缓存按钮使用的时间限制:一小时内不允许重复使用
var lastBuild = this._storage.getLastBuildTs();
if (lastBuild) {
var lave = Date.now() - lastBuild;
if (lave < 60 * 60 * 1000) {
this.$e.searchUpdate.prop('disabled', true).val('请勿频繁使用');
}
}
//点击搜索
this.$e.search.on('click', function () {
that._search();
});
this.$e.searchText.on('keyup', function (e) {
if (e.keyCode == 13) {
that._search();
}
});
//结果翻页
this.$e.resultMore.on('click', function () {
that._nextResultPage();
});
};
/**
* 显示隐藏搜索面板
* @param {String} type - on 显示 off 隐藏
* @param {Function} callback
* @public
*/
Search.prototype.displayBox = function (type, callback) {
var that = this;
var $box = this.$e.searchBox;
if (type == 'on' && !$box.hasClass('on')) {
$box
.addClass('on')
.css({
'display': 'block',
'width': '0',
'opacity': 0
})
.animate({
'width': '100%',
'opacity': 1
}, 300, 'swing', function () {
callback && callback();
});
} else if (type == 'off' && $box.hasClass('on')) {
$box
.removeClass('on')
.animate({
'width': '30%',
'opacity': 0
}, 200, 'swing', function () {
$box.removeAttr('style');
callback && callback();
});
}
};
/**
* 启动搜素
* @private
*/
Search.prototype._search = function () {
var that = this;
if (this.$e.searchText.val() == '') {
this.$e.searchText.focus();
return;
}
var words = this.$e.searchText.val();
this.$e.resultMsg.show().text('创建搜索中...');
if (typeof win.Worker !== "undefined") {
//开启一次新搜索时,如果存在搜索子进程,则干掉子进程
if (this._worker) {
this._worker.terminate();
this._worker = null;
this.$e.resultMsg.hide();
}
try {
//创建搜素子进程搜素
this._worker = new win.Worker('amWiki/js/amWiki.search.worker.js');
this._searchByWorker(words);
} catch (e) {
//在当前环境搜索
this._searchByPresent(words);
}
} else {
//在当前环境搜索
this._searchByPresent(words);
}
};
/**
* 搜索子进程通讯
* @param {String} words
* @private
*/
Search.prototype._searchByWorker = function (words) {
var that = this;
//收到子进程搜素消息
this._worker.onmessage = function (event) {
var data = event.data;
//加载成功后发送文档数据
if (data.type == 'searcher:loaded') {
that._worker.postMessage({type: 'searcher:docs', docs: that._storage.getAllDocs()});
}
//文档预处理完成后开始搜索
else if (data.type == 'searcher:ready') {
that.$e.resultMsg.show().html('正在搜索,请稍后...');
that._worker.postMessage({type: 'searcher:search', words: words});
}
//搜索结果排行
else if (data.type == 'searcher:result') {
that._data.result = data.result;
that._showResultList();
that._worker.terminate();
that._worker = null;
}
};
//子进程出错
this._worker.onerror = function (e) {
console.error(e);
this.$e.resultMsg.show().text('Sorry出错了<br/>' + e.msg);
that._worker.terminate();
that._worker = null;
};
};
/**
* 在当前环境搜索
* @param {String} words
* @private
*/
Search.prototype._searchByPresent = function (words) {
var searcher = new AWSearcher();
searcher.initDocs(this._storage.getAllDocs());
this.$e.resultMsg.show().html('正在搜索,请稍后...');
searcher.matchWords(words);
this._data.result = searcher.getResult();
this._showResultList();
};
/**
* 显示结果列表
* @private
*/
Search.prototype._showResultList = function () {
this.$e.results.children('ul').children().remove();
this.$e.resultMsg.hide();
this._data.pagination = 0;
this._nextResultPage();
};
/**
* 显示结果列表下一页
* @private
*/
Search.prototype._nextResultPage = function () {
var html = '';
var count = 0;
for (var i = this._data.pagination * this._data.pageSize, item; item = this._data.result[i]; i++) {
html += this._renderRankItem(this._data.template, item);
//超过页码跳出
if (++count >= this._data.pageSize) {
break;
}
}
this.$e.results.children('ul').append(html);
this._data.pagination++;
//如果还有结果没显示完,显示显示更多按钮
if (this._data.pagination * this._data.pageSize >= this._data.result.length) {
this.$e.resultMore.hide();
} else {
this.$e.resultMore.show();
}
};
/**
* 渲染单条模板
* @param {String} template
* @param {Object} data
* @returns {String}
* @private
*/
Search.prototype._renderRankItem = function (template, data) {
var tmpl = template;
data.time = win.tools.formatTime(data.timestamp);
delete data.timestamp;
for (var p in data) {
if (data.hasOwnProperty(p)) {
tmpl = tmpl.replace(new RegExp('{{' + p + '}}', 'g'), data[p]);
}
}
return tmpl;
};
return win.AWSearch = Search;
})(window);