diff --git a/README.md b/README.md
index cb409bd..3cde38c 100644
--- a/README.md
+++ b/README.md
@@ -152,7 +152,15 @@ $http.post('/save', data, {
```
+#### Auto Increment
+By default, the loading bar will increment by a random amount that gets smaller as the bar fills, you can disable this:
+```js
+angular.module('myApp', ['angular-loading-bar'])
+ .config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
+ cfpLoadingBarProvider.autoIncrement = false;
+ }])
+```
## How it works:
@@ -190,7 +198,15 @@ cfpLoadingBar.status() // Returns the loading bar's progress.
cfpLoadingBar.complete()
// Set the loading bar's progress to 100%, and then remove it from the DOM.
-
+//
+// If your requests don't go through the $http service and can't be automatically detected,
+// use the following
+cfpLoadingBar.push(x)
+// signals the start of a request
+// it will broadcast x on the 'cfpLoadingBar:loading' event when called
+cfpLoadingBar.pop(y)
+// signals the completion of a request
+// if it is the last request to complete, broadcasts y on the 'cfpLoadingBar:loaded' event
```
## Events
diff --git a/build/loading-bar.css b/build/loading-bar.css
index 72408d1..d547f5b 100644
--- a/build/loading-bar.css
+++ b/build/loading-bar.css
@@ -1,7 +1,7 @@
/*!
* angular-loading-bar v0.9.0
* https://chieffancypants.github.io/angular-loading-bar
- * Copyright (c) 2016 Wes Cruver
+ * Copyright (c) 2017 Wes Cruver
* License: MIT
*/
diff --git a/build/loading-bar.js b/build/loading-bar.js
index 01630c0..7b7c7e0 100644
--- a/build/loading-bar.js
+++ b/build/loading-bar.js
@@ -1,7 +1,7 @@
/*!
* angular-loading-bar v0.9.0
* https://chieffancypants.github.io/angular-loading-bar
- * Copyright (c) 2016 Wes Cruver
+ * Copyright (c) 2017 Wes Cruver
* License: MIT
*/
/*
@@ -32,39 +32,7 @@ angular.module('chieffancypants.loadingBar', ['cfp.loadingBarInterceptor']);
angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
.config(['$httpProvider', function ($httpProvider) {
- var interceptor = ['$q', '$cacheFactory', '$timeout', '$rootScope', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $timeout, $rootScope, $log, cfpLoadingBar) {
-
- /**
- * The total number of requests made
- */
- var reqsTotal = 0;
-
- /**
- * The number of requests completed (either successfully or not)
- */
- var reqsCompleted = 0;
-
- /**
- * The amount of time spent fetching before showing the loading bar
- */
- var latencyThreshold = cfpLoadingBar.latencyThreshold;
-
- /**
- * $timeout handle for latencyThreshold
- */
- var startTimeout;
-
-
- /**
- * calls cfpLoadingBar.complete() which removes the
- * loading bar from the DOM.
- */
- function setComplete() {
- $timeout.cancel(startTimeout);
- cfpLoadingBar.complete();
- reqsCompleted = 0;
- reqsTotal = 0;
- }
+ var interceptor = ['$q', '$cacheFactory', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $log, cfpLoadingBar) {
/**
* Determine if the response has already been cached
@@ -100,14 +68,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
// Check to make sure this request hasn't already been cached and that
// the requester didn't explicitly ask us to ignore this request:
if (!config.ignoreLoadingBar && !isCached(config)) {
- $rootScope.$broadcast('cfpLoadingBar:loading', {url: config.url});
- if (reqsTotal === 0) {
- startTimeout = $timeout(function() {
- cfpLoadingBar.start();
- }, latencyThreshold);
- }
- reqsTotal++;
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
+ cfpLoadingBar.push({url: config.url});
}
return config;
},
@@ -119,13 +80,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
}
if (!response.config.ignoreLoadingBar && !isCached(response.config)) {
- reqsCompleted++;
- if (reqsCompleted >= reqsTotal) {
- $rootScope.$broadcast('cfpLoadingBar:loaded', {url: response.config.url, result: response});
- setComplete();
- } else {
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
- }
+ cfpLoadingBar.pop({url: response.config.url, result: response});
}
return response;
},
@@ -137,13 +92,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
}
if (!rejection.config.ignoreLoadingBar && !isCached(rejection.config)) {
- reqsCompleted++;
- if (reqsCompleted >= reqsTotal) {
- $rootScope.$broadcast('cfpLoadingBar:loaded', {url: rejection.config.url, result: rejection});
- setComplete();
- } else {
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
- }
+ cfpLoadingBar.pop({url: rejection.config.url, result: rejection});
}
return $q.reject(rejection);
}
@@ -192,6 +141,37 @@ angular.module('cfp.loadingBar', [])
var includeBar = this.includeBar;
var startSize = this.startSize;
+ /**
+ * The total number of requests made
+ */
+ var reqsTotal = 0;
+
+ /**
+ * The number of requests completed (either successfully or not)
+ */
+ var reqsCompleted = 0;
+
+ /**
+ * The amount of time spent fetching before showing the loading bar
+ */
+ var latencyThreshold = this.latencyThreshold;
+
+ /**
+ * $timeout handle for latencyThreshold
+ */
+ var startTimeout;
+
+ /**
+ * calls cfpLoadingBar.complete() which removes the
+ * loading bar from the DOM.
+ */
+ function setComplete() {
+ $timeout.cancel(startTimeout);
+ _complete();
+ reqsCompleted = 0;
+ reqsTotal = 0;
+ }
+
/**
* Inserts the loading bar element into the dom, and sets it to 2%
*/
@@ -321,12 +301,35 @@ angular.module('cfp.loadingBar', [])
}, 500);
}
+ function _push(info) {
+ $rootScope.$broadcast('cfpLoadingBar:loading', info);
+ if (reqsTotal === 0) {
+ startTimeout = $timeout(function() {
+ _start();
+ }, latencyThreshold);
+ }
+ reqsTotal++;
+ _set(reqsCompleted / reqsTotal);
+ }
+
+ function _pop(info) {
+ reqsCompleted++;
+ if (reqsCompleted >= reqsTotal) {
+ $rootScope.$broadcast('cfpLoadingBar:loaded', info);
+ setComplete();
+ } else {
+ _set(reqsCompleted / reqsTotal);
+ }
+ }
+
return {
start : _start,
set : _set,
status : _status,
inc : _inc,
complete : _complete,
+ push : _push,
+ pop : _pop,
autoIncrement : this.autoIncrement,
includeSpinner : this.includeSpinner,
latencyThreshold : this.latencyThreshold,
diff --git a/build/loading-bar.min.css b/build/loading-bar.min.css
index 0f9f106..75bfc7c 100644
--- a/build/loading-bar.min.css
+++ b/build/loading-bar.min.css
@@ -1 +1 @@
-#loading-bar,#loading-bar-spinner{pointer-events:none;-webkit-pointer-events:none;-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar-spinner.ng-enter,#loading-bar-spinner.ng-leave.ng-leave-active,#loading-bar.ng-enter,#loading-bar.ng-leave.ng-leave-active{opacity:0}#loading-bar-spinner.ng-enter.ng-enter-active,#loading-bar-spinner.ng-leave,#loading-bar.ng-enter.ng-enter-active,#loading-bar.ng-leave{opacity:1}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:10002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px;opacity:.45;-moz-box-shadow:#29d 1px 0 6px 1px;-ms-box-shadow:#29d 1px 0 6px 1px;-webkit-box-shadow:#29d 1px 0 6px 1px;box-shadow:#29d 1px 0 6px 1px;-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}#loading-bar-spinner{display:block;position:fixed;z-index:10002;top:10px;left:10px}#loading-bar-spinner .spinner-icon{width:14px;height:14px;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:loading-bar-spinner 400ms linear infinite;-moz-animation:loading-bar-spinner 400ms linear infinite;-ms-animation:loading-bar-spinner 400ms linear infinite;-o-animation:loading-bar-spinner 400ms linear infinite;animation:loading-bar-spinner 400ms linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
\ No newline at end of file
+#loading-bar,#loading-bar-spinner{pointer-events:none;-webkit-pointer-events:none;-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar-spinner.ng-enter,#loading-bar-spinner.ng-leave.ng-leave-active,#loading-bar.ng-enter,#loading-bar.ng-leave.ng-leave-active{opacity:0}#loading-bar-spinner.ng-enter.ng-enter-active,#loading-bar-spinner.ng-leave,#loading-bar.ng-enter.ng-enter-active,#loading-bar.ng-leave{opacity:1}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:10002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px;opacity:.45;-moz-box-shadow:#29d 1px 0 6px 1px;-ms-box-shadow:#29d 1px 0 6px 1px;-webkit-box-shadow:#29d 1px 0 6px 1px;box-shadow:#29d 1px 0 6px 1px;-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}#loading-bar-spinner{display:block;position:fixed;z-index:10002;top:10px;left:10px}#loading-bar-spinner .spinner-icon{width:14px;height:14px;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:loading-bar-spinner .4s linear infinite;-moz-animation:loading-bar-spinner .4s linear infinite;-ms-animation:loading-bar-spinner .4s linear infinite;-o-animation:loading-bar-spinner .4s linear infinite;animation:loading-bar-spinner .4s linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
\ No newline at end of file
diff --git a/build/loading-bar.min.js b/build/loading-bar.min.js
index e4b18ad..06c97f6 100644
--- a/build/loading-bar.min.js
+++ b/build/loading-bar.min.js
@@ -1,7 +1,8 @@
/*!
* angular-loading-bar v0.9.0
* https://chieffancypants.github.io/angular-loading-bar
- * Copyright (c) 2016 Wes Cruver
+ * Copyright (c) 2017 Wes Cruver
* License: MIT
*/
-!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(a){var b=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(b,c,d,e,f,g){function h(){d.cancel(j),g.complete(),l=0,k=0}function i(b){var d,e=c.get("$http"),f=a.defaults;!b.cache&&!f.cache||b.cache===!1||"GET"!==b.method&&"JSONP"!==b.method||(d=angular.isObject(b.cache)?b.cache:angular.isObject(f.cache)?f.cache:e);var g=void 0!==d?void 0!==d.get(b.url):!1;return void 0!==b.cached&&g!==b.cached?b.cached:(b.cached=g,g)}var j,k=0,l=0,m=g.latencyThreshold;return{request:function(a){return a.ignoreLoadingBar||i(a)||(e.$broadcast("cfpLoadingBar:loading",{url:a.url}),0===k&&(j=d(function(){g.start()},m)),k++,g.set(l/k)),a},response:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,l>=k?(e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),h()):g.set(l/k)),a):(f.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),a)},responseError:function(a){return a&&a.config?(a.config.ignoreLoadingBar||i(a.config)||(l++,l>=k?(e.$broadcast("cfpLoadingBar:loaded",{url:a.config.url,result:a}),h()):g.set(l/k)),b.reject(a)):(f.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),b.reject(a))}}}];a.interceptors.push(b)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.autoIncrement=!0,this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='
',this.loadingBarTemplate='',this.$get=["$injector","$document","$timeout","$rootScope",function(a,b,c,d){function e(){if(k||(k=a.get("$animate")),c.cancel(m),!r){var e=b[0],g=e.querySelector?e.querySelector(n):b.find(n)[0];g||(g=e.getElementsByTagName("body")[0]);var h=angular.element(g),i=g.lastChild&&angular.element(g.lastChild);d.$broadcast("cfpLoadingBar:started"),r=!0,v&&k.enter(o,h,i),u&&k.enter(q,h,o),f(w)}}function f(a){if(r){var b=100*a+"%";p.css("width",b),s=a,t&&(c.cancel(l),l=c(function(){g()},250))}}function g(){if(!(h()>=1)){var a=0,b=h();a=b>=0&&.25>b?(3*Math.random()+3)/100:b>=.25&&.65>b?3*Math.random()/100:b>=.65&&.9>b?2*Math.random()/100:b>=.9&&.99>b?.005:0;var c=h()+a;f(c)}}function h(){return s}function i(){s=0,r=!1}function j(){k||(k=a.get("$animate")),f(1),c.cancel(m),m=c(function(){var a=k.leave(o,i);a&&a.then&&a.then(i),k.leave(q),d.$broadcast("cfpLoadingBar:completed")},500)}var k,l,m,n=this.parentSelector,o=angular.element(this.loadingBarTemplate),p=o.find("div").eq(0),q=angular.element(this.spinnerTemplate),r=!1,s=0,t=this.autoIncrement,u=this.includeSpinner,v=this.includeBar,w=this.startSize;return{start:e,set:f,status:h,inc:g,complete:j,autoIncrement:this.autoIncrement,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}();
\ No newline at end of file
+
+!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(e){var n=["$q","$cacheFactory","$log","cfpLoadingBar",function(n,t,a,r){function i(n){var a,r=t.get("$http"),i=e.defaults;!n.cache&&!i.cache||!1===n.cache||"GET"!==n.method&&"JSONP"!==n.method||(a=angular.isObject(n.cache)?n.cache:angular.isObject(i.cache)?i.cache:r);var c=void 0!==a&&void 0!==a.get(n.url);return void 0!==n.cached&&c!==n.cached?n.cached:(n.cached=c,c)}return{request:function(e){return e.ignoreLoadingBar||i(e)||r.push({url:e.url}),e},response:function(e){return e&&e.config?(e.config.ignoreLoadingBar||i(e.config)||r.pop({url:e.config.url,result:e}),e):(a.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),e)},responseError:function(e){return e&&e.config?(e.config.ignoreLoadingBar||i(e.config)||r.pop({url:e.config.url,result:e}),n.reject(e)):(a.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),n.reject(e))}}}];e.interceptors.push(n)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.autoIncrement=!0,this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='',this.loadingBarTemplate='',this.$get=["$injector","$document","$timeout","$rootScope",function(e,n,t,a){function r(){t.cancel(m),u(),z=0,q=0}function i(){if(p||(p=e.get("$animate")),t.cancel(f),!$){var r=n[0],i=r.querySelector?r.querySelector(v):n.find(v)[0];i||(i=r.getElementsByTagName("body")[0]);var o=angular.element(i),l=i.lastChild&&angular.element(i.lastChild);a.$broadcast("cfpLoadingBar:started"),$=!0,j&&p.enter(B,o,l),L&&p.enter(S,o,B),c(I)}}function c(e){if($){var n=100*e+"%";b.css("width",n),y=e,T&&(t.cancel(g),g=t(function(){o()},250))}}function o(){if(!(l()>=1)){var e=0,n=l();e=n>=0&&n<.25?(3*Math.random()+3)/100:n>=.25&&n<.65?3*Math.random()/100:n>=.65&&n<.9?2*Math.random()/100:n>=.9&&n<.99?.005:0,c(l()+e)}}function l(){return y}function d(){y=0,$=!1}function u(){p||(p=e.get("$animate")),c(1),t.cancel(f),f=t(function(){var e=p.leave(B,d);e&&e.then&&e.then(d),p.leave(S),a.$broadcast("cfpLoadingBar:completed")},500)}function s(e){a.$broadcast("cfpLoadingBar:loading",e),0===q&&(m=t(function(){i()},C)),c(z/++q)}function h(e){++z>=q?(a.$broadcast("cfpLoadingBar:loaded",e),r()):c(z/q)}var p,g,f,m,v=this.parentSelector,B=angular.element(this.loadingBarTemplate),b=B.find("div").eq(0),S=angular.element(this.spinnerTemplate),$=!1,y=0,T=this.autoIncrement,L=this.includeSpinner,j=this.includeBar,I=this.startSize,q=0,z=0,C=this.latencyThreshold;return{start:i,set:c,status:l,inc:o,complete:u,push:s,pop:h,autoIncrement:this.autoIncrement,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}();
\ No newline at end of file
diff --git a/package.json b/package.json
index 6529008..9942ee7 100644
--- a/package.json
+++ b/package.json
@@ -31,16 +31,17 @@
},
"homepage": "https://chieffancypants.github.io/angular-loading-bar",
"devDependencies": {
- "karma-jasmine": "^0.1.3",
- "karma-coffee-preprocessor": "^0.2.0",
- "karma-phantomjs-launcher": "^0.1.0",
- "karma": "~0.12.0",
- "karma-coverage": "^0.1.0",
- "grunt": "~0.4.1",
- "grunt-contrib-jshint": "~0.6.4",
- "grunt-contrib-uglify": "^0.9.1",
- "grunt-contrib-cssmin": "~0.12.0",
- "grunt-karma": "~0.11.0",
- "grunt-contrib-concat": "^0.5.0"
+ "grunt": "^1.0.1",
+ "grunt-contrib-concat": "^1.0.1",
+ "grunt-contrib-cssmin": "^2.2.0",
+ "grunt-contrib-jshint": "^1.1.0",
+ "grunt-contrib-uglify": "^3.0.0",
+ "grunt-karma": "^2.0.0",
+ "jasmine-core": "^2.6.2",
+ "karma": "^1.7.0",
+ "karma-coffee-preprocessor": "^1.0.1",
+ "karma-coverage": "^1.1.1",
+ "karma-jasmine": "^1.1.0",
+ "karma-phantomjs-launcher": "^1.0.4"
}
}
diff --git a/src/loading-bar.js b/src/loading-bar.js
index 44e092a..501a949 100644
--- a/src/loading-bar.js
+++ b/src/loading-bar.js
@@ -26,39 +26,7 @@ angular.module('chieffancypants.loadingBar', ['cfp.loadingBarInterceptor']);
angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
.config(['$httpProvider', function ($httpProvider) {
- var interceptor = ['$q', '$cacheFactory', '$timeout', '$rootScope', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $timeout, $rootScope, $log, cfpLoadingBar) {
-
- /**
- * The total number of requests made
- */
- var reqsTotal = 0;
-
- /**
- * The number of requests completed (either successfully or not)
- */
- var reqsCompleted = 0;
-
- /**
- * The amount of time spent fetching before showing the loading bar
- */
- var latencyThreshold = cfpLoadingBar.latencyThreshold;
-
- /**
- * $timeout handle for latencyThreshold
- */
- var startTimeout;
-
-
- /**
- * calls cfpLoadingBar.complete() which removes the
- * loading bar from the DOM.
- */
- function setComplete() {
- $timeout.cancel(startTimeout);
- cfpLoadingBar.complete();
- reqsCompleted = 0;
- reqsTotal = 0;
- }
+ var interceptor = ['$q', '$cacheFactory', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $log, cfpLoadingBar) {
/**
* Determine if the response has already been cached
@@ -94,14 +62,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
// Check to make sure this request hasn't already been cached and that
// the requester didn't explicitly ask us to ignore this request:
if (!config.ignoreLoadingBar && !isCached(config)) {
- $rootScope.$broadcast('cfpLoadingBar:loading', {url: config.url});
- if (reqsTotal === 0) {
- startTimeout = $timeout(function() {
- cfpLoadingBar.start();
- }, latencyThreshold);
- }
- reqsTotal++;
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
+ cfpLoadingBar.push({url: config.url});
}
return config;
},
@@ -113,13 +74,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
}
if (!response.config.ignoreLoadingBar && !isCached(response.config)) {
- reqsCompleted++;
- if (reqsCompleted >= reqsTotal) {
- $rootScope.$broadcast('cfpLoadingBar:loaded', {url: response.config.url, result: response});
- setComplete();
- } else {
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
- }
+ cfpLoadingBar.pop({url: response.config.url, result: response});
}
return response;
},
@@ -131,13 +86,7 @@ angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar'])
}
if (!rejection.config.ignoreLoadingBar && !isCached(rejection.config)) {
- reqsCompleted++;
- if (reqsCompleted >= reqsTotal) {
- $rootScope.$broadcast('cfpLoadingBar:loaded', {url: rejection.config.url, result: rejection});
- setComplete();
- } else {
- cfpLoadingBar.set(reqsCompleted / reqsTotal);
- }
+ cfpLoadingBar.pop({url: rejection.config.url, result: rejection});
}
return $q.reject(rejection);
}
@@ -186,6 +135,37 @@ angular.module('cfp.loadingBar', [])
var includeBar = this.includeBar;
var startSize = this.startSize;
+ /**
+ * The total number of requests made
+ */
+ var reqsTotal = 0;
+
+ /**
+ * The number of requests completed (either successfully or not)
+ */
+ var reqsCompleted = 0;
+
+ /**
+ * The amount of time spent fetching before showing the loading bar
+ */
+ var latencyThreshold = this.latencyThreshold;
+
+ /**
+ * $timeout handle for latencyThreshold
+ */
+ var startTimeout;
+
+ /**
+ * calls cfpLoadingBar.complete() which removes the
+ * loading bar from the DOM.
+ */
+ function setComplete() {
+ $timeout.cancel(startTimeout);
+ _complete();
+ reqsCompleted = 0;
+ reqsTotal = 0;
+ }
+
/**
* Inserts the loading bar element into the dom, and sets it to 2%
*/
@@ -315,12 +295,35 @@ angular.module('cfp.loadingBar', [])
}, 500);
}
+ function _push(info) {
+ $rootScope.$broadcast('cfpLoadingBar:loading', info);
+ if (reqsTotal === 0) {
+ startTimeout = $timeout(function() {
+ _start();
+ }, latencyThreshold);
+ }
+ reqsTotal++;
+ _set(reqsCompleted / reqsTotal);
+ }
+
+ function _pop(info) {
+ reqsCompleted++;
+ if (reqsCompleted >= reqsTotal) {
+ $rootScope.$broadcast('cfpLoadingBar:loaded', info);
+ setComplete();
+ } else {
+ _set(reqsCompleted / reqsTotal);
+ }
+ }
+
return {
start : _start,
set : _set,
status : _status,
inc : _inc,
complete : _complete,
+ push : _push,
+ pop : _pop,
autoIncrement : this.autoIncrement,
includeSpinner : this.includeSpinner,
latencyThreshold : this.latencyThreshold,
diff --git a/test/loading-bar-interceptor-config.coffee b/test/loading-bar-interceptor-config.coffee
index f29ab1e..b33cd8d 100644
--- a/test/loading-bar-interceptor-config.coffee
+++ b/test/loading-bar-interceptor-config.coffee
@@ -44,28 +44,27 @@ describe 'loadingBarInterceptor Service - config options', ->
cfpLoadingBar.complete()
$timeout.flush()
- it 'should not auto increment loadingBar if configured', (done) ->
- module 'chieffancypants.loadingBar', (cfpLoadingBarProvider) ->
- cfpLoadingBarProvider.autoIncrement = false
- return
- inject ($timeout, cfpLoadingBar) ->
- flag = false
- cfpLoadingBar.start()
- cfpLoadingBar.set(.5)
- runs ->
+ describe 'loadingBarInterceptor Service - config options, async tests', ->
+ beforeEach (done) ->
+ module 'chieffancypants.loadingBar', (cfpLoadingBarProvider) ->
+ cfpLoadingBarProvider.autoIncrement = false
+ return
+ inject ($timeout, cfpLoadingBar) ->
+ cfpLoadingBar.start()
+ cfpLoadingBar.set(.5)
setTimeout ->
- flag = true
+ done()
, 500
- waitsFor ->
- return flag
- , "500ms timeout"
- , 1000
+ it 'should not auto increment loadingBar if configured', (done) ->
+ inject ($timeout, cfpLoadingBar) ->
+ setTimeout ->
+ expect(cfpLoadingBar.status()).toBe .5;
+ cfpLoadingBar.complete();
+ $timeout.flush();
+ done();
+ , 500
- runs ->
- expect(cfpLoadingBar.status()).toBe .5;
- cfpLoadingBar.complete()
- $timeout.flush()
it 'should auto increment loadingBar if configured', ->
module 'chieffancypants.loadingBar', (cfpLoadingBarProvider) ->
diff --git a/test/loading-bar-interceptor.coffee b/test/loading-bar-interceptor.coffee
index 241967f..cf0ab64 100644
--- a/test/loading-bar-interceptor.coffee
+++ b/test/loading-bar-interceptor.coffee
@@ -34,13 +34,21 @@ describe 'loadingBarInterceptor Service', ->
$animate.triggerCallbacks && $animate.triggerCallbacks()
beforeEach ->
- this.addMatchers
- toBeBetween: (high, low) ->
- if low > high
- temp = low
- low = high
- high = temp
- return this.actual > low && this.actual < high
+ jasmine.addMatchers
+ toBeBetween: () ->
+ return compare: (actual, high, low) ->
+ if low > high
+ temp = low
+ low = high
+ high = temp
+ passed = actual > low && actual < high
+ result =
+ pass:
+ passed
+ message:
+ 'expected ' + actual + ' to ' + (if passed then 'not ' else '') + 'be between ' + low + ' and ' + high
+ return result
+
afterEach ->
@@ -494,6 +502,28 @@ describe 'LoadingBar only', ->
expect(isLoadingBarInjected($document.find(cfpLoadingBar.parentSelector))).toBe false
+ it 'should allow for explicit calls to push and pop', ->
+ cfpLoadingBar.start()
+ $timeout.flush()
+
+ # pushing adds only to reqsTotal, and shouldn't set the status above 0, even with multiple calls
+ cfpLoadingBar.push({})
+ expect(cfpLoadingBar.status()).toBe(0)
+ cfpLoadingBar.push({})
+ cfpLoadingBar.push({})
+ cfpLoadingBar.push({})
+ expect(cfpLoadingBar.status()).toBe(0)
+
+ # pushing adds to reqsCompleted, and should set the status to reqsCompleted/reqsTotal
+ cfpLoadingBar.pop({})
+ expect(cfpLoadingBar.status()).toBe(0.25)
+ cfpLoadingBar.pop({})
+ expect(cfpLoadingBar.status()).toBe(0.5)
+ cfpLoadingBar.pop({})
+ expect(cfpLoadingBar.status()).toBe(0.75)
+ cfpLoadingBar.pop({})
+ expect(cfpLoadingBar.status()).toBe(1)
+
describe 'Interceptor tests', ->
provider = $http = $httpBackend = $log = null