pace.js 25 KB

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