添加模糊查找功能

This commit is contained in:
fofolee 2019-05-07 19:24:58 +08:00
parent f0d73ed3d5
commit 63356a5054
5 changed files with 74 additions and 112 deletions

View File

@ -1,8 +1,3 @@
// 正则转义
escapeRe = s => {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
// html实体编码 // html实体编码
escapeHtml = s => { escapeHtml = s => {
return s.replace(/</g, "&lt;") return s.replace(/</g, "&lt;")
@ -11,60 +6,46 @@ escapeHtml = s => {
.replace(/'/g, "&apos;"); .replace(/'/g, "&apos;");
} }
// 列表
list = (path, initial, type, name ,desc) => {
return `<div class='info' path='${path}'>
<div class="initial">${initial}</div>
<div class="type">${type}</div>
<div class="name">${name}</div>
<div class="description">${desc}</div>
</div>`
}
// 显示列表 // 显示列表
showList = (text, index, listnum) => { showList = (text, index, listnum) => {
window.ResultList = []; window.infoRows = [];
window.ResultIndex = []; var topRows = [],
var obn = []; tailRows = [];
var obd = [];
index.forEach(i => { index.forEach(i => {
let reg = new RegExp(escapeRe(text), "i",) let displayName = escapeHtml(i.name),
match1 = reg.exec(i.name), displatDesc = i.desc != undefined ? escapeHtml(i.desc) : "",
match2 = reg.exec(i.desc), displayType = i.type != undefined ? escapeHtml(i.type) : "",
name = escapeHtml(i.name), upName = i.name.toUpperCase(),
desc = i.desc != undefined ? escapeHtml(i.desc) : "", upDesc = i.desc.toUpperCase(),
type = i.type != undefined ? escapeHtml(i.type) : ""; initial = upName.slice(0, 1),
let initial = i.name.slice(0, 1).toUpperCase(); topRow = true,
// let initial = /^([a-zA-Z])/.exec(i.name); matched = true;
// initial = initial ? initial[1].toUpperCase() : '*'; // 多关键词搜索
// 优先显示名称匹配的内容 text.trim().split(' ').forEach(keyword => {
if (match1) { upName.includes(keyword) || (topRow = false);
name = highlightList(name, match1[0]); (upName.includes(keyword) || upDesc.includes(keyword)) || (matched = false);
if (match2) desc = highlightList(desc, match2[0]); })
// 置顶全字匹配的内容 var list = `<div class='info' path='${i.path}'>
if (i.name.toUpperCase() == text.toUpperCase()) { <div class="initial">${initial}</div>
obn.unshift(list(i.path, initial, type, name, desc)); <div class="type">${displayType}</div>
window.ResultIndex.push(i); <div class="name">${displayName}</div>
} else { <div class="description">${displatDesc}</div>
obn.push(list(i.path, initial, type, name, desc)); </div>`
window.ResultIndex.push(i); // 排序规则:置顶全字匹配,优先显示名称匹配
} topRow && ((upName == text) && topRows.unshift(list) || topRows.push(list)) || (matched && tailRows.push(list));
// 其次显示描述匹配的内容
} else if (match2) {
desc = highlightList(desc, match2[0]);
obd.push(list(i.path, initial, type, name, desc));
}
}); });
window.ResultList = obn.concat(obd); window.infoRows = topRows.concat(tailRows);
$("#mainlist").html(window.ResultList.slice(0, listnum).join('')); $("#mainlist").html(window.infoRows.slice(0, listnum).join(''));
let num = $(".info").length let num = $(".info").length
utools.setExpendHeight(num > 11 ? 550 : 50 * num); utools.setExpendHeight(num > 11 ? 550 : 50 * num);
$(".select").removeClass('select'); $(".select").removeClass('select');
$(".info:first").addClass('select'); $(".info:first").addClass('select');
$('html').getNiceScroll().resize();
// 鼠标锁,方式鼠标抢占选择条 // 鼠标锁,方式鼠标抢占选择条
window.mouseLockTime = new Date().getTime(); window.mouseLockTime = new Date().getTime();
} }
// 显示手册 // 显示手册
showManual = path => { showManual = path => {
utools.setExpendHeight(550); utools.setExpendHeight(550);
@ -106,16 +87,13 @@ showManual = path => {
// 手册/配置页搜索结果高亮 // 手册/配置页搜索结果高亮
highlightManual = (selector, text) => { highlightManual = (selector, text) => {
$(selector).removeHighlight() ; $(selector).removeHighlight('founds') ;
if (text) { if (text) {
$(selector).highlight(text); $(selector).highlight(text, 'founds');
window.findex = 0; window.findex = 0;
} }
} }
// 列表搜索结果高亮
highlightList = (string, match) => string.replace(match, `<span style="color:#ff5722">${match}</span>`)
// 初始化 // 初始化
init = () => { init = () => {
$("#mainlist").fadeOut(0); $("#mainlist").fadeOut(0);
@ -132,54 +110,30 @@ sendText = text => {
window.paste(); window.paste();
} }
// 检查升级
checkUpdate = () => {
let cv = 'v0.0.2',
pg = 'https://yuanliao.info/d/356';
if (!utools.db.get(cv)) {
$.get(pg, data => {
data = /<title>\[插件\]\[程序员手册 (.*?)\](.*?) - 猿料<\/title>/.exec(data);
let lv = data[1],
desc = data[2];
if (lv != cv) {
options = {
type: 'info',
title: '插件有可用更新',
icon: window.getLogo(),
cancelId: 1,
message: `发现新版本 ${lv},是否前往更新?\n更新内容:\n${desc}`,
buttons: ['起驾', '朕知道了', '别再烦朕']
};
window.messageBox(options, index => {
if (index == 0) {
window.open(pg)
} else if (index == 2) {
utools.db.put({ _id: cv, data: "pass" })
}
})
}
})
}
}
// 切换列表和手册视图 // 切换列表和手册视图
toggleView = () => { toggleView = () => {
if ($("#manual").is(":hidden") && $("#mainlist").is(":visible")) { if ($("#manual").is(":hidden") && $("#mainlist").is(":visible")) {
$("#manual").fadeIn(); $("#manual").fadeIn();
$("#mainlist").fadeOut(); $("#mainlist").fadeOut();
utools.setExpendHeight(550);
} else if ($("#manual").is(":visible") && $("#mainlist").is(":hidden")) { } else if ($("#manual").is(":visible") && $("#mainlist").is(":hidden")) {
$("#manual").fadeOut(); $("#manual").fadeOut();
$("#mainlist").fadeIn(); $("#mainlist").fadeIn();
let num = $(".info").length
utools.setExpendHeight(num > 11 ? 550 : 50 * num);
} }
} }
// 加载剩余列表 // 继续加载内容
loadList = listnum => { loadList = addnum => {
if ($(window).scrollTop() >= (listnum * 50 - 550) && $(".info").length <= listnum) { if ($('#manual').is(':hidden') && $("#mainlist").is(":visible")) {
$("#mainlist").append(window.ResultList.slice(listnum).join('')); var listnum = $(".info").length;
if ($(window).scrollTop() >= (listnum * 50 - 550)) {
$("#mainlist").append(window.infoRows.slice(listnum, listnum + addnum).join(''));
$('html').getNiceScroll().resize(); $('html').getNiceScroll().resize();
} }
} }
}
// 进入插件 // 进入插件
utools.onPluginEnter( async ({ code, type, payload }) => { utools.onPluginEnter( async ({ code, type, payload }) => {
@ -249,12 +203,11 @@ utools.onPluginEnter( async ({ code, type, payload }) => {
utools.setSubInput(({ text }) => { utools.setSubInput(({ text }) => {
// 列表搜索 // 列表搜索
if ($('#manual').is(':hidden')) { if ($('#manual').is(':hidden')) {
// 空格进行多关键词搜索 showList(text.toUpperCase(), index, 500);
if (text.includes(' ')) { // 高亮结果
showList(text.split(' ').pop(), window.ResultIndex, 500) text.split(' ').forEach(keyword => {
} else { keyword && $(".name,.description").highlight(keyword, 'listFounds');
showList(text, index, 500); });
}
// 手册搜索 // 手册搜索
} else { } else {
highlightManual("#manual", text); highlightManual("#manual", text);

View File

@ -220,12 +220,12 @@ $("#options").on('click', '.selectBtn', function () {
}) })
// 保存 // 保存
$("#options").on('click', '.saveBtn', function () { $("#options").on('click', '.saveBtn', async function () {
var code = $('#code').val() var code = $('#code').val()
var allFts = getManuals(); var allFts = await getManuals();
if (code in allFts && $("#code").prop('disabled') == false) { if (code in allFts && $("#code").prop('disabled') == false) {
$('#code').css({ 'border-bottom-color': '#ec1212' }) $('#code').css({ 'border-bottom-color': '#ec1212' })
window.messageBox({ type: 'error', message: "名称与现有的手册重复!", buttons: ['朕知道了'] }) window.messageBox({ type: 'error', icon: window.logo, message: "名称与现有的手册重复!", buttons: ['朕知道了'] })
} else { } else {
var kw = $('#kw').val().split(','), var kw = $('#kw').val().split(','),
desc = $('#desc').val(), desc = $('#desc').val(),

View File

@ -85,6 +85,10 @@
border-radius: 4px; border-radius: 4px;
} }
.listFounds {
color: #FF5722;
}
.firstFound{ .firstFound{
box-shadow: 0px 0px 5px 1px #FF5722; box-shadow: 0px 0px 5px 1px #FF5722;
} }

View File

@ -1,10 +1,10 @@
{ {
"pluginName": "程序员手册", "pluginName": "程序员手册",
"description": "内置了多个实用的离线中文手册包括Linux、PHP、Python、JS、C、Vim、Git、Docker、Sql、uTools等", "description": "内置了多个实用的离线中文手册包括Linux、PHP、Python、JS等,以及提供了搜索devdocs、dash上的文档的功能",
"main": "index.html", "main": "index.html",
"homepage": "https://github.com/fofolee/uTools-Manuals", "homepage": "https://github.com/fofolee/uTools-Manuals",
"publishPage": "https://yuanliao.info/d/356", "publishPage": "https://yuanliao.info/d/356",
"version": "0.0.2", "version": "0.0.3",
"author": "云之轩", "author": "云之轩",
"logo": "logo.png", "logo": "logo.png",
"platform": [ "win32", "darwin" ], "platform": [ "win32", "darwin" ],

View File

@ -1,17 +1,30 @@
const fs = require('fs'); const { clipboard } = require('electron');
const { shell, clipboard } = require('electron');
const { dialog, BrowserWindow, nativeImage } = require('electron').remote
const path = require("path")
const { exec } = require('child_process'); const { exec } = require('child_process');
const robot = require('./robotjs') const robot = require('./robotjs')
dirname = __dirname; //-------checkUpdate------
const fs = require('fs');
const path = require("path")
const { dialog, BrowserWindow, nativeImage } = require('electron').remote
const { shell } = require('electron');
isWin = process.platform == 'win32' ? true : false; pluginInfo = JSON.parse(fs.readFileSync(path.join(__dirname, 'plugin.json')));
logo = nativeImage.createFromPath(path.join(__dirname, 'logo.png'));
messageBox = (options, callback) => {
dialog.showMessageBox(BrowserWindow.getFocusedWindow(), options, index => {
callback(index);
})
}
open = url => { open = url => {
shell.openExternal(url); shell.openExternal(url);
} }
// ------------------------
dirname = __dirname;
isWin = process.platform == 'win32' ? true : false;
openFolder = () => { openFolder = () => {
return dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), { return dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), {
@ -28,14 +41,6 @@ readFile = file =>
}); });
}); });
getLogo = () => nativeImage.createFromPath(path.join(__dirname, 'logo.png'));
messageBox = (options, callback) => {
dialog.showMessageBox(BrowserWindow.getFocusedWindow(), options, index => {
callback(index);
})
}
exists = path => { exists = path => {
return fs.existsSync(path); return fs.existsSync(path);
} }