pace.js 26 KB

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