-
Notifications
You must be signed in to change notification settings - Fork 1
/
SHRT.js
259 lines (227 loc) · 6.86 KB
/
SHRT.js
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/* Original JavaScript code by Chirp Internet: www.chirp.com.au
Modified by Musuda Alitsi [email protected] on 02-March-2017
Please acknowledge use of this code by including this header.
SHRT - Search_Highlight_Replace_Text
parameters
id = the id of the tag you want searched
tag= the tag you want used for highlighting
URL - https://github.com/mashtullah/Search_Highlight_Replace_Text
Demo - https://mashtullah.github.io/Search_Highlight_Replace_Text/
*/
function SHRT(id, tag)
{
var targetNode = document.getElementById(id) || document.body;
var hiliteTag = tag || "EM";
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM|SPAN)$");
var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
var wordColor = [];
var colorIdx = 0;
var matchRegex = "";
var openLeft = false;
var openRight = false;
var words=[];
var replacedWords=[];
var replacedNodes=[];
var regIndex=[];
var regIndex_=[];
var replaceString="";
var replacedWords_=[];
var replacedNodes_=[];
var c=0;
var currentWordReplaced=false;
// characters to strip from start and end of the input string
var endCharRegex = new RegExp("^[^\\\w]+|[^\\\w]+$", "g");
// characters used to break up the input string into words
var breakCharRegex = new RegExp("[^\\\w'-]+", "g");
this.setMatchType = function(type)
{
switch(type)
{
case "left":
this.openLeft = false;
this.openRight = true;
break;
case "right":
this.openLeft = true;
this.openRight = false;
break;
case "open":
this.openLeft = this.openRight = true;
break;
default:
this.openLeft = this.openRight = false;
}
};
this.setRegex = function(input)
{
input = input.replace(endCharRegex, "");
input = input.replace(breakCharRegex, "|");
input = input.replace(/^\||\|$/g, "");
if(input) {
var re = "(" + input + ")";
if(!this.openLeft) re = "\\b" + re;
if(!this.openRight) re = re + "\\b";
matchRegex = new RegExp(re, "i");
words=input.split('|');
return true;
}
return false;
};
this.getRegex = function()
{
var retval = matchRegex.toString();
retval = retval.replace(/(^\/(\\b)?|\(|\)|(\\b)?\/i$)/g, "");
retval = retval.replace(/\|/g, " ");
return retval;
};
// recursively apply word highlighting
this.hiliteWords = function(node)
{
if(node === undefined || !node) return;
if(!matchRegex) return;
if(skipTags.test(node.nodeName)) return;
if(node.hasChildNodes()) {
for(var i=0; i < node.childNodes.length; i++)
this.hiliteWords(node.childNodes[i]);
}
if(node.nodeType == 3) { // NODE_TEXT
if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
if(!wordColor[regs[0].toLowerCase()]) {
wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
}
var match = document.createElement(hiliteTag);
match.appendChild(document.createTextNode(regs[0]));
match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
match.style.fontStyle = "inherit";
match.style.color = "#000";
var after = node.splitText(regs.index);
after.nodeValue = after.nodeValue.substring(regs[0].length);
node.parentNode.insertBefore(match, after);
}
};
};
// recursively replace words
this.replaceWords = function(node,rp,ind_=0)
{
if(node === undefined || !node) return;
if(!matchRegex) return;
if(skipTags.test(node.nodeName)) return;
if(node.hasChildNodes()) {
for(var i=0; i < node.childNodes.length; i++)
this.replaceWords(node.childNodes[i],rp);
}
if(node.nodeType == 3) {
if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
if(!wordColor[regs[0].toLowerCase()]) {
wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
}
var rp_="";
if(regs[0]==words[c])
{
if(c<words.length)
{
if(!currentWordReplaced){
rp_=rp;
currentWordReplaced=true;
}
var match = document.createElement(hiliteTag);
match.appendChild(document.createTextNode(rp_));
match.style.fontStyle = "inherit";
if(ind_==0)
var after = node.splitText(regs.index);
else
var after = node.splitText(ind_);
after.nodeValue = after.nodeValue.substring(regs[0].length);
node.parentNode.insertBefore(match, after);
replacedWords.push(regs[0]);
replacedNodes.push(node);
regIndex.push(regs.index);
}
c++;
if(c==words.length)
{
replacedWords=[];
replacedNodes=[];
regIndex=[];
c=0;
currentWordReplaced=false;
}
}
else{
if(c>0){
replacedWords_.push(replacedWords.join(" "));
replacedNodes_.push(replacedNodes[0]);
regIndex_.push(regIndex[0]);
replacedWords=[];
replacedNodes=[];
regIndex=[];
c=0;
}
rp_=rp;
currentWordReplaced=false;
var match = document.createElement(hiliteTag);
match.appendChild(document.createTextNode(rp_));
match.style.fontStyle = "inherit";
var after = node.splitText(regs.index);
after.nodeValue = after.nodeValue.substring(regs[0].length);
node.parentNode.insertBefore(match, after);
replacedWords.push(regs[0]);
replacedNodes.push(node);
regIndex.push(regs.index);
currentWordReplaced=true;
if(regs[0]!=words[0]){
replacedWords_.push(replacedWords.join(" "));
replacedNodes_.push(replacedNodes[0]);
regIndex_.push(regIndex[0]);
}
c++;
}
}
};
};
// remove highlighting
this.remove = function()
{
var arr = document.getElementsByTagName(hiliteTag);
while(arr.length && (el = arr[0])) {
var parent = el.parentNode;
parent.replaceChild(el.firstChild, el);
parent.normalize();
}
};
// start highlighting at target nodes
this.apply = function(input)
{
this.remove();
if(input === undefined || !input) return;
if(this.setRegex(input)) {
this.hiliteWords(targetNode);
}
};
// start replacing text at target nodes
this.replace = function(input,rp)
{
this.remove();
if(input === undefined || !input) return;
if(this.setRegex(input)) {
replaceString=rp;
this.replaceWords(targetNode,rp);
}
if(c>0){
replacedWords_.push(replacedWords.join(" "));
replacedNodes_.push(replacedNodes[0]);
regIndex_.push(regIndex[0]);
}
for(var i=0; i <replacedNodes_.length; i++)
{
this.setRegex(replaceString);
var match = document.createElement(hiliteTag);
match.appendChild(document.createTextNode(replacedWords_[i]));
match.style.fontStyle = "inherit";
var after = replacedNodes_[i].splitText(regIndex_[i]);
after.nodeValue = after.nodeValue.substring(replacedWords_[i].length);
replacedNodes_[i].parentNode.insertBefore(match, after);
after.nextSibling.remove();
}
};
}