source: sasview/calculator/docs/sphinx/_build/html/_static/searchtools.js @ ddf6df3

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since ddf6df3 was beb374a, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on documentation

  • Property mode set to 100644
File size: 13.5 KB
Line 
1/*
2 * searchtools.js
3 * ~~~~~~~~~~~~~~
4 *
5 * Sphinx JavaScript utilties for the full-text search.
6 *
7 * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 * :license: BSD, see LICENSE for details.
9 *
10 */
11
12/**
13 * helper function to return a node containing the
14 * search summary for a given text. keywords is a list
15 * of stemmed words, hlwords is the list of normal, unstemmed
16 * words. the first one is used to find the occurance, the
17 * latter for highlighting it.
18 */
19
20jQuery.makeSearchSummary = function(text, keywords, hlwords) {
21  var textLower = text.toLowerCase();
22  var start = 0;
23  $.each(keywords, function() {
24    var i = textLower.indexOf(this.toLowerCase());
25    if (i > -1)
26      start = i;
27  });
28  start = Math.max(start - 120, 0);
29  var excerpt = ((start > 0) ? '...' : '') +
30  $.trim(text.substr(start, 240)) +
31  ((start + 240 - text.length) ? '...' : '');
32  var rv = $('<div class="context"></div>').text(excerpt);
33  $.each(hlwords, function() {
34    rv = rv.highlightText(this, 'highlighted');
35  });
36  return rv;
37}
38
39/**
40 * Porter Stemmer
41 */
42var PorterStemmer = function() {
43
44  var step2list = {
45    ational: 'ate',
46    tional: 'tion',
47    enci: 'ence',
48    anci: 'ance',
49    izer: 'ize',
50    bli: 'ble',
51    alli: 'al',
52    entli: 'ent',
53    eli: 'e',
54    ousli: 'ous',
55    ization: 'ize',
56    ation: 'ate',
57    ator: 'ate',
58    alism: 'al',
59    iveness: 'ive',
60    fulness: 'ful',
61    ousness: 'ous',
62    aliti: 'al',
63    iviti: 'ive',
64    biliti: 'ble',
65    logi: 'log'
66  };
67
68  var step3list = {
69    icate: 'ic',
70    ative: '',
71    alize: 'al',
72    iciti: 'ic',
73    ical: 'ic',
74    ful: '',
75    ness: ''
76  };
77
78  var c = "[^aeiou]";          // consonant
79  var v = "[aeiouy]";          // vowel
80  var C = c + "[^aeiouy]*";    // consonant sequence
81  var V = v + "[aeiou]*";      // vowel sequence
82
83  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
84  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
85  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
86  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
87
88  this.stemWord = function (w) {
89    var stem;
90    var suffix;
91    var firstch;
92    var origword = w;
93
94    if (w.length < 3)
95      return w;
96
97    var re;
98    var re2;
99    var re3;
100    var re4;
101
102    firstch = w.substr(0,1);
103    if (firstch == "y")
104      w = firstch.toUpperCase() + w.substr(1);
105
106    // Step 1a
107    re = /^(.+?)(ss|i)es$/;
108    re2 = /^(.+?)([^s])s$/;
109
110    if (re.test(w))
111      w = w.replace(re,"$1$2");
112    else if (re2.test(w))
113      w = w.replace(re2,"$1$2");
114
115    // Step 1b
116    re = /^(.+?)eed$/;
117    re2 = /^(.+?)(ed|ing)$/;
118    if (re.test(w)) {
119      var fp = re.exec(w);
120      re = new RegExp(mgr0);
121      if (re.test(fp[1])) {
122        re = /.$/;
123        w = w.replace(re,"");
124      }
125    }
126    else if (re2.test(w)) {
127      var fp = re2.exec(w);
128      stem = fp[1];
129      re2 = new RegExp(s_v);
130      if (re2.test(stem)) {
131        w = stem;
132        re2 = /(at|bl|iz)$/;
133        re3 = new RegExp("([^aeiouylsz])\\1$");
134        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
135        if (re2.test(w))
136          w = w + "e";
137        else if (re3.test(w)) {
138          re = /.$/;
139          w = w.replace(re,"");
140        }
141        else if (re4.test(w))
142          w = w + "e";
143      }
144    }
145
146    // Step 1c
147    re = /^(.+?)y$/;
148    if (re.test(w)) {
149      var fp = re.exec(w);
150      stem = fp[1];
151      re = new RegExp(s_v);
152      if (re.test(stem))
153        w = stem + "i";
154    }
155
156    // Step 2
157    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
158    if (re.test(w)) {
159      var fp = re.exec(w);
160      stem = fp[1];
161      suffix = fp[2];
162      re = new RegExp(mgr0);
163      if (re.test(stem))
164        w = stem + step2list[suffix];
165    }
166
167    // Step 3
168    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
169    if (re.test(w)) {
170      var fp = re.exec(w);
171      stem = fp[1];
172      suffix = fp[2];
173      re = new RegExp(mgr0);
174      if (re.test(stem))
175        w = stem + step3list[suffix];
176    }
177
178    // Step 4
179    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
180    re2 = /^(.+?)(s|t)(ion)$/;
181    if (re.test(w)) {
182      var fp = re.exec(w);
183      stem = fp[1];
184      re = new RegExp(mgr1);
185      if (re.test(stem))
186        w = stem;
187    }
188    else if (re2.test(w)) {
189      var fp = re2.exec(w);
190      stem = fp[1] + fp[2];
191      re2 = new RegExp(mgr1);
192      if (re2.test(stem))
193        w = stem;
194    }
195
196    // Step 5
197    re = /^(.+?)e$/;
198    if (re.test(w)) {
199      var fp = re.exec(w);
200      stem = fp[1];
201      re = new RegExp(mgr1);
202      re2 = new RegExp(meq1);
203      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
204      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
205        w = stem;
206    }
207    re = /ll$/;
208    re2 = new RegExp(mgr1);
209    if (re.test(w) && re2.test(w)) {
210      re = /.$/;
211      w = w.replace(re,"");
212    }
213
214    // and turn initial Y back to y
215    if (firstch == "y")
216      w = firstch.toLowerCase() + w.substr(1);
217    return w;
218  }
219}
220
221
222/**
223 * Search Module
224 */
225var Search = {
226
227  _index : null,
228  _queued_query : null,
229  _pulse_status : -1,
230
231  init : function() {
232      var params = $.getQueryParameters();
233      if (params.q) {
234          var query = params.q[0];
235          $('input[name="q"]')[0].value = query;
236          this.performSearch(query);
237      }
238  },
239
240  /**
241   * Sets the index
242   */
243  setIndex : function(index) {
244    var q;
245    this._index = index;
246    if ((q = this._queued_query) !== null) {
247      this._queued_query = null;
248      Search.query(q);
249    }
250  },
251
252  hasIndex : function() {
253      return this._index !== null;
254  },
255
256  deferQuery : function(query) {
257      this._queued_query = query;
258  },
259
260  stopPulse : function() {
261      this._pulse_status = 0;
262  },
263
264  startPulse : function() {
265    if (this._pulse_status >= 0)
266        return;
267    function pulse() {
268      Search._pulse_status = (Search._pulse_status + 1) % 4;
269      var dotString = '';
270      for (var i = 0; i < Search._pulse_status; i++)
271        dotString += '.';
272      Search.dots.text(dotString);
273      if (Search._pulse_status > -1)
274        window.setTimeout(pulse, 500);
275    };
276    pulse();
277  },
278
279  /**
280   * perform a search for something
281   */
282  performSearch : function(query) {
283    // create the required interface elements
284    this.out = $('#search-results');
285    this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
286    this.dots = $('<span></span>').appendTo(this.title);
287    this.status = $('<p style="display: none"></p>').appendTo(this.out);
288    this.output = $('<ul class="search"/>').appendTo(this.out);
289
290    $('#search-progress').text(_('Preparing search...'));
291    this.startPulse();
292
293    // index already loaded, the browser was quick!
294    if (this.hasIndex())
295      this.query(query);
296    else
297      this.deferQuery(query);
298  },
299
300  query : function(query) {
301    var stopwords = ['and', 'then', 'into', 'it', 'as', 'are', 'in',
302                     'if', 'for', 'no', 'there', 'their', 'was', 'is',
303                     'be', 'to', 'that', 'but', 'they', 'not', 'such',
304                     'with', 'by', 'a', 'on', 'these', 'of', 'will',
305                     'this', 'near', 'the', 'or', 'at'];
306
307    // stem the searchterms and add them to the correct list
308    var stemmer = new PorterStemmer();
309    var searchterms = [];
310    var excluded = [];
311    var hlterms = [];
312    var tmp = query.split(/\s+/);
313    var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null;
314    for (var i = 0; i < tmp.length; i++) {
315      if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
316          tmp[i] == "") {
317        // skip this "word"
318        continue;
319      }
320      // stem the word
321      var word = stemmer.stemWord(tmp[i]).toLowerCase();
322      // select the correct list
323      if (word[0] == '-') {
324        var toAppend = excluded;
325        word = word.substr(1);
326      }
327      else {
328        var toAppend = searchterms;
329        hlterms.push(tmp[i].toLowerCase());
330      }
331      // only add if not already in the list
332      if (!$.contains(toAppend, word))
333        toAppend.push(word);
334    };
335    var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
336
337    // console.debug('SEARCH: searching for:');
338    // console.info('required: ', searchterms);
339    // console.info('excluded: ', excluded);
340
341    // prepare search
342    var filenames = this._index.filenames;
343    var titles = this._index.titles;
344    var terms = this._index.terms;
345    var objects = this._index.objects;
346    var objtypes = this._index.objtypes;
347    var objnames = this._index.objnames;
348    var fileMap = {};
349    var files = null;
350    // different result priorities
351    var importantResults = [];
352    var objectResults = [];
353    var regularResults = [];
354    var unimportantResults = [];
355    $('#search-progress').empty();
356
357    // lookup as object
358    if (object != null) {
359      for (var prefix in objects) {
360        for (var name in objects[prefix]) {
361          var fullname = (prefix ? prefix + '.' : '') + name;
362          if (fullname.toLowerCase().indexOf(object) > -1) {
363            match = objects[prefix][name];
364            descr = objnames[match[1]] + _(', in ') + titles[match[0]];
365            // XXX the generated anchors are not generally correct
366            // XXX there may be custom prefixes
367            result = [filenames[match[0]], fullname, '#'+fullname, descr];
368            switch (match[2]) {
369            case 1: objectResults.push(result); break;
370            case 0: importantResults.push(result); break;
371            case 2: unimportantResults.push(result); break;
372            }
373          }
374        }
375      }
376    }
377
378    // sort results descending
379    objectResults.sort(function(a, b) {
380      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
381    });
382
383    importantResults.sort(function(a, b) {
384      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
385    });
386
387    unimportantResults.sort(function(a, b) {
388      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
389    });
390
391
392    // perform the search on the required terms
393    for (var i = 0; i < searchterms.length; i++) {
394      var word = searchterms[i];
395      // no match but word was a required one
396      if ((files = terms[word]) == null)
397        break;
398      if (files.length == undefined) {
399        files = [files];
400      }
401      // create the mapping
402      for (var j = 0; j < files.length; j++) {
403        var file = files[j];
404        if (file in fileMap)
405          fileMap[file].push(word);
406        else
407          fileMap[file] = [word];
408      }
409    }
410
411    // now check if the files don't contain excluded terms
412    for (var file in fileMap) {
413      var valid = true;
414
415      // check if all requirements are matched
416      if (fileMap[file].length != searchterms.length)
417        continue;
418
419      // ensure that none of the excluded terms is in the
420      // search result.
421      for (var i = 0; i < excluded.length; i++) {
422        if (terms[excluded[i]] == file ||
423            $.contains(terms[excluded[i]] || [], file)) {
424          valid = false;
425          break;
426        }
427      }
428
429      // if we have still a valid result we can add it
430      // to the result list
431      if (valid)
432        regularResults.push([filenames[file], titles[file], '', null]);
433    }
434
435    // delete unused variables in order to not waste
436    // memory until list is retrieved completely
437    delete filenames, titles, terms;
438
439    // now sort the regular results descending by title
440    regularResults.sort(function(a, b) {
441      var left = a[1].toLowerCase();
442      var right = b[1].toLowerCase();
443      return (left > right) ? -1 : ((left < right) ? 1 : 0);
444    });
445
446    // combine all results
447    var results = unimportantResults.concat(regularResults)
448      .concat(objectResults).concat(importantResults);
449
450    // print the results
451    var resultCount = results.length;
452    function displayNextItem() {
453      // results left, load the summary and display it
454      if (results.length) {
455        var item = results.pop();
456        var listItem = $('<li style="display:none"></li>');
457        listItem.append($('<a/>').attr(
458          'href',
459          item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
460          highlightstring + item[2]).html(item[1]));
461        if (item[3]) {
462          listItem.append($('<span> (' + item[3] + ')</span>'));
463          Search.output.append(listItem);
464          listItem.slideDown(5, function() {
465            displayNextItem();
466          });
467        } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
468          $.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
469                item[0] + '.txt', function(data) {
470            if (data != '') {
471              listItem.append($.makeSearchSummary(data, searchterms, hlterms));
472              Search.output.append(listItem);
473              listItem.slideDown(5, function() {
474                displayNextItem();
475              });
476            }
477          });
478        } else {
479          // no source available, just display title
480          Search.output.append(listItem);
481          listItem.slideDown(5, function() {
482            displayNextItem();
483          });
484        }
485      }
486      // search finished, update title and status message
487      else {
488        Search.stopPulse();
489        Search.title.text(_('Search Results'));
490        if (!resultCount)
491          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.'));
492        else
493            Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
494        Search.status.fadeIn(500);
495      }
496    }
497    displayNextItem();
498  }
499}
500
501$(document).ready(function() {
502  Search.init();
503});
Note: See TracBrowser for help on using the repository browser.