js/moris/morris.js   F
last analyzed

Complexity

Total Complexity 418
Complexity/F 2.65

Size

Lines of Code 1767
Function Count 158

Duplication

Duplicated Lines 19
Ratio 1.08 %

Importance

Changes 0
Metric Value
cc 0
eloc 1289
nc 0
dl 19
loc 1767
rs 0.8
c 0
b 0
f 0
wmc 418
mnd 9
bc 386
fnc 158
bpm 2.443
cpm 2.6455
noi 99

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like js/moris/morris.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
(function() {
2
  var $, Morris, minutesSpecHelper, secondsSpecHelper,
3
    __slice = [].slice,
4
    __hasProp = {}.hasOwnProperty,
5
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
0 ignored issues
show
Coding Style Best Practice introduced by
By convention, constructors like ctor should be capitalized.
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...
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...
6
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
7
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -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...
8
9
  Morris = window.Morris = {};
10
11
  $ = jQuery;
12
13
  Morris.EventEmitter = (function() {
14
15
    function EventEmitter() {}
16
17
    EventEmitter.prototype.on = function(name, handler) {
18
      if (this.handlers == null) {
19
        this.handlers = {};
20
      }
21
      if (this.handlers[name] == null) {
22
        this.handlers[name] = [];
23
      }
24
      this.handlers[name].push(handler);
25
      return this;
26
    };
27
28
    EventEmitter.prototype.fire = function() {
29
      var args, handler, name, _i, _len, _ref, _results;
30
      name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
31
      if ((this.handlers != null) && (this.handlers[name] != null)) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.handlers != null &&...s.handlers.name != null 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...
32
        _ref = this.handlers[name];
33
        _results = [];
34
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
35
          handler = _ref[_i];
36
          _results.push(handler.apply(null, args));
37
        }
38
        return _results;
39
      }
40
    };
41
42
    return EventEmitter;
43
44
  })();
45
46
  Morris.commas = function(num) {
47
    var absnum, intnum, ret, strabsnum;
48
    if (num != null) {
49
      ret = num < 0 ? "-" : "";
50
      absnum = Math.abs(num);
51
      intnum = Math.floor(absnum).toFixed(0);
52
      ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
53
      strabsnum = absnum.toString();
54
      if (strabsnum.length > intnum.length) {
55
        ret += strabsnum.slice(intnum.length);
56
      }
57
      return ret;
58
    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
59
      return '-';
60
    }
61
  };
62
63
  Morris.pad2 = function(number) {
64
    return (number < 10 ? '0' : '') + number;
65
  };
66
67
  Morris.Grid = (function(_super) {
68
69
    __extends(Grid, _super);
70
71
    function Grid(options) {
72
      var _this = this;
73
      if (typeof options.element === 'string') {
74
        this.el = $(document.getElementById(options.element));
75
      } else {
76
        this.el = $(options.element);
77
      }
78
      if (!(this.el != null) || this.el.length === 0) {
79
        throw new Error("Graph container element not found");
80
      }
81
      if (this.el.css('position') === 'static') {
82
        this.el.css('position', 'relative');
83
      }
84
      this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options);
85
      if (typeof this.options.units === 'string') {
86
        this.options.postUnits = options.units;
87
      }
88
      this.raphael = new Raphael(this.el[0]);
89
      this.elementWidth = null;
90
      this.elementHeight = null;
91
      this.dirty = false;
92
      if (this.init) {
93
        this.init();
94
      }
95
      this.setData(this.options.data);
96
      this.el.bind('mousemove', function(evt) {
97
        var offset;
98
        offset = _this.el.offset();
99
        return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);
100
      });
101
      this.el.bind('mouseout', function(evt) {
0 ignored issues
show
Unused Code introduced by
The parameter evt 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...
102
        return _this.fire('hoverout');
103
      });
104
      this.el.bind('touchstart touchmove touchend', function(evt) {
105
        var offset, touch;
106
        touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
107
        offset = _this.el.offset();
108
        _this.fire('hover', touch.pageX - offset.left, touch.pageY - offset.top);
109
        return touch;
110
      });
111
      this.el.bind('click', function(evt) {
112
        var offset;
113
        offset = _this.el.offset();
114
        return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top);
115
      });
116
      if (this.postInit) {
117
        this.postInit();
118
      }
119
    }
120
121
    Grid.prototype.gridDefaults = {
122
      dateFormat: null,
123
      axes: true,
124
      grid: true,
125
      gridLineColor: '#aaa',
126
      gridStrokeWidth: 0.5,
127
      gridTextColor: '#888',
128
      gridTextSize: 12,
129
      gridTextFamily: 'sans-serif',
130
      gridTextWeight: 'normal',
131
      hideHover: false,
132
      yLabelFormat: null,
133
      xLabelAngle: 0,
134
      numLines: 5,
135
      padding: 25,
136
      parseTime: true,
137
      postUnits: '',
138
      preUnits: '',
139
      ymax: 'auto',
140
      ymin: 'auto 0',
141
      goals: [],
142
      goalStrokeWidth: 1.0,
143
      goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'],
144
      events: [],
145
      eventStrokeWidth: 1.0,
146
      eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502']
147
    };
148
149
    Grid.prototype.setData = function(data, redraw) {
150
      var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval;
151
      if (redraw == null) {
152
        redraw = true;
153
      }
154
      this.options.data = data;
155
      if (!(data != null) || data.length === 0) {
156
        this.data = [];
157
        this.raphael.clear();
158
        if (this.hover != null) {
159
          this.hover.hide();
160
        }
161
        return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
162
      }
163
      ymax = this.cumulative ? 0 : null;
164
      ymin = this.cumulative ? 0 : null;
165
      if (this.options.goals.length > 0) {
166
        minGoal = Math.min.apply(null, this.options.goals);
167
        maxGoal = Math.max.apply(null, this.options.goals);
168
        ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;
169
        ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;
170
      }
171
      this.data = (function() {
172
        var _i, _len, _results;
173
        _results = [];
174
        for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) {
175
          row = data[index];
0 ignored issues
show
Bug introduced by
The variable index is changed as part of the for loop for example by ++_i on line 174. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
176
          ret = {};
177
          ret.label = row[this.options.xkey];
0 ignored issues
show
Bug introduced by
The variable ret is changed as part of the for loop for example by {} on line 176. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable row is changed as part of the for loop for example by data.index on line 175. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
178
          if (this.options.parseTime) {
179
            ret.x = Morris.parseDate(ret.label);
180
            if (this.options.dateFormat) {
181
              ret.label = this.options.dateFormat(ret.x);
182
            } else if (typeof ret.label === 'number') {
183
              ret.label = new Date(ret.label).toString();
184
            }
185
          } else {
186
            ret.x = index;
187
            if (this.options.xLabelFormat) {
188
              ret.label = this.options.xLabelFormat(ret);
189
            }
190
          }
191
          total = 0;
192
          ret.y = (function() {
193
            var _j, _len1, _ref, _results1;
194
            _ref = this.options.ykeys;
195
            _results1 = [];
196
            for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) {
197
              ykey = _ref[idx];
0 ignored issues
show
Bug introduced by
The variable idx is changed as part of the for loop for example by ++_j on line 196. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
198
              yval = row[ykey];
0 ignored issues
show
Bug introduced by
The variable ykey is changed as part of the for loop for example by _ref.idx on line 197. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
199
              if (typeof yval === 'string') {
0 ignored issues
show
Bug introduced by
The variable yval is changed as part of the for loop for example by row.ykey on line 198. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
200
                yval = parseFloat(yval);
201
              }
202
              if ((yval != null) && typeof yval !== 'number') {
203
                yval = null;
204
              }
205
              if (yval != null) {
206
                if (this.cumulative) {
207
                  total += yval;
0 ignored issues
show
Bug introduced by
The variable total is changed as part of the for loop for example by yval on line 207. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
208
                } else {
209
                  if (ymax != null) {
0 ignored issues
show
Bug introduced by
The variable ymax is changed as part of the for loop for example by Math.max(total, ymax) on line 218. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
210
                    ymax = Math.max(yval, ymax);
211
                    ymin = Math.min(yval, ymin);
0 ignored issues
show
Bug introduced by
The variable ymin is changed as part of the for loop for example by yval on line 213. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
212
                  } else {
213
                    ymax = ymin = yval;
214
                  }
215
                }
216
              }
217
              if (this.cumulative && (total != null)) {
218
                ymax = Math.max(total, ymax);
219
                ymin = Math.min(total, ymin);
220
              }
221
              _results1.push(yval);
222
            }
223
            return _results1;
224
          }).call(this);
225
          _results.push(ret);
226
        }
227
        return _results;
228
      }).call(this);
229
      if (this.options.parseTime) {
230
        this.data = this.data.sort(function(a, b) {
231
          return (a.x > b.x) - (b.x > a.x);
232
        });
233
      }
234
      this.xmin = this.data[0].x;
235
      this.xmax = this.data[this.data.length - 1].x;
236
      this.events = [];
237
      if (this.options.parseTime && this.options.events.length > 0) {
238
        this.events = (function() {
239
          var _i, _len, _ref, _results;
240
          _ref = this.options.events;
241
          _results = [];
242
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
243
            e = _ref[_i];
244
            _results.push(Morris.parseDate(e));
0 ignored issues
show
Bug introduced by
The variable e is changed as part of the for loop for example by _ref._i on line 243. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
245
          }
246
          return _results;
247
        }).call(this);
248
        this.xmax = Math.max(this.xmax, Math.max.apply(null, this.events));
249
        this.xmin = Math.min(this.xmin, Math.min.apply(null, this.events));
250
      }
251
      if (this.xmin === this.xmax) {
252
        this.xmin -= 1;
253
        this.xmax += 1;
254
      }
255
      this.ymin = this.yboundary('min', ymin);
256
      this.ymax = this.yboundary('max', ymax);
257
      if (this.ymin === this.ymax) {
258
        if (ymin) {
259
          this.ymin -= 1;
260
        }
261
        this.ymax += 1;
262
      }
263
      if (this.options.axes === true || this.options.grid === true) {
264
        if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) {
265
          this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines);
266
          this.ymin = Math.min(this.ymin, this.grid[0]);
267
          this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]);
268
        } else {
269
          step = (this.ymax - this.ymin) / (this.options.numLines - 1);
270
          this.grid = (function() {
271
            var _i, _ref, _ref1, _results;
272
            _results = [];
273
            for (y = _i = _ref = this.ymin, _ref1 = this.ymax; _ref <= _ref1 ? _i <= _ref1 : _i >= _ref1; y = _i += step) {
274
              _results.push(y);
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _i += step on line 273. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
275
            }
276
            return _results;
277
          }).call(this);
278
        }
279
      }
280
      this.dirty = true;
281
      if (redraw) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if redraw 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...
282
        return this.redraw();
283
      }
284
    };
285
286
    Grid.prototype.yboundary = function(boundaryType, currentValue) {
287
      var boundaryOption, suggestedValue;
288
      boundaryOption = this.options["y" + boundaryType];
289
      if (typeof boundaryOption === 'string') {
290
        if (boundaryOption.slice(0, 4) === 'auto') {
291
          if (boundaryOption.length > 5) {
292
            suggestedValue = parseInt(boundaryOption.slice(5), 10);
293
            if (currentValue == null) {
294
              return suggestedValue;
295
            }
296
            return Math[boundaryType](currentValue, suggestedValue);
297
          } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
298
            if (currentValue != null) {
299
              return currentValue;
300
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
301
              return 0;
302
            }
303
          }
304
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
305
          return parseInt(boundaryOption, 10);
306
        }
307
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
308
        return boundaryOption;
309
      }
310
    };
311
312
    Grid.prototype.autoGridLines = function(ymin, ymax, nlines) {
313
      var gmax, gmin, grid, smag, span, step, unit, y, ymag;
314
      span = ymax - ymin;
315
      ymag = Math.floor(Math.log(span) / Math.log(10));
316
      unit = Math.pow(10, ymag);
317
      gmin = Math.floor(ymin / unit) * unit;
318
      gmax = Math.ceil(ymax / unit) * unit;
319
      step = (gmax - gmin) / (nlines - 1);
320
      if (unit === 1 && step > 1 && Math.ceil(step) !== step) {
321
        step = Math.ceil(step);
322
        gmax = gmin + step * (nlines - 1);
323
      }
324
      if (gmin < 0 && gmax > 0) {
325
        gmin = Math.floor(ymin / step) * step;
326
        gmax = Math.ceil(ymax / step) * step;
327
      }
328
      if (step < 1) {
329
        smag = Math.floor(Math.log(step) / Math.log(10));
330
        grid = (function() {
331
          var _i, _results;
332
          _results = [];
333
          for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) {
334
            _results.push(parseFloat(y.toFixed(1 - smag)));
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _i += step on line 333. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
335
          }
336
          return _results;
337
        })();
338
      } else {
339
        grid = (function() {
340
          var _i, _results;
341
          _results = [];
342
          for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) {
343
            _results.push(y);
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _i += step on line 342. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
344
          }
345
          return _results;
346
        })();
347
      }
348
      return grid;
349
    };
350
351
    Grid.prototype._calc = function() {
352
      var bottomOffsets, gridLine, h, i, w, yLabelWidths;
353
      w = this.el.width();
354
      h = this.el.height();
355
      if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.elementWidth !== w ...ght !== h || this.dirty 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...
356
        this.elementWidth = w;
357
        this.elementHeight = h;
358
        this.dirty = false;
359
        this.left = this.options.padding;
360
        this.right = this.elementWidth - this.options.padding;
361
        this.top = this.options.padding;
362
        this.bottom = this.elementHeight - this.options.padding;
363
        if (this.options.axes) {
364
          yLabelWidths = (function() {
365
            var _i, _len, _ref, _results;
366
            _ref = this.grid;
367
            _results = [];
368
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
369
              gridLine = _ref[_i];
370
              _results.push(this.measureText(this.yAxisFormat(gridLine)).width);
0 ignored issues
show
Bug introduced by
The variable gridLine is changed as part of the for loop for example by _ref._i on line 369. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
371
            }
372
            return _results;
373
          }).call(this);
374
          this.left += Math.max.apply(Math, yLabelWidths);
375
          bottomOffsets = (function() {
376
            var _i, _ref, _results;
377
            _results = [];
378
            for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
379
              _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height);
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by 0 <= _ref ? ++_i: --_i on line 378. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
380
            }
381
            return _results;
382
          }).call(this);
383
          this.bottom -= Math.max.apply(Math, bottomOffsets);
384
        }
385
        this.width = Math.max(1, this.right - this.left);
386
        this.height = Math.max(1, this.bottom - this.top);
387
        this.dx = this.width / (this.xmax - this.xmin);
388
        this.dy = this.height / (this.ymax - this.ymin);
389
        if (this.calc) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.calc 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...
390
          return this.calc();
391
        }
392
      }
393
    };
394
395
    Grid.prototype.transY = function(y) {
396
      return this.bottom - (y - this.ymin) * this.dy;
397
    };
398
399
    Grid.prototype.transX = function(x) {
400
      if (this.data.length === 1) {
401
        return (this.left + this.right) / 2;
402
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
403
        return this.left + (x - this.xmin) * this.dx;
404
      }
405
    };
406
407
    Grid.prototype.redraw = function() {
408
      this.raphael.clear();
409
      this._calc();
410
      this.drawGrid();
411
      this.drawGoals();
412
      this.drawEvents();
413
      if (this.draw) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.draw 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...
414
        return this.draw();
415
      }
416
    };
417
418
    Grid.prototype.measureText = function(text, angle) {
419
      var ret, tt;
420
      if (angle == null) {
421
        angle = 0;
422
      }
423
      tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle);
424
      ret = tt.getBBox();
425
      tt.remove();
426
      return ret;
427
    };
428
429
    Grid.prototype.yAxisFormat = function(label) {
430
      return this.yLabelFormat(label);
431
    };
432
433
    Grid.prototype.yLabelFormat = function(label) {
434
      if (typeof this.options.yLabelFormat === 'function') {
435
        return this.options.yLabelFormat(label);
436
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
437
        return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;
438
      }
439
    };
440
441
    Grid.prototype.updateHover = function(x, y) {
442
      var hit, _ref;
443
      hit = this.hitTest(x, y);
444
      if (hit != null) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if hit != null 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...
445
        return (_ref = this.hover).update.apply(_ref, hit);
446
      }
447
    };
448
449
    Grid.prototype.drawGrid = function() {
450
      var lineY, y, _i, _len, _ref, _results;
451
      if (this.options.grid === false && this.options.axes === false) {
452
        return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
453
      }
454
      _ref = this.grid;
455
      _results = [];
456
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
457
        lineY = _ref[_i];
458
        y = this.transY(lineY);
459
        if (this.options.axes) {
460
          this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY));
461
        }
462
        if (this.options.grid) {
463
          _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width)));
464
        } else {
465
          _results.push(void 0);
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
466
        }
467
      }
468
      return _results;
469
    };
470
471
    Grid.prototype.drawGoals = function() {
472
      var color, goal, i, _i, _len, _ref, _results;
473
      _ref = this.options.goals;
474
      _results = [];
475
      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
476
        goal = _ref[i];
477
        color = this.options.goalLineColors[i % this.options.goalLineColors.length];
478
        _results.push(this.drawGoal(goal, color));
479
      }
480
      return _results;
481
    };
482
483
    Grid.prototype.drawEvents = function() {
484
      var color, event, i, _i, _len, _ref, _results;
485
      _ref = this.events;
486
      _results = [];
487
      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
488
        event = _ref[i];
489
        color = this.options.eventLineColors[i % this.options.eventLineColors.length];
490
        _results.push(this.drawEvent(event, color));
491
      }
492
      return _results;
493
    };
494
495
    Grid.prototype.drawGoal = function(goal, color) {
496
      return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth);
497
    };
498
499
    Grid.prototype.drawEvent = function(event, color) {
500
      return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth);
501
    };
502
503
    Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) {
504
      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
505
    };
506
507
    Grid.prototype.drawGridLine = function(path) {
508
      return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
509
    };
510
511
    return Grid;
512
513
  })(Morris.EventEmitter);
514
515
  Morris.parseDate = function(date) {
516
    var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs;
517
    if (typeof date === 'number') {
518
      return date;
519
    }
520
    m = date.match(/^(\d+) Q(\d)$/);
521
    n = date.match(/^(\d+)-(\d+)$/);
522
    o = date.match(/^(\d+)-(\d+)-(\d+)$/);
523
    p = date.match(/^(\d+) W(\d+)$/);
524
    q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/);
525
    r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/);
526
    if (m) {
527
      return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime();
528
    } else if (n) {
529
      return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime();
530
    } else if (o) {
531
      return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime();
532
    } else if (p) {
533
      ret = new Date(parseInt(p[1], 10), 0, 1);
534
      if (ret.getDay() !== 4) {
535
        ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);
536
      }
537
      return ret.getTime() + parseInt(p[2], 10) * 604800000;
538
    } else if (q) {
539
      if (!q[6]) {
540
        return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime();
541
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
542
        offsetmins = 0;
543
        if (q[6] !== 'Z') {
544
          offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10);
545
          if (q[7] === '+') {
546
            offsetmins = 0 - offsetmins;
547
          }
548
        }
549
        return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins);
550
      }
551
    } else if (r) {
552
      secs = parseFloat(r[6]);
553
      isecs = Math.floor(secs);
554
      msecs = Math.round((secs - isecs) * 1000);
555
      if (!r[8]) {
556
        return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime();
557
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
558
        offsetmins = 0;
559
        if (r[8] !== 'Z') {
560
          offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);
561
          if (r[9] === '+') {
562
            offsetmins = 0 - offsetmins;
563
          }
564
        }
565
        return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs);
566
      }
567
    } else {
568
      return new Date(parseInt(date, 10), 0, 1).getTime();
569
    }
570
  };
571
572
  Morris.Hover = (function() {
573
574
    Hover.defaults = {
575
      "class": 'morris-hover morris-default-style'
576
    };
577
578
    function Hover(options) {
579
      if (options == null) {
580
        options = {};
581
      }
582
      this.options = $.extend({}, Morris.Hover.defaults, options);
583
      this.el = $("<div class='" + this.options["class"] + "'></div>");
584
      this.el.hide();
585
      this.options.parent.append(this.el);
586
    }
587
588
    Hover.prototype.update = function(html, x, y) {
589
      this.html(html);
590
      this.show();
591
      return this.moveTo(x, y);
592
    };
593
594
    Hover.prototype.html = function(content) {
595
      return this.el.html(content);
596
    };
597
598
    Hover.prototype.moveTo = function(x, y) {
599
      var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top;
600
      parentWidth = this.options.parent.innerWidth();
601
      parentHeight = this.options.parent.innerHeight();
602
      hoverWidth = this.el.outerWidth();
603
      hoverHeight = this.el.outerHeight();
604
      left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth);
605 View Code Duplication
      if (y != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
606
        top = y - hoverHeight - 10;
607
        if (top < 0) {
608
          top = y + 10;
609
          if (top + hoverHeight > parentHeight) {
610
            top = parentHeight / 2 - hoverHeight / 2;
611
          }
612
        }
613
      } else {
614
        top = parentHeight / 2 - hoverHeight / 2;
615
      }
616
      return this.el.css({
617
        left: left + "px",
618
        top: parseInt(top) + "px"
619
      });
620
    };
621
622
    Hover.prototype.show = function() {
623
      return this.el.show();
624
    };
625
626
    Hover.prototype.hide = function() {
627
      return this.el.hide();
628
    };
629
630
    return Hover;
631
632
  })();
633
634
  Morris.Line = (function(_super) {
635
636
    __extends(Line, _super);
637
638
    function Line(options) {
639
      this.hilight = __bind(this.hilight, this);
640
641
      this.onHoverOut = __bind(this.onHoverOut, this);
642
643
      this.onHoverMove = __bind(this.onHoverMove, this);
644
645
      this.onGridClick = __bind(this.onGridClick, this);
646
      if (!(this instanceof Morris.Line)) {
647
        return new Morris.Line(options);
648
      }
649
      Line.__super__.constructor.call(this, options);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
650
    }
651
652
    Line.prototype.init = function() {
653
      this.pointGrow = Raphael.animation({
654
        r: this.options.pointSize + 3
655
      }, 25, 'linear');
656
      this.pointShrink = Raphael.animation({
657
        r: this.options.pointSize
658
      }, 25, 'linear');
659
      if (this.options.hideHover !== 'always') {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover !== "always" 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...
660
        this.hover = new Morris.Hover({
661
          parent: this.el
662
        });
663
        this.on('hovermove', this.onHoverMove);
664
        this.on('hoverout', this.onHoverOut);
665
        return this.on('gridclick', this.onGridClick);
666
      }
667
    };
668
669
    Line.prototype.defaults = {
670
      lineWidth: 3,
671
      pointSize: 4,
672
      lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
673
      pointWidths: [1],
674
      pointStrokeColors: ['#ffffff'],
675
      pointFillColors: [],
676
      smooth: true,
677
      xLabels: 'auto',
678
      xLabelFormat: null,
679
      xLabelMargin: 24,
680
      continuousLine: true,
681
      hideHover: false
682
    };
683
684
    Line.prototype.calc = function() {
685
      this.calcPoints();
686
      return this.generatePaths();
687
    };
688
689
    Line.prototype.calcPoints = function() {
690
      var row, y, _i, _len, _ref, _results;
691
      _ref = this.data;
692
      _results = [];
693
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
694
        row = _ref[_i];
695
        row._x = this.transX(row.x);
696
        row._y = (function() {
697
          var _j, _len1, _ref1, _results1;
698
          _ref1 = row.y;
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref._i on line 694. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
699
          _results1 = [];
700
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
701
            y = _ref1[_j];
702
            if (y != null) {
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _ref1._j on line 701. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
703
              _results1.push(this.transY(y));
704
            } else {
705
              _results1.push(y);
706
            }
707
          }
708
          return _results1;
709
        }).call(this);
710
        _results.push(row._ymax = Math.min.apply(null, [this.bottom].concat((function() {
711
          var _j, _len1, _ref1, _results1;
712
          _ref1 = row._y;
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref._i on line 694. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
713
          _results1 = [];
714
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
715
            y = _ref1[_j];
716
            if (y != null) {
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _ref1._j on line 715. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
717
              _results1.push(y);
718
            }
719
          }
720
          return _results1;
721
        })())));
722
      }
723
      return _results;
724
    };
725
726
    Line.prototype.hitTest = function(x, y) {
0 ignored issues
show
Unused Code introduced by
The parameter y 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...
727
      var index, r, _i, _len, _ref;
728
      if (this.data.length === 0) {
729
        return null;
730
      }
731
      _ref = this.data.slice(1);
732
      for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
733
        r = _ref[index];
734
        if (x < (r._x + this.data[index]._x) / 2) {
735
          break;
736
        }
737
      }
738
      return index;
739
    };
740
741
    Line.prototype.onGridClick = function(x, y) {
742
      var index;
743
      index = this.hitTest(x, y);
744
      return this.fire('click', index, this.options.data[index], x, y);
745
    };
746
747
    Line.prototype.onHoverMove = function(x, y) {
748
      var index;
749
      index = this.hitTest(x, y);
750
      return this.displayHoverForRow(index);
751
    };
752
753
    Line.prototype.onHoverOut = function() {
754
      if (this.options.hideHover !== false) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover !== false 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...
755
        return this.displayHoverForRow(null);
756
      }
757
    };
758
759
    Line.prototype.displayHoverForRow = function(index) {
760
      var _ref;
761
      if (index != null) {
762
        (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
763
        return this.hilight(index);
764
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
765
        this.hover.hide();
766
        return this.hilight();
767
      }
768
    };
769
770
    Line.prototype.hoverContentForRow = function(index) {
771
      var content, j, row, y, _i, _len, _ref;
772
      row = this.data[index];
773
      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
774
      _ref = row.y;
775 View Code Duplication
      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
776
        y = _ref[j];
777
        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
778
      }
779
      if (typeof this.options.hoverCallback === 'function') {
780
        content = this.options.hoverCallback(index, this.options, content);
781
      }
782
      return [content, row._x, row._ymax];
783
    };
784
785
    Line.prototype.generatePaths = function() {
786
      var c, coords, i, r, smooth;
787
      return this.paths = (function() {
788
        var _i, _ref, _ref1, _results;
789
        _results = [];
790
        for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
791
          smooth = this.options.smooth === true || (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0);
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
Bug introduced by
The variable i is changed as part of the for loop for example by 0 <= _ref ? ++_i: --_i on line 790. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
792
          coords = (function() {
793
            var _j, _len, _ref2, _results1;
794
            _ref2 = this.data;
795
            _results1 = [];
796
            for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
797
              r = _ref2[_j];
798
              if (r._y[i] !== void 0) {
0 ignored issues
show
Bug introduced by
The variable r is changed as part of the for loop for example by _ref2._j on line 797. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
799
                _results1.push({
800
                  x: r._x,
801
                  y: r._y[i]
802
                });
803
              }
804
            }
805
            return _results1;
806
          }).call(this);
807
          if (this.options.continuousLine) {
808
            coords = (function() {
809
              var _j, _len, _results1;
810
              _results1 = [];
811
              for (_j = 0, _len = coords.length; _j < _len; _j++) {
812
                c = coords[_j];
813
                if (c.y !== null) {
0 ignored issues
show
Bug introduced by
The variable c is changed as part of the for loop for example by coords._j on line 812. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
814
                  _results1.push(c);
815
                }
816
              }
817
              return _results1;
818
            })();
819
          }
820
          if (coords.length > 1) {
0 ignored issues
show
Bug introduced by
The variable coords is changed as part of the for loop for example by function() { var _j, _le...; return _results1; }() on line 808. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
821
            _results.push(Morris.Line.createPath(coords, smooth, this.bottom));
0 ignored issues
show
Bug introduced by
The variable smooth is changed as part of the for loop for example by this.options.smooth === ...ons.smooth, _ref1) >= 0 on line 791. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
822
          } else {
823
            _results.push(null);
824
          }
825
        }
826
        return _results;
827
      }).call(this);
828
    };
829
830
    Line.prototype.draw = function() {
831
      if (this.options.axes) {
832
        this.drawXAxis();
833
      }
834
      this.drawSeries();
835
      if (this.options.hideHover === false) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover === false 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...
836
        return this.displayHoverForRow(this.data.length - 1);
837
      }
838
    };
839
840
    Line.prototype.drawXAxis = function() {
841
      var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results,
842
        _this = this;
843
      ypos = this.bottom + this.options.padding / 2;
844
      prevLabelMargin = null;
845
      prevAngleMargin = null;
846
      drawLabel = function(labelText, xpos) {
847
        var label, labelBox, margin, offset, textBox;
848
        label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText);
849
        textBox = label.getBBox();
850
        label.transform("r" + (-_this.options.xLabelAngle));
851
        labelBox = label.getBBox();
852
        label.transform("t0," + (labelBox.height / 2) + "...");
853
        if (_this.options.xLabelAngle !== 0) {
854
          offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0);
855
          label.transform("t" + offset + ",0...");
856
        }
857
        labelBox = label.getBBox();
858
        if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) {
859
          if (_this.options.xLabelAngle !== 0) {
860
            margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0);
861
            prevAngleMargin = labelBox.x - margin;
862
          }
863
          return prevLabelMargin = labelBox.x - _this.options.xLabelMargin;
864
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
865
          return label.remove();
866
        }
867
      };
868
      if (this.options.parseTime) {
869
        if (this.data.length === 1 && this.options.xLabels === 'auto') {
870
          labels = [[this.data[0].label, this.data[0].x]];
871
        } else {
872
          labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);
873
        }
874
      } else {
875
        labels = (function() {
876
          var _i, _len, _ref, _results;
877
          _ref = this.data;
878
          _results = [];
879
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
880
            row = _ref[_i];
881
            _results.push([row.label, row.x]);
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref._i on line 880. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
882
          }
883
          return _results;
884
        }).call(this);
885
      }
886
      labels.reverse();
887
      _results = [];
888
      for (_i = 0, _len = labels.length; _i < _len; _i++) {
889
        l = labels[_i];
890
        _results.push(drawLabel(l[0], l[1]));
891
      }
892
      return _results;
893
    };
894
895
    Line.prototype.drawSeries = function() {
896
      var i, _i, _j, _ref, _ref1, _results;
897
      this.seriesPoints = [];
898
      for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
899
        this._drawLineFor(i);
900
      }
901
      _results = [];
902
      for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
903
        _results.push(this._drawPointFor(i));
904
      }
905
      return _results;
906
    };
907
908
    Line.prototype._drawPointFor = function(index) {
909
      var circle, row, _i, _len, _ref, _results;
910
      this.seriesPoints[index] = [];
911
      _ref = this.data;
912
      _results = [];
913
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
914
        row = _ref[_i];
915
        circle = null;
916
        if (row._y[index] != null) {
917
          circle = this.drawLinePoint(row._x, row._y[index], this.options.pointSize, this.colorFor(row, index, 'point'), index);
918
        }
919
        _results.push(this.seriesPoints[index].push(circle));
920
      }
921
      return _results;
922
    };
923
924
    Line.prototype._drawLineFor = function(index) {
925
      var path;
926
      path = this.paths[index];
927
      if (path !== null) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if path !== null 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...
928
        return this.drawLinePath(path, this.colorFor(null, index, 'line'));
929
      }
930
    };
931
932
    Line.createPath = function(coords, smooth, bottom) {
933
      var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;
934
      path = "";
935
      if (smooth) {
936
        grads = Morris.Line.gradients(coords);
937
      }
938
      prevCoord = {
939
        y: null
940
      };
941
      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
942
        coord = coords[i];
943
        if (coord.y != null) {
944
          if (prevCoord.y != null) {
945
            if (smooth) {
946
              g = grads[i];
0 ignored issues
show
Bug introduced by
The variable grads does not seem to be initialized in case smooth on line 935 is false. Are you sure this can never be the case?
Loading history...
947
              lg = grads[i - 1];
948
              ix = (coord.x - prevCoord.x) / 4;
949
              x1 = prevCoord.x + ix;
950
              y1 = Math.min(bottom, prevCoord.y + ix * lg);
951
              x2 = coord.x - ix;
952
              y2 = Math.min(bottom, coord.y - ix * g);
953
              path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y;
954
            } else {
955
              path += "L" + coord.x + "," + coord.y;
956
            }
957
          } else {
958
            if (!smooth || (grads[i] != null)) {
959
              path += "M" + coord.x + "," + coord.y;
960
            }
961
          }
962
        }
963
        prevCoord = coord;
964
      }
965
      return path;
966
    };
967
968
    Line.gradients = function(coords) {
969
      var coord, grad, i, nextCoord, prevCoord, _i, _len, _results;
970
      grad = function(a, b) {
971
        return (a.y - b.y) / (a.x - b.x);
972
      };
973
      _results = [];
974
      for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
975
        coord = coords[i];
976
        if (coord.y != null) {
977
          nextCoord = coords[i + 1] || {
978
            y: null
979
          };
980
          prevCoord = coords[i - 1] || {
981
            y: null
982
          };
983
          if ((prevCoord.y != null) && (nextCoord.y != null)) {
984
            _results.push(grad(prevCoord, nextCoord));
985
          } else if (prevCoord.y != null) {
986
            _results.push(grad(prevCoord, coord));
987
          } else if (nextCoord.y != null) {
988
            _results.push(grad(coord, nextCoord));
989
          } else {
990
            _results.push(null);
991
          }
992
        } else {
993
          _results.push(null);
994
        }
995
      }
996
      return _results;
997
    };
998
999
    Line.prototype.hilight = function(index) {
1000
      var i, _i, _j, _ref, _ref1;
1001
      if (this.prevHilight !== null && this.prevHilight !== index) {
1002
        for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
1003
          if (this.seriesPoints[i][this.prevHilight]) {
1004
            this.seriesPoints[i][this.prevHilight].animate(this.pointShrink);
1005
          }
1006
        }
1007
      }
1008
      if (index !== null && this.prevHilight !== index) {
1009
        for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
1010
          if (this.seriesPoints[i][index]) {
1011
            this.seriesPoints[i][index].animate(this.pointGrow);
1012
          }
1013
        }
1014
      }
1015
      return this.prevHilight = index;
1016
    };
1017
1018
    Line.prototype.colorFor = function(row, sidx, type) {
1019
      if (typeof this.options.lineColors === 'function') {
1020
        return this.options.lineColors.call(this, row, sidx, type);
1021
      } else if (type === 'point') {
1022
        return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length];
1023
      } else {
1024
        return this.options.lineColors[sidx % this.options.lineColors.length];
1025
      }
1026
    };
1027
1028
    Line.prototype.drawXAxisLabel = function(xPos, yPos, text) {
1029
      return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
1030
    };
1031
1032
    Line.prototype.drawLinePath = function(path, lineColor) {
1033
      return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.options.lineWidth);
1034
    };
1035
1036
    Line.prototype.drawLinePoint = function(xPos, yPos, size, pointColor, lineIndex) {
1037
      return this.raphael.circle(xPos, yPos, size).attr('fill', pointColor).attr('stroke-width', this.strokeWidthForSeries(lineIndex)).attr('stroke', this.strokeForSeries(lineIndex));
1038
    };
1039
1040
    Line.prototype.strokeWidthForSeries = function(index) {
1041
      return this.options.pointWidths[index % this.options.pointWidths.length];
1042
    };
1043
1044
    Line.prototype.strokeForSeries = function(index) {
1045
      return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length];
1046
    };
1047
1048
    return Line;
1049
1050
  })(Morris.Grid);
1051
1052
  Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) {
1053
    var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;
1054
    ddensity = 200 * (dmax - dmin) / pxwidth;
1055
    d0 = new Date(dmin);
1056
    spec = Morris.LABEL_SPECS[specName];
1057
    if (spec === void 0) {
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
1058
      _ref = Morris.AUTO_LABEL_ORDER;
1059
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1060
        name = _ref[_i];
1061
        s = Morris.LABEL_SPECS[name];
1062
        if (ddensity >= s.span) {
1063
          spec = s;
1064
          break;
1065
        }
1066
      }
1067
    }
1068
    if (spec === void 0) {
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
1069
      spec = Morris.LABEL_SPECS["second"];
1070
    }
1071
    if (xLabelFormat) {
1072
      spec = $.extend({}, spec, {
1073
        fmt: xLabelFormat
1074
      });
1075
    }
1076
    d = spec.start(d0);
1077
    ret = [];
1078
    while ((t = d.getTime()) <= dmax) {
1079
      if (t >= dmin) {
1080
        ret.push([spec.fmt(d), t]);
1081
      }
1082
      spec.incr(d);
1083
    }
1084
    return ret;
1085
  };
1086
1087
  minutesSpecHelper = function(interval) {
1088
    return {
1089
      span: interval * 60 * 1000,
1090
      start: function(d) {
1091
        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());
1092
      },
1093
      fmt: function(d) {
1094
        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes()));
1095
      },
1096
      incr: function(d) {
1097
        return d.setUTCMinutes(d.getUTCMinutes() + interval);
1098
      }
1099
    };
1100
  };
1101
1102
  secondsSpecHelper = function(interval) {
1103
    return {
1104
      span: interval * 1000,
1105
      start: function(d) {
1106
        return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());
1107
      },
1108
      fmt: function(d) {
1109
        return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds()));
1110
      },
1111
      incr: function(d) {
1112
        return d.setUTCSeconds(d.getUTCSeconds() + interval);
1113
      }
1114
    };
1115
  };
1116
1117
  Morris.LABEL_SPECS = {
1118
    "decade": {
1119
      span: 172800000000,
1120
      start: function(d) {
1121
        return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1);
1122
      },
1123
      fmt: function(d) {
1124
        return "" + (d.getFullYear());
1125
      },
1126
      incr: function(d) {
1127
        return d.setFullYear(d.getFullYear() + 10);
1128
      }
1129
    },
1130
    "year": {
1131
      span: 17280000000,
1132
      start: function(d) {
1133
        return new Date(d.getFullYear(), 0, 1);
1134
      },
1135
      fmt: function(d) {
1136
        return "" + (d.getFullYear());
1137
      },
1138
      incr: function(d) {
1139
        return d.setFullYear(d.getFullYear() + 1);
1140
      }
1141
    },
1142
    "month": {
1143
      span: 2419200000,
1144
      start: function(d) {
1145
        return new Date(d.getFullYear(), d.getMonth(), 1);
1146
      },
1147
      fmt: function(d) {
1148
        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1));
1149
      },
1150
      incr: function(d) {
1151
        return d.setMonth(d.getMonth() + 1);
1152
      }
1153
    },
1154
    "day": {
1155
      span: 86400000,
1156
      start: function(d) {
1157
        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
1158
      },
1159
      fmt: function(d) {
1160
        return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
1161
      },
1162
      incr: function(d) {
1163
        return d.setDate(d.getDate() + 1);
1164
      }
1165
    },
1166
    "hour": minutesSpecHelper(60),
1167
    "30min": minutesSpecHelper(30),
1168
    "15min": minutesSpecHelper(15),
1169
    "10min": minutesSpecHelper(10),
1170
    "5min": minutesSpecHelper(5),
1171
    "minute": minutesSpecHelper(1),
1172
    "30sec": secondsSpecHelper(30),
1173
    "15sec": secondsSpecHelper(15),
1174
    "10sec": secondsSpecHelper(10),
1175
    "5sec": secondsSpecHelper(5),
1176
    "second": secondsSpecHelper(1)
1177
  };
1178
1179
  Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
1180
1181
  Morris.Area = (function(_super) {
1182
    var areaDefaults;
1183
1184
    __extends(Area, _super);
1185
1186
    areaDefaults = {
1187
      fillOpacity: 'auto',
1188
      behaveLikeLine: false
1189
    };
1190
1191
    function Area(options) {
1192
      var areaOptions;
1193
      if (!(this instanceof Morris.Area)) {
1194
        return new Morris.Area(options);
1195
      }
1196
      areaOptions = $.extend({}, areaDefaults, options);
1197
      this.cumulative = !areaOptions.behaveLikeLine;
1198
      if (areaOptions.fillOpacity === 'auto') {
1199
        areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;
1200
      }
1201
      Area.__super__.constructor.call(this, areaOptions);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1202
    }
1203
1204
    Area.prototype.calcPoints = function() {
1205
      var row, total, y, _i, _len, _ref, _results;
1206
      _ref = this.data;
1207
      _results = [];
1208
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1209
        row = _ref[_i];
1210
        row._x = this.transX(row.x);
1211
        total = 0;
1212
        row._y = (function() {
1213
          var _j, _len1, _ref1, _results1;
1214
          _ref1 = row.y;
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref._i on line 1209. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1215
          _results1 = [];
1216
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
1217
            y = _ref1[_j];
1218
            if (this.options.behaveLikeLine) {
1219
              _results1.push(this.transY(y));
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _ref1._j on line 1217. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1220
            } else {
1221
              total += y || 0;
0 ignored issues
show
Bug introduced by
The variable total is changed as part of the for loop for example by y || 0 on line 1221. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1222
              _results1.push(this.transY(total));
1223
            }
1224
          }
1225
          return _results1;
1226
        }).call(this);
1227
        _results.push(row._ymax = Math.max.apply(Math, row._y));
1228
      }
1229
      return _results;
1230
    };
1231
1232
    Area.prototype.drawSeries = function() {
1233
      var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;
0 ignored issues
show
Unused Code introduced by
The variable _i seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable _j seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable _ref seems to be never used. Consider removing it.
Loading history...
1234
      this.seriesPoints = [];
1235
      if (this.options.behaveLikeLine) {
1236
        range = (function() {
1237
          _results = [];
1238
          for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
1239
          return _results;
1240
        }).apply(this);
1241
      } else {
1242
        range = (function() {
1243
          _results1 = [];
1244
          for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }
1245
          return _results1;
1246
        }).apply(this);
1247
      }
1248
      _results2 = [];
1249
      for (_k = 0, _len = range.length; _k < _len; _k++) {
1250
        i = range[_k];
1251
        this._drawFillFor(i);
1252
        this._drawLineFor(i);
1253
        _results2.push(this._drawPointFor(i));
1254
      }
1255
      return _results2;
1256
    };
1257
1258
    Area.prototype._drawFillFor = function(index) {
1259
      var path;
1260
      path = this.paths[index];
1261
      if (path !== null) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if path !== null 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...
1262
        path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z");
1263
        return this.drawFilledPath(path, this.fillForSeries(index));
1264
      }
1265
    };
1266
1267
    Area.prototype.fillForSeries = function(i) {
1268
      var color;
1269
      color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));
1270
      return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));
1271
    };
1272
1273
    Area.prototype.drawFilledPath = function(path, fill) {
1274
      return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke-width', 0);
1275
    };
1276
1277
    return Area;
1278
1279
  })(Morris.Line);
1280
1281
  Morris.Bar = (function(_super) {
1282
1283
    __extends(Bar, _super);
1284
1285
    function Bar(options) {
1286
      this.onHoverOut = __bind(this.onHoverOut, this);
1287
1288
      this.onHoverMove = __bind(this.onHoverMove, this);
1289
1290
      this.onGridClick = __bind(this.onGridClick, this);
1291
      if (!(this instanceof Morris.Bar)) {
1292
        return new Morris.Bar(options);
1293
      }
1294
      Bar.__super__.constructor.call(this, $.extend({}, options, {
1295
        parseTime: false
1296
      }));
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1297
    }
1298
1299
    Bar.prototype.init = function() {
1300
      this.cumulative = this.options.stacked;
1301
      if (this.options.hideHover !== 'always') {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover !== "always" 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...
1302
        this.hover = new Morris.Hover({
1303
          parent: this.el
1304
        });
1305
        this.on('hovermove', this.onHoverMove);
1306
        this.on('hoverout', this.onHoverOut);
1307
        return this.on('gridclick', this.onGridClick);
1308
      }
1309
    };
1310
1311
    Bar.prototype.defaults = {
1312
      barSizeRatio: 0.75,
1313
      barGap: 3,
1314
      barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
1315
      xLabelMargin: 50
1316
    };
1317
1318
    Bar.prototype.calc = function() {
1319
      var _ref;
1320
      this.calcBars();
1321
      if (this.options.hideHover === false) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover === false 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...
1322
        return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1));
1323
      }
1324
    };
1325
1326
    Bar.prototype.calcBars = function() {
1327
      var idx, row, y, _i, _len, _ref, _results;
1328
      _ref = this.data;
1329
      _results = [];
1330
      for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
1331
        row = _ref[idx];
1332
        row._x = this.left + this.width * (idx + 0.5) / this.data.length;
1333
        _results.push(row._y = (function() {
1334
          var _j, _len1, _ref1, _results1;
1335
          _ref1 = row.y;
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref.idx on line 1331. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1336
          _results1 = [];
1337
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
1338
            y = _ref1[_j];
1339
            if (y != null) {
0 ignored issues
show
Bug introduced by
The variable y is changed as part of the for loop for example by _ref1._j on line 1338. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1340
              _results1.push(this.transY(y));
1341
            } else {
1342
              _results1.push(null);
1343
            }
1344
          }
1345
          return _results1;
1346
        }).call(this));
1347
      }
1348
      return _results;
1349
    };
1350
1351
    Bar.prototype.draw = function() {
1352
      if (this.options.axes) {
1353
        this.drawXAxis();
1354
      }
1355
      return this.drawSeries();
1356
    };
1357
1358
    Bar.prototype.drawXAxis = function() {
1359
      var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;
1360
      ypos = this.bottom + this.options.padding / 2;
1361
      prevLabelMargin = null;
1362
      prevAngleMargin = null;
1363
      _results = [];
1364
      for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
1365
        row = this.data[this.data.length - 1 - i];
1366
        label = this.drawXAxisLabel(row._x, ypos, row.label);
1367
        textBox = label.getBBox();
1368
        label.transform("r" + (-this.options.xLabelAngle));
1369
        labelBox = label.getBBox();
1370
        label.transform("t0," + (labelBox.height / 2) + "...");
1371
        if (this.options.xLabelAngle !== 0) {
1372
          offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0);
1373
          label.transform("t" + offset + ",0...");
1374
        }
1375
        if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) {
1376
          if (this.options.xLabelAngle !== 0) {
1377
            margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0);
1378
            prevAngleMargin = labelBox.x - margin;
1379
          }
1380
          _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin);
1381
        } else {
1382
          _results.push(label.remove());
1383
        }
1384
      }
1385
      return _results;
1386
    };
1387
1388
    Bar.prototype.drawSeries = function() {
1389
      var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, top, ypos, zeroPos;
1390
      groupWidth = this.width / this.options.data.length;
1391
      numBars = this.options.stacked != null ? 1 : this.options.ykeys.length;
1392
      barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;
1393
      leftPadding = groupWidth * (1 - this.options.barSizeRatio) / 2;
1394
      zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;
1395
      return this.bars = (function() {
1396
        var _i, _len, _ref, _results;
1397
        _ref = this.data;
1398
        _results = [];
1399
        for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
1400
          row = _ref[idx];
0 ignored issues
show
Bug introduced by
The variable idx is changed as part of the for loop for example by ++_i on line 1399. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1401
          lastTop = 0;
1402
          _results.push((function() {
1403
            var _j, _len1, _ref1, _results1;
1404
            _ref1 = row._y;
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref.idx on line 1400. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1405
            _results1 = [];
1406
            for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {
1407
              ypos = _ref1[sidx];
0 ignored issues
show
Bug introduced by
The variable sidx is changed as part of the for loop for example by ++_j on line 1406. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1408
              if (ypos !== null) {
0 ignored issues
show
Bug introduced by
The variable ypos is changed as part of the for loop for example by _ref1.sidx on line 1407. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1409
                if (zeroPos) {
1410
                  top = Math.min(ypos, zeroPos);
1411
                  bottom = Math.max(ypos, zeroPos);
1412
                } else {
1413
                  top = ypos;
1414
                  bottom = this.bottom;
1415
                }
1416
                left = this.left + idx * groupWidth + leftPadding;
1417
                if (!this.options.stacked) {
1418
                  left += sidx * (barWidth + this.options.barGap);
0 ignored issues
show
Bug introduced by
The variable left is changed as part of the for loop for example by this.left + idx * groupWidth + leftPadding on line 1416. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1419
                }
1420
                size = bottom - top;
0 ignored issues
show
Bug introduced by
The variable top is changed as part of the for loop for example by Math.min(ypos, zeroPos) on line 1410. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable bottom is changed as part of the for loop for example by Math.max(ypos, zeroPos) on line 1411. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1421
                if (this.options.stacked) {
1422
                  top -= lastTop;
0 ignored issues
show
Bug introduced by
The variable lastTop is changed as part of the for loop for example by size on line 1425. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1423
                }
1424
                this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'));
0 ignored issues
show
Bug introduced by
The variable size is changed as part of the for loop for example by bottom - top on line 1420. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1425
                _results1.push(lastTop += size);
1426
              } else {
1427
                _results1.push(null);
1428
              }
1429
            }
1430
            return _results1;
1431
          }).call(this));
1432
        }
1433
        return _results;
1434
      }).call(this);
1435
    };
1436
1437
    Bar.prototype.colorFor = function(row, sidx, type) {
1438
      var r, s;
1439
      if (typeof this.options.barColors === 'function') {
1440
        r = {
1441
          x: row.x,
1442
          y: row.y[sidx],
1443
          label: row.label
1444
        };
1445
        s = {
1446
          index: sidx,
1447
          key: this.options.ykeys[sidx],
1448
          label: this.options.labels[sidx]
1449
        };
1450
        return this.options.barColors.call(this, r, s, type);
1451
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1452
        return this.options.barColors[sidx % this.options.barColors.length];
1453
      }
1454
    };
1455
1456
    Bar.prototype.hitTest = function(x, y) {
0 ignored issues
show
Unused Code introduced by
The parameter y 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...
1457
      if (this.data.length === 0) {
1458
        return null;
1459
      }
1460
      x = Math.max(Math.min(x, this.right), this.left);
1461
      return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length)));
1462
    };
1463
1464
    Bar.prototype.onGridClick = function(x, y) {
1465
      var index;
1466
      index = this.hitTest(x, y);
1467
      return this.fire('click', index, this.options.data[index], x, y);
1468
    };
1469
1470
    Bar.prototype.onHoverMove = function(x, y) {
1471
      var index, _ref;
1472
      index = this.hitTest(x, y);
1473
      return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
1474
    };
1475
1476
    Bar.prototype.onHoverOut = function() {
1477
      if (this.options.hideHover !== false) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.options.hideHover !== false 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...
1478
        return this.hover.hide();
1479
      }
1480
    };
1481
1482
    Bar.prototype.hoverContentForRow = function(index) {
1483
      var content, j, row, x, y, _i, _len, _ref;
1484
      row = this.data[index];
1485
      content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
1486
      _ref = row.y;
1487 View Code Duplication
      for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1488
        y = _ref[j];
1489
        content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n  " + this.options.labels[j] + ":\n  " + (this.yLabelFormat(y)) + "\n</div>";
1490
      }
1491
      if (typeof this.options.hoverCallback === 'function') {
1492
        content = this.options.hoverCallback(index, this.options, content);
1493
      }
1494
      x = this.left + (index + 0.5) * this.width / this.data.length;
1495
      return [content, x];
1496
    };
1497
1498
    Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) {
1499
      var label;
1500
      return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
0 ignored issues
show
Unused Code introduced by
The variable label seems to be never used. Consider removing it.
Loading history...
Comprehensibility introduced by
Are you sure you want to assign to label here, or did you intend to make a comparison like label === this.raphael.t....options.gridTextColor)?
Loading history...
1501
    };
1502
1503
    Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor) {
1504
      return this.raphael.rect(xPos, yPos, width, height).attr('fill', barColor).attr('stroke-width', 0);
1505
    };
1506
1507
    return Bar;
1508
1509
  })(Morris.Grid);
1510
1511
  Morris.Donut = (function(_super) {
1512
1513
    __extends(Donut, _super);
1514
1515
    Donut.prototype.defaults = {
1516
      colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
1517
      backgroundColor: '#FFFFFF',
1518
      labelColor: '#000000',
1519
      formatter: Morris.commas
1520
    };
1521
1522
    function Donut(options) {
1523
      this.select = __bind(this.select, this);
1524
1525
      this.click = __bind(this.click, this);
1526
1527
      var row;
1528
      if (!(this instanceof Morris.Donut)) {
1529
        return new Morris.Donut(options);
1530
      }
1531
      if (typeof options.element === 'string') {
1532
        this.el = $(document.getElementById(options.element));
1533
      } else {
1534
        this.el = $(options.element);
1535
      }
1536
      this.options = $.extend({}, this.defaults, options);
1537
      if (this.el === null || this.el.length === 0) {
1538
        throw new Error("Graph placeholder not found.");
1539
      }
1540
      if (options.data === void 0 || options.data.length === 0) {
0 ignored issues
show
Coding Style introduced by
Consider using undefined instead of void(0). It is equivalent and more straightforward to read.
Loading history...
1541
        return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
1542
      }
1543
      this.data = options.data;
1544
      this.values = (function() {
1545
        var _i, _len, _ref, _results;
1546
        _ref = this.data;
1547
        _results = [];
1548
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1549
          row = _ref[_i];
1550
          _results.push(parseFloat(row.value));
0 ignored issues
show
Bug introduced by
The variable row is changed as part of the for loop for example by _ref._i on line 1549. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1551
        }
1552
        return _results;
1553
      }).call(this);
1554
      this.redraw();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1555
    }
1556
1557
    Donut.prototype.redraw = function() {
1558
      var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
1559
      this.el.empty();
1560
      this.raphael = new Raphael(this.el[0]);
1561
      cx = this.el.width() / 2;
1562
      cy = this.el.height() / 2;
1563
      w = (Math.min(cx, cy) - 10) / 3;
1564
      total = 0;
1565
      _ref = this.values;
1566
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1567
        value = _ref[_i];
1568
        total += value;
1569
      }
1570
      min = 5 / (2 * w);
1571
      C = 1.9999 * Math.PI - min * this.data.length;
1572
      last = 0;
1573
      idx = 0;
1574
      this.segments = [];
1575
      _ref1 = this.values;
1576
      for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
1577
        value = _ref1[i];
1578
        next = last + min + C * (value / total);
1579
        seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
1580
        seg.render();
1581
        this.segments.push(seg);
1582
        seg.on('hover', this.select);
1583
        seg.on('click', this.click);
1584
        last = next;
1585
        idx += 1;
1586
      }
1587
      this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
1588
      this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
1589
      max_value = Math.max.apply(null, (function() {
1590
        var _k, _len2, _ref2, _results;
1591
        _ref2 = this.values;
1592
        _results = [];
1593
        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
1594
          value = _ref2[_k];
1595
          _results.push(value);
0 ignored issues
show
Bug introduced by
The variable value is changed as part of the for loop for example by _ref2._k on line 1594. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1596
        }
1597
        return _results;
1598
      }).call(this));
1599
      idx = 0;
1600
      _ref2 = this.values;
1601
      _results = [];
1602
      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
1603
        value = _ref2[_k];
1604
        if (value === max_value) {
1605
          this.select(idx);
1606
          break;
1607
        }
1608
        _results.push(idx += 1);
1609
      }
1610
      return _results;
1611
    };
1612
1613
    Donut.prototype.click = function(idx) {
1614
      return this.fire('click', idx, this.data[idx]);
1615
    };
1616
1617
    Donut.prototype.select = function(idx) {
1618
      var row, s, segment, _i, _len, _ref;
1619
      _ref = this.segments;
1620
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1621
        s = _ref[_i];
1622
        s.deselect();
1623
      }
1624
      segment = this.segments[idx];
1625
      segment.select();
1626
      row = this.data[idx];
1627
      return this.setLabels(row.label, this.options.formatter(row.value, row));
1628
    };
1629
1630
    Donut.prototype.setLabels = function(label1, label2) {
1631
      var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale;
1632
      inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3;
1633
      maxWidth = 1.8 * inner;
1634
      maxHeightTop = inner / 2;
1635
      maxHeightBottom = inner / 3;
1636
      this.text1.attr({
1637
        text: label1,
1638
        transform: ''
1639
      });
1640
      text1bbox = this.text1.getBBox();
1641
      text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height);
1642
      this.text1.attr({
1643
        transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height)
1644
      });
1645
      this.text2.attr({
1646
        text: label2,
1647
        transform: ''
1648
      });
1649
      text2bbox = this.text2.getBBox();
1650
      text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height);
1651
      return this.text2.attr({
1652
        transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y
1653
      });
1654
    };
1655
1656
    Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) {
1657
      var text;
1658
      text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color);
1659
      if (fontWeight != null) {
1660
        text.attr('font-weight', fontWeight);
1661
      }
1662
      return text;
1663
    };
1664
1665
    return Donut;
1666
1667
  })(Morris.EventEmitter);
1668
1669
  Morris.DonutSegment = (function(_super) {
1670
1671
    __extends(DonutSegment, _super);
1672
1673
    function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) {
1674
      this.cx = cx;
1675
      this.cy = cy;
1676
      this.inner = inner;
1677
      this.outer = outer;
1678
      this.color = color;
1679
      this.backgroundColor = backgroundColor;
1680
      this.index = index;
1681
      this.raphael = raphael;
1682
      this.deselect = __bind(this.deselect, this);
1683
1684
      this.select = __bind(this.select, this);
1685
1686
      this.sin_p0 = Math.sin(p0);
1687
      this.cos_p0 = Math.cos(p0);
1688
      this.sin_p1 = Math.sin(p1);
1689
      this.cos_p1 = Math.cos(p1);
1690
      this.is_long = (p1 - p0) > Math.PI ? 1 : 0;
1691
      this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5);
1692
      this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer);
1693
      this.hilight = this.calcArc(this.inner);
1694
    }
1695
1696
    DonutSegment.prototype.calcArcPoints = function(r) {
1697
      return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1];
1698
    };
1699
1700
    DonutSegment.prototype.calcSegment = function(r1, r2) {
1701
      var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1;
1702
      _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
1703
      _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
1704
      return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z";
1705
    };
1706
1707
    DonutSegment.prototype.calcArc = function(r) {
1708
      var ix0, ix1, iy0, iy1, _ref;
1709
      _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
0 ignored issues
show
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
1710
      return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1);
1711
    };
1712
1713
    DonutSegment.prototype.render = function() {
1714
      var _this = this;
1715
      this.arc = this.drawDonutArc(this.hilight, this.color);
1716
      return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() {
1717
        return _this.fire('hover', _this.index);
1718
      }, function() {
1719
        return _this.fire('click', _this.index);
1720
      });
1721
    };
1722
1723
    DonutSegment.prototype.drawDonutArc = function(path, color) {
1724
      return this.raphael.path(path).attr({
1725
        stroke: color,
1726
        'stroke-width': 2,
1727
        opacity: 0
1728
      });
1729
    };
1730
1731
    DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) {
1732
      return this.raphael.path(path).attr({
1733
        fill: fillColor,
1734
        stroke: strokeColor,
1735
        'stroke-width': 3
1736
      }).hover(hoverFunction).click(clickFunction);
1737
    };
1738
1739
    DonutSegment.prototype.select = function() {
1740
      if (!this.selected) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if !this.selected 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...
1741
        this.seg.animate({
1742
          path: this.selectedPath
1743
        }, 150, '<>');
1744
        this.arc.animate({
1745
          opacity: 1
1746
        }, 150, '<>');
1747
        return this.selected = true;
1748
      }
1749
    };
1750
1751
    DonutSegment.prototype.deselect = function() {
1752
      if (this.selected) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.selected 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...
1753
        this.seg.animate({
1754
          path: this.path
1755
        }, 150, '<>');
1756
        this.arc.animate({
1757
          opacity: 0
1758
        }, 150, '<>');
1759
        return this.selected = false;
1760
      }
1761
    };
1762
1763
    return DonutSegment;
1764
1765
  })(Morris.EventEmitter);
1766
1767
}).call(this);
1768