app/assets/javascripts/pace/pace.js in pace-rails-0.0.5 vs app/assets/javascripts/pace/pace.js in pace-rails-0.0.6

- old
+ new

@@ -1,7 +1,7 @@ (function() { - var AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Events, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, animation, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, firstLoad, getFromDOM, handlePushState, init, intercept, now, options, requestAnimationFrame, result, runAnimation, scalers, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _pushState, _replaceState, + var AjaxMonitor, Bar, DocumentMonitor, ElementMonitor, ElementTracker, EventLagMonitor, Events, NoTargetError, RequestIntercept, SOURCE_KEYS, Scaler, SocketRequestTracker, XHRRequestTracker, animation, avgAmplitude, bar, cancelAnimation, cancelAnimationFrame, defaultOptions, extend, extendNative, getFromDOM, getIntercept, handlePushState, init, now, options, requestAnimationFrame, result, runAnimation, scalers, sources, uniScaler, _WebSocket, _XDomainRequest, _XMLHttpRequest, _intercept, _pushState, _ref, _replaceState, __slice = [].slice, __hasProp = {}.hasOwnProperty, __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; }, __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; }; @@ -12,22 +12,24 @@ ghostTime: 250, maxProgressPerFrame: 10, easeFactor: 1.25, startOnPageLoad: true, restartOnPushState: true, - restartOnBackboneRoute: true, + restartOnRequestAfter: 500, target: 'body', elements: { checkInterval: 100, selectors: ['body'] }, eventLag: { - minSamples: 10 + minSamples: 10, + sampleCount: 3, + lagThreshold: 3 }, ajax: { trackMethods: ['GET'], - trackWebSockets: true + trackWebSockets: false } }; now = function() { var _ref; @@ -89,10 +91,21 @@ } } return out; }; + avgAmplitude = function(arr) { + var count, sum, v, _i, _len; + sum = count = 0; + for (_i = 0, _len = arr.length; _i < _len; _i++) { + v = arr[_i]; + sum += Math.abs(v); + count++; + } + return sum / count; + }; + getFromDOM = function(key, json) { var data, e, el; if (key == null) { key = 'options'; } @@ -119,22 +132,39 @@ window.Pace = {}; } options = Pace.options = extend(defaultOptions, window.paceOptions, getFromDOM()); + NoTargetError = (function(_super) { + __extends(NoTargetError, _super); + + function NoTargetError() { + _ref = NoTargetError.__super__.constructor.apply(this, arguments); + return _ref; + } + + return NoTargetError; + + })(Error); + Bar = (function() { function Bar() { this.progress = 0; } Bar.prototype.getElement = function() { var targetElement; if (this.el == null) { + targetElement = document.querySelector(options.target); + if (!targetElement) { + throw new NoTargetError; + } this.el = document.createElement('div'); this.el.className = "pace pace-active"; + document.body.className = document.body.className.replace('pace-done', ''); + document.body.className += ' pace-running'; this.el.innerHTML = '<div class="pace-progress">\n <div class="pace-progress-inner"></div>\n</div>\n<div class="pace-activity"></div>'; - targetElement = document.querySelector(options.target); if (targetElement.firstChild != null) { targetElement.insertBefore(this.el, targetElement.firstChild); } else { targetElement.appendChild(this.el); } @@ -144,20 +174,26 @@ Bar.prototype.finish = function() { var el; el = this.getElement(); el.className = el.className.replace('pace-active', ''); - return el.className += ' pace-inactive'; + el.className += ' pace-inactive'; + document.body.className = document.body.className.replace('pace-running', ''); + return document.body.className += ' pace-done'; }; Bar.prototype.update = function(prog) { this.progress = prog; return this.render(); }; Bar.prototype.destroy = function() { - this.getElement().parentNode.removeChild(this.getElement()); + try { + this.getElement().parentNode.removeChild(this.getElement()); + } catch (_error) { + NoTargetError = _error; + } return this.el = void 0; }; Bar.prototype.render = function() { var el, progressStr; @@ -165,18 +201,18 @@ return false; } el = this.getElement(); el.children[0].style.width = "" + this.progress + "%"; if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) { - el.setAttribute('data-progress-text', "" + (this.progress | 0) + "%"); + el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%"); if (this.progress >= 100) { progressStr = '99'; } else { progressStr = this.progress < 10 ? "0" : ""; progressStr += this.progress | 0; } - el.setAttribute('data-progress', "" + progressStr); + el.children[0].setAttribute('data-progress', "" + progressStr); } return this.lastRenderedProgress = this.progress; }; Bar.prototype.done = function() { @@ -191,16 +227,16 @@ function Events() { this.bindings = {}; } Events.prototype.trigger = function(name, val) { - var binding, _i, _len, _ref, _results; + var binding, _i, _len, _ref1, _results; if (this.bindings[name] != null) { - _ref = this.bindings[name]; + _ref1 = this.bindings[name]; _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - binding = _ref[_i]; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + binding = _ref1[_i]; _results.push(binding.call(this, val)); } return _results; } }; @@ -250,12 +286,12 @@ RequestIntercept.__super__.constructor.apply(this, arguments); monitorXHR = function(req) { var _open; _open = req.open; return req.open = function(type, url, async) { - var _ref; - if (_ref = (type != null ? type : 'GET').toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref) >= 0) { + var _ref1; + if (_ref1 = (type != null ? type : 'GET').toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref1) >= 0) { _this.trigger('request', { type: type, url: url, request: req }); @@ -297,17 +333,57 @@ return RequestIntercept; })(Events); - intercept = new RequestIntercept; + _intercept = null; + getIntercept = function() { + if (_intercept == null) { + _intercept = new RequestIntercept; + } + return _intercept; + }; + + if (options.restartOnRequestAfter !== false) { + getIntercept().on('request', function(_arg) { + var args, request, type; + type = _arg.type, request = _arg.request; + if (!Pace.running) { + args = arguments; + return setTimeout(function() { + var source, stillActive, _i, _len, _ref1, _ref2, _results; + if (type === 'socket') { + stillActive = request.readyState < 2; + } else { + stillActive = (0 < (_ref1 = request.readyState) && _ref1 < 4); + } + if (stillActive) { + Pace.restart(); + _ref2 = Pace.sources; + _results = []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + source = _ref2[_i]; + if (source instanceof AjaxMonitor) { + source.watch.apply(source, args); + break; + } else { + _results.push(void 0); + } + } + return _results; + } + }, options.restartOnRequestAfter); + } + }); + } + AjaxMonitor = (function() { function AjaxMonitor() { var _this = this; this.elements = []; - intercept.on('request', function() { + getIntercept().on('request', function() { return _this.watch.apply(_this, arguments); }); } AjaxMonitor.prototype.watch = function(_arg) { @@ -325,11 +401,11 @@ })(); XHRRequestTracker = (function() { function XHRRequestTracker(request) { - var event, size, _i, _len, _onreadystatechange, _ref, + var event, size, _i, _len, _onreadystatechange, _ref1, _this = this; this.progress = 0; if (window.ProgressEvent != null) { size = null; request.addEventListener('progress', function(evt) { @@ -337,22 +413,22 @@ return _this.progress = 100 * evt.loaded / evt.total; } else { return _this.progress = _this.progress + (100 - _this.progress) / 2; } }); - _ref = ['load', 'abort', 'timeout', 'error']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; + _ref1 = ['load', 'abort', 'timeout', 'error']; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + event = _ref1[_i]; request.addEventListener(event, function() { return _this.progress = 100; }); } } else { _onreadystatechange = request.onreadystatechange; request.onreadystatechange = function() { - var _ref1; - if ((_ref1 = request.readyState) === 0 || _ref1 === 4) { + var _ref2; + if ((_ref2 = request.readyState) === 0 || _ref2 === 4) { _this.progress = 100; } else if (request.readyState === 3) { _this.progress = 50; } return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0; @@ -364,16 +440,16 @@ })(); SocketRequestTracker = (function() { function SocketRequestTracker(request) { - var event, _i, _len, _ref, + var event, _i, _len, _ref1, _this = this; this.progress = 0; - _ref = ['error', 'open']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; + _ref1 = ['error', 'open']; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + event = _ref1[_i]; request.addEventListener(event, function() { return _this.progress = 100; }); } } @@ -382,21 +458,21 @@ })(); ElementMonitor = (function() { function ElementMonitor(options) { - var selector, _i, _len, _ref; + var selector, _i, _len, _ref1; if (options == null) { options = {}; } this.elements = []; if (options.selectors == null) { options.selectors = []; } - _ref = options.selectors; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - selector = _ref[_i]; + _ref1 = options.selectors; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + selector = _ref1[_i]; this.elements.push(new ElementTracker(selector)); } } return ElementMonitor; @@ -435,13 +511,13 @@ interactive: 50, complete: 100 }; function DocumentMonitor() { - var _onreadystatechange, _ref, + var _onreadystatechange, _ref1, _this = this; - this.progress = (_ref = this.states[document.readyState]) != null ? _ref : 100; + this.progress = (_ref1 = this.states[document.readyState]) != null ? _ref1 : 100; _onreadystatechange = document.onreadystatechange; document.onreadystatechange = function() { if (_this.states[document.readyState] != null) { _this.progress = _this.states[document.readyState]; } @@ -453,25 +529,32 @@ })(); EventLagMonitor = (function() { function EventLagMonitor() { - var avg, last, points, + var avg, interval, last, points, samples, _this = this; this.progress = 0; avg = 0; + samples = []; points = 0; last = now(); - setInterval(function() { + interval = setInterval(function() { var diff; diff = now() - last - 50; last = now(); - avg = avg + (diff - avg) / 15; - if (points++ > options.eventLag.minSamples && Math.abs(avg) < 3) { - avg = 0; + samples.push(diff); + if (samples.length > options.eventLag.sampleCount) { + samples.shift(); } - return _this.progress = 100 * (3 / (avg + 3)); + avg = avgAmplitude(samples); + if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) { + _this.progress = 100; + return clearInterval(interval); + } else { + return _this.progress = 100 * (3 / (avg + 3)); + } }, 50); } return EventLagMonitor; @@ -533,10 +616,12 @@ animation = null; cancelAnimation = null; + Pace.running = false; + handlePushState = function() { if (options.restartOnPushState) { return Pace.restart(); } }; @@ -555,72 +640,39 @@ handlePushState(); return _replaceState.apply(window.history, arguments); }; } - firstLoad = true; - - if (options.restartOnBackboneRoute) { - setTimeout(function() { - if (window.Backbone == null) { - return; - } - return Backbone.history.on('route', function(router, name) { - var routeName, rule, _i, _len, _results; - if (!(rule = options.restartOnBackboneRoute)) { - return; - } - if (firstLoad) { - firstLoad = false; - return; - } - if (typeof rule === 'object') { - _results = []; - for (_i = 0, _len = rule.length; _i < _len; _i++) { - routeName = rule[_i]; - if (!(routeName === name)) { - continue; - } - Pace.restart(); - break; - } - return _results; - } else { - return Pace.restart(); - } - }); - }, 0); - } - SOURCE_KEYS = { ajax: AjaxMonitor, elements: ElementMonitor, document: DocumentMonitor, eventLag: EventLagMonitor }; (init = function() { - var source, type, _i, _j, _len, _len1, _ref, _ref1, _ref2; + var source, type, _i, _j, _len, _len1, _ref1, _ref2, _ref3; Pace.sources = sources = []; - _ref = ['ajax', 'elements', 'document', 'eventLag']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - type = _ref[_i]; + _ref1 = ['ajax', 'elements', 'document', 'eventLag']; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + type = _ref1[_i]; if (options[type] !== false) { sources.push(new SOURCE_KEYS[type](options[type])); } } - _ref2 = (_ref1 = options.extraSources) != null ? _ref1 : []; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - source = _ref2[_j]; + _ref3 = (_ref2 = options.extraSources) != null ? _ref2 : []; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + source = _ref3[_j]; sources.push(new source(options)); } Pace.bar = bar = new Bar; scalers = []; return uniScaler = new Scaler; })(); Pace.stop = function() { + Pace.running = false; bar.destroy(); cancelAnimation = true; if (animation != null) { if (typeof cancelAnimationFrame === "function") { cancelAnimationFrame(animation); @@ -630,25 +682,26 @@ return init(); }; Pace.restart = function() { Pace.stop(); - return Pace.go(); + return Pace.start(); }; Pace.go = function() { + Pace.running = true; bar.render(); cancelAnimation = false; return animation = runAnimation(function(frameTime, enqueueNextFrame) { - var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, source, start, sum, _i, _j, _len, _len1, _ref; + var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, source, start, sum, _i, _j, _len, _len1, _ref1; remaining = 100 - bar.progress; count = sum = 0; done = true; for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { source = sources[i]; scalerList = scalers[i] != null ? scalers[i] : scalers[i] = []; - elements = (_ref = source.elements) != null ? _ref : [source]; + elements = (_ref1 = source.elements) != null ? _ref1 : [source]; for (j = _j = 0, _len1 = elements.length; _j < _len1; j = ++_j) { element = elements[j]; scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element); done &= scaler.done; if (scaler.done) { @@ -662,20 +715,26 @@ bar.update(uniScaler.tick(frameTime, avg)); start = now(); if (bar.done() || done || cancelAnimation) { bar.update(100); return setTimeout(function() { - return bar.finish(); + bar.finish(); + return Pace.running = false; }, Math.max(options.ghostTime, Math.min(options.minTime, now() - start))); } else { return enqueueNextFrame(); } }); }; Pace.start = function(_options) { extend(options, _options); - bar.render(); + Pace.running = true; + try { + bar.render(); + } catch (_error) { + NoTargetError = _error; + } if (!document.querySelector('.pace')) { return setTimeout(Pace.start, 50); } else { return Pace.go(); } \ No newline at end of file