resources/lib/pace/pace.js   F
last analyzed

Complexity

Total Complexity 235
Complexity/F 2.64

Size

Lines of Code 935
Function Count 89

Duplication

Duplicated Lines 45
Ratio 4.81 %

Importance

Changes 0
Metric Value
cc 0
nc 0
dl 45
loc 935
rs 2.1818
c 0
b 0
f 0
wmc 235
mnd 4
bc 224
fnc 89
bpm 2.5168
cpm 2.6404
noi 17

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 resources/lib/pace/pace.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 AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Evented, Events, NoTargetError, Pace, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, animation, avgAmplitude, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, getFromDOM, getIntercept, handlePushState, ignoreStack, init, now, options, requestAnimationFrame, result, runAnimation, scalers, shouldIgnoreURL, shouldTrack, source, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _i, _intercept, _len, _pushState, _ref, _ref1, _replaceState,
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...
6
    __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; };
7
8
  defaultOptions = {
9
    catchupTime: 100,
10
    initialRate: .03,
11
    minTime: 250,
12
    ghostTime: 100,
13
    maxProgressPerFrame: 20,
14
    easeFactor: 1.25,
15
    startOnPageLoad: true,
16
    restartOnPushState: true,
17
    restartOnRequestAfter: 500,
18
    target: 'body',
19
    elements: {
20
      checkInterval: 100,
21
      selectors: ['body']
22
    },
23
    eventLag: {
24
      minSamples: 10,
25
      sampleCount: 3,
26
      lagThreshold: 3
27
    },
28
    ajax: {
29
      trackMethods: ['GET'],
30
      trackWebSockets: true,
31
      ignoreURLs: []
32
    }
33
  };
34
35
  now = function() {
36
    var _ref;
37
    return (_ref = typeof performance !== "undefined" && performance !== null ? typeof performance.now === "function" ? performance.now() : void 0 : void 0) != null ? _ref : +(new Date);
0 ignored issues
show
Bug introduced by
The variable performance seems to be never declared. If this is a global, consider adding a /** global: performance */ comment.

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

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

Loading history...
38
  };
39
40
  requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
41
42
  cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
43
44
  if (requestAnimationFrame == null) {
45
    requestAnimationFrame = function(fn) {
46
      return setTimeout(fn, 50);
47
    };
48
    cancelAnimationFrame = function(id) {
49
      return clearTimeout(id);
50
    };
51
  }
52
53
  runAnimation = function(fn) {
54
    var last, tick;
55
    last = now();
56
    tick = function() {
57
      var diff;
58
      diff = now() - last;
59
      if (diff >= 33) {
60
        last = now();
61
        return fn(diff, function() {
62
          return requestAnimationFrame(tick);
63
        });
64
      } else {
65
        return setTimeout(tick, 33 - diff);
66
      }
67
    };
68
    return tick();
69
  };
70
71
  result = function() {
72
    var args, key, obj;
73
    obj = arguments[0], key = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
74
    if (typeof obj[key] === 'function') {
75
      return obj[key].apply(obj, args);
76
    } else {
77
      return obj[key];
78
    }
79
  };
80
81
  extend = function() {
82
    var key, out, source, sources, val, _i, _len;
83
    out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
84
    for (_i = 0, _len = sources.length; _i < _len; _i++) {
85
      source = sources[_i];
86
      if (source) {
87
        for (key in source) {
88
          if (!__hasProp.call(source, key)) continue;
89
          val = source[key];
90
          if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') {
91
            extend(out[key], val);
92
          } else {
93
            out[key] = val;
94
          }
95
        }
96
      }
97
    }
98
    return out;
99
  };
100
101
  avgAmplitude = function(arr) {
102
    var count, sum, v, _i, _len;
103
    sum = count = 0;
104
    for (_i = 0, _len = arr.length; _i < _len; _i++) {
105
      v = arr[_i];
106
      sum += Math.abs(v);
107
      count++;
108
    }
109
    return sum / count;
110
  };
111
112
  getFromDOM = function(key, json) {
113
    var data, e, el;
114
    if (key == null) {
115
      key = 'options';
116
    }
117
    if (json == null) {
118
      json = true;
119
    }
120
    el = document.querySelector("[data-pace-" + key + "]");
121
    if (!el) {
122
      return;
123
    }
124
    data = el.getAttribute("data-pace-" + key);
125
    if (!json) {
126
      return data;
127
    }
128
    try {
129
      return JSON.parse(data);
130
    } catch (_error) {
131
      e = _error;
132
      return typeof console !== "undefined" && console !== null ? console.error("Error parsing inline pace options", e) : void 0;
133
    }
134
  };
135
136
  Evented = (function() {
137
    function Evented() {}
138
139
    Evented.prototype.on = function(event, handler, ctx, once) {
140
      var _base;
141
      if (once == null) {
142
        once = false;
143
      }
144
      if (this.bindings == null) {
145
        this.bindings = {};
146
      }
147
      if ((_base = this.bindings)[event] == null) {
148
        _base[event] = [];
149
      }
150
      return this.bindings[event].push({
151
        handler: handler,
152
        ctx: ctx,
153
        once: once
154
      });
155
    };
156
157
    Evented.prototype.once = function(event, handler, ctx) {
158
      return this.on(event, handler, ctx, true);
159
    };
160
161
    Evented.prototype.off = function(event, handler) {
162
      var i, _ref, _results;
163
      if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) {
164
        return;
165
      }
166
      if (handler == null) {
167
        return delete this.bindings[event];
168
      } else {
169
        i = 0;
170
        _results = [];
171
        while (i < this.bindings[event].length) {
172
          if (this.bindings[event][i].handler === handler) {
173
            _results.push(this.bindings[event].splice(i, 1));
174
          } else {
175
            _results.push(i++);
176
          }
177
        }
178
        return _results;
179
      }
180
    };
181
182
    Evented.prototype.trigger = function() {
183
      var args, ctx, event, handler, i, once, _ref, _ref1, _results;
184
      event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
185
      if ((_ref = this.bindings) != null ? _ref[event] : void 0) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if _ref = this.bindings != null ? _ref.event: void(0) 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...
186
        i = 0;
187
        _results = [];
188
        while (i < this.bindings[event].length) {
189
          _ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once;
190
          handler.apply(ctx != null ? ctx : this, args);
191
          if (once) {
192
            _results.push(this.bindings[event].splice(i, 1));
193
          } else {
194
            _results.push(i++);
195
          }
196
        }
197
        return _results;
198
      }
199
    };
200
201
    return Evented;
202
203
  })();
204
205
  Pace = window.Pace || {};
206
207
  window.Pace = Pace;
208
209
  extend(Pace, Evented.prototype);
210
211
  options = Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM());
212
213
  _ref = ['ajax', 'document', 'eventLag', 'elements'];
214
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
215
    source = _ref[_i];
216
    if (options[source] === true) {
217
      options[source] = defaultOptions[source];
218
    }
219
  }
220
221
  NoTargetError = (function(_super) {
222
    __extends(NoTargetError, _super);
223
224
    function NoTargetError() {
225
      _ref1 = NoTargetError.__super__.constructor.apply(this, arguments);
226
      return _ref1;
227
    }
228
229
    return NoTargetError;
230
231
  })(Error);
232
233
  Bar = (function() {
234
    function Bar() {
235
      this.progress = 0;
236
    }
237
238
    Bar.prototype.getElement = function() {
239
      var targetElement;
240
      if (this.el == null) {
241
        targetElement = document.querySelector(options.target);
242
        if (!targetElement) {
243
          throw new NoTargetError;
244
        }
245
        this.el = document.createElement('div');
246
        this.el.className = "pace pace-active";
247
        document.body.className = document.body.className.replace(/pace-done/g, '');
248
        document.body.className += ' pace-running';
249
        this.el.innerHTML = '<div class="pace-progress">\n  <div class="pace-progress-inner"></div>\n</div>\n<div class="pace-activity"></div>';
250
        if (targetElement.firstChild != null) {
251
          targetElement.insertBefore(this.el, targetElement.firstChild);
252
        } else {
253
          targetElement.appendChild(this.el);
254
        }
255
      }
256
      return this.el;
257
    };
258
259
    Bar.prototype.finish = function() {
260
      var el;
261
      el = this.getElement();
262
      el.className = el.className.replace('pace-active', '');
263
      el.className += ' pace-inactive';
264
      document.body.className = document.body.className.replace('pace-running', '');
265
      return document.body.className += ' pace-done';
266
    };
267
268
    Bar.prototype.update = function(prog) {
269
      this.progress = prog;
270
      return this.render();
271
    };
272
273
    Bar.prototype.destroy = function() {
274
      try {
275
        this.getElement().parentNode.removeChild(this.getElement());
276
      } catch (_error) {
277
        NoTargetError = _error;
278
      }
279
      return this.el = void 0;
280
    };
281
282
    Bar.prototype.render = function() {
283
      var el, key, progressStr, transform, _j, _len1, _ref2;
284
      if (document.querySelector(options.target) == null) {
285
        return false;
286
      }
287
      el = this.getElement();
288
      transform = "translate3d(" + this.progress + "%, 0, 0)";
289
      _ref2 = ['webkitTransform', 'msTransform', 'transform'];
290
      for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
291
        key = _ref2[_j];
292
        el.children[0].style[key] = transform;
293
      }
294
      if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) {
0 ignored issues
show
introduced by
You have used a bitwise operator | in a condition. Did you maybe want to use the logical operator ||
Loading history...
295
        el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%");
296
        if (this.progress >= 100) {
297
          progressStr = '99';
298
        } else {
299
          progressStr = this.progress < 10 ? "0" : "";
300
          progressStr += this.progress | 0;
301
        }
302
        el.children[0].setAttribute('data-progress', "" + progressStr);
303
      }
304
      return this.lastRenderedProgress = this.progress;
305
    };
306
307
    Bar.prototype.done = function() {
308
      return this.progress >= 100;
309
    };
310
311
    return Bar;
312
313
  })();
314
315
  Events = (function() {
316
    function Events() {
317
      this.bindings = {};
318
    }
319
320
    Events.prototype.trigger = function(name, val) {
321
      var binding, _j, _len1, _ref2, _results;
322
      if (this.bindings[name] != null) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.bindings.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...
323
        _ref2 = this.bindings[name];
324
        _results = [];
325
        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
326
          binding = _ref2[_j];
327
          _results.push(binding.call(this, val));
328
        }
329
        return _results;
330
      }
331
    };
332
333
    Events.prototype.on = function(name, fn) {
334
      var _base;
335
      if ((_base = this.bindings)[name] == null) {
336
        _base[name] = [];
337
      }
338
      return this.bindings[name].push(fn);
339
    };
340
341
    return Events;
342
343
  })();
344
345
  _XMLHttpRequest = window.XMLHttpRequest;
346
347
  _XDomainRequest = window.XDomainRequest;
348
349
  _WebSocket = window.WebSocket;
350
351
  extendNative = function(to, from) {
352
    var e, key, _results;
353
    _results = [];
354
    for (key in from.prototype) {
355
      try {
356
        if ((to[key] == null) && typeof from[key] !== 'function') {
357
          if (typeof Object.defineProperty === 'function') {
358
            _results.push(Object.defineProperty(to, key, {
359
              get: function() {
360
                return from.prototype[key];
0 ignored issues
show
introduced by
The variable key is changed by the for-each loop on line 354. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
361
              },
362
              configurable: true,
363
              enumerable: true
364
            }));
365
          } else {
366
            _results.push(to[key] = from.prototype[key]);
367
          }
368
        } else {
369
          _results.push(void 0);
370
        }
371
      } catch (_error) {
372
        e = _error;
0 ignored issues
show
Unused Code introduced by
The variable e seems to be never used. Consider removing it.
Loading history...
373
      }
374
    }
375
    return _results;
376
  };
377
378
  ignoreStack = [];
379
380
  Pace.ignore = function() {
381
    var args, fn, ret;
382
    fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
383
    ignoreStack.unshift('ignore');
384
    ret = fn.apply(null, args);
385
    ignoreStack.shift();
386
    return ret;
387
  };
388
389
  Pace.track = function() {
390
    var args, fn, ret;
391
    fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
392
    ignoreStack.unshift('track');
393
    ret = fn.apply(null, args);
394
    ignoreStack.shift();
395
    return ret;
396
  };
397
398
  shouldTrack = function(method) {
399
    var _ref2;
400
    if (method == null) {
401
      method = 'GET';
402
    }
403
    if (ignoreStack[0] === 'track') {
404
      return 'force';
405
    }
406
    if (!ignoreStack.length && options.ajax) {
407
      if (method === 'socket' && options.ajax.trackWebSockets) {
408
        return true;
409
      } else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) {
410
        return true;
411
      }
412
    }
413
    return false;
414
  };
415
416
  RequestIntercept = (function(_super) {
417
    __extends(RequestIntercept, _super);
418
419
    function RequestIntercept() {
420
      var monitorXHR,
421
        _this = this;
422
      RequestIntercept.__super__.constructor.apply(this, arguments);
423
      monitorXHR = function(req) {
424
        var _open;
425
        _open = req.open;
426
        return req.open = function(type, url, async) {
0 ignored issues
show
Unused Code introduced by
The parameter async 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...
427
          if (shouldTrack(type)) {
428
            _this.trigger('request', {
429
              type: type,
430
              url: url,
431
              request: req
432
            });
433
          }
434
          return _open.apply(req, arguments);
435
        };
436
      };
437
      window.XMLHttpRequest = function(flags) {
438
        var req;
439
        req = new _XMLHttpRequest(flags);
440
        monitorXHR(req);
441
        return req;
442
      };
443
      try {
444
        extendNative(window.XMLHttpRequest, _XMLHttpRequest);
445
      } catch (_error) {}
446
      if (_XDomainRequest != null) {
447
        window.XDomainRequest = function() {
448
          var req;
449
          req = new _XDomainRequest;
450
          monitorXHR(req);
451
          return req;
452
        };
453
        try {
454
          extendNative(window.XDomainRequest, _XDomainRequest);
455
        } catch (_error) {}
456
      }
457
      if ((_WebSocket != null) && options.ajax.trackWebSockets) {
458
        window.WebSocket = function(url, protocols) {
459
          var req;
460
          if (protocols != null) {
461
            req = new _WebSocket(url, protocols);
462
          } else {
463
            req = new _WebSocket(url);
464
          }
465
          if (shouldTrack('socket')) {
466
            _this.trigger('request', {
467
              type: 'socket',
468
              url: url,
469
              protocols: protocols,
470
              request: req
471
            });
472
          }
473
          return req;
474
        };
475
        try {
476
          extendNative(window.WebSocket, _WebSocket);
477
        } catch (_error) {}
478
      }
479
    }
480
481
    return RequestIntercept;
482
483
  })(Events);
484
485
  _intercept = null;
486
487
  getIntercept = function() {
488
    if (_intercept == null) {
489
      _intercept = new RequestIntercept;
490
    }
491
    return _intercept;
492
  };
493
494
  shouldIgnoreURL = function(url) {
495
    var pattern, _j, _len1, _ref2;
496
    _ref2 = options.ajax.ignoreURLs;
497
    for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
498
      pattern = _ref2[_j];
499
      if (typeof pattern === 'string') {
500
        if (url.indexOf(pattern) !== -1) {
501
          return true;
502
        }
503
      } else {
504
        if (pattern.test(url)) {
505
          return true;
506
        }
507
      }
508
    }
509
    return false;
510
  };
511
512
  getIntercept().on('request', function(_arg) {
513
    var after, args, request, type, url;
514
    type = _arg.type, request = _arg.request, url = _arg.url;
515
    if (shouldIgnoreURL(url)) {
516
      return;
517
    }
518
    if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if !Pace.running && options...Track(type) === "force" 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...
519
      args = arguments;
520
      after = options.restartOnRequestAfter || 0;
521
      if (typeof after === 'boolean') {
522
        after = 0;
523
      }
524
      return setTimeout(function() {
525
        var stillActive, _j, _len1, _ref2, _ref3, _results;
526
        if (type === 'socket') {
527
          stillActive = request.readyState < 2;
528
        } else {
529
          stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4);
530
        }
531
        if (stillActive) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if stillActive 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...
532
          Pace.restart();
533
          _ref3 = Pace.sources;
534
          _results = [];
535
          for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
536
            source = _ref3[_j];
537
            if (source instanceof AjaxMonitor) {
0 ignored issues
show
Bug introduced by
The variable source is changed as part of the for loop for example by _ref3._j on line 536. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
538
              source.watch.apply(source, args);
539
              break;
540
            } else {
541
              _results.push(void 0);
542
            }
543
          }
544
          return _results;
545
        }
546
      }, after);
547
    }
548
  });
549
550
  AjaxMonitor = (function() {
551
    function AjaxMonitor() {
552
      var _this = this;
553
      this.elements = [];
554
      getIntercept().on('request', function() {
555
        return _this.watch.apply(_this, arguments);
556
      });
557
    }
558
559
    AjaxMonitor.prototype.watch = function(_arg) {
560
      var request, tracker, type, url;
561
      type = _arg.type, request = _arg.request, url = _arg.url;
562
      if (shouldIgnoreURL(url)) {
563
        return;
564
      }
565
      if (type === 'socket') {
566
        tracker = new SocketRequestTracker(request);
567
      } else {
568
        tracker = new XHRRequestTracker(request);
569
      }
570
      return this.elements.push(tracker);
571
    };
572
573
    return AjaxMonitor;
574
575
  })();
576
577
  XHRRequestTracker = (function() {
578
    function XHRRequestTracker(request) {
579
      var event, size, _j, _len1, _onreadystatechange, _ref2,
580
        _this = this;
581
      this.progress = 0;
582
      if (window.ProgressEvent != null) {
583
        size = null;
0 ignored issues
show
Unused Code introduced by
The variable size seems to be never used. Consider removing it.
Loading history...
584
        request.addEventListener('progress', function(evt) {
585
          if (evt.lengthComputable) {
586
            return _this.progress = 100 * evt.loaded / evt.total;
587
          } else {
588
            return _this.progress = _this.progress + (100 - _this.progress) / 2;
589
          }
590
        }, false);
591
        _ref2 = ['load', 'abort', 'timeout', 'error'];
592
        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
593
          event = _ref2[_j];
594
          request.addEventListener(event, function() {
595
            return _this.progress = 100;
596
          }, false);
597
        }
598
      } else {
599
        _onreadystatechange = request.onreadystatechange;
600
        request.onreadystatechange = function() {
601
          var _ref3;
602
          if ((_ref3 = request.readyState) === 0 || _ref3 === 4) {
603
            _this.progress = 100;
604
          } else if (request.readyState === 3) {
605
            _this.progress = 50;
606
          }
607
          return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
608
        };
609
      }
610
    }
611
612
    return XHRRequestTracker;
613
614
  })();
615
616
  SocketRequestTracker = (function() {
617
    function SocketRequestTracker(request) {
618
      var event, _j, _len1, _ref2,
619
        _this = this;
620
      this.progress = 0;
621
      _ref2 = ['error', 'open'];
622
      for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
623
        event = _ref2[_j];
624
        request.addEventListener(event, function() {
625
          return _this.progress = 100;
626
        }, false);
627
      }
628
    }
629
630
    return SocketRequestTracker;
631
632
  })();
633
634
  ElementMonitor = (function() {
635
    function ElementMonitor(options) {
636
      var selector, _j, _len1, _ref2;
637
      if (options == null) {
638
        options = {};
639
      }
640
      this.elements = [];
641
      if (options.selectors == null) {
642
        options.selectors = [];
643
      }
644
      _ref2 = options.selectors;
645
      for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
646
        selector = _ref2[_j];
647
        this.elements.push(new ElementTracker(selector));
648
      }
649
    }
650
651
    return ElementMonitor;
652
653
  })();
654
655
  ElementTracker = (function() {
656
    function ElementTracker(selector) {
657
      this.selector = selector;
658
      this.progress = 0;
659
      this.check();
660
    }
661
662
    ElementTracker.prototype.check = function() {
663
      var _this = this;
664
      if (document.querySelector(this.selector)) {
665
        return this.done();
666
      } else {
667
        return setTimeout((function() {
668
          return _this.check();
669
        }), options.elements.checkInterval);
670
      }
671
    };
672
673
    ElementTracker.prototype.done = function() {
674
      return this.progress = 100;
675
    };
676
677
    return ElementTracker;
678
679
  })();
680
681
  DocumentMonitor = (function() {
682
    DocumentMonitor.prototype.states = {
683
      loading: 0,
684
      interactive: 50,
685
      complete: 100
686
    };
687
688
    function DocumentMonitor() {
689
      var _onreadystatechange, _ref2,
690
        _this = this;
691
      this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
692
      _onreadystatechange = document.onreadystatechange;
693
      document.onreadystatechange = function() {
694
        if (_this.states[document.readyState] != null) {
695
          _this.progress = _this.states[document.readyState];
696
        }
697
        return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
698
      };
699
    }
700
701
    return DocumentMonitor;
702
703
  })();
704
705
  EventLagMonitor = (function() {
706
    function EventLagMonitor() {
707
      var avg, interval, last, points, samples,
708
        _this = this;
709
      this.progress = 0;
710
      avg = 0;
711
      samples = [];
712
      points = 0;
713
      last = now();
714
      interval = setInterval(function() {
715
        var diff;
716
        diff = now() - last - 50;
717
        last = now();
718
        samples.push(diff);
719
        if (samples.length > options.eventLag.sampleCount) {
720
          samples.shift();
721
        }
722
        avg = avgAmplitude(samples);
723
        if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
724
          _this.progress = 100;
725
          return clearInterval(interval);
726
        } else {
727
          return _this.progress = 100 * (3 / (avg + 3));
728
        }
729
      }, 50);
730
    }
731
732
    return EventLagMonitor;
733
734
  })();
735
736 View Code Duplication
  Scaler = (function() {
737
    function Scaler(source) {
738
      this.source = source;
739
      this.last = this.sinceLastUpdate = 0;
740
      this.rate = options.initialRate;
741
      this.catchup = 0;
742
      this.progress = this.lastProgress = 0;
743
      if (this.source != null) {
744
        this.progress = result(this.source, 'progress');
745
      }
746
    }
747
748
    Scaler.prototype.tick = function(frameTime, val) {
749
      var scaling;
750
      if (val == null) {
751
        val = result(this.source, 'progress');
752
      }
753
      if (val >= 100) {
754
        this.done = true;
755
      }
756
      if (val === this.last) {
757
        this.sinceLastUpdate += frameTime;
758
      } else {
759
        if (this.sinceLastUpdate) {
760
          this.rate = (val - this.last) / this.sinceLastUpdate;
761
        }
762
        this.catchup = (val - this.progress) / options.catchupTime;
763
        this.sinceLastUpdate = 0;
764
        this.last = val;
765
      }
766
      if (val > this.progress) {
767
        this.progress += this.catchup * frameTime;
768
      }
769
      scaling = 1 - Math.pow(this.progress / 100, options.easeFactor);
770
      this.progress += scaling * this.rate * frameTime;
771
      this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress);
772
      this.progress = Math.max(0, this.progress);
773
      this.progress = Math.min(100, this.progress);
774
      this.lastProgress = this.progress;
775
      return this.progress;
776
    };
777
778
    return Scaler;
779
780
  })();
781
782
  sources = null;
783
784
  scalers = null;
785
786
  bar = null;
787
788
  uniScaler = null;
789
790
  animation = null;
791
792
  cancelAnimation = null;
793
794
  Pace.running = false;
795
796
  handlePushState = function() {
797
    if (options.restartOnPushState) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if options.restartOnPushState 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...
798
      return Pace.restart();
799
    }
800
  };
801
802
  if (window.history.pushState != null) {
803
    _pushState = window.history.pushState;
804
    window.history.pushState = function() {
805
      handlePushState();
806
      return _pushState.apply(window.history, arguments);
807
    };
808
  }
809
810
  if (window.history.replaceState != null) {
811
    _replaceState = window.history.replaceState;
812
    window.history.replaceState = function() {
813
      handlePushState();
814
      return _replaceState.apply(window.history, arguments);
815
    };
816
  }
817
818
  SOURCE_KEYS = {
819
    ajax: AjaxMonitor,
820
    elements: ElementMonitor,
821
    document: DocumentMonitor,
822
    eventLag: EventLagMonitor
823
  };
824
825
  (init = function() {
826
    var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4;
827
    Pace.sources = sources = [];
828
    _ref2 = ['ajax', 'elements', 'document', 'eventLag'];
829
    for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
830
      type = _ref2[_j];
831
      if (options[type] !== false) {
832
        sources.push(new SOURCE_KEYS[type](options[type]));
833
      }
834
    }
835
    _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : [];
836
    for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
837
      source = _ref4[_k];
838
      sources.push(new source(options));
0 ignored issues
show
Bug introduced by
The variable source is changed as part of the for loop for example by _ref4._k on line 837. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Coding Style Best Practice introduced by
By convention, constructors like source should be capitalized.
Loading history...
839
    }
840
    Pace.bar = bar = new Bar;
841
    scalers = [];
842
    return uniScaler = new Scaler;
843
  })();
844
845
  Pace.stop = function() {
846
    Pace.trigger('stop');
847
    Pace.running = false;
848
    bar.destroy();
849
    cancelAnimation = true;
850
    if (animation != null) {
851
      if (typeof cancelAnimationFrame === "function") {
852
        cancelAnimationFrame(animation);
853
      }
854
      animation = null;
855
    }
856
    return init();
857
  };
858
859
  Pace.restart = function() {
860
    Pace.trigger('restart');
861
    Pace.stop();
862
    return Pace.start();
863
  };
864
865
  Pace.go = function() {
866
    var start;
867
    Pace.running = true;
868
    bar.render();
869
    start = now();
870
    cancelAnimation = false;
871
    return animation = runAnimation(function(frameTime, enqueueNextFrame) {
872
      var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2;
873
      remaining = 100 - bar.progress;
0 ignored issues
show
Unused Code introduced by
The variable remaining seems to be never used. Consider removing it.
Loading history...
874
      count = sum = 0;
875
      done = true;
876
      for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) {
877
        source = sources[i];
878
        scalerList = scalers[i] != null ? scalers[i] : scalers[i] = [];
879
        elements = (_ref2 = source.elements) != null ? _ref2 : [source];
0 ignored issues
show
Bug introduced by
The variable source is changed as part of the for loop for example by sources.i on line 877. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
880
        for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) {
881
          element = elements[j];
882
          scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element);
883
          done &= scaler.done;
884
          if (scaler.done) {
885
            continue;
886
          }
887
          count++;
888
          sum += scaler.tick(frameTime);
889
        }
890
      }
891
      avg = sum / count;
892
      bar.update(uniScaler.tick(frameTime, avg));
893
      if (bar.done() || done || cancelAnimation) {
894
        bar.update(100);
895
        Pace.trigger('done');
896
        return setTimeout(function() {
897
          bar.finish();
898
          Pace.running = false;
899
          return Pace.trigger('hide');
900
        }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0)));
901
      } else {
902
        return enqueueNextFrame();
903
      }
904
    });
905
  };
906
907
  Pace.start = function(_options) {
908
    extend(options, _options);
909
    Pace.running = true;
910
    try {
911
      bar.render();
912
    } catch (_error) {
913
      NoTargetError = _error;
914
    }
915
    if (!document.querySelector('.pace')) {
916
      return setTimeout(Pace.start, 50);
917
    } else {
918
      Pace.trigger('start');
919
      return Pace.go();
920
    }
921
  };
922
923
  if (typeof define === 'function' && define.amd) {
924
    define(['pace'], function() {
925
      return Pace;
926
    });
927
  } else if (typeof exports === 'object') {
928
    module.exports = Pace;
929
  } else {
930
    if (options.startOnPageLoad) {
931
      Pace.start();
932
    }
933
  }
934
935
}).call(this);
936