Skip to content

Commit

Permalink
commit message goes here
Browse files Browse the repository at this point in the history
  • Loading branch information
chieffancypants committed Sep 10, 2013
1 parent 57ae0fa commit e1d6cc4
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true


[*]

# Change these settings to your own preference
indent_style = space
indent_size = 2

# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
Empty file added .gitignore
Empty file.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,16 @@ angular-loading-bar
===================

Automatically add a loading bar to your angular apps, automatically. Automatic.


## Why I created this

I made this for two reasons:
1. To make sure it was automatic
2. To make sure it was fully tested

### Automated
There are a couple projects similar to this out there, but none are ideal. All implementations I've seen are based on the excellent [nprogress](https://github.com/rstacruz/nprogress) by rstacruz, which requires that you maintain state on behalf of the loading bar. In other words, you're setting the value of the loading/progress bar manually from potentially many different locations. This becomes complicated when you have a very large application with several services all making independant XHR requests.

### Tested
The basis of Angular is that it's easy to test. So it pains me to see angular modules without tests. This loading bar aims for 100% code coverage.
142 changes: 142 additions & 0 deletions src/loading-bar-interceptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* angular-loading-bar
*
* intercepts XHR requests and creates a loading bar when that shit happens.
* Based on the excellent nprogress work by rstacruz (more info in readme)
*
* (c) 2013 Wes Cruver
* License: MIT
*/



/**
* loadingBarInterceptor service
*
* Registers itself as an Angular interceptor and listens for XHR requests.
*/
angular.module('chieffancypants.loadingBar', [])
.factory('loadingBarInterceptor', function($q, loadingBar) {

/**
* The total number of requests made
* @type {Number}
*/
var reqsTotal = 0;

/**
* The number of requests completed (either successfully or not)
* @type {Number}
*/
var reqsCompleted = 0;


/**
* increments the reqsCompleted, and checks if all XHR requests have
* completed. If so, it calls loadingBar.complete() which removes the
* loading bar from the DOM.
*/
function checkComplete() {
reqsCompleted++;
if (reqsCompleted === reqsTotal) {
loadingBar.complete();
}
}

return {
'request': function(config) {
reqsTotal++;
return config;
},

'response': function(response) {
checkComplete();
loadingBar.set(reqsCompleted / reqsTotal);
return response;
},

'responseError': function(rejection) {
checkComplete();
loadingBar.set(reqsCompleted / reqsTotal);
return $q.reject(rejection);
}

};
})

/**
* Loading Bar
*
* This service handles actually adding and removing the element from the DOM.
* Because this is such a light-weight element, the
*/
.factory('cfpLoadingBar', ['$document', '$timeout', function ($document, $timeout) {
'use strict';

var $body = $document.find('body'),
loadingBarContainer = angular.element('<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>'),
loadingBar = loadingBarContainer.find('div').eq(0);

var started = false,
status = 0;


/**
* Inserts the loading bar element into the dom, and sets it to 1%
*/
function _start() {
started = true;
$body.append(loadingBarContainer);
loadingBar.css('width', '1%').css('opacity', 1);
}

/**
* Set the loading bar's width to a certain percent.
*
* @param n any value between 0 and 1
*/
function _set(n) {
if (!started) {
_start();
}
var pct = (n * 100) + '%';
loadingBar.css('width', pct);
status = n;

// give the illusion that there is always progress...
$timeout(function() {
_inc();
}, 500);
}

/**
* Increments the loading bar by a random amount between .1% and .9%
*/
function _inc() {
if (_status() >= 1) {
return;
}
var pct = _status() + (Math.random() / 100);
_set(pct);
console.log('status is', _status());
}

function _status() {
return status;
}

return {
start: _start,
set: _set,
status: _status,

complete: function () {
$timeout(function() {
loadingBar.css('opacity', 0);
started = false;
}, 500);
}

};
}]);

74 changes: 74 additions & 0 deletions src/loading-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
angular.module('kzo.services')

/**
* Metric service
*/
.factory('loadingBar', ['$document', '$timeout', function ($document, $timeout) {
'use strict';

var $body = $document.find('body'),
loadingBarContainer = angular.element('<div id="loading-bar"><div class="bar"><div class="peg"></div></div></div>'),
loadingBar = loadingBarContainer.find('div').eq(0);

var started = false,
status = 0;


/**
* Inserts the loading bar element into the dom, and sets it to 1%
*/
function _start() {
started = true;
$body.append(loadingBarContainer);
loadingBar.css('width', '1%').css('opacity', 1);
}

/**
* Set the loading bar's width to a certain percent.
*
* @param n any value between 0 and 1
*/
function _set(n) {
if (!started) {
_start();
}
var pct = (n * 100) + '%';
loadingBar.css('width', pct);
status = n;

// give the illusion that there is always progress...
$timeout(function() {
_inc();
}, 500);
}

/**
* Increments the loading bar by a random amount between .1% and .9%
*/
function _inc() {
if (_status() >= 1) {
return;
}
var pct = _status() + (Math.random() / 100);
_set(pct);
console.log('status is', _status());
}

function _status() {
return status;
}

return {
start: _start,
set: _set,
status: _status,

complete: function () {
$timeout(function() {
loadingBar.css('opacity', 0);
started = false;
}, 500);
}

};
}]);
27 changes: 27 additions & 0 deletions test/loading-bar-interceptor.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
describe 'loadingBarInterceptor Service', ->

$http = $httpBackend = $document = result = null
response = {message:'OK'}
endpoint = '/service'

beforeEach ->
module 'kzo.services'
result = null
inject (_$http_, _$httpBackend_, _$document_) ->
$http = _$http_
$httpBackend = _$httpBackend_
$document = _$document_

it 'should insert the loadingbar when a request is sent', ->
$httpBackend.expectGET(endpoint).respond response
$http.get(endpoint).then (data) ->
result = data


$httpBackend.flush()
expect(result.data.message).toBe 'OK'




# $httpBackend.expectGET(endpoint).respond 401, {result: 'failure'}

0 comments on commit e1d6cc4

Please sign in to comment.