1 | /** global: UB */ |
||
2 | |||
3 | var stringFuncs = { |
||
4 | |||
5 | |||
6 | // primary search functions |
||
7 | indexOf: function(search, startAt = null){ |
||
8 | return this.smartIndexOf(search, true, true, startAt); |
||
9 | }, |
||
10 | indexOfCI: function(search, startAt = null){ |
||
11 | return this.smartIndexOf(search, false, true, startAt); |
||
12 | }, |
||
13 | smartIndexOf: function(search, caseSensitive = true, first = true, startAt = null, substringIsLower = false, wholeWords = false){ |
||
14 | var text = this; |
||
15 | |||
16 | // temps |
||
17 | var sl = search.length; |
||
18 | var ml = (text.length - sl); |
||
19 | |||
20 | // quick checks |
||
21 | if (ml < sl) { |
||
22 | return -1; |
||
23 | } |
||
24 | |||
25 | // only check equality of both strings of equal length |
||
26 | if (ml == sl) { |
||
27 | if (caseSensitive && !wholeWords) { |
||
28 | return (text == search) ? 0 : -1; |
||
29 | } |
||
30 | return text.isEqual(search, caseSensitive, false, substringIsLower) ? 0 : -1; |
||
31 | } |
||
32 | |||
33 | |||
34 | // default start at |
||
35 | if (first) { |
||
36 | if (startAt == null) { |
||
37 | startAt = 0; |
||
38 | } |
||
39 | } else { |
||
40 | if (startAt == null) { |
||
41 | startAt = ml - sl; |
||
42 | } |
||
43 | } |
||
44 | |||
45 | |||
46 | // if using whole words, slower version is used |
||
47 | if (wholeWords) { |
||
48 | var regex = UB.regex.New(search, wholeWords, caseSensitive, true); |
||
49 | if (first) { |
||
50 | var i = startAt === 0 ? text.search(regex) : text.substring(startAt).search(regex); |
||
51 | } else { |
||
52 | /*var i:int = startAt == (ml - sl) ? text.search(regex) : text.substring(startAt).search(regex);*/ |
||
53 | /// unsupported |
||
54 | i = -1; |
||
55 | } |
||
56 | return i; |
||
57 | } |
||
58 | |||
59 | |||
60 | |||
61 | if (first) { |
||
62 | |||
63 | // FIRST INDEX |
||
64 | |||
65 | // CASE INSENSITIVE |
||
66 | if (!caseSensitive) { |
||
67 | |||
68 | // very fast CI comparison |
||
69 | return text._indexOfCI(search, startAt, substringIsLower, sl, ml); |
||
70 | |||
71 | // much faster than this: |
||
72 | //return text.toUpperCase().indexOf(search.toUpperCase(), startAt); |
||
73 | } |
||
74 | |||
75 | // CASE SENSITIVE |
||
76 | return text.indexOf(search, startAt); |
||
77 | |||
78 | } |
||
79 | |||
80 | |||
81 | // LAST INDEX |
||
82 | |||
83 | // CASE INSENSITIVE |
||
84 | if (!caseSensitive) { |
||
85 | |||
86 | // very fast CI comparison |
||
87 | return text._lastIndexOfCI(search, startAt, substringIsLower, sl); |
||
88 | |||
89 | // much faster than this: |
||
90 | //return text.toUpperCase().lastIndexOf(search.toUpperCase(), startAt); |
||
91 | } |
||
92 | |||
93 | // CASE SENSITIVE |
||
94 | return text.lastIndexOf(search, startAt); |
||
95 | }, |
||
96 | |||
97 | View Code Duplication | _indexOfCI: function(search, startAt, substringIsLower, sl, ml){ |
|
98 | var text = this; |
||
99 | |||
100 | // init casing tables |
||
101 | if (UB.UTF_lowerToUpper == null){ |
||
102 | UB.initCasing(); |
||
103 | } |
||
104 | |||
105 | // per main char |
||
106 | for (var m = startAt;m <= ml;m++){ |
||
107 | |||
108 | |||
109 | // per substring char |
||
110 | var match = true; |
||
111 | for (var s = 0;s<sl;s++){ |
||
112 | |||
113 | var c1 = text.charCodeAt(m + s); |
||
114 | var c2 = search.charCodeAt(s); |
||
115 | |||
116 | // CI |
||
117 | if (c1 <= UB.UTF_casingTablesMax){ /// CI |
||
118 | c1 = UB.UTF_upperToLower[c1]; |
||
119 | } |
||
120 | if (!substringIsLower){ |
||
121 | if (c2 <= UB.UTF_casingTablesMax){ /// CI |
||
122 | c2 = UB.UTF_upperToLower[c2]; |
||
123 | } |
||
124 | } |
||
125 | |||
126 | if (c1 != c2) { |
||
127 | match = false; |
||
128 | break; |
||
129 | } |
||
130 | |||
131 | } |
||
132 | |||
133 | if (match){ |
||
134 | return m; |
||
135 | } |
||
136 | |||
137 | } |
||
138 | |||
139 | return -1; |
||
140 | }, |
||
141 | |||
142 | View Code Duplication | _lastIndexOfCI: function(search, startAt, substringIsLower, sl){ |
|
143 | var text = this; |
||
144 | |||
145 | // init casing tables |
||
146 | if (UB.UTF_lowerToUpper == null){ |
||
147 | UB.initCasing(); |
||
148 | } |
||
149 | |||
150 | // per main char |
||
151 | for (var m = startAt;m >= 0;m--){ |
||
152 | |||
153 | |||
154 | // per substring char |
||
155 | match = true; |
||
156 | for (var s = 0;s<sl;s++){ |
||
157 | |||
158 | c1 = text.charCodeAt(m + s); |
||
159 | c2 = search.charCodeAt(s); |
||
160 | |||
161 | // CI |
||
162 | if (c1 <= UB.UTF_casingTablesMax){ /// CI |
||
163 | c1 = UB.UTF_upperToLower[c1]; |
||
164 | } |
||
165 | if (!substringIsLower){ |
||
166 | if (c2 <= UB.UTF_casingTablesMax){ /// CI |
||
167 | c2 = UB.UTF_upperToLower[c2]; |
||
168 | } |
||
169 | } |
||
170 | |||
171 | if (c1 != c2) { |
||
172 | match = false; |
||
173 | break; |
||
174 | } |
||
175 | |||
176 | } |
||
177 | |||
178 | if (match){ |
||
179 | return m; |
||
180 | } |
||
181 | |||
182 | } |
||
183 | |||
184 | return -1; |
||
185 | }, |
||
186 | |||
187 | countOf: function(find, caseSensitive = true){ |
||
188 | var text = this; |
||
189 | |||
190 | // use regex method for case insensitive comparison |
||
191 | if (!caseSensitive){ |
||
192 | var char = UB.regex.Escape(find); |
||
193 | var flags = 'ig'; |
||
194 | return parseInt(text.match(new RegExp(char, flags)).length); |
||
195 | } |
||
196 | |||
197 | // use faster method for case sensitive comparison |
||
198 | var count = 0; |
||
199 | var index = 0; |
||
200 | var len = find.length; |
||
201 | while ((index = text.indexOf(find, index)) > -1) { |
||
202 | count++; |
||
203 | index += len; |
||
204 | } |
||
205 | return count; |
||
206 | }, |
||
207 | |||
208 | /** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the smallest/largest index (depending on `first`) */ |
||
209 | indexOfAny: function(searchFor, first = true, caseSensitive = true, startAt = null){ |
||
210 | var str = this; |
||
211 | |||
212 | // index of first |
||
213 | if (first) { |
||
214 | return str.indexOfFirstAny(searchFor, caseSensitive, startAt); |
||
215 | } |
||
216 | |||
217 | // index of last |
||
218 | if (startAt == null) { |
||
219 | startAt = 0; |
||
220 | } |
||
221 | return str.indexOfLastAny(searchFor, caseSensitive, startAt); |
||
222 | }, |
||
223 | /** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the largest index */ |
||
224 | indexOfLastAny: function(searchFor, caseSensitive = true, startAt = null){ |
||
225 | var str = this; |
||
226 | |||
227 | // case insensitive if wanted |
||
228 | if (!caseSensitive){ |
||
229 | str = str.toLowerCase(); |
||
230 | } |
||
231 | |||
232 | // per search term |
||
233 | var indices = []; |
||
234 | for (var s = 0, sl = searchFor.length;s<sl;s++){ |
||
235 | var sWord = searchFor[s]; |
||
236 | |||
237 | // case insensitive if wanted |
||
238 | if (!caseSensitive){ |
||
239 | sWord = sWord.toLowerCase(); |
||
240 | } |
||
241 | |||
242 | // check where found |
||
243 | indices[s] = str.lastIndexOf(sWord, startAt); |
||
244 | } |
||
245 | |||
246 | // return last found term |
||
247 | return indices.max(); |
||
248 | }, |
||
249 | /** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the smallest index */ |
||
250 | indexOfFirstAny: function(searchFor, caseSensitive = true, startAt = 0){ |
||
251 | var str = this; |
||
252 | |||
253 | // case insensitive if wanted |
||
254 | if (!caseSensitive){ |
||
255 | str = str.toLowerCase(); |
||
256 | } |
||
257 | |||
258 | // per search term |
||
259 | var indices = []; |
||
260 | for (var s = 0, sl = searchFor.length;s<sl;s++){ |
||
261 | var sWord = searchFor[s]; |
||
262 | |||
263 | // case insensitive if wanted |
||
264 | if (!caseSensitive){ |
||
265 | sWord = sWord.toLowerCase(); |
||
266 | } |
||
267 | |||
268 | // check where found |
||
269 | indices[s] = str.indexOf(sWord, startAt); |
||
270 | |||
271 | // change -1 otherwise looks like first found term |
||
272 | if (indices[s] === -1) { |
||
273 | indices[s] = UB.intMaxValue; |
||
274 | } |
||
275 | } |
||
276 | |||
277 | // return first found term |
||
278 | return indices.min(); |
||
279 | }, |
||
280 | endIndexOfLastAny: function(searchFor, caseSensitive = true){ |
||
281 | var str = this; |
||
282 | |||
283 | // case insensitive if wanted |
||
284 | if (!caseSensitive){ |
||
285 | str = str.toLowerCase(); |
||
286 | } |
||
287 | |||
288 | // per search term |
||
289 | var indices = []; |
||
290 | for (var s = 0, sl = searchFor.length;s<sl;s++){ |
||
291 | var sWord = searchFor[s]; |
||
292 | |||
293 | // case insensitive if wanted |
||
294 | if (!caseSensitive){ |
||
295 | sWord = sWord.toLowerCase(); |
||
296 | } |
||
297 | |||
298 | // check where found |
||
299 | indices[s] = str.endIndexOfLast(sWord); |
||
300 | } |
||
301 | |||
302 | // return last found term |
||
303 | return indices.max(); |
||
304 | }, |
||
305 | endIndexOfFirstAny: function(searchFor, caseSensitive = true){ |
||
306 | var str = this; |
||
307 | |||
308 | // case insensitive if wanted |
||
309 | if (!caseSensitive){ |
||
310 | str = str.toLowerCase(); |
||
311 | } |
||
312 | |||
313 | // per search term |
||
314 | var indices = []; |
||
315 | for (var s = 0, sl = searchFor.length;s<sl;s++){ |
||
316 | var sWord = searchFor[s]; |
||
317 | |||
318 | // case insensitive if wanted |
||
319 | if (!caseSensitive){ |
||
320 | sWord = sWord.toLowerCase(); |
||
321 | } |
||
322 | |||
323 | // check where found |
||
324 | indices[s] = str.endIndexOfFirst(sWord); |
||
325 | |||
326 | // change -1 otherwise looks like first found term |
||
327 | if (indices[s] === -1) { |
||
328 | indices[s] = UB.intMaxValue; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | // return first found term |
||
333 | return indices.min(); |
||
334 | }, |
||
335 | endIndexOfFirst: function(find){ |
||
336 | var str = this; |
||
337 | var pos = str.indexOf(find); |
||
338 | if (pos === -1) return -1; |
||
0 ignored issues
–
show
|
|||
339 | return pos + find.length; |
||
340 | }, |
||
341 | endIndexOfLast: function(find){ |
||
342 | var str = this; |
||
343 | var pos = str.lastIndexOf(find); |
||
344 | if (pos === -1) return -1; |
||
0 ignored issues
–
show
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later. Consider: if (a > 0)
b = 42;
If you or someone else later decides to put another statement in, only the first statement will be executed. if (a > 0)
console.log("a > 0");
b = 42;
In this case the statement if (a > 0) {
console.log("a > 0");
b = 42;
}
ensures that the proper code will be executed conditionally no matter how many statements are added or removed. ![]() |
|||
345 | return pos + find.length; |
||
346 | }, |
||
347 | indexOfNumber: function(startAt = 0, not = false, lenIfNotFound = false){ |
||
348 | var str = this; |
||
349 | for (var c = (startAt>0?startAt:0), cl = str.length;c<cl;c++){ |
||
350 | var char = str.charAt(c); |
||
351 | if (char.isNumber() != not) { |
||
352 | return c; |
||
353 | } |
||
354 | } |
||
355 | return lenIfNotFound ? str.length : -1; |
||
356 | }, |
||
357 | indexOfAlphaNumeric: function(startAt = 0, not = false, lenIfNotFound = false){ |
||
358 | var str = this; |
||
359 | for (var c = (startAt>0?startAt:0), cl = str.length;c<cl;c++){ |
||
360 | var char = str.charAt(c); |
||
361 | if (char.isAlphaNumeric() != not) { |
||
362 | return c; |
||
363 | } |
||
364 | } |
||
365 | return lenIfNotFound ? str.length : -1; |
||
366 | }, |
||
367 | |||
368 | indexOfMany: function(find, startAt = 0){ |
||
369 | var str = this; |
||
370 | |||
371 | // returns the index, of the FIRST FOUND item in the string |
||
372 | |||
373 | var found = -1; |
||
374 | for (var f = 0, fl = find.length;f<fl;f++){ |
||
375 | var at = str.indexOf(find[f], startAt); |
||
376 | if (at != -1 && (at < found || found === -1)) { |
||
377 | found = at; |
||
378 | } |
||
379 | } |
||
380 | return found; |
||
381 | }, |
||
382 | |||
383 | |||
384 | indexOfAll: function(find, caseSensitive = true, startAt = 0, wholeWords = false){ |
||
385 | var str = this; |
||
386 | var indices = []; |
||
387 | |||
388 | var len = str.length; |
||
389 | var c = startAt; |
||
390 | while (c < len) { |
||
391 | c = str.smartIndexOf(find, caseSensitive, true, c, false, wholeWords); |
||
392 | if (c === -1) { |
||
393 | break; |
||
394 | } |
||
395 | indices.push(c); |
||
396 | c += find.length; |
||
397 | } |
||
398 | |||
399 | return indices; |
||
400 | }, |
||
401 | |||
402 | findAll: function(find){ |
||
403 | var str = this.toString(); |
||
404 | var matches = []; |
||
405 | |||
406 | // if regex return all matches |
||
407 | if (find.isRegex()){ |
||
408 | do { |
||
409 | var match = find.exec(str); |
||
410 | if (match) { |
||
411 | matches.push(match); |
||
412 | } |
||
413 | } while (match); |
||
414 | } |
||
415 | |||
416 | // if string find and return all matches |
||
417 | if (find.isString()){ |
||
418 | var indices = str.indexOfAll(); |
||
419 | for (var i=0; i<indices.length; i++){ |
||
420 | var index = indices[i]; |
||
421 | var match = {startIndex:index, endIndex:index+find.length, text:find}; |
||
422 | } |
||
423 | } |
||
424 | |||
425 | return matches; |
||
426 | }, |
||
427 | |||
428 | indexOfNth(search, nth, wholeWords = false, matchCase = true) { |
||
429 | var text = this.toString(); |
||
430 | |||
431 | // quickly test if text contains wanted var |
||
432 | if (!matchCase || text.contains(search)) { |
||
433 | |||
434 | // create regex to find |
||
435 | var regex = UB.regex.New(search, wholeWords, matchCase); |
||
436 | |||
437 | |||
438 | // find and return index if found |
||
439 | var match = null; |
||
440 | for (var n = 0; n < nth; n++) { |
||
441 | match = regex.exec(text); |
||
442 | if (match == null || match < 0) { |
||
443 | return -1; |
||
444 | } else { |
||
445 | //startAt = match + 1; |
||
446 | } |
||
447 | } |
||
448 | return match == null ? -1 : match; |
||
449 | } |
||
450 | |||
451 | return -1; |
||
452 | }, |
||
453 | |||
454 | |||
455 | none:null |
||
456 | }; |
||
457 | |||
458 | // register funcs |
||
459 | UB.registerFuncs(String.prototype, stringFuncs); |
Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.
Consider:
If you or someone else later decides to put another statement in, only the first statement will be executed.
In this case the statement
b = 42
will always be executed, while the logging statement will be executed conditionally.ensures that the proper code will be executed conditionally no matter how many statements are added or removed.