Mercurial > repos > yating-l > hac
comparison doc/_build/html/_static/searchtools.js @ 0:0bca8a6364a7 draft default tip
planemo upload for repository https://github.com/Yating-L/hubarchivecreator-test commit 48b59e91e2dcc2e97735ee35d587960cbfbce932-dirty
| author | yating-l |
|---|---|
| date | Wed, 21 Dec 2016 17:21:18 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:0bca8a6364a7 |
|---|---|
| 1 /* | |
| 2 * searchtools.js_t | |
| 3 * ~~~~~~~~~~~~~~~~ | |
| 4 * | |
| 5 * Sphinx JavaScript utilities for the full-text search. | |
| 6 * | |
| 7 * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. | |
| 8 * :license: BSD, see LICENSE for details. | |
| 9 * | |
| 10 */ | |
| 11 | |
| 12 | |
| 13 /* Non-minified version JS is _stemmer.js if file is provided */ | |
| 14 /** | |
| 15 * Porter Stemmer | |
| 16 */ | |
| 17 var Stemmer = function() { | |
| 18 | |
| 19 var step2list = { | |
| 20 ational: 'ate', | |
| 21 tional: 'tion', | |
| 22 enci: 'ence', | |
| 23 anci: 'ance', | |
| 24 izer: 'ize', | |
| 25 bli: 'ble', | |
| 26 alli: 'al', | |
| 27 entli: 'ent', | |
| 28 eli: 'e', | |
| 29 ousli: 'ous', | |
| 30 ization: 'ize', | |
| 31 ation: 'ate', | |
| 32 ator: 'ate', | |
| 33 alism: 'al', | |
| 34 iveness: 'ive', | |
| 35 fulness: 'ful', | |
| 36 ousness: 'ous', | |
| 37 aliti: 'al', | |
| 38 iviti: 'ive', | |
| 39 biliti: 'ble', | |
| 40 logi: 'log' | |
| 41 }; | |
| 42 | |
| 43 var step3list = { | |
| 44 icate: 'ic', | |
| 45 ative: '', | |
| 46 alize: 'al', | |
| 47 iciti: 'ic', | |
| 48 ical: 'ic', | |
| 49 ful: '', | |
| 50 ness: '' | |
| 51 }; | |
| 52 | |
| 53 var c = "[^aeiou]"; // consonant | |
| 54 var v = "[aeiouy]"; // vowel | |
| 55 var C = c + "[^aeiouy]*"; // consonant sequence | |
| 56 var V = v + "[aeiou]*"; // vowel sequence | |
| 57 | |
| 58 var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 | |
| 59 var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 | |
| 60 var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 | |
| 61 var s_v = "^(" + C + ")?" + v; // vowel in stem | |
| 62 | |
| 63 this.stemWord = function (w) { | |
| 64 var stem; | |
| 65 var suffix; | |
| 66 var firstch; | |
| 67 var origword = w; | |
| 68 | |
| 69 if (w.length < 3) | |
| 70 return w; | |
| 71 | |
| 72 var re; | |
| 73 var re2; | |
| 74 var re3; | |
| 75 var re4; | |
| 76 | |
| 77 firstch = w.substr(0,1); | |
| 78 if (firstch == "y") | |
| 79 w = firstch.toUpperCase() + w.substr(1); | |
| 80 | |
| 81 // Step 1a | |
| 82 re = /^(.+?)(ss|i)es$/; | |
| 83 re2 = /^(.+?)([^s])s$/; | |
| 84 | |
| 85 if (re.test(w)) | |
| 86 w = w.replace(re,"$1$2"); | |
| 87 else if (re2.test(w)) | |
| 88 w = w.replace(re2,"$1$2"); | |
| 89 | |
| 90 // Step 1b | |
| 91 re = /^(.+?)eed$/; | |
| 92 re2 = /^(.+?)(ed|ing)$/; | |
| 93 if (re.test(w)) { | |
| 94 var fp = re.exec(w); | |
| 95 re = new RegExp(mgr0); | |
| 96 if (re.test(fp[1])) { | |
| 97 re = /.$/; | |
| 98 w = w.replace(re,""); | |
| 99 } | |
| 100 } | |
| 101 else if (re2.test(w)) { | |
| 102 var fp = re2.exec(w); | |
| 103 stem = fp[1]; | |
| 104 re2 = new RegExp(s_v); | |
| 105 if (re2.test(stem)) { | |
| 106 w = stem; | |
| 107 re2 = /(at|bl|iz)$/; | |
| 108 re3 = new RegExp("([^aeiouylsz])\\1$"); | |
| 109 re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); | |
| 110 if (re2.test(w)) | |
| 111 w = w + "e"; | |
| 112 else if (re3.test(w)) { | |
| 113 re = /.$/; | |
| 114 w = w.replace(re,""); | |
| 115 } | |
| 116 else if (re4.test(w)) | |
| 117 w = w + "e"; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 // Step 1c | |
| 122 re = /^(.+?)y$/; | |
| 123 if (re.test(w)) { | |
| 124 var fp = re.exec(w); | |
| 125 stem = fp[1]; | |
| 126 re = new RegExp(s_v); | |
| 127 if (re.test(stem)) | |
| 128 w = stem + "i"; | |
| 129 } | |
| 130 | |
| 131 // Step 2 | |
| 132 re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; | |
| 133 if (re.test(w)) { | |
| 134 var fp = re.exec(w); | |
| 135 stem = fp[1]; | |
| 136 suffix = fp[2]; | |
| 137 re = new RegExp(mgr0); | |
| 138 if (re.test(stem)) | |
| 139 w = stem + step2list[suffix]; | |
| 140 } | |
| 141 | |
| 142 // Step 3 | |
| 143 re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; | |
| 144 if (re.test(w)) { | |
| 145 var fp = re.exec(w); | |
| 146 stem = fp[1]; | |
| 147 suffix = fp[2]; | |
| 148 re = new RegExp(mgr0); | |
| 149 if (re.test(stem)) | |
| 150 w = stem + step3list[suffix]; | |
| 151 } | |
| 152 | |
| 153 // Step 4 | |
| 154 re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; | |
| 155 re2 = /^(.+?)(s|t)(ion)$/; | |
| 156 if (re.test(w)) { | |
| 157 var fp = re.exec(w); | |
| 158 stem = fp[1]; | |
| 159 re = new RegExp(mgr1); | |
| 160 if (re.test(stem)) | |
| 161 w = stem; | |
| 162 } | |
| 163 else if (re2.test(w)) { | |
| 164 var fp = re2.exec(w); | |
| 165 stem = fp[1] + fp[2]; | |
| 166 re2 = new RegExp(mgr1); | |
| 167 if (re2.test(stem)) | |
| 168 w = stem; | |
| 169 } | |
| 170 | |
| 171 // Step 5 | |
| 172 re = /^(.+?)e$/; | |
| 173 if (re.test(w)) { | |
| 174 var fp = re.exec(w); | |
| 175 stem = fp[1]; | |
| 176 re = new RegExp(mgr1); | |
| 177 re2 = new RegExp(meq1); | |
| 178 re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); | |
| 179 if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) | |
| 180 w = stem; | |
| 181 } | |
| 182 re = /ll$/; | |
| 183 re2 = new RegExp(mgr1); | |
| 184 if (re.test(w) && re2.test(w)) { | |
| 185 re = /.$/; | |
| 186 w = w.replace(re,""); | |
| 187 } | |
| 188 | |
| 189 // and turn initial Y back to y | |
| 190 if (firstch == "y") | |
| 191 w = firstch.toLowerCase() + w.substr(1); | |
| 192 return w; | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 | |
| 197 | |
| 198 /** | |
| 199 * Simple result scoring code. | |
| 200 */ | |
| 201 var Scorer = { | |
| 202 // Implement the following function to further tweak the score for each result | |
| 203 // The function takes a result array [filename, title, anchor, descr, score] | |
| 204 // and returns the new score. | |
| 205 /* | |
| 206 score: function(result) { | |
| 207 return result[4]; | |
| 208 }, | |
| 209 */ | |
| 210 | |
| 211 // query matches the full name of an object | |
| 212 objNameMatch: 11, | |
| 213 // or matches in the last dotted part of the object name | |
| 214 objPartialMatch: 6, | |
| 215 // Additive scores depending on the priority of the object | |
| 216 objPrio: {0: 15, // used to be importantResults | |
| 217 1: 5, // used to be objectResults | |
| 218 2: -5}, // used to be unimportantResults | |
| 219 // Used when the priority is not in the mapping. | |
| 220 objPrioDefault: 0, | |
| 221 | |
| 222 // query found in title | |
| 223 title: 15, | |
| 224 // query found in terms | |
| 225 term: 5 | |
| 226 }; | |
| 227 | |
| 228 | |
| 229 /** | |
| 230 * Search Module | |
| 231 */ | |
| 232 var Search = { | |
| 233 | |
| 234 _index : null, | |
| 235 _queued_query : null, | |
| 236 _pulse_status : -1, | |
| 237 | |
| 238 init : function() { | |
| 239 var params = $.getQueryParameters(); | |
| 240 if (params.q) { | |
| 241 var query = params.q[0]; | |
| 242 $('input[name="q"]')[0].value = query; | |
| 243 this.performSearch(query); | |
| 244 } | |
| 245 }, | |
| 246 | |
| 247 loadIndex : function(url) { | |
| 248 $.ajax({type: "GET", url: url, data: null, | |
| 249 dataType: "script", cache: true, | |
| 250 complete: function(jqxhr, textstatus) { | |
| 251 if (textstatus != "success") { | |
| 252 document.getElementById("searchindexloader").src = url; | |
| 253 } | |
| 254 }}); | |
| 255 }, | |
| 256 | |
| 257 setIndex : function(index) { | |
| 258 var q; | |
| 259 this._index = index; | |
| 260 if ((q = this._queued_query) !== null) { | |
| 261 this._queued_query = null; | |
| 262 Search.query(q); | |
| 263 } | |
| 264 }, | |
| 265 | |
| 266 hasIndex : function() { | |
| 267 return this._index !== null; | |
| 268 }, | |
| 269 | |
| 270 deferQuery : function(query) { | |
| 271 this._queued_query = query; | |
| 272 }, | |
| 273 | |
| 274 stopPulse : function() { | |
| 275 this._pulse_status = 0; | |
| 276 }, | |
| 277 | |
| 278 startPulse : function() { | |
| 279 if (this._pulse_status >= 0) | |
| 280 return; | |
| 281 function pulse() { | |
| 282 var i; | |
| 283 Search._pulse_status = (Search._pulse_status + 1) % 4; | |
| 284 var dotString = ''; | |
| 285 for (i = 0; i < Search._pulse_status; i++) | |
| 286 dotString += '.'; | |
| 287 Search.dots.text(dotString); | |
| 288 if (Search._pulse_status > -1) | |
| 289 window.setTimeout(pulse, 500); | |
| 290 } | |
| 291 pulse(); | |
| 292 }, | |
| 293 | |
| 294 /** | |
| 295 * perform a search for something (or wait until index is loaded) | |
| 296 */ | |
| 297 performSearch : function(query) { | |
| 298 // create the required interface elements | |
| 299 this.out = $('#search-results'); | |
| 300 this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out); | |
| 301 this.dots = $('<span></span>').appendTo(this.title); | |
| 302 this.status = $('<p style="display: none"></p>').appendTo(this.out); | |
| 303 this.output = $('<ul class="search"/>').appendTo(this.out); | |
| 304 | |
| 305 $('#search-progress').text(_('Preparing search...')); | |
| 306 this.startPulse(); | |
| 307 | |
| 308 // index already loaded, the browser was quick! | |
| 309 if (this.hasIndex()) | |
| 310 this.query(query); | |
| 311 else | |
| 312 this.deferQuery(query); | |
| 313 }, | |
| 314 | |
| 315 /** | |
| 316 * execute search (requires search index to be loaded) | |
| 317 */ | |
| 318 query : function(query) { | |
| 319 var i; | |
| 320 var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; | |
| 321 | |
| 322 // stem the searchterms and add them to the correct list | |
| 323 var stemmer = new Stemmer(); | |
| 324 var searchterms = []; | |
| 325 var excluded = []; | |
| 326 var hlterms = []; | |
| 327 var tmp = query.split(/\W+/); | |
| 328 var objectterms = []; | |
| 329 for (i = 0; i < tmp.length; i++) { | |
| 330 if (tmp[i] !== "") { | |
| 331 objectterms.push(tmp[i].toLowerCase()); | |
| 332 } | |
| 333 | |
| 334 if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) || | |
| 335 tmp[i] === "") { | |
| 336 // skip this "word" | |
| 337 continue; | |
| 338 } | |
| 339 // stem the word | |
| 340 var word = stemmer.stemWord(tmp[i].toLowerCase()); | |
| 341 var toAppend; | |
| 342 // select the correct list | |
| 343 if (word[0] == '-') { | |
| 344 toAppend = excluded; | |
| 345 word = word.substr(1); | |
| 346 } | |
| 347 else { | |
| 348 toAppend = searchterms; | |
| 349 hlterms.push(tmp[i].toLowerCase()); | |
| 350 } | |
| 351 // only add if not already in the list | |
| 352 if (!$u.contains(toAppend, word)) | |
| 353 toAppend.push(word); | |
| 354 } | |
| 355 var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" ")); | |
| 356 | |
| 357 // console.debug('SEARCH: searching for:'); | |
| 358 // console.info('required: ', searchterms); | |
| 359 // console.info('excluded: ', excluded); | |
| 360 | |
| 361 // prepare search | |
| 362 var terms = this._index.terms; | |
| 363 var titleterms = this._index.titleterms; | |
| 364 | |
| 365 // array of [filename, title, anchor, descr, score] | |
| 366 var results = []; | |
| 367 $('#search-progress').empty(); | |
| 368 | |
| 369 // lookup as object | |
| 370 for (i = 0; i < objectterms.length; i++) { | |
| 371 var others = [].concat(objectterms.slice(0, i), | |
| 372 objectterms.slice(i+1, objectterms.length)); | |
| 373 results = results.concat(this.performObjectSearch(objectterms[i], others)); | |
| 374 } | |
| 375 | |
| 376 // lookup as search terms in fulltext | |
| 377 results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms)); | |
| 378 | |
| 379 // let the scorer override scores with a custom scoring function | |
| 380 if (Scorer.score) { | |
| 381 for (i = 0; i < results.length; i++) | |
| 382 results[i][4] = Scorer.score(results[i]); | |
| 383 } | |
| 384 | |
| 385 // now sort the results by score (in opposite order of appearance, since the | |
| 386 // display function below uses pop() to retrieve items) and then | |
| 387 // alphabetically | |
| 388 results.sort(function(a, b) { | |
| 389 var left = a[4]; | |
| 390 var right = b[4]; | |
| 391 if (left > right) { | |
| 392 return 1; | |
| 393 } else if (left < right) { | |
| 394 return -1; | |
| 395 } else { | |
| 396 // same score: sort alphabetically | |
| 397 left = a[1].toLowerCase(); | |
| 398 right = b[1].toLowerCase(); | |
| 399 return (left > right) ? -1 : ((left < right) ? 1 : 0); | |
| 400 } | |
| 401 }); | |
| 402 | |
| 403 // for debugging | |
| 404 //Search.lastresults = results.slice(); // a copy | |
| 405 //console.info('search results:', Search.lastresults); | |
| 406 | |
| 407 // print the results | |
| 408 var resultCount = results.length; | |
| 409 function displayNextItem() { | |
| 410 // results left, load the summary and display it | |
| 411 if (results.length) { | |
| 412 var item = results.pop(); | |
| 413 var listItem = $('<li style="display:none"></li>'); | |
| 414 if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') { | |
| 415 // dirhtml builder | |
| 416 var dirname = item[0] + '/'; | |
| 417 if (dirname.match(/\/index\/$/)) { | |
| 418 dirname = dirname.substring(0, dirname.length-6); | |
| 419 } else if (dirname == 'index/') { | |
| 420 dirname = ''; | |
| 421 } | |
| 422 listItem.append($('<a/>').attr('href', | |
| 423 DOCUMENTATION_OPTIONS.URL_ROOT + dirname + | |
| 424 highlightstring + item[2]).html(item[1])); | |
| 425 } else { | |
| 426 // normal html builders | |
| 427 listItem.append($('<a/>').attr('href', | |
| 428 item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX + | |
| 429 highlightstring + item[2]).html(item[1])); | |
| 430 } | |
| 431 if (item[3]) { | |
| 432 listItem.append($('<span> (' + item[3] + ')</span>')); | |
| 433 Search.output.append(listItem); | |
| 434 listItem.slideDown(5, function() { | |
| 435 displayNextItem(); | |
| 436 }); | |
| 437 } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) { | |
| 438 $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt', | |
| 439 dataType: "text", | |
| 440 complete: function(jqxhr, textstatus) { | |
| 441 var data = jqxhr.responseText; | |
| 442 if (data !== '' && data !== undefined) { | |
| 443 listItem.append(Search.makeSearchSummary(data, searchterms, hlterms)); | |
| 444 } | |
| 445 Search.output.append(listItem); | |
| 446 listItem.slideDown(5, function() { | |
| 447 displayNextItem(); | |
| 448 }); | |
| 449 }}); | |
| 450 } else { | |
| 451 // no source available, just display title | |
| 452 Search.output.append(listItem); | |
| 453 listItem.slideDown(5, function() { | |
| 454 displayNextItem(); | |
| 455 }); | |
| 456 } | |
| 457 } | |
| 458 // search finished, update title and status message | |
| 459 else { | |
| 460 Search.stopPulse(); | |
| 461 Search.title.text(_('Search Results')); | |
| 462 if (!resultCount) | |
| 463 Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.')); | |
| 464 else | |
| 465 Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount)); | |
| 466 Search.status.fadeIn(500); | |
| 467 } | |
| 468 } | |
| 469 displayNextItem(); | |
| 470 }, | |
| 471 | |
| 472 /** | |
| 473 * search for object names | |
| 474 */ | |
| 475 performObjectSearch : function(object, otherterms) { | |
| 476 var filenames = this._index.filenames; | |
| 477 var objects = this._index.objects; | |
| 478 var objnames = this._index.objnames; | |
| 479 var titles = this._index.titles; | |
| 480 | |
| 481 var i; | |
| 482 var results = []; | |
| 483 | |
| 484 for (var prefix in objects) { | |
| 485 for (var name in objects[prefix]) { | |
| 486 var fullname = (prefix ? prefix + '.' : '') + name; | |
| 487 if (fullname.toLowerCase().indexOf(object) > -1) { | |
| 488 var score = 0; | |
| 489 var parts = fullname.split('.'); | |
| 490 // check for different match types: exact matches of full name or | |
| 491 // "last name" (i.e. last dotted part) | |
| 492 if (fullname == object || parts[parts.length - 1] == object) { | |
| 493 score += Scorer.objNameMatch; | |
| 494 // matches in last name | |
| 495 } else if (parts[parts.length - 1].indexOf(object) > -1) { | |
| 496 score += Scorer.objPartialMatch; | |
| 497 } | |
| 498 var match = objects[prefix][name]; | |
| 499 var objname = objnames[match[1]][2]; | |
| 500 var title = titles[match[0]]; | |
| 501 // If more than one term searched for, we require other words to be | |
| 502 // found in the name/title/description | |
| 503 if (otherterms.length > 0) { | |
| 504 var haystack = (prefix + ' ' + name + ' ' + | |
| 505 objname + ' ' + title).toLowerCase(); | |
| 506 var allfound = true; | |
| 507 for (i = 0; i < otherterms.length; i++) { | |
| 508 if (haystack.indexOf(otherterms[i]) == -1) { | |
| 509 allfound = false; | |
| 510 break; | |
| 511 } | |
| 512 } | |
| 513 if (!allfound) { | |
| 514 continue; | |
| 515 } | |
| 516 } | |
| 517 var descr = objname + _(', in ') + title; | |
| 518 | |
| 519 var anchor = match[3]; | |
| 520 if (anchor === '') | |
| 521 anchor = fullname; | |
| 522 else if (anchor == '-') | |
| 523 anchor = objnames[match[1]][1] + '-' + fullname; | |
| 524 // add custom score for some objects according to scorer | |
| 525 if (Scorer.objPrio.hasOwnProperty(match[2])) { | |
| 526 score += Scorer.objPrio[match[2]]; | |
| 527 } else { | |
| 528 score += Scorer.objPrioDefault; | |
| 529 } | |
| 530 results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]); | |
| 531 } | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 return results; | |
| 536 }, | |
| 537 | |
| 538 /** | |
| 539 * search for full-text terms in the index | |
| 540 */ | |
| 541 performTermsSearch : function(searchterms, excluded, terms, titleterms) { | |
| 542 var filenames = this._index.filenames; | |
| 543 var titles = this._index.titles; | |
| 544 | |
| 545 var i, j, file; | |
| 546 var fileMap = {}; | |
| 547 var scoreMap = {}; | |
| 548 var results = []; | |
| 549 | |
| 550 // perform the search on the required terms | |
| 551 for (i = 0; i < searchterms.length; i++) { | |
| 552 var word = searchterms[i]; | |
| 553 var files = []; | |
| 554 var _o = [ | |
| 555 {files: terms[word], score: Scorer.term}, | |
| 556 {files: titleterms[word], score: Scorer.title} | |
| 557 ]; | |
| 558 | |
| 559 // no match but word was a required one | |
| 560 if ($u.every(_o, function(o){return o.files === undefined;})) { | |
| 561 break; | |
| 562 } | |
| 563 // found search word in contents | |
| 564 $u.each(_o, function(o) { | |
| 565 var _files = o.files; | |
| 566 if (_files === undefined) | |
| 567 return | |
| 568 | |
| 569 if (_files.length === undefined) | |
| 570 _files = [_files]; | |
| 571 files = files.concat(_files); | |
| 572 | |
| 573 // set score for the word in each file to Scorer.term | |
| 574 for (j = 0; j < _files.length; j++) { | |
| 575 file = _files[j]; | |
| 576 if (!(file in scoreMap)) | |
| 577 scoreMap[file] = {} | |
| 578 scoreMap[file][word] = o.score; | |
| 579 } | |
| 580 }); | |
| 581 | |
| 582 // create the mapping | |
| 583 for (j = 0; j < files.length; j++) { | |
| 584 file = files[j]; | |
| 585 if (file in fileMap) | |
| 586 fileMap[file].push(word); | |
| 587 else | |
| 588 fileMap[file] = [word]; | |
| 589 } | |
| 590 } | |
| 591 | |
| 592 // now check if the files don't contain excluded terms | |
| 593 for (file in fileMap) { | |
| 594 var valid = true; | |
| 595 | |
| 596 // check if all requirements are matched | |
| 597 if (fileMap[file].length != searchterms.length) | |
| 598 continue; | |
| 599 | |
| 600 // ensure that none of the excluded terms is in the search result | |
| 601 for (i = 0; i < excluded.length; i++) { | |
| 602 if (terms[excluded[i]] == file || | |
| 603 titleterms[excluded[i]] == file || | |
| 604 $u.contains(terms[excluded[i]] || [], file) || | |
| 605 $u.contains(titleterms[excluded[i]] || [], file)) { | |
| 606 valid = false; | |
| 607 break; | |
| 608 } | |
| 609 } | |
| 610 | |
| 611 // if we have still a valid result we can add it to the result list | |
| 612 if (valid) { | |
| 613 // select one (max) score for the file. | |
| 614 // for better ranking, we should calculate ranking by using words statistics like basic tf-idf... | |
| 615 var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]})); | |
| 616 results.push([filenames[file], titles[file], '', null, score]); | |
| 617 } | |
| 618 } | |
| 619 return results; | |
| 620 }, | |
| 621 | |
| 622 /** | |
| 623 * helper function to return a node containing the | |
| 624 * search summary for a given text. keywords is a list | |
| 625 * of stemmed words, hlwords is the list of normal, unstemmed | |
| 626 * words. the first one is used to find the occurrence, the | |
| 627 * latter for highlighting it. | |
| 628 */ | |
| 629 makeSearchSummary : function(text, keywords, hlwords) { | |
| 630 var textLower = text.toLowerCase(); | |
| 631 var start = 0; | |
| 632 $.each(keywords, function() { | |
| 633 var i = textLower.indexOf(this.toLowerCase()); | |
| 634 if (i > -1) | |
| 635 start = i; | |
| 636 }); | |
| 637 start = Math.max(start - 120, 0); | |
| 638 var excerpt = ((start > 0) ? '...' : '') + | |
| 639 $.trim(text.substr(start, 240)) + | |
| 640 ((start + 240 - text.length) ? '...' : ''); | |
| 641 var rv = $('<div class="context"></div>').text(excerpt); | |
| 642 $.each(hlwords, function() { | |
| 643 rv = rv.highlightText(this, 'highlighted'); | |
| 644 }); | |
| 645 return rv; | |
| 646 } | |
| 647 }; | |
| 648 | |
| 649 $(document).ready(function() { | |
| 650 Search.init(); | |
| 651 }); |
