pace.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  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. extendNative(window.XMLHttpRequest, _XMLHttpRequest);
  381. if (_XDomainRequest != null) {
  382. window.XDomainRequest = function() {
  383. var req;
  384. req = new _XDomainRequest;
  385. monitorXHR(req);
  386. return req;
  387. };
  388. extendNative(window.XDomainRequest, _XDomainRequest);
  389. }
  390. if ((_WebSocket != null) && options.ajax.trackWebSockets) {
  391. window.WebSocket = function(url, protocols) {
  392. var req;
  393. if (protocols != null) {
  394. req = new _WebSocket(url, protocols);
  395. } else {
  396. req = new _WebSocket(url);
  397. }
  398. if (shouldTrack('socket')) {
  399. _this.trigger('request', {
  400. type: 'socket',
  401. url: url,
  402. protocols: protocols,
  403. request: req
  404. });
  405. }
  406. return req;
  407. };
  408. extendNative(window.WebSocket, _WebSocket);
  409. }
  410. }
  411. return RequestIntercept;
  412. })(Events);
  413. _intercept = null;
  414. getIntercept = function() {
  415. if (_intercept == null) {
  416. _intercept = new RequestIntercept;
  417. }
  418. return _intercept;
  419. };
  420. shouldIgnoreURL = function(url) {
  421. var pattern, _j, _len1, _ref2;
  422. _ref2 = options.ajax.ignoreURLs;
  423. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  424. pattern = _ref2[_j];
  425. if (typeof pattern === 'string') {
  426. if (url.indexOf(pattern) !== -1) {
  427. return true;
  428. }
  429. } else {
  430. if (pattern.test(url)) {
  431. return true;
  432. }
  433. }
  434. }
  435. return false;
  436. };
  437. getIntercept().on('request', function(_arg) {
  438. var after, args, request, type, url;
  439. type = _arg.type, request = _arg.request, url = _arg.url;
  440. if (shouldIgnoreURL(url)) {
  441. return;
  442. }
  443. if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) {
  444. args = arguments;
  445. after = options.restartOnRequestAfter || 0;
  446. if (typeof after === 'boolean') {
  447. after = 0;
  448. }
  449. return setTimeout(function() {
  450. var stillActive, _j, _len1, _ref2, _ref3, _results;
  451. if (type === 'socket') {
  452. stillActive = request.readyState < 2;
  453. } else {
  454. stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4);
  455. }
  456. if (stillActive) {
  457. Pace.restart();
  458. _ref3 = Pace.sources;
  459. _results = [];
  460. for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
  461. source = _ref3[_j];
  462. if (source instanceof AjaxMonitor) {
  463. source.watch.apply(source, args);
  464. break;
  465. } else {
  466. _results.push(void 0);
  467. }
  468. }
  469. return _results;
  470. }
  471. }, after);
  472. }
  473. });
  474. AjaxMonitor = (function() {
  475. function AjaxMonitor() {
  476. var _this = this;
  477. this.elements = [];
  478. getIntercept().on('request', function() {
  479. return _this.watch.apply(_this, arguments);
  480. });
  481. }
  482. AjaxMonitor.prototype.watch = function(_arg) {
  483. var request, tracker, type, url;
  484. type = _arg.type, request = _arg.request, url = _arg.url;
  485. if (shouldIgnoreURL(url)) {
  486. return;
  487. }
  488. if (type === 'socket') {
  489. tracker = new SocketRequestTracker(request);
  490. } else {
  491. tracker = new XHRRequestTracker(request);
  492. }
  493. return this.elements.push(tracker);
  494. };
  495. return AjaxMonitor;
  496. })();
  497. XHRRequestTracker = (function() {
  498. function XHRRequestTracker(request) {
  499. var event, size, _j, _len1, _onreadystatechange, _ref2,
  500. _this = this;
  501. this.progress = 0;
  502. if (window.ProgressEvent != null) {
  503. size = null;
  504. request.addEventListener('progress', function(evt) {
  505. if (evt.lengthComputable) {
  506. return _this.progress = 100 * evt.loaded / evt.total;
  507. } else {
  508. return _this.progress = _this.progress + (100 - _this.progress) / 2;
  509. }
  510. });
  511. _ref2 = ['load', 'abort', 'timeout', 'error'];
  512. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  513. event = _ref2[_j];
  514. request.addEventListener(event, function() {
  515. return _this.progress = 100;
  516. });
  517. }
  518. } else {
  519. _onreadystatechange = request.onreadystatechange;
  520. request.onreadystatechange = function() {
  521. var _ref3;
  522. if ((_ref3 = request.readyState) === 0 || _ref3 === 4) {
  523. _this.progress = 100;
  524. } else if (request.readyState === 3) {
  525. _this.progress = 50;
  526. }
  527. return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
  528. };
  529. }
  530. }
  531. return XHRRequestTracker;
  532. })();
  533. SocketRequestTracker = (function() {
  534. function SocketRequestTracker(request) {
  535. var event, _j, _len1, _ref2,
  536. _this = this;
  537. this.progress = 0;
  538. _ref2 = ['error', 'open'];
  539. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  540. event = _ref2[_j];
  541. request.addEventListener(event, function() {
  542. return _this.progress = 100;
  543. });
  544. }
  545. }
  546. return SocketRequestTracker;
  547. })();
  548. ElementMonitor = (function() {
  549. function ElementMonitor(options) {
  550. var selector, _j, _len1, _ref2;
  551. if (options == null) {
  552. options = {};
  553. }
  554. this.elements = [];
  555. if (options.selectors == null) {
  556. options.selectors = [];
  557. }
  558. _ref2 = options.selectors;
  559. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  560. selector = _ref2[_j];
  561. this.elements.push(new ElementTracker(selector));
  562. }
  563. }
  564. return ElementMonitor;
  565. })();
  566. ElementTracker = (function() {
  567. function ElementTracker(selector) {
  568. this.selector = selector;
  569. this.progress = 0;
  570. this.check();
  571. }
  572. ElementTracker.prototype.check = function() {
  573. var _this = this;
  574. if (document.querySelector(this.selector)) {
  575. return this.done();
  576. } else {
  577. return setTimeout((function() {
  578. return _this.check();
  579. }), options.elements.checkInterval);
  580. }
  581. };
  582. ElementTracker.prototype.done = function() {
  583. return this.progress = 100;
  584. };
  585. return ElementTracker;
  586. })();
  587. DocumentMonitor = (function() {
  588. DocumentMonitor.prototype.states = {
  589. loading: 0,
  590. interactive: 50,
  591. complete: 100
  592. };
  593. function DocumentMonitor() {
  594. var _onreadystatechange, _ref2,
  595. _this = this;
  596. this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
  597. _onreadystatechange = document.onreadystatechange;
  598. document.onreadystatechange = function() {
  599. if (_this.states[document.readyState] != null) {
  600. _this.progress = _this.states[document.readyState];
  601. }
  602. return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
  603. };
  604. }
  605. return DocumentMonitor;
  606. })();
  607. EventLagMonitor = (function() {
  608. function EventLagMonitor() {
  609. var avg, interval, last, points, samples,
  610. _this = this;
  611. this.progress = 0;
  612. avg = 0;
  613. samples = [];
  614. points = 0;
  615. last = now();
  616. interval = setInterval(function() {
  617. var diff;
  618. diff = now() - last - 50;
  619. last = now();
  620. samples.push(diff);
  621. if (samples.length > options.eventLag.sampleCount) {
  622. samples.shift();
  623. }
  624. avg = avgAmplitude(samples);
  625. if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
  626. _this.progress = 100;
  627. return clearInterval(interval);
  628. } else {
  629. return _this.progress = 100 * (3 / (avg + 3));
  630. }
  631. }, 50);
  632. }
  633. return EventLagMonitor;
  634. })();
  635. Scaler = (function() {
  636. function Scaler(source) {
  637. this.source = source;
  638. this.last = this.sinceLastUpdate = 0;
  639. this.rate = options.initialRate;
  640. this.catchup = 0;
  641. this.progress = this.lastProgress = 0;
  642. if (this.source != null) {
  643. this.progress = result(this.source, 'progress');
  644. }
  645. }
  646. Scaler.prototype.tick = function(frameTime, val) {
  647. var scaling;
  648. if (val == null) {
  649. val = result(this.source, 'progress');
  650. }
  651. if (val >= 100) {
  652. this.done = true;
  653. }
  654. if (val === this.last) {
  655. this.sinceLastUpdate += frameTime;
  656. } else {
  657. if (this.sinceLastUpdate) {
  658. this.rate = (val - this.last) / this.sinceLastUpdate;
  659. }
  660. this.catchup = (val - this.progress) / options.catchupTime;
  661. this.sinceLastUpdate = 0;
  662. this.last = val;
  663. }
  664. if (val > this.progress) {
  665. this.progress += this.catchup * frameTime;
  666. }
  667. scaling = 1 - Math.pow(this.progress / 100, options.easeFactor);
  668. this.progress += scaling * this.rate * frameTime;
  669. this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress);
  670. this.progress = Math.max(0, this.progress);
  671. this.progress = Math.min(100, this.progress);
  672. this.lastProgress = this.progress;
  673. return this.progress;
  674. };
  675. return Scaler;
  676. })();
  677. sources = null;
  678. scalers = null;
  679. bar = null;
  680. uniScaler = null;
  681. animation = null;
  682. cancelAnimation = null;
  683. Pace.running = false;
  684. handlePushState = function() {
  685. if (options.restartOnPushState) {
  686. return Pace.restart();
  687. }
  688. };
  689. if (window.history.pushState != null) {
  690. _pushState = window.history.pushState;
  691. window.history.pushState = function() {
  692. handlePushState();
  693. return _pushState.apply(window.history, arguments);
  694. };
  695. }
  696. if (window.history.replaceState != null) {
  697. _replaceState = window.history.replaceState;
  698. window.history.replaceState = function() {
  699. handlePushState();
  700. return _replaceState.apply(window.history, arguments);
  701. };
  702. }
  703. SOURCE_KEYS = {
  704. ajax: AjaxMonitor,
  705. elements: ElementMonitor,
  706. document: DocumentMonitor,
  707. eventLag: EventLagMonitor
  708. };
  709. (init = function() {
  710. var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4;
  711. Pace.sources = sources = [];
  712. _ref2 = ['ajax', 'elements', 'document', 'eventLag'];
  713. for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
  714. type = _ref2[_j];
  715. if (options[type] !== false) {
  716. sources.push(new SOURCE_KEYS[type](options[type]));
  717. }
  718. }
  719. _ref4 = (_ref3 = options.extraSources) != null ? _ref3 : [];
  720. for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
  721. source = _ref4[_k];
  722. sources.push(new source(options));
  723. }
  724. Pace.bar = bar = new Bar;
  725. scalers = [];
  726. return uniScaler = new Scaler;
  727. })();
  728. Pace.stop = function() {
  729. Pace.trigger('stop');
  730. Pace.running = false;
  731. bar.destroy();
  732. cancelAnimation = true;
  733. if (animation != null) {
  734. if (typeof cancelAnimationFrame === "function") {
  735. cancelAnimationFrame(animation);
  736. }
  737. animation = null;
  738. }
  739. return init();
  740. };
  741. Pace.restart = function() {
  742. Pace.trigger('restart');
  743. Pace.stop();
  744. return Pace.start();
  745. };
  746. Pace.go = function() {
  747. var start;
  748. Pace.running = true;
  749. bar.render();
  750. start = now();
  751. cancelAnimation = false;
  752. return animation = runAnimation(function(frameTime, enqueueNextFrame) {
  753. var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2;
  754. remaining = 100 - bar.progress;
  755. count = sum = 0;
  756. done = true;
  757. for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) {
  758. source = sources[i];
  759. scalerList = scalers[i] != null ? scalers[i] : scalers[i] = [];
  760. elements = (_ref2 = source.elements) != null ? _ref2 : [source];
  761. for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) {
  762. element = elements[j];
  763. scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element);
  764. done &= scaler.done;
  765. if (scaler.done) {
  766. continue;
  767. }
  768. count++;
  769. sum += scaler.tick(frameTime);
  770. }
  771. }
  772. avg = sum / count;
  773. bar.update(uniScaler.tick(frameTime, avg));
  774. if (bar.done() || done || cancelAnimation) {
  775. bar.update(100);
  776. Pace.trigger('done');
  777. return setTimeout(function() {
  778. bar.finish();
  779. Pace.running = false;
  780. return Pace.trigger('hide');
  781. }, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0)));
  782. } else {
  783. return enqueueNextFrame();
  784. }
  785. });
  786. };
  787. Pace.start = function(_options) {
  788. extend(options, _options);
  789. Pace.running = true;
  790. try {
  791. bar.render();
  792. } catch (_error) {
  793. NoTargetError = _error;
  794. }
  795. if (!document.querySelector('.pace')) {
  796. return setTimeout(Pace.start, 50);
  797. } else {
  798. Pace.trigger('start');
  799. return Pace.go();
  800. }
  801. };
  802. if (typeof define === 'function' && define.amd) {
  803. define(function() {
  804. return Pace;
  805. });
  806. } else if (typeof exports === 'object') {
  807. module.exports = Pace;
  808. } else {
  809. if (options.startOnPageLoad) {
  810. Pace.start();
  811. }
  812. }
  813. }).call(this);