angular-tek-progress-bar
Version:
angular-tek-progress-bar is an AngularJS module to create and controls progress bar.
322 lines (297 loc) • 12 kB
JavaScript
/**
* angular-tek-progress-bar - angular-tek-progress-bar is an AngularJS module to create and controls progress bar.
* @version v0.2.0
* @link https://github.com/TekVanDo/Angular-Tek-Progress-bar
* @license MIT
*/
(function () {
"use strict";
angular.module('Tek.progressBar', []).run(['$templateCache', function ($templateCache) {
$templateCache.put('Tek.progressBarDirective.html', "<div class='progress' ng-class='bar.containerClass'><div class='progress-bar' ng-class='bar.barClass' ng-transclude></div></div>");
}]);
}());
(function () {
"use strict";
angular.module('Tek.progressBar').directive('tekProgressBar', function () {
return {
scope: {
manager: "=",
containerClass: "@class",
barClass: "@",
ngModel: "=",
mode: '@'
},
restrict: "E",
transclude: true,
controllerAs: "bar",
templateUrl: "Tek.progressBarDirective.html",
bindToController: true,
controller: ['$scope', '$element', function ($scope, $element) {
var bar = this;
var settings = {
fullClass: 'full-bar',
emptyClass: 'empty-bar',
verticalClass: 'vertical',
horizontalClass: ''
};
function ProgressObj(element, mode) {
var divElements = element.find('div');
this.mode = mode;
this.containerElement = angular.element(divElements[0]);
this.containerElement.addClass(settings[mode + 'Class']);
this.barContainer = angular.element(divElements[1]);
this.value = 0;
}
ProgressObj.prototype.get = function () {
return this.value;
};
ProgressObj.prototype.set = function (val) {
this.value = val;
if(this.mode === 'horizontal'){
this.barContainer.css('width', val + '%');
}
if(this.mode === 'vertical'){
this.barContainer.css('height', val + '%');
}
this.updateClasses();
};
ProgressObj.prototype.updateClasses = function () {
if (this.value <= 0) {
this.containerElement.removeClass(settings.fullClass);
return this.containerElement.addClass(settings.emptyClass);
}
if (this.value >= 100) {
this.containerElement.removeClass(settings.emptyClass);
return this.containerElement.addClass(settings.fullClass);
}
this.containerElement.removeClass(settings.fullClass);
this.containerElement.removeClass(settings.emptyClass);
};
ProgressObj.prototype.setAnimation = function (val) {
if(val === true){
this.barContainer.css('transition', '');
}else{
this.barContainer.css('transition', 'none');
}
};
bar.init = function () {
bar.mode = (bar.mode === 'vertical') ? bar.mode : 'horizontal';
bar.progressObj = new ProgressObj($element, bar.mode);
var facade = {
get: function () {
return bar.progressObj.get();
},
set: function (newVal) {
if (bar.ngModel !== undefined) { // todo setInterval problem
$scope.$evalAsync(function () {
bar.ngModel = newVal;
});
} else {
bar.progressObj.set(newVal);
}
},
setAnimation: function (val) {
bar.progressObj.setAnimation(val);
}
};
if (bar.manager) {
bar.manager._getDefer().resolve(facade);
$scope.$on('$destroy', function () {
bar.manager._updateDefer();
});
}
if (bar.ngModel !== undefined) {
$scope.$watch('bar.ngModel', function (newVal) {
if(typeof newVal !== 'number' || newVal < 0 || newVal !== newVal){
newVal = 0;
}
if(newVal > 100){
newVal = 100;
}
if (bar.manager) {
bar.manager._updateValue(newVal);
}
bar.progressObj.set(newVal);
});
}
};
bar.init();
}]
}
});
}());
(function () {
"use strict";
var requestAnimationFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
angular.module('Tek.progressBar').factory('progressBarManager', ['$q', function ($q) {
return function (params) {
var deferred = $q.defer();
var instance = null;
var lastVal = 0;
var animation = true;
var requiredClear = false;
var settings = {
incrementSpeed: 300,
incrementStrategy: function (stat) {
var rnd = 0;
if (stat >= 0 && stat < 25) {
rnd = (Math.random() * (5 - 3 + 1) + 3);
} else if (stat >= 25 && stat < 65) {
rnd = (Math.random() * 3);
} else if (stat >= 65 && stat < 90) {
rnd = (Math.random() * 2);
} else if (stat >= 90 && stat < 99) {
rnd = 0.5;
}
return Math.round((stat + rnd) * 100) / 100;
}
};
if(params) {
angular.extend(settings, params);
}
var intervalCont = (function () {
var interval = null;
return {
increment: function () {
progressBarManager.set(settings.incrementStrategy(lastVal));
},
setInterval: function () {
var self = this;
if (requiredClear) {
requiredClear = false;
progressBarManager.clear();
}
if (!interval) {
interval = setInterval(function () {
self.increment();
}, settings.incrementSpeed);
}
},
clearInterval: function () {
clearInterval(interval);
interval = null;
},
isInProgress: function () {
return !!interval;
}
};
}());
var progressBarManager = {
_getDefer: function () {
return deferred;
},
_updateDefer: function () {
deferred = $q.defer();
instance = null;
deferred.promise.then(function (data) {
instance = data;
instance.set(lastVal);
instance.setAnimation(animation);
});
},
_updateValue: function (val) {
lastVal = val;
},
getPromise: function () {
return deferred.promise;
},
set: function (val) {
//Checking value is number and not NaN
if (typeof val !== 'number' || val !== val) {
throw new Error("Wrong value");
}
if (val < 0) {
val = 0;
}
if (val > 100) {
val = 100;
}
lastVal = val;
//huck if need to clear before new set
if (requiredClear) {
requiredClear = false;
this.clear(val);
return this;
} else {
if (instance) {
instance.set(lastVal);
}
}
return this;
},
get: function () {
return lastVal;
},
isInProgress: function () {
return intervalCont.isInProgress();
},
increase: function (value) {
if(typeof value === 'number' && value === value){
this.set(lastVal + value);
}else{
intervalCont.increment();
}
return this;
},
start: function () {
intervalCont.setInterval();
return this;
},
stop: function () {
intervalCont.clearInterval();
return this;
},
done: function () {
this.stop();
this.set(100);
requiredClear = true;
return this;
},
reset: function () {
this.stop();
this.set(0);
return this;
},
clear: function (val) {
var animationVal = this.isAnimated();
var self = this;
this.stop();
this.setAnimation(false);
this.reset();
var deferred = $q.defer();
requestAnimationFrame(function () {
self.setAnimation(animationVal);
deferred.resolve();
});
deferred.promise.then(function () {
if(val !== undefined) {
self.set(val);
}
});
return this;
},
setAnimation: function (val) {
animation = !!val;
deferred.promise.then(function (data) {
data.setAnimation(animation);
});
return this;
},
isAnimated: function () {
return animation;
}
};
progressBarManager._updateDefer(0);
return progressBarManager;
}
}]);
}());