Completed
Pull Request — master (#70)
by Ron
13:25
created

docs/build/html/_static/doctools.js   F

Complexity

Total Complexity 63
Complexity/F 2.17

Size

Lines of Code 300
Function Count 29

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 168
nc 123
dl 0
loc 300
rs 3.36
c 0
b 0
f 0
wmc 63
mnd 3
bc 45
fnc 29
bpm 1.5517
cpm 2.1724
noi 24

18 Functions

Rating   Name   Duplication   Size   Complexity  
A jQuery.uaMatch 0 15 1
A Documentation.addContextElements 0 14 1
A Documentation.addTranslations 0 6 2
A Documentation.getCurrentURL 0 10 1
A Documentation.ngettext 0 6 3
A Documentation.init 0 8 2
A Documentation.initIndexTable 0 14 2
A Documentation.hideSearchWords 0 4 1
B jQuery.fn.highlightText 0 50 2
A Documentation.gettext 0 6 3
A Documentation.initOnKeyListeners 0 22 1
A jQuery.urldecode 0 3 1
A Documentation.PLURAL_EXPR 0 1 2
A jQuery.getQueryParameters 0 16 4
A Documentation.highlightSearchWords 0 18 4
A Documentation.makeURL 0 3 1
A Documentation.fixFirefoxAnchorBug 0 6 3
A $(document).ready 0 3 1

How to fix   Complexity   

Complexity

Complex classes like docs/build/html/_static/doctools.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
 * doctools.js
3
 * ~~~~~~~~~~~
4
 *
5
 * Sphinx JavaScript utilities for all documentation.
6
 *
7
 * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8
 * :license: BSD, see LICENSE for details.
9
 *
10
 */
11
12
/**
13
 * select a different prefix for underscore
14
 */
15
$u = _.noConflict();
0 ignored issues
show
Bug introduced by
The variable $u seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.$u.
Loading history...
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ 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...
16
17
/**
18
 * make the code below compatible with browsers without
19
 * an installed firebug like debugger
20
if (!window.console || !console.firebug) {
21
  var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
22
    "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
23
    "profile", "profileEnd"];
24
  window.console = {};
25
  for (var i = 0; i < names.length; ++i)
26
    window.console[names[i]] = function() {};
27
}
28
 */
29
30
/**
31
 * small helper function to urldecode strings
32
 */
33
jQuery.urldecode = function(x) {
34
  return decodeURIComponent(x).replace(/\+/g, ' ');
35
};
36
37
/**
38
 * small helper function to urlencode strings
39
 */
40
jQuery.urlencode = encodeURIComponent;
0 ignored issues
show
Bug introduced by
The variable encodeURIComponent seems to be never declared. If this is a global, consider adding a /** global: encodeURIComponent */ 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...
41
42
/**
43
 * This function returns the parsed url parameters of the
44
 * current request. Multiple values per key are supported,
45
 * it will always return arrays of strings for the value parts.
46
 */
47
jQuery.getQueryParameters = function(s) {
48
  if (typeof s === 'undefined')
49
    s = document.location.search;
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...
50
  var parts = s.substr(s.indexOf('?') + 1).split('&');
51
  var result = {};
52
  for (var i = 0; i < parts.length; i++) {
53
    var tmp = parts[i].split('=', 2);
54
    var key = jQuery.urldecode(tmp[0]);
55
    var value = jQuery.urldecode(tmp[1]);
56
    if (key in result)
57
      result[key].push(value);
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...
58
    else
59
      result[key] = [value];
60
  }
61
  return result;
62
};
63
64
/**
65
 * highlight a given string on a jquery object by wrapping it in
66
 * span elements with the given class name.
67
 */
68
jQuery.fn.highlightText = function(text, className) {
69
  function highlight(node, addItems) {
70
    if (node.nodeType === 3) {
71
      var val = node.nodeValue;
72
      var pos = val.toLowerCase().indexOf(text);
73
      if (pos >= 0 &&
74
          !jQuery(node.parentNode).hasClass(className) &&
75
          !jQuery(node.parentNode).hasClass("nohighlight")) {
76
        var span;
77
        var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
78
        if (isInSVG) {
79
          span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
80
        } else {
81
          span = document.createElement("span");
82
          span.className = className;
83
        }
84
        span.appendChild(document.createTextNode(val.substr(pos, text.length)));
85
        node.parentNode.insertBefore(span, node.parentNode.insertBefore(
86
          document.createTextNode(val.substr(pos + text.length)),
87
          node.nextSibling));
88
        node.nodeValue = val.substr(0, pos);
89
        if (isInSVG) {
90
          var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
91
          var bbox = node.parentElement.getBBox();
92
          rect.x.baseVal.value = bbox.x;
93
          rect.y.baseVal.value = bbox.y;
94
          rect.width.baseVal.value = bbox.width;
95
          rect.height.baseVal.value = bbox.height;
96
          rect.setAttribute('class', className);
97
          addItems.push({
98
              "parent": node.parentNode,
99
              "target": rect});
100
        }
101
      }
102
    }
103
    else if (!jQuery(node).is("button, select, textarea")) {
104
      jQuery.each(node.childNodes, function() {
105
        highlight(this, addItems);
106
      });
107
    }
108
  }
109
  var addItems = [];
110
  var result = this.each(function() {
111
    highlight(this, addItems);
112
  });
113
  for (var i = 0; i < addItems.length; ++i) {
114
    jQuery(addItems[i].parent).before(addItems[i].target);
115
  }
116
  return result;
117
};
118
119
/*
120
 * backward compatibility for jQuery.browser
121
 * This will be supported until firefox bug is fixed.
122
 */
123
if (!jQuery.browser) {
124
  jQuery.uaMatch = function(ua) {
125
    ua = ua.toLowerCase();
126
127
    var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
128
      /(webkit)[ \/]([\w.]+)/.exec(ua) ||
129
      /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
130
      /(msie) ([\w.]+)/.exec(ua) ||
131
      ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
132
      [];
133
134
    return {
135
      browser: match[ 1 ] || "",
136
      version: match[ 2 ] || "0"
137
    };
138
  };
139
  jQuery.browser = {};
140
  jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ 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...
141
}
142
143
/**
144
 * Small JavaScript module for the documentation.
145
 */
146
var Documentation = {
147
148
  init : function() {
149
    this.fixFirefoxAnchorBug();
150
    this.highlightSearchWords();
151
    this.initIndexTable();
152
    if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
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...
153
      this.initOnKeyListeners();
154
    }
155
  },
156
157
  /**
158
   * i18n support
159
   */
160
  TRANSLATIONS : {},
161
  PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
162
  LOCALE : 'unknown',
163
164
  // gettext and ngettext don't access this so that the functions
165
  // can safely bound to a different name (_ = Documentation.gettext)
166
  gettext : function(string) {
167
    var translated = Documentation.TRANSLATIONS[string];
168
    if (typeof translated === 'undefined')
169
      return string;
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...
170
    return (typeof translated === 'string') ? translated : translated[0];
171
  },
172
173
  ngettext : function(singular, plural, n) {
174
    var translated = Documentation.TRANSLATIONS[singular];
175
    if (typeof translated === 'undefined')
176
      return (n == 1) ? singular : plural;
0 ignored issues
show
Best Practice introduced by
Comparing n to 1 using the == operator is not safe. Consider using === instead.
Loading history...
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...
177
    return translated[Documentation.PLURALEXPR(n)];
178
  },
179
180
  addTranslations : function(catalog) {
181
    for (var key in catalog.messages)
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...
182
      this.TRANSLATIONS[key] = catalog.messages[key];
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...
183
    this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
0 ignored issues
show
Performance Best Practice introduced by
Using new Function() to create a function is slow and difficult to debug. Such functions do not create a closure. Consider using another way to define your function.
Loading history...
184
    this.LOCALE = catalog.locale;
185
  },
186
187
  /**
188
   * add context elements like header anchor links
189
   */
190
  addContextElements : function() {
191
    $('div[id] > :header:first').each(function() {
192
      $('<a class="headerlink">\u00B6</a>').
193
      attr('href', '#' + this.id).
194
      attr('title', _('Permalink to this headline')).
195
      appendTo(this);
196
    });
197
    $('dt[id]').each(function() {
198
      $('<a class="headerlink">\u00B6</a>').
199
      attr('href', '#' + this.id).
200
      attr('title', _('Permalink to this definition')).
201
      appendTo(this);
202
    });
203
  },
204
205
  /**
206
   * workaround a firefox stupidity
207
   * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
208
   */
209
  fixFirefoxAnchorBug : function() {
210
    if (document.location.hash && $.browser.mozilla)
211
      window.setTimeout(function() {
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...
212
        document.location.href += '';
213
      }, 10);
214
  },
215
216
  /**
217
   * highlight the search words provided in the url in the text
218
   */
219
  highlightSearchWords : function() {
220
    var params = $.getQueryParameters();
221
    var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
222
    if (terms.length) {
223
      var body = $('div.body');
224
      if (!body.length) {
225
        body = $('body');
226
      }
227
      window.setTimeout(function() {
228
        $.each(terms, function() {
229
          body.highlightText(this.toLowerCase(), 'highlighted');
230
        });
231
      }, 10);
232
      $('<p class="highlight-link"><a href="javascript:Documentation.' +
233
        'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
234
          .appendTo($('#searchbox'));
235
    }
236
  },
237
238
  /**
239
   * init the domain index toggle buttons
240
   */
241
  initIndexTable : function() {
242
    var togglers = $('img.toggler').click(function() {
243
      var src = $(this).attr('src');
244
      var idnum = $(this).attr('id').substr(7);
245
      $('tr.cg-' + idnum).toggle();
246
      if (src.substr(-9) === 'minus.png')
247
        $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
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...
248
      else
249
        $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
250
    }).css('display', '');
251
    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
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...
252
        togglers.click();
253
    }
254
  },
255
256
  /**
257
   * helper function to hide the search marks again
258
   */
259
  hideSearchWords : function() {
260
    $('#searchbox .highlight-link').fadeOut(300);
261
    $('span.highlighted').removeClass('highlighted');
262
  },
263
264
  /**
265
   * make the url absolute
266
   */
267
  makeURL : function(relativeURL) {
268
    return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
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...
269
  },
270
271
  /**
272
   * get the current relative url
273
   */
274
  getCurrentURL : function() {
275
    var path = document.location.pathname;
276
    var parts = path.split(/\//);
277
    $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
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...
278
      if (this === '..')
279
        parts.pop();
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
    });
281
    var url = parts.join('/');
282
    return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
283
  },
284
285
  initOnKeyListeners: function() {
286
    $(document).keyup(function(event) {
287
      var activeElementType = document.activeElement.tagName;
288
      // don't navigate when in search box or textarea
289
      if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if activeElementType !== "T...lementType !== "SELECT" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
290
        switch (event.keyCode) {
291
          case 37: // left
292
            var prevHref = $('link[rel="prev"]').prop('href');
293
            if (prevHref) {
294
              window.location.href = prevHref;
295
              return false;
296
            }
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
297
          case 39: // right
298
            var nextHref = $('link[rel="next"]').prop('href');
299
            if (nextHref) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if nextHref is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
300
              window.location.href = nextHref;
301
              return false;
302
            }
303
        }
0 ignored issues
show
Comprehensibility introduced by
There is no default case in this switch, so nothing gets returned when all cases fail. You might want to consider adding a default or return undefined explicitly.
Loading history...
304
      }
305
    });
306
  }
307
};
308
309
// quick alias for translations
310
_ = Documentation.gettext;
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window._.
Loading history...
311
312
$(document).ready(function() {
313
  Documentation.init();
314
});
315