Files: eaffcf142a7836aa59f9b83355a378d57912fb10 / index.js
3558 bytesRaw
1 | (function (global) { |
2 | |
3 | function addAccents(str) { |
4 | // http://www.the-art-of-web.com/javascript/search-highlight/ |
5 | return str |
6 | // .replace(/([ao])e/ig, "$1") |
7 | .replace(/e/ig, "[eèéêë]") |
8 | .replace(/a/ig, "([aàâä]|ae)") |
9 | .replace(/i/ig, "[iîï]") |
10 | .replace(/o/ig, "([oôö]|oe)") |
11 | .replace(/u/ig, "[uùûü]") |
12 | .replace(/y/ig, "[yÿ]"); |
13 | } |
14 | |
15 | function setSelection(startNode, startOffset, endNode, endOffset) { |
16 | var range = document.createRange(); |
17 | range.setStart(startNode, startOffset); |
18 | range.setEnd(endNode, endOffset); |
19 | |
20 | var sel = window.getSelection(); |
21 | sel.removeAllRanges(); |
22 | sel.addRange(range); |
23 | } |
24 | |
25 | function TextNodeSearcher(container) { |
26 | this.container = container; |
27 | } |
28 | |
29 | TextNodeSearcher.prototype.setQuery = function (str) { |
30 | if (str == this.queryStr) |
31 | return; |
32 | |
33 | this.queryStr = str; |
34 | this.query = new RegExp(addAccents(str), "ig"); |
35 | }; |
36 | |
37 | function shouldDescendInto(node) { |
38 | return node.nodeName != "SCRIPT" && node.nodeName != "STYLE"; |
39 | } |
40 | |
41 | function getNextTextNode(node, container, wrap) { |
42 | outer: do { |
43 | if (shouldDescendInto(node) && node.firstChild) { |
44 | node = node.firstChild; |
45 | } else if (node.nextSibling) { |
46 | node = node.nextSibling; |
47 | } else { |
48 | do { |
49 | if (node == container) { |
50 | if (!wrap) |
51 | return null; |
52 | wrap = false; |
53 | continue outer; |
54 | } |
55 | node = node.parentNode; |
56 | } while (!node.nextSibling); |
57 | node = node.nextSibling; |
58 | } |
59 | } while (node.nodeType != Node.TEXT_NODE); |
60 | return node; |
61 | } |
62 | |
63 | function getPrevTextNode(node, container, wrap) { |
64 | do { |
65 | if (node == container) { |
66 | if (!wrap) |
67 | return null; |
68 | while (shouldDescendInto(node) && node.lastChild) |
69 | node = node.lastChild; |
70 | wrap = false; |
71 | } else if (node.previousSibling) { |
72 | node = node.previousSibling; |
73 | while (shouldDescendInto(node) && node.lastChild) |
74 | node = node.lastChild; |
75 | } else { |
76 | node = node.parentNode; |
77 | } |
78 | } while (node.nodeType != Node.TEXT_NODE); |
79 | return node; |
80 | } |
81 | |
82 | function matchLast(re, str) { |
83 | var last; |
84 | re.lastIndex = 0; |
85 | for (var m = re.exec(str); m; m = re.exec(str)) |
86 | last = m; |
87 | return last; |
88 | } |
89 | |
90 | TextNodeSearcher.prototype.selectNext = function () { |
91 | if (!this.queryStr) |
92 | return; |
93 | |
94 | var sel = window.getSelection(); |
95 | var startNode = sel.focusNode; |
96 | var startOffset = 0; |
97 | if (!startNode || startNode.nodeType != Node.TEXT_NODE || |
98 | !this.container.contains(startNode)) |
99 | startNode = getNextTextNode(startNode, this.container, true); |
100 | else |
101 | startOffset = sel.focusOffset; |
102 | |
103 | for (var node = startNode; node; |
104 | node = getNextTextNode(node, this.container, true)) { |
105 | var str = node.data; |
106 | this.query.lastIndex = startOffset; |
107 | if (startOffset) |
108 | startOffset = 0; |
109 | var m = this.query.exec(str); |
110 | if (m) { |
111 | setSelection(node, m.index, node, m.index + m[0].length); |
112 | return; |
113 | } |
114 | } |
115 | }; |
116 | |
117 | TextNodeSearcher.prototype.selectPrev = function () { |
118 | if (!this.queryStr) |
119 | return; |
120 | |
121 | var sel = window.getSelection(); |
122 | var endNode = sel.anchorNode; |
123 | var endOffset = 0; |
124 | if (!endNode || endNode.nodeType != Node.TEXT_NODE || |
125 | !this.container.contains(endNode)) |
126 | endNode = getPrevTextNode(endNode, this.container, true); |
127 | else |
128 | endOffset = sel.anchorOffset; |
129 | |
130 | for (var node = endNode; node; |
131 | node = getPrevTextNode(node, this.container, true)) { |
132 | var str = node.data; |
133 | if (endOffset < Infinity) { |
134 | str = node.data.substr(0, endOffset); |
135 | endOffset = Infinity; |
136 | } |
137 | var m = matchLast(this.query, str); |
138 | if (m) { |
139 | setSelection(node, m.index, node, m.index + m[0].length); |
140 | return; |
141 | } |
142 | } |
143 | }; |
144 | |
145 | if (global.module) |
146 | module.exports = TextNodeSearcher; |
147 | else |
148 | global.TextNodeSearcher = TextNodeSearcher; |
149 | }(this)); |
150 |
Built with git-ssb-web