17 var Stemmer =
function() {
55 var C = c +
"[^aeiouy]*";
56 var V = v +
"[aeiou]*";
58 var mgr0 =
"^(" + C +
")?" + V + C;
59 var meq1 =
"^(" + C +
")?" + V + C +
"(" + V +
")?$";
60 var mgr1 =
"^(" + C +
")?" + V + C + V + C;
61 var s_v =
"^(" + C +
")?" + v;
63 this.stemWord =
function (w) {
77 firstch = w.substr(0,1);
79 w = firstch.toUpperCase() + w.substr(1);
82 re = /^(.+?)(ss|i)es$/;
83 re2 = /^(.+?)([^s])s$/;
86 w = w.replace(re,
"$1$2");
88 w = w.replace(re2,
"$1$2");
92 re2 = /^(.+?)(ed|ing)$/;
95 re =
new RegExp(mgr0);
101 else if (re2.test(w)) {
102 var fp = re2.exec(w);
104 re2 =
new RegExp(s_v);
105 if (re2.test(stem)) {
108 re3 =
new RegExp(
"([^aeiouylsz])\\1$");
109 re4 =
new RegExp(
"^" + C + v +
"[^aeiouwxy]$");
112 else if (re3.test(w)) {
114 w = w.replace(re,
"");
116 else if (re4.test(w))
126 re =
new RegExp(s_v);
132 re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
137 re =
new RegExp(mgr0);
139 w = stem + step2list[suffix];
143 re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
148 re =
new RegExp(mgr0);
150 w = stem + step3list[suffix];
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)$/;
159 re =
new RegExp(mgr1);
163 else if (re2.test(w)) {
164 var fp = re2.exec(w);
165 stem = fp[1] + fp[2];
166 re2 =
new RegExp(mgr1);
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))))
183 re2 =
new RegExp(mgr1);
184 if (re.test(w) && re2.test(w)) {
186 w = w.replace(re,
"");
191 w = firstch.toLowerCase() + w.substr(1);
235 _queued_query : null,
239 var params = $.getQueryParameters();
241 var query = params.q[0];
242 $(
'input[name="q"]')[0].value = query;
243 this.performSearch(query);
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;
257 setIndex :
function(index) {
260 if ((q = this._queued_query) !== null) {
261 this._queued_query = null;
266 hasIndex :
function() {
267 return this._index !== null;
270 deferQuery :
function(query) {
271 this._queued_query = query;
274 stopPulse :
function() {
275 this._pulse_status = 0;
278 startPulse :
function() {
279 if (this._pulse_status >= 0)
283 Search._pulse_status = (Search._pulse_status + 1) % 4;
285 for (i = 0; i < Search._pulse_status; i++)
287 Search.dots.text(dotString);
288 if (Search._pulse_status > -1)
289 window.setTimeout(pulse, 500);
297 performSearch :
function(query) {
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);
305 $(
'#search-progress').text(_(
'Preparing search...'));
312 this.deferQuery(query);
318 query :
function(query) {
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"];
323 var stemmer =
new Stemmer();
324 var searchterms = [];
327 var tmp = query.split(/\s+/);
328 var objectterms = [];
329 for (i = 0; i < tmp.length; i++) {
331 objectterms.push(tmp[i].toLowerCase());
334 if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
340 var word = stemmer.stemWord(tmp[i].toLowerCase());
343 if (word[0] ==
'-') {
345 word = word.substr(1);
348 toAppend = searchterms;
349 hlterms.push(tmp[i].toLowerCase());
352 if (!$u.contains(toAppend, word))
355 var highlightstring =
'?highlight=' + $.urlencode(hlterms.join(
" "));
362 var terms = this._index.terms;
363 var titleterms = this._index.titleterms;
367 $(
'#search-progress').empty();
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));
377 results = results.concat(this.performTermsSearch(searchterms, excluded, terms, Scorer.term))
378 .concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
382 for (i = 0; i < results.length; i++)
383 results[i][4] = Scorer.score(results[i]);
389 results.sort(
function(
a, b) {
394 }
else if (left < right) {
398 left =
a[1].toLowerCase();
399 right = b[1].toLowerCase();
400 return (left > right) ? -1 : ((left < right) ? 1 : 0);
409 var resultCount = results.length;
410 function displayNextItem() {
412 if (results.length) {
413 var item = results.pop();
414 var listItem = $(
'<li style="display:none"></li>');
415 if (DOCUMENTATION_OPTIONS.FILE_SUFFIX ===
'') {
417 var dirname = item[0] +
'/';
418 if (dirname.match(/\/index\/$/)) {
419 dirname = dirname.substring(0, dirname.length-6);
420 }
else if (dirname ==
'index/') {
423 listItem.append($(
'<a/>').attr(
'href',
424 DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
425 highlightstring + item[2]).html(item[1]));
428 listItem.append($(
'<a/>').attr(
'href',
429 item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
430 highlightstring + item[2]).html(item[1]));
433 listItem.append($(
'<span> (' + item[3] +
')</span>'));
434 Search.output.append(listItem);
435 listItem.slideDown(5,
function() {
438 }
else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
439 $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT +
'_sources/' + item[0] +
'.txt',
441 complete:
function(jqxhr, textstatus) {
442 var data = jqxhr.responseText;
443 if (data !==
'' && data !== undefined) {
444 listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
446 Search.output.append(listItem);
447 listItem.slideDown(5,
function() {
453 Search.output.append(listItem);
454 listItem.slideDown(5,
function() {
462 Search.title.text(_(
'Search Results'));
464 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.'));
466 Search.status.text(_(
'Search finished, found %s page(s) matching the search query.').replace(
'%s', resultCount));
467 Search.status.fadeIn(500);
476 performObjectSearch :
function(object, otherterms) {
477 var filenames = this._index.filenames;
478 var objects = this._index.objects;
479 var objnames = this._index.objnames;
480 var titles = this._index.titles;
485 for (var prefix in objects) {
486 for (var name in objects[prefix]) {
487 var fullname = (prefix ? prefix +
'.' :
'') + name;
488 if (fullname.toLowerCase().indexOf(
object) > -1) {
490 var parts = fullname.split(
'.');
493 if (fullname ==
object || parts[parts.length - 1] ==
object) {
494 score += Scorer.objNameMatch;
496 }
else if (parts[parts.length - 1].indexOf(
object) > -1) {
497 score += Scorer.objPartialMatch;
499 var match = objects[prefix][name];
500 var objname = objnames[match[1]][2];
501 var title = titles[match[0]];
504 if (otherterms.length > 0) {
505 var haystack = (prefix +
' ' + name +
' ' +
506 objname +
' ' + title).toLowerCase();
508 for (i = 0; i < otherterms.length; i++) {
509 if (haystack.indexOf(otherterms[i]) == -1) {
518 var descr = objname + _(
', in ') + title;
520 var anchor = match[3];
523 else if (anchor ==
'-')
524 anchor = objnames[match[1]][1] +
'-' + fullname;
526 if (Scorer.objPrio.hasOwnProperty(match[2])) {
527 score += Scorer.objPrio[match[2]];
529 score += Scorer.objPrioDefault;
531 results.push([filenames[match[0]], fullname,
'#'+anchor, descr, score]);
542 performTermsSearch :
function(searchterms, excluded, terms, score) {
543 var filenames = this._index.filenames;
544 var titles = this._index.titles;
546 var i, j, file, files;
551 for (i = 0; i < searchterms.length; i++) {
552 var word = searchterms[i];
554 if ((files = terms[word]) === undefined)
556 if (files.length === undefined) {
560 for (j = 0; j < files.length; j++) {
563 fileMap[file].push(word);
565 fileMap[file] = [word];
570 for (file in fileMap) {
574 if (fileMap[file].length != searchterms.length)
578 for (i = 0; i < excluded.length; i++) {
579 if (terms[excluded[i]] == file ||
580 $u.contains(terms[excluded[i]] || [], file)) {
588 results.push([filenames[file], titles[file],
'', null, score]);
601 makeSearchSummary :
function(text, keywords, hlwords) {
602 var textLower = text.toLowerCase();
604 $.each(keywords,
function() {
605 var i = textLower.indexOf(this.toLowerCase());
609 start = Math.max(start - 120, 0);
610 var excerpt = ((start > 0) ?
'...' :
'') +
611 $.trim(text.substr(start, 240)) +
612 ((start + 240 - text.length) ?
'...' :
'');
613 var rv = $(
'<div class="context"></div>').text(excerpt);
614 $.each(hlwords,
function() {
615 rv = rv.highlightText(
this,
'highlighted');
621 $(document).ready(
function() {