pace.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  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; },
  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 key, out, source, sources, val, _i, _len;
  75. out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  76. for (_i = 0, _len = sources.length; _i < _len; _i++) {
  77. source = sources[_i];
  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, sum, v, _i, _len;
  94. sum = count = 0;
  95. for (_i = 0, _len = arr.length; _i < _len; _i++) {
  96. v = arr[_i];
  97. sum += Math.abs(v);
  98. count++;
  99. }
  100. return sum / count;
  101. };
  102. getFromDOM = function(key, json) {
  103. var data, e, el;
  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 (_i = 0, _len = _ref.length; _i < _len; _i++) {
  193. source = _ref[_i];
  194. if (options[source] === true) {
  195. options[source] = defaultOptions[source];
  196. }
  197. }
  198. NoTargetError = (function(_super) {
  199. __extends(NoTargetError, _super);
  200. function NoTargetError() {
  201. _ref1 = NoTargetError.__super__.constructor.apply(this, arguments);
  202. return _ref1;
  203. }
  204. return NoTargetError;
  205. })(Error);
  206. Bar = (function() {
  207. function Bar() {
  208. this.progress = 0;
  209. }
  210. Bar.prototype.getElement = function() {
  211. var targetElement;
  212. if (this.el == null) {
  213. targetElement = document.querySelector(options.target);
  214. if (!targetElement) {
  215. throw new NoTargetError;
  216. }
  217. this.el = document.createElement('div');
  218. this.el.className = "pace pace-active";
  219. document.body.className = document.body.className.replace(/pace-done/g, '');
  220. document.body.className += ' 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.className = el.className.replace('pace-active', '');
  234. el.className += ' pace-inactive';
  235. document.body.className = document.body.className.replace('pace-running', '');
  236. return document.body.className += ' pace-done';
  237. };
  238. Bar.prototype.update = function(prog) {
  239. this.progress = prog;
  240. return this.render();
  241. };
  242. Bar.prototype.destroy = function() {
  243. try {
  244. this.getElement().parentNode.removeChild(this.getElement());
  245. } catch (_error) {
  246. NoTargetError = _error;
  247. }
  248. return this.el = void 0;
  249. };
  250. Bar.prototype.render = function() {
  251. var el, key, progressStr, transform, _j, _len1, _ref2;
  252. if (document.querySelector(options.target) == null) {
  253. return false;
  254. }
  255. el = this.getElement();
  256. transform = "translate3d(" + this.progress + "%, 0, 0)";
  257. _ref2 = ['webkitTransform', 'msTransform', 'transform'];
  258. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  259. key = _ref2[_j];
  260. el.children[0].style[key] = transform;
  261. }
  262. if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) {
  263. el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%");
  264. if (this.progress >= 100) {
  265. progressStr = '99';
  266. } else {
  267. progressStr = this.progress < 10 ? "0" : "";
  268. progressStr += this.progress | 0;
  269. }
  270. el.children[0].setAttribute('data-progress', "" + progressStr);
  271. }
  272. return this.lastRenderedProgress = this.progress;
  273. };
  274. Bar.prototype.done = function() {
  275. return this.progress >= 100;
  276. };
  277. return Bar;
  278. })();
  279. Events = (function() {
  280. function Events() {
  281. this.bindings = {};
  282. }
  283. Events.prototype.trigger = function(name, val) {
  284. var binding, _j, _len1, _ref2, _results;
  285. if (this.bindings[name] != null) {
  286. _ref2 = this.bindings[name];
  287. _results = [];
  288. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  289. binding = _ref2[_j];
  290. _results.push(binding.call(this, val));
  291. }
  292. return _results;
  293. }
  294. };
  295. Events.prototype.on = function(name, fn) {
  296. var _base;
  297. if ((_base = this.bindings)[name] == null) {
  298. _base[name] = [];
  299. }
  300. return this.bindings[name].push(fn);
  301. };
  302. return Events;
  303. })();
  304. _XMLHttpRequest = window.XMLHttpRequest;
  305. _XDomainRequest = window.XDomainRequest;
  306. _WebSocket = window.WebSocket;
  307. extendNative = function(to, from) {
  308. var e, key, _results;
  309. _results = [];
  310. for (key in from.prototype) {
  311. try {
  312. if ((to[key] == null) && typeof from[key] !== 'function') {
  313. if (typeof Object.defineProperty === 'function') {
  314. _results.push(Object.defineProperty(to, key, {
  315. get: function() {
  316. return from.prototype[key];
  317. },
  318. configurable: true,
  319. enumerable: true
  320. }));
  321. } else {
  322. _results.push(to[key] = from.prototype[key]);
  323. }
  324. } else {
  325. _results.push(void 0);
  326. }
  327. } catch (_error) {
  328. e = _error;
  329. }
  330. }
  331. return _results;
  332. };
  333. ignoreStack = [];
  334. Pace.ignore = function() {
  335. var args, fn, ret;
  336. fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  337. ignoreStack.unshift('ignore');
  338. ret = fn.apply(null, args);
  339. ignoreStack.shift();
  340. return ret;
  341. };
  342. Pace.track = function() {
  343. var args, fn, ret;
  344. fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  345. ignoreStack.unshift('track');
  346. ret = fn.apply(null, args);
  347. ignoreStack.shift();
  348. return ret;
  349. };
  350. shouldTrack = function(method) {
  351. var _ref2;
  352. if (method == null) {
  353. method = 'GET';
  354. }
  355. if (ignoreStack[0] === 'track') {
  356. return 'force';
  357. }
  358. if (!ignoreStack.length && options.ajax) {
  359. if (method === 'socket' && options.ajax.trackWebSockets) {
  360. return true;
  361. } else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) {
  362. return true;
  363. }
  364. }
  365. return false;
  366. };
  367. RequestIntercept = (function(_super) {
  368. __extends(RequestIntercept, _super);
  369. function RequestIntercept() {
  370. var monitorXHR,
  371. _this = this;
  372. RequestIntercept.__super__.constructor.apply(this, arguments);
  373. monitorXHR = function(req) {
  374. var _open;
  375. _open = req.open;
  376. return req.open = function(type, url, async) {
  377. if (shouldTrack(type)) {
  378. _this.trigger('request', {
  379. type: type,
  380. url: url,
  381. request: req
  382. });
  383. }
  384. return _open.apply(req, arguments);
  385. };
  386. };
  387. window.XMLHttpRequest = function(flags) {
  388. var req;
  389. req = new _XMLHttpRequest(flags);
  390. monitorXHR(req);
  391. return req;
  392. };
  393. try {
  394. extendNative(window.XMLHttpRequest, _XMLHttpRequest);
  395. } catch (_error) {}
  396. if (_XDomainRequest != null) {
  397. window.XDomainRequest = function() {
  398. var req;
  399. req = new _XDomainRequest;
  400. monitorXHR(req);
  401. return req;
  402. };
  403. try {
  404. extendNative(window.XDomainRequest, _XDomainRequest);
  405. } catch (_error) {}
  406. }
  407. if ((_WebSocket != null) && options.ajax.trackWebSockets) {
  408. window.WebSocket = function(url, protocols) {
  409. var req;
  410. if (protocols != null) {
  411. req = new _WebSocket(url, protocols);
  412. } else {
  413. req = new _WebSocket(url);
  414. }
  415. if (shouldTrack('socket')) {
  416. _this.trigger('request', {
  417. type: 'socket',
  418. url: url,
  419. protocols: protocols,
  420. request: req
  421. });
  422. }
  423. return req;
  424. };
  425. try {
  426. extendNative(window.WebSocket, _WebSocket);
  427. } catch (_error) {}
  428. }
  429. }
  430. return RequestIntercept;
  431. })(Events);
  432. _intercept = null;
  433. getIntercept = function() {
  434. if (_intercept == null) {
  435. _intercept = new RequestIntercept;
  436. }
  437. return _intercept;
  438. };
  439. shouldIgnoreURL = function(url) {
  440. var pattern, _j, _len1, _ref2;
  441. _ref2 = options.ajax.ignoreURLs;
  442. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  443. pattern = _ref2[_j];
  444. if (typeof pattern === 'string') {
  445. if (url.indexOf(pattern) !== -1) {
  446. return true;
  447. }
  448. } else {
  449. if (pattern.test(url)) {
  450. return true;
  451. }
  452. }
  453. }
  454. return false;
  455. };
  456. getIntercept().on('request', function(_arg) {
  457. var after, args, request, type, url;
  458. type = _arg.type, request = _arg.request, url = _arg.url;
  459. if (shouldIgnoreURL(url)) {
  460. return;
  461. }
  462. if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) {
  463. args = arguments;
  464. after = options.restartOnRequestAfter || 0;
  465. if (typeof after === 'boolean') {
  466. after = 0;
  467. }
  468. return setTimeout(function() {
  469. var stillActive, _j, _len1, _ref2, _ref3, _results;
  470. if (type === 'socket') {
  471. stillActive = request.readyState < 2;
  472. } else {
  473. stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4);
  474. }
  475. if (stillActive) {
  476. Pace.restart();
  477. _ref3 = Pace.sources;
  478. _results = [];
  479. for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
  480. source = _ref3[_j];
  481. if (source instanceof AjaxMonitor) {
  482. source.watch.apply(source, args);
  483. break;
  484. } else {
  485. _results.push(void 0);
  486. }
  487. }
  488. return _results;
  489. }
  490. }, after);
  491. }
  492. });
  493. AjaxMonitor = (function() {
  494. function AjaxMonitor() {
  495. var _this = this;
  496. this.elements = [];
  497. getIntercept().on('request', function() {
  498. return _this.watch.apply(_this, arguments);
  499. });
  500. }
  501. AjaxMonitor.prototype.watch = function(_arg) {
  502. var request, tracker, type, url;
  503. type = _arg.type, request = _arg.request, url = _arg.url;
  504. if (shouldIgnoreURL(url)) {
  505. return;
  506. }
  507. if (type === 'socket') {
  508. tracker = new SocketRequestTracker(request);
  509. } else {
  510. tracker = new XHRRequestTracker(request);
  511. }
  512. return this.elements.push(tracker);
  513. };
  514. return AjaxMonitor;
  515. })();
  516. XHRRequestTracker = (function() {
  517. function XHRRequestTracker(request) {
  518. var event, size, _j, _len1, _onreadystatechange, _ref2,
  519. _this = this;
  520. this.progress = 0;
  521. if (window.ProgressEvent != null) {
  522. size = null;
  523. request.addEventListener('progress', function(evt) {
  524. if (evt.lengthComputable) {
  525. return _this.progress = 100 * evt.loaded / evt.total;
  526. } else {
  527. return _this.progress = _this.progress + (100 - _this.progress) / 2;
  528. }
  529. }, false);
  530. _ref2 = ['load', 'abort', 'timeout', 'error'];
  531. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  532. event = _ref2[_j];
  533. request.addEventListener(event, function() {
  534. return _this.progress = 100;
  535. }, false);
  536. }
  537. } else {
  538. _onreadystatechange = request.onreadystatechange;
  539. request.onreadystatechange = function() {
  540. var _ref3;
  541. if ((_ref3 = request.readyState) === 0 || _ref3 === 4) {
  542. _this.progress = 100;
  543. } else if (request.readyState === 3) {
  544. _this.progress = 50;
  545. }
  546. return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
  547. };
  548. }
  549. }
  550. return XHRRequestTracker;
  551. })();
  552. SocketRequestTracker = (function() {
  553. function SocketRequestTracker(request) {
  554. var event, _j, _len1, _ref2,
  555. _this = this;
  556. this.progress = 0;
  557. _ref2 = ['error', 'open'];
  558. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  559. event = _ref2[_j];
  560. request.addEventListener(event, function() {
  561. return _this.progress = 100;
  562. }, false);
  563. }
  564. }
  565. return SocketRequestTracker;
  566. })();
  567. ElementMonitor = (function() {
  568. function ElementMonitor(options) {
  569. var selector, _j, _len1, _ref2;
  570. if (options == null) {
  571. options = {};
  572. }
  573. this.elements = [];
  574. if (options.selectors == null) {
  575. options.selectors = [];
  576. }
  577. _ref2 = options.selectors;
  578. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  579. selector = _ref2[_j];
  580. this.elements.push(new ElementTracker(selector));
  581. }
  582. }
  583. return ElementMonitor;
  584. })();
  585. ElementTracker = (function() {
  586. function ElementTracker(selector) {
  587. this.selector = selector;
  588. this.progress = 0;
  589. this.check();
  590. }
  591. ElementTracker.prototype.check = function() {
  592. var _this = this;
  593. if (document.querySelector(this.selector)) {
  594. return this.done();
  595. } else {
  596. return setTimeout((function() {
  597. return _this.check();
  598. }), options.elements.checkInterval);
  599. }
  600. };
  601. ElementTracker.prototype.done = function() {
  602. return this.progress = 100;
  603. };
  604. return ElementTracker;
  605. })();
  606. DocumentMonitor = (function() {
  607. DocumentMonitor.prototype.states = {
  608. loading: 0,
  609. interactive: 50,
  610. complete: 100
  611. };
  612. function DocumentMonitor() {
  613. var _onreadystatechange, _ref2,
  614. _this = this;
  615. this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
  616. _onreadystatechange = document.onreadystatechange;
  617. document.onreadystatechange = function() {
  618. if (_this.states[document.readyState] != null) {
  619. _this.progress = _this.states[document.readyState];
  620. }
  621. return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
  622. };
  623. }
  624. return DocumentMonitor;
  625. })();
  626. EventLagMonitor = (function() {
  627. function EventLagMonitor() {
  628. var avg, interval, last, points, samples,
  629. _this = this;
  630. this.progress = 0;
  631. avg = 0;
  632. samples = [];
  633. points = 0;
  634. last = now();
  635. interval = setInterval(function() {
  636. var diff;
  637. diff = now() - last - 50;
  638. last = now();
  639. samples.push(diff);
  640. if (samples.length > options.eventLag.sampleCount) {
  641. samples.shift();
  642. }
  643. avg = avgAmplitude(samples);
  644. if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
  645. _this.progress = 100;
  646. return clearInterval(interval);
  647. } else {
  648. return _this.progress = 100 * (3 / (avg + 3));
  649. }
  650. }, 50);
  651. }
  652. return EventLagMonitor;
  653. })();
  654. Scaler = (function() {
  655. function Scaler(source) {
  656. this.source = source;
  657. this.last = this.sinceLastUpdate = 0;
  658. this.rate = options.initialRate;
  659. this.catchup = 0;
  660. this.progress = this.lastProgress = 0;
  661. if (this.source != null) {
  662. this.progress = result(this.source, 'progress');
  663. }
  664. }
  665. Scaler.prototype.tick = function(frameTime, val) {
  666. var scaling;
  667. if (val == null) {
  668. val = result(this.source, 'progress');
  669. }
  670. if (val >= 100) {
  671. this.done = true;
  672. }
  673. if (val === this.last) {
  674. this.sinceLastUpdate += frameTime;
  675. } else {
  676. if (this.sinceLastUpdate) {
  677. this.rate = (val - this.last) / this.sinceLastUpdate;
  678. }
  679. this.catchup = (val - this.progress) / options.catchupTime;
  680. this.sinceLastUpdate = 0;
  681. this.last = val;
  682. }
  683. if (val > this.progress) {
  684. this.progress += this.catchup * frameTime;
  685. }
  686. scaling = 1 - Math.pow(this.progress / 100, options.easeFactor);
  687. this.progress += scaling * this.rate * frameTime;
  688. this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress);
  689. this.progress = Math.max(0, this.progress);
  690. this.progress = Math.min(100, this.progress);
  691. this.lastProgress = this.progress;
  692. return this.progress;
  693. };
  694. return Scaler;
  695. })();
  696. sources = null;
  697. scalers = null;
  698. bar = null;
  699. uniScaler = null;
  700. animation = null;
  701. cancelAnimation = null;
  702. Pace.running = false;
  703. handlePushState = function() {
  704. if (options.restartOnPushState) {
  705. return Pace.restart();
  706. }
  707. };
  708. if (window.history.pushState != null) {
  709. _pushState = window.history.pushState;
  710. window.history.pushState = function() {
  711. handlePushState();
  712. return _pushState.apply(window.history, arguments);
  713. };
  714. }
  715. if (window.history.replaceState != null) {
  716. _replaceState = window.history.replaceState;
  717. window.history.replaceState = function() {
  718. handlePushState();
  719. return _replaceState.apply(window.history, arguments);
  720. };
  721. }
  722. SOURCE_KEYS = {
  723. ajax: AjaxMonitor,
  724. elements: ElementMonitor,
  725. document: DocumentMonitor,
  726. eventLag: EventLagMonitor
  727. };
  728. (init = function() {
  729. var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4;
  730. Pace.sources = sources = [];
  731. _ref2 = ['ajax', 'elements', 'document', 'eventLag'];
  732. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  733. type = _ref2[_j];
  734. if (options[type] !== false) {
  735. sources.push(new SOURCE_KEYS[type](options[type]));
  736. }
  737. }
  738. _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : [];
  739. for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
  740. source = _ref4[_k];
  741. sources.push(new source(options));
  742. }
  743. Pace.bar = bar = new Bar;
  744. scalers = [];
  745. return uniScaler = new Scaler;
  746. })();
  747. Pace.stop = function() {
  748. Pace.trigger('stop');
  749. Pace.running = false;
  750. bar.destroy();
  751. cancelAnimation = true;
  752. if (animation != null) {
  753. if (typeof cancelAnimationFrame === "function") {
  754. cancelAnimationFrame(animation);
  755. }
  756. animation = null;
  757. }
  758. return init();
  759. };
  760. Pace.restart = function() {
  761. Pace.trigger('restart');
  762. Pace.stop();
  763. return Pace.start();
  764. };
  765. Pace.go = function() {
  766. var start;
  767. Pace.running = true;
  768. bar.render();
  769. start = now();
  770. cancelAnimation = false;
  771. return animation = runAnimation(function(frameTime, enqueueNextFrame) {
  772. var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2;
  773. remaining = 100 - bar.progress;
  774. count = sum = 0;
  775. done = true;
  776. for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) {
  777. source = sources[i];
  778. scalerList = scalers[i] != null ? scalers[i] : scalers[i] = [];
  779. elements = (_ref2 = source.elements) != null ? _ref2 : [source];
  780. for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) {
  781. element = elements[j];
  782. scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element);
  783. done &= scaler.done;
  784. if (scaler.done) {
  785. continue;
  786. }
  787. count++;
  788. sum += scaler.tick(frameTime);
  789. }
  790. }
  791. avg = sum / count;
  792. bar.update(uniScaler.tick(frameTime, avg));
  793. if (bar.done() || done || cancelAnimation) {
  794. bar.update(100);
  795. Pace.trigger('done');
  796. return setTimeout(function() {
  797. bar.finish();
  798. Pace.running = false;
  799. return Pace.trigger('hide');
  800. }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0)));
  801. } else {
  802. return enqueueNextFrame();
  803. }
  804. });
  805. };
  806. Pace.start = function(_options) {
  807. extend(options, _options);
  808. Pace.running = true;
  809. try {
  810. bar.render();
  811. } catch (_error) {
  812. NoTargetError = _error;
  813. }
  814. if (!document.querySelector('.pace')) {
  815. return setTimeout(Pace.start, 50);
  816. } else {
  817. Pace.trigger('start');
  818. return Pace.go();
  819. }
  820. };
  821. if (typeof define === 'function' && define.amd) {
  822. define(['pace'], function() {
  823. return Pace;
  824. });
  825. } else if (typeof exports === 'object') {
  826. module.exports = Pace;
  827. } else {
  828. if (options.startOnPageLoad) {
  829. Pace.start();
  830. }
  831. }
  832. }).call(this);