|
61 | 61 | }
|
62 | 62 | $('#' + from)[0].scrollIntoView();
|
63 | 63 | $('.line-numbers span').removeClass('line-highlighted');
|
64 |
| - for (i = from; i <= to; i += 1) { |
| 64 | + for (i = from; i <= to; ++i) { |
65 | 65 | $('#' + i).addClass('line-highlighted');
|
66 | 66 | }
|
67 | 67 | }
|
|
102 | 102 | stripped = '',
|
103 | 103 | len = rootPath.match(/\.\.\//g).length + 1;
|
104 | 104 |
|
105 |
| - for (i = 0; i < len; i += 1) { |
| 105 | + for (i = 0; i < len; ++i) { |
106 | 106 | match = url.match(/\/[^\/]*$/);
|
107 | 107 | if (i < len - 1) {
|
108 | 108 | stripped = match[0] + stripped;
|
|
114 | 114 |
|
115 | 115 | document.location.href = url;
|
116 | 116 | });
|
| 117 | + /** |
| 118 | + * A function to compute the Levenshtein distance between two strings |
| 119 | + * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported |
| 120 | + * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode |
| 121 | + * This code is an unmodified version of the code written by Marco de Wit |
| 122 | + * and was found at http://stackoverflow.com/a/18514751/745719 |
| 123 | + */ |
| 124 | + var levenshtein = (function() { |
| 125 | + var row2 = []; |
| 126 | + return function(s1, s2) { |
| 127 | + if (s1 === s2) { |
| 128 | + return 0; |
| 129 | + } else { |
| 130 | + var s1_len = s1.length, s2_len = s2.length; |
| 131 | + if (s1_len && s2_len) { |
| 132 | + var i1 = 0, i2 = 0, a, b, c, c2, row = row2; |
| 133 | + while (i1 < s1_len) |
| 134 | + row[i1] = ++i1; |
| 135 | + while (i2 < s2_len) { |
| 136 | + c2 = s2.charCodeAt(i2); |
| 137 | + a = i2; |
| 138 | + ++i2; |
| 139 | + b = i2; |
| 140 | + for (i1 = 0; i1 < s1_len; ++i1) { |
| 141 | + c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0); |
| 142 | + a = row[i1]; |
| 143 | + b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c); |
| 144 | + row[i1] = b; |
| 145 | + } |
| 146 | + } |
| 147 | + return b; |
| 148 | + } else { |
| 149 | + return s1_len + s2_len; |
| 150 | + } |
| 151 | + } |
| 152 | + }; |
| 153 | + })(); |
117 | 154 |
|
118 | 155 | function initSearch(rawSearchIndex) {
|
119 | 156 | var currentResults, index, searchIndex;
|
| 157 | + var MAX_LEV_DISTANCE = 3; |
120 | 158 | var params = getQueryStringParams();
|
121 | 159 |
|
122 | 160 | // Populate search bar with query string search term when provided,
|
|
143 | 181 | split = valLower.split("::");
|
144 | 182 |
|
145 | 183 | //remove empty keywords
|
146 |
| - for (var j = 0; j < split.length; j++) { |
| 184 | + for (var j = 0; j < split.length; ++j) { |
147 | 185 | split[j].toLowerCase();
|
148 | 186 | if (split[j] === "") {
|
149 | 187 | split.splice(j, 1);
|
|
156 | 194 | val.charAt(val.length - 1) === val.charAt(0))
|
157 | 195 | {
|
158 | 196 | val = val.substr(1, val.length - 2);
|
159 |
| - for (var i = 0; i < nSearchWords; i += 1) { |
| 197 | + for (var i = 0; i < nSearchWords; ++i) { |
160 | 198 | if (searchWords[i] === val) {
|
161 | 199 | // filter type: ... queries
|
162 | 200 | if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
|
|
170 | 208 | } else {
|
171 | 209 | // gather matching search results up to a certain maximum
|
172 | 210 | val = val.replace(/\_/g, "");
|
173 |
| - for (var i = 0; i < split.length; i++) { |
174 |
| - for (var j = 0; j < nSearchWords; j += 1) { |
| 211 | + for (var i = 0; i < split.length; ++i) { |
| 212 | + for (var j = 0; j < nSearchWords; ++j) { |
| 213 | + var lev_distance; |
175 | 214 | if (searchWords[j].indexOf(split[i]) > -1 ||
|
176 | 215 | searchWords[j].indexOf(val) > -1 ||
|
177 | 216 | searchWords[j].replace(/_/g, "").indexOf(val) > -1)
|
178 | 217 | {
|
179 | 218 | // filter type: ... queries
|
180 | 219 | if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
|
181 |
| - results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)}); |
| 220 | + results.push({ |
| 221 | + id: j, |
| 222 | + index: searchWords[j].replace(/_/g, "").indexOf(val), |
| 223 | + lev: 0, |
| 224 | + }); |
| 225 | + } |
| 226 | + } else if ( |
| 227 | + (lev_distance = levenshtein(searchWords[j], val)) <= |
| 228 | + MAX_LEV_DISTANCE) { |
| 229 | + if (typeFilter < 0 || typeFilter === searchIndex[j].ty) { |
| 230 | + results.push({ |
| 231 | + id: j, |
| 232 | + index: 0, |
| 233 | + // we want lev results to go lower than others |
| 234 | + lev: lev_distance, |
| 235 | + }); |
182 | 236 | }
|
183 | 237 | }
|
184 | 238 | if (results.length === max) {
|
|
189 | 243 | }
|
190 | 244 |
|
191 | 245 | var nresults = results.length;
|
192 |
| - for (var i = 0; i < nresults; i += 1) { |
| 246 | + for (var i = 0; i < nresults; ++i) { |
193 | 247 | results[i].word = searchWords[results[i].id];
|
194 | 248 | results[i].item = searchIndex[results[i].id] || {};
|
195 | 249 | }
|
|
201 | 255 | results.sort(function(aaa, bbb) {
|
202 | 256 | var a, b;
|
203 | 257 |
|
| 258 | + // Sort by non levenshtein results and then levenshtein results by the distance |
| 259 | + // (less changes required to match means higher rankings) |
| 260 | + a = (aaa.lev); |
| 261 | + b = (bbb.lev); |
| 262 | + if (a !== b) return a - b; |
| 263 | + |
204 | 264 | // sort by crate (non-current crate goes later)
|
205 | 265 | a = (aaa.item.crate !== window.currentCrate);
|
206 | 266 | b = (bbb.item.crate !== window.currentCrate);
|
|
258 | 318 | results[i].id = -1;
|
259 | 319 | }
|
260 | 320 | }
|
261 |
| - for (var i = 0; i < results.length; i++) { |
| 321 | + for (var i = 0; i < results.length; ++i) { |
262 | 322 | var result = results[i],
|
263 | 323 | name = result.item.name.toLowerCase(),
|
264 | 324 | path = result.item.path.toLowerCase(),
|
|
288 | 348 | * @return {[boolean]} [Whether the result is valid or not]
|
289 | 349 | */
|
290 | 350 | function validateResult(name, path, keys, parent) {
|
291 |
| - //initially valid |
292 |
| - var validate = true; |
293 |
| - //if there is a parent, then validate against parent |
294 |
| - if (parent !== undefined) { |
295 |
| - for (var i = 0; i < keys.length; i++) { |
296 |
| - // if previous keys are valid and current key is in the |
297 |
| - // path, name or parent |
298 |
| - if ((validate) && |
299 |
| - (name.toLowerCase().indexOf(keys[i]) > -1 || |
300 |
| - path.toLowerCase().indexOf(keys[i]) > -1 || |
301 |
| - parent.name.toLowerCase().indexOf(keys[i]) > -1)) |
302 |
| - { |
303 |
| - validate = true; |
304 |
| - } else { |
305 |
| - validate = false; |
306 |
| - } |
307 |
| - } |
308 |
| - } else { |
309 |
| - for (var i = 0; i < keys.length; i++) { |
310 |
| - // if previous keys are valid and current key is in the |
311 |
| - // path, name |
312 |
| - if ((validate) && |
313 |
| - (name.toLowerCase().indexOf(keys[i]) > -1 || |
314 |
| - path.toLowerCase().indexOf(keys[i]) > -1)) |
315 |
| - { |
316 |
| - validate = true; |
317 |
| - } else { |
318 |
| - validate = false; |
319 |
| - } |
| 351 | + for (var i=0; i < keys.length; ++i) { |
| 352 | + // each check is for validation so we negate the conditions and invalidate |
| 353 | + if (!( |
| 354 | + // check for an exact name match |
| 355 | + name.toLowerCase().indexOf(keys[i]) > -1 || |
| 356 | + // then an exact path match |
| 357 | + path.toLowerCase().indexOf(keys[i]) > -1 || |
| 358 | + // next if there is a parent, check for exact parent match |
| 359 | + (parent !== undefined && |
| 360 | + parent.name.toLowerCase().indexOf(keys[i]) > -1) || |
| 361 | + // lastly check to see if the name was a levenshtein match |
| 362 | + levenshtein(name.toLowerCase(), keys[i]) <= |
| 363 | + MAX_LEV_DISTANCE)) { |
| 364 | + return false; |
320 | 365 | }
|
321 | 366 | }
|
322 |
| - return validate; |
| 367 | + return true; |
323 | 368 | }
|
324 | 369 |
|
325 | 370 | function getQuery() {
|
|
499 | 544 |
|
500 | 545 | resultIndex = execQuery(query, 20000, index);
|
501 | 546 | len = resultIndex.length;
|
502 |
| - for (i = 0; i < len; i += 1) { |
| 547 | + for (i = 0; i < len; ++i) { |
503 | 548 | if (resultIndex[i].id > -1) {
|
504 | 549 | obj = searchIndex[resultIndex[i].id];
|
505 | 550 | filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
|
|
571 | 616 | // faster analysis operations
|
572 | 617 | var len = items.length;
|
573 | 618 | var lastPath = "";
|
574 |
| - for (var i = 0; i < len; i += 1) { |
| 619 | + for (var i = 0; i < len; ++i) { |
575 | 620 | var rawRow = items[i];
|
576 | 621 | var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
|
577 | 622 | path: rawRow[2] || lastPath, desc: rawRow[3],
|
|
643 | 688 | crates.push(crate);
|
644 | 689 | }
|
645 | 690 | crates.sort();
|
646 |
| - for (var i = 0; i < crates.length; i++) { |
| 691 | + for (var i = 0; i < crates.length; ++i) { |
647 | 692 | var klass = 'crate';
|
648 | 693 | if (crates[i] == window.currentCrate) {
|
649 | 694 | klass += ' current';
|
|
660 | 705 | window.register_implementors = function(imp) {
|
661 | 706 | var list = $('#implementors-list');
|
662 | 707 | var libs = Object.getOwnPropertyNames(imp);
|
663 |
| - for (var i = 0; i < libs.length; i++) { |
| 708 | + for (var i = 0; i < libs.length; ++i) { |
664 | 709 | if (libs[i] == currentCrate) continue;
|
665 | 710 | var structs = imp[libs[i]];
|
666 |
| - for (var j = 0; j < structs.length; j++) { |
| 711 | + for (var j = 0; j < structs.length; ++j) { |
667 | 712 | var code = $('<code>').append(structs[j]);
|
668 | 713 | $.each(code.find('a'), function(idx, a) {
|
669 | 714 | var href = $(a).attr('href');
|
|
0 commit comments