YingXingAI/node_modules/mp-html/plugins/search/miniprogram/index.js

138 lines
4.0 KiB
JavaScript

/**
* @fileoverview search 插件
*/
function Search (vm) {
/**
* @description 关键词搜索
* @param {regexp|string} key 要搜索的关键词
* @param {boolean} anchor 是否将搜索结果设置为锚点
* @param {string} style 搜索结果的样式
*/
vm.search = function (key, anchor, style = 'background-color:yellow') {
const obj = {}
const stack = []
const res = [];
// 遍历搜索
(function traversal (nodes, path) {
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i]
if (node.type === 'text' && key) {
const arr = node.text.split(key)
const children = []
if (arr.length > 1) {
// 找到关键词
for (let j = 0; j < arr.length; j++) {
if (arr[j]) {
children.push({
type: 'text',
text: arr[j]
})
}
if (j !== arr.length - 1) {
// 关键词转为一个 span
res.push(`${path}[${i}].children[${children.length}].attrs.style`)
children.push({
name: 'span',
attrs: {
id: anchor ? 'search' + res.length : undefined, // 用于锚点的 id
style
},
children: [{
type: 'text',
text: key instanceof RegExp ? key.exec(node.text)[0] : key
}]
})
}
}
if (key instanceof RegExp) {
key.exec(node.text)
}
if (anchor) {
for (let l = stack.length; l--;) {
// 给父组件做标记,将该标签暴露出来
if (stack[l].c) {
break
} else {
obj[stack[l].path] = 1
}
}
}
obj[`${path}[${i}]`] = {
name: 'span',
c: anchor ? 1 : undefined,
s: 1,
children
}
}
} else if (node.s) {
let text = ''
// 复原上一次的结果
for (let k = 0; k < node.children.length; k++) {
const child = node.children[k]
if (child.text) {
text += child.text
} else {
text += child.children[0].text
}
}
nodes[i] = {
type: 'text',
text
}
if (key && (key instanceof RegExp ? key.test(text) : text.includes(key))) {
i--
} else {
obj[`${path}[${i}]`] = nodes[i]
}
} else if (node.children) {
stack.push({
path: `${path}[${i}].c`,
c: node.c || node.name === 'table'
})
traversal(node.children, `${path}[${i}].children`)
stack.pop()
}
}
})(vm.data.nodes, 'nodes')
return new Promise(function (resolve) {
vm.setData(obj, () => {
resolve({
num: res.length, // 结果数量
/**
* @description 高亮某一个结果
* @param {number} i 第几个
* @param {string} hlstyle 高亮的样式
*/
highlight (i, hlstyle = 'background-color:#FF9632') {
if (i < 1 || i > res.length) return
const obj = {}
if (this.last) {
obj[res[this.last - 1]] = style
}
this.last = i
obj[res[i - 1]] = hlstyle
vm.setData(obj)
},
/**
* @description 跳转到搜索结果
* @param {number} i 第几个
* @param {number} offset 偏移量
*/
jump: anchor
? (i, offset) => {
if (i > 0 && i <= res.length) {
vm.navigateTo('search' + i, offset)
}
}
: undefined
})
})
})
}
}
module.exports = Search