1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| export default { data() { return { searchText: '', matches: [], currentMatch: -1, isShowCustomSearch: false } }, created() { this.initCustomSearch() }, methods: { reset(isShowCustomSearch = false) { this.searchText = '' this.matches = [] this.currentMatch = -1 this.isShowCustomSearch = isShowCustomSearch CSS.highlights.clear() }, goPrev() { if (!this.matches.length) return if (this.currentMatch > 0) { this.currentMatch-- } else { this.currentMatch = this.matches.length - 1 } this.highlightMatch() }, goNext() { if (!this.matches.length) return if (this.currentMatch < this.matches.length - 1) { this.currentMatch++ } else { this.currentMatch = 0 } this.highlightMatch() }, highlightMatch() { const range = new Range() const { word, parentNode, offset } = this.matches[this.currentMatch] range.setStart(parentNode, offset) range.setEnd(parentNode, offset + word.length) document.getSelection().removeAllRanges() document.getSelection().addRange(range) const targetSelector = document.getSelection() if (targetSelector && targetSelector.focusNode && targetSelector.focusNode.parentElement) { targetSelector.focusNode.parentElement.scrollIntoView() } }, highlightAllMatches() { const ranges = [] for (const item of this.matches) { const range = new Range() const { word, parentNode, offset } = item range.setStart(parentNode, offset) range.setEnd(parentNode, offset + word.length) ranges.push(range) } const highlight = new Highlight(...ranges) CSS.highlights.set('custom-search-highlight', highlight) }, search() { this.matches = [] this.currentMatch = -1 const treeWalker = document.createTreeWalker(this.$refs.qbContent, NodeFilter.SHOW_TEXT) const allTextNodes = [] let currentNode = treeWalker.nextNode() while (currentNode) { if (getComputedStyle(currentNode.parentNode).display !== 'none') { allTextNodes.push(currentNode) } currentNode = treeWalker.nextNode() } console.log(allTextNodes)
const allWords = [] const reg = new RegExp(`(?![^<]*>)(${this.searchText})`, 'gi') for (const textNode of allTextNodes) { for (const word of textNode.textContent.matchAll(reg)) { allWords.push({ word: word[0], parentNode: textNode, offset: word.index }) } } console.log(allWords) this.matches = allWords if (this.matches.length > 0) { this.currentMatch = 0 this.highlightMatch() } this.highlightAllMatches() }, initCustomSearch() { document.addEventListener('keydown', this.preventBrowserDefaultSearch) }, removeCustomSearch() { document.removeEventListener('keydown', this.preventBrowserDefaultSearch) }, preventBrowserDefaultSearch(event) { if (event.keyCode === 114 || ((event.ctrlKey || event.metaKey) && event.keyCode === 70)) { this.isShowCustomSearch = true event.preventDefault() } }, closeCustomSearch() { this.reset() }, handleCustomSearchChange(val) { if (val && !this.isLoading) { this.search() } if (!val) { this.reset(true) } } }, }
|