Test Failed
Push — master ( 9811b7...5b4ca1 )
by Chad
16:14 queued 01:44
created

doc/build/_static/searchtools.js   F

Complexity

Total Complexity 111
Complexity/F 4.44

Size

Lines of Code 607
Function Count 25

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 111
dl 0
loc 607
rs 3.0617
c 1
b 0
f 0
cc 0
nc 1
mnd 6
bc 78
fnc 25
bpm 3.12
cpm 4.44
noi 41

13 Functions

Rating   Name   Duplication   Size   Complexity  
A Search.performSearch 0 17 2
A Search.init 0 8 2
A Search.setIndex 0 8 2
A Search.makeSearchSummary 0 18 3
C Search.performObjectSearch 0 62 15
A Search.loadIndex 0 9 1
A $(document).ready 0 3 1
A Search.startPulse 0 15 2
C Search.performTermsSearch 0 51 12
A Search.hasIndex 0 3 1
A Search.stopPulse 0 3 1
D Search.query 0 154 11
A Search.deferQuery 0 3 1

How to fix   Complexity   

Complexity

Complex classes like doc/build/_static/searchtools.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
 * searchtools.js_t
3
 * ~~~~~~~~~~~~~~~~
4
 *
5
 * Sphinx JavaScript utilties for the full-text search.
6
 *
7
 * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
8
 * :license: BSD, see LICENSE for details.
9
 *
10
 */
11
12
13
/**
14
 * Porter Stemmer
15
 */
16
var Stemmer = function() {
17
18
  var step2list = {
19
    ational: 'ate',
20
    tional: 'tion',
21
    enci: 'ence',
22
    anci: 'ance',
23
    izer: 'ize',
24
    bli: 'ble',
25
    alli: 'al',
26
    entli: 'ent',
27
    eli: 'e',
28
    ousli: 'ous',
29
    ization: 'ize',
30
    ation: 'ate',
31
    ator: 'ate',
32
    alism: 'al',
33
    iveness: 'ive',
34
    fulness: 'ful',
35
    ousness: 'ous',
36
    aliti: 'al',
37
    iviti: 'ive',
38
    biliti: 'ble',
39
    logi: 'log'
40
  };
41
42
  var step3list = {
43
    icate: 'ic',
44
    ative: '',
45
    alize: 'al',
46
    iciti: 'ic',
47
    ical: 'ic',
48
    ful: '',
49
    ness: ''
50
  };
51
52
  var c = "[^aeiou]";          // consonant
53
  var v = "[aeiouy]";          // vowel
54
  var C = c + "[^aeiouy]*";    // consonant sequence
55
  var V = v + "[aeiou]*";      // vowel sequence
56
57
  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
58
  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
59
  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
60
  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
61
62
  this.stemWord = function (w) {
63
    var stem;
64
    var suffix;
65
    var firstch;
66
    var origword = w;
0 ignored issues
show
Unused Code introduced by
The variable origword seems to be never used. Consider removing it.
Loading history...
67
68
    if (w.length < 3)
69
      return w;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
70
71
    var re;
72
    var re2;
73
    var re3;
74
    var re4;
75
76
    firstch = w.substr(0,1);
77
    if (firstch == "y")
78
      w = firstch.toUpperCase() + w.substr(1);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
79
80
    // Step 1a
81
    re = /^(.+?)(ss|i)es$/;
82
    re2 = /^(.+?)([^s])s$/;
83
84
    if (re.test(w))
85
      w = w.replace(re,"$1$2");
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
86
    else if (re2.test(w))
87
      w = w.replace(re2,"$1$2");
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
88
89
    // Step 1b
90
    re = /^(.+?)eed$/;
91
    re2 = /^(.+?)(ed|ing)$/;
92
    if (re.test(w)) {
93
      var fp = re.exec(w);
94
      re = new RegExp(mgr0);
95
      if (re.test(fp[1])) {
96
        re = /.$/;
97
        w = w.replace(re,"");
98
      }
99
    }
100
    else if (re2.test(w)) {
101
      var fp = re2.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
102
      stem = fp[1];
103
      re2 = new RegExp(s_v);
104
      if (re2.test(stem)) {
105
        w = stem;
106
        re2 = /(at|bl|iz)$/;
107
        re3 = new RegExp("([^aeiouylsz])\\1$");
108
        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
109
        if (re2.test(w))
110
          w = w + "e";
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
111
        else if (re3.test(w)) {
112
          re = /.$/;
113
          w = w.replace(re,"");
114
        }
115
        else if (re4.test(w))
116
          w = w + "e";
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
117
      }
118
    }
119
120
    // Step 1c
121
    re = /^(.+?)y$/;
122
    if (re.test(w)) {
123
      var fp = re.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
124
      stem = fp[1];
125
      re = new RegExp(s_v);
126
      if (re.test(stem))
127
        w = stem + "i";
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
128
    }
129
130
    // Step 2
131
    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
132
    if (re.test(w)) {
133
      var fp = re.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
134
      stem = fp[1];
135
      suffix = fp[2];
136
      re = new RegExp(mgr0);
137
      if (re.test(stem))
138
        w = stem + step2list[suffix];
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
139
    }
140
141
    // Step 3
142
    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
143
    if (re.test(w)) {
144
      var fp = re.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
145
      stem = fp[1];
146
      suffix = fp[2];
147
      re = new RegExp(mgr0);
148
      if (re.test(stem))
149
        w = stem + step3list[suffix];
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
150
    }
151
152
    // Step 4
153
    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
154
    re2 = /^(.+?)(s|t)(ion)$/;
155
    if (re.test(w)) {
156
      var fp = re.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
157
      stem = fp[1];
158
      re = new RegExp(mgr1);
159
      if (re.test(stem))
160
        w = stem;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
161
    }
162
    else if (re2.test(w)) {
163
      var fp = re2.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
164
      stem = fp[1] + fp[2];
165
      re2 = new RegExp(mgr1);
166
      if (re2.test(stem))
167
        w = stem;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
168
    }
169
170
    // Step 5
171
    re = /^(.+?)e$/;
172
    if (re.test(w)) {
173
      var fp = re.exec(w);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable fp already seems to be declared on line 93. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
174
      stem = fp[1];
175
      re = new RegExp(mgr1);
176
      re2 = new RegExp(meq1);
177
      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
178
      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
179
        w = stem;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
180
    }
181
    re = /ll$/;
182
    re2 = new RegExp(mgr1);
183
    if (re.test(w) && re2.test(w)) {
184
      re = /.$/;
185
      w = w.replace(re,"");
186
    }
187
188
    // and turn initial Y back to y
189
    if (firstch == "y")
190
      w = firstch.toLowerCase() + w.substr(1);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
191
    return w;
192
  }
193
}
194
195
196
197
/**
198
 * Simple result scoring code.
199
 */
200
var Scorer = {
201
  // Implement the following function to further tweak the score for each result
202
  // The function takes a result array [filename, title, anchor, descr, score]
203
  // and returns the new score.
204
  /*
205
  score: function(result) {
206
    return result[4];
207
  },
208
  */
209
210
  // query matches the full name of an object
211
  objNameMatch: 11,
212
  // or matches in the last dotted part of the object name
213
  objPartialMatch: 6,
214
  // Additive scores depending on the priority of the object
215
  objPrio: {0:  15,   // used to be importantResults
216
            1:  5,   // used to be objectResults
217
            2: -5},  // used to be unimportantResults
218
  //  Used when the priority is not in the mapping.
219
  objPrioDefault: 0,
220
221
  // query found in title
222
  title: 15,
223
  // query found in terms
224
  term: 5
225
};
226
227
228
/**
229
 * Search Module
230
 */
231
var Search = {
232
233
  _index : null,
234
  _queued_query : null,
235
  _pulse_status : -1,
236
237
  init : function() {
238
      var params = $.getQueryParameters();
239
      if (params.q) {
240
          var query = params.q[0];
241
          $('input[name="q"]')[0].value = query;
242
          this.performSearch(query);
243
      }
244
  },
245
246
  loadIndex : function(url) {
247
    $.ajax({type: "GET", url: url, data: null,
248
            dataType: "script", cache: true,
249
            complete: function(jqxhr, textstatus) {
250
              if (textstatus != "success") {
251
                document.getElementById("searchindexloader").src = url;
252
              }
253
            }});
254
  },
255
256
  setIndex : function(index) {
257
    var q;
258
    this._index = index;
259
    if ((q = this._queued_query) !== null) {
260
      this._queued_query = null;
261
      Search.query(q);
262
    }
263
  },
264
265
  hasIndex : function() {
266
      return this._index !== null;
267
  },
268
269
  deferQuery : function(query) {
270
      this._queued_query = query;
271
  },
272
273
  stopPulse : function() {
274
      this._pulse_status = 0;
275
  },
276
277
  startPulse : function() {
278
    if (this._pulse_status >= 0)
279
        return;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
280
    function pulse() {
281
      var i;
282
      Search._pulse_status = (Search._pulse_status + 1) % 4;
283
      var dotString = '';
284
      for (i = 0; i < Search._pulse_status; i++)
285
        dotString += '.';
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
286
      Search.dots.text(dotString);
287
      if (Search._pulse_status > -1)
288
        window.setTimeout(pulse, 500);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
289
    }
290
    pulse();
291
  },
292
293
  /**
294
   * perform a search for something (or wait until index is loaded)
295
   */
296
  performSearch : function(query) {
297
    // create the required interface elements
298
    this.out = $('#search-results');
299
    this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
300
    this.dots = $('<span></span>').appendTo(this.title);
301
    this.status = $('<p style="display: none"></p>').appendTo(this.out);
302
    this.output = $('<ul class="search"/>').appendTo(this.out);
303
304
    $('#search-progress').text(_('Preparing search...'));
305
    this.startPulse();
306
307
    // index already loaded, the browser was quick!
308
    if (this.hasIndex())
309
      this.query(query);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
310
    else
311
      this.deferQuery(query);
312
  },
313
314
  /**
315
   * execute search (requires search index to be loaded)
316
   */
317
  query : function(query) {
318
    var i;
319
    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"];
320
321
    // stem the searchterms and add them to the correct list
322
    var stemmer = new Stemmer();
323
    var searchterms = [];
324
    var excluded = [];
325
    var hlterms = [];
326
    var tmp = query.split(/\s+/);
327
    var objectterms = [];
328
    for (i = 0; i < tmp.length; i++) {
329
      if (tmp[i] !== "") {
330
          objectterms.push(tmp[i].toLowerCase());
331
      }
332
333
      if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
0 ignored issues
show
Bug introduced by
The variable $u seems to be never declared. If this is a global, consider adding a /** global: $u */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
334
          tmp[i] === "") {
335
        // skip this "word"
336
        continue;
337
      }
338
      // stem the word
339
      var word = stemmer.stemWord(tmp[i].toLowerCase());
340
      var toAppend;
341
      // select the correct list
342
      if (word[0] == '-') {
343
        toAppend = excluded;
344
        word = word.substr(1);
345
      }
346
      else {
347
        toAppend = searchterms;
348
        hlterms.push(tmp[i].toLowerCase());
349
      }
350
      // only add if not already in the list
351
      if (!$u.contains(toAppend, word))
352
        toAppend.push(word);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
353
    }
354
    var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
355
356
    // console.debug('SEARCH: searching for:');
357
    // console.info('required: ', searchterms);
358
    // console.info('excluded: ', excluded);
359
360
    // prepare search
361
    var terms = this._index.terms;
362
    var titleterms = this._index.titleterms;
363
364
    // array of [filename, title, anchor, descr, score]
365
    var results = [];
366
    $('#search-progress').empty();
367
368
    // lookup as object
369
    for (i = 0; i < objectterms.length; i++) {
370
      var others = [].concat(objectterms.slice(0, i),
371
                             objectterms.slice(i+1, objectterms.length));
372
      results = results.concat(this.performObjectSearch(objectterms[i], others));
373
    }
374
375
    // lookup as search terms in fulltext
376
    results = results.concat(this.performTermsSearch(searchterms, excluded, terms, Scorer.term))
377
                     .concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
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]);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
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 === '') {
0 ignored issues
show
Bug introduced by
The variable DOCUMENTATION_OPTIONS seems to be never declared. If this is a global, consider adding a /** global: DOCUMENTATION_OPTIONS */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
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) {
0 ignored issues
show
Bug introduced by
The variable DOCUMENTATION_OPTIONS seems to be never declared. If this is a global, consider adding a /** global: DOCUMENTATION_OPTIONS */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
438
          $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
439
                  dataType: "text",
440
                  complete: function(jqxhr, textstatus) {
0 ignored issues
show
Unused Code introduced by
The parameter textstatus is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
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.'));
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
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) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
485
      for (var name in objects[prefix]) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
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;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
522
          else if (anchor == '-')
523
            anchor = objnames[match[1]][1] + '-' + fullname;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
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, score) {
542
    var filenames = this._index.filenames;
543
    var titles = this._index.titles;
544
545
    var i, j, file, files;
546
    var fileMap = {};
547
    var results = [];
548
549
    // perform the search on the required terms
550
    for (i = 0; i < searchterms.length; i++) {
551
      var word = searchterms[i];
552
      // no match but word was a required one
553
      if ((files = terms[word]) === undefined)
554
        break;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
555
      if (files.length === undefined) {
556
        files = [files];
557
      }
558
      // create the mapping
559
      for (j = 0; j < files.length; j++) {
560
        file = files[j];
561
        if (file in fileMap)
562
          fileMap[file].push(word);
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
563
        else
564
          fileMap[file] = [word];
565
      }
566
    }
567
568
    // now check if the files don't contain excluded terms
569
    for (file in fileMap) {
570
      var valid = true;
571
572
      // check if all requirements are matched
573
      if (fileMap[file].length != searchterms.length)
574
          continue;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
575
576
      // ensure that none of the excluded terms is in the search result
577
      for (i = 0; i < excluded.length; i++) {
578
        if (terms[excluded[i]] == file ||
579
          $u.contains(terms[excluded[i]] || [], file)) {
0 ignored issues
show
Bug introduced by
The variable $u seems to be never declared. If this is a global, consider adding a /** global: $u */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
580
          valid = false;
581
          break;
582
        }
583
      }
584
585
      // if we have still a valid result we can add it to the result list
586
      if (valid) {
587
        results.push([filenames[file], titles[file], '', null, score]);
588
      }
589
    }
590
    return results;
591
  },
592
593
  /**
594
   * helper function to return a node containing the
595
   * search summary for a given text. keywords is a list
596
   * of stemmed words, hlwords is the list of normal, unstemmed
597
   * words. the first one is used to find the occurance, the
598
   * latter for highlighting it.
599
   */
600
  makeSearchSummary : function(text, keywords, hlwords) {
601
    var textLower = text.toLowerCase();
602
    var start = 0;
603
    $.each(keywords, function() {
604
      var i = textLower.indexOf(this.toLowerCase());
605
      if (i > -1)
606
        start = i;
0 ignored issues
show
Coding Style Best Practice introduced by
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 b = 42 will always be executed, while the logging statement will be executed conditionally.

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.

Loading history...
607
    });
608
    start = Math.max(start - 120, 0);
609
    var excerpt = ((start > 0) ? '...' : '') +
610
      $.trim(text.substr(start, 240)) +
611
      ((start + 240 - text.length) ? '...' : '');
612
    var rv = $('<div class="context"></div>').text(excerpt);
613
    $.each(hlwords, function() {
614
      rv = rv.highlightText(this, 'highlighted');
615
    });
616
    return rv;
617
  }
618
};
619
620
$(document).ready(function() {
621
  Search.init();
622
});