Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(progressbar): add max attribute & support transclusion
Browse files Browse the repository at this point in the history
 * General refactor. Move logic to controller.
 * Remove `onFull` & `onEmpty` handlers.
 * Remove automatic types and stacked types.
 * `progress` & `bar` transclude content to support text & extra elements.

BREAKING CHANGE: The onFull/onEmpty handlers & auto/stacked types have been removed.

  To migrate your code change your markup like below.

  Before:

  <progress percent="var" class="progress-warning"></progress>

  After:

  <progressbar value="var" type="warning"></progressbar>

  and for stacked instead of passing array/objects you can do:

  <progress><bar ng-repeat="obj in objs" value="obj.var" type="{{obj.type}}"></bar></progress>
  • Loading branch information
bekos committed Nov 30, 2013
1 parent d64f4a9 commit 365573a
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 394 deletions.
32 changes: 14 additions & 18 deletions src/progressbar/docs/demo.html
@@ -1,27 +1,23 @@
<div ng-controller="ProgressDemoCtrl" class="well">
<h2>Static</h2>

<h3>Static</h3>
<div class="row-fluid">
<div class="span4"><progress percent="55"></progress></div>
<div class="span4"><progress percent="22" class="progress-warning progress-striped"></progress></div>
<div class="span4"><progress percent="88" class="progress-danger progress-striped active"></div>
<div class="span4"><progressbar value="55"></progressbar></div>
<div class="span4"><progressbar class="progress-striped" value="22" type="warning">22%</progressbar></div>
<div class="span4"><progressbar class="progress-striped active" max="200" value="166" type="danger"><i>166 / 200</i></progressbar></div>
</div>

<h2>Dynamic <button class="btn btn-primary" type="button" ng-click="random()">Randomize</button></h2>
<pre>Value: {{dynamic}}</pre>
<progress percent="dynamic"></progress>

<h3>Dynamic <button class="btn btn-small btn-primary" type="button" ng-click="random()">Randomize</button></h3>
<progressbar max="max" value="dynamic"><span style="color:black; white-space:nowrap;">{{dynamic}} / {{max}}</span></progressbar>

<small><em>No animation</em></small>
<progress percent="dynamic" class="progress-success" animate="false"></progress>
<progressbar animate="false" value="dynamic" type="success"><b>{{dynamic}}%</b></progressbar>

<small><em>Object (changes type based on value)</em></small>
<progress percent="dynamicObject" class="progress-striped active"></progress>
<progressbar class="progress-striped active" value="dynamic" type="{{type}}">{{type}} <i ng-show="showWarning">!!! Watch out !!!</i></progressbar>

<h2>Stacked <button class="btn btn-primary" type="button" ng-click="randomStacked()">Randomize</button></h2>
<small><em>Array values with automatic types</em></small>
<pre>Value: {{stackedArray}}</pre>
<progress percent="stackedArray" auto-type="true"></progress>

<small><em>Objects</em></small>
<pre>Value: {{stacked}}</pre>
<progress percent="stacked"></progress>

<h3>Stacked <button class="btn btn-small btn-primary" type="button" ng-click="randomStacked()">Randomize</button></h3>
<progress><bar ng-repeat="bar in stacked" value="bar.value" type="{{bar.type}}"><span ng-hide="bar.value < 5">{{bar.value}}%</span></bar></progress>

</div>
27 changes: 11 additions & 16 deletions src/progressbar/docs/demo.js
@@ -1,7 +1,9 @@
var ProgressDemoCtrl = function ($scope) {


$scope.max = 200;

$scope.random = function() {
var value = Math.floor((Math.random()*100)+1);
var value = Math.floor((Math.random() * 100) + 1);
var type;

if (value < 25) {
Expand All @@ -14,28 +16,21 @@ var ProgressDemoCtrl = function ($scope) {
type = 'danger';
}

$scope.showWarning = (type === 'danger' || type === 'warning');

$scope.dynamic = value;
$scope.dynamicObject = {
value: value,
type: type
};
$scope.type = type;
};
$scope.random();

var types = ['success', 'info', 'warning', 'danger'];
$scope.randomStacked = function() {
$scope.stackedArray = [];
$scope.stacked = [];
var types = ['success', 'info', 'warning', 'danger'];

var n = Math.floor((Math.random()*4)+1);

for (var i=0; i < n; i++) {
var value = Math.floor((Math.random()*30)+1);
$scope.stackedArray.push(value);

var index = Math.floor((Math.random()*4));
for (var i = 0, n = Math.floor((Math.random() * 4) + 1); i < n; i++) {
var index = Math.floor((Math.random() * 4));
$scope.stacked.push({
value: value,
value: Math.floor((Math.random() * 30) + 1),
type: types[index]
});
}
Expand Down
30 changes: 28 additions & 2 deletions src/progressbar/docs/readme.md
@@ -1,3 +1,29 @@
A lightweight progress bar directive that is focused on providing progress visualization!
A progress bar directive that is focused on providing feedback on the progress of a workflow or action.

The progress bar directive supports multiple (stacked) bars into the same element, optional transition animation, event handler for full & empty state and many more.
It supports multiple (stacked) bars into the same `<progress>` element or a single `<progressbar>` elemtnt with optional `max` attribute and transition animations.

### Settings ###

#### `<progressbar>` ####

* `value` <i class="icon-eye-open"></i>
:
The current value of progress completed.

* `type`
_(Default: null)_ :
Style type. Possible values are 'success', 'warning' etc.

* `max`
_(Default: 100)_ :
A number that specifies the total value of bars that is required.

* `animate`
_(Default: true)_ :
Whether bars use transitions to achieve the width change.


### Stacked ###

Place multiple `<bars>` into the same `<progress>` element to stack them.
`<progress>` supports `max` and `animate` & `<bar>` supports `value` and `type` attributes.
138 changes: 66 additions & 72 deletions src/progressbar/progressbar.js
Expand Up @@ -2,105 +2,99 @@ angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])

.constant('progressConfig', {
animate: true,
autoType: false,
stackedTypes: ['success', 'info', 'warning', 'danger']
max: 100
})

.controller('ProgressBarController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) {
.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) {
var self = this,
bars = [],
max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max,
animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

// Whether bar transitions should be animated
var animate = angular.isDefined($attrs.animate) ? $scope.$eval($attrs.animate) : progressConfig.animate;
var autoType = angular.isDefined($attrs.autoType) ? $scope.$eval($attrs.autoType) : progressConfig.autoType;
var stackedTypes = angular.isDefined($attrs.stackedTypes) ? $scope.$eval('[' + $attrs.stackedTypes + ']') : progressConfig.stackedTypes;
this.addBar = function(bar, element) {
var oldValue = 0, index = bar.$parent.$index;
if ( angular.isDefined(index) && bars[index] ) {
oldValue = bars[index].value;
}
bars.push(bar);

this.update(element, bar.value, oldValue);

// Create bar object
this.makeBar = function(newBar, oldBar, index) {
var newValue = (angular.isObject(newBar)) ? newBar.value : (newBar || 0);
var oldValue = (angular.isObject(oldBar)) ? oldBar.value : (oldBar || 0);
var type = (angular.isObject(newBar) && angular.isDefined(newBar.type)) ? newBar.type : (autoType) ? getStackedType(index || 0) : null;
bar.$watch('value', function(value, oldValue) {
if (value !== oldValue) {
self.update(element, value, oldValue);
}
});

return {
from: oldValue,
to: newValue,
type: type,
animate: animate
};
bar.$on('$destroy', function() {
self.removeBar(bar);
});
};

function getStackedType(index) {
return stackedTypes[index];
}
// Update bar element width
this.update = function(element, newValue, oldValue) {
var percent = this.getPercentage(newValue);

if (animate) {
element.css('width', this.getPercentage(oldValue) + '%');
$transition(element, {width: percent + '%'});
} else {
element.css({'transition': 'none', 'width': percent + '%'});
}
};

this.addBar = function(bar) {
$scope.bars.push(bar);
$scope.totalPercent += bar.to;
this.removeBar = function(bar) {
bars.splice(bars.indexOf(bar), 1);
};

this.clearBars = function() {
$scope.bars = [];
$scope.totalPercent = 0;
this.getPercentage = function(value) {
return Math.round(100 * value / max);
};
this.clearBars();
}])

.directive('progress', function() {
return {
restrict: 'EA',
replace: true,
controller: 'ProgressBarController',
transclude: true,
controller: 'ProgressController',
require: 'progress',
scope: {},
template: '<div class="progress" ng-transclude></div>'
//templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2
};
})

.directive('bar', function() {
return {
restrict: 'EA',
replace: true,
transclude: true,
require: '^progress',
scope: {
value: '=percent',
onFull: '&',
onEmpty: '&'
value: '=',
type: '@'
},
templateUrl: 'template/progressbar/progress.html',
link: function(scope, element, attrs, controller) {
scope.$watch('value', function(newValue, oldValue) {
controller.clearBars();

if (angular.isArray(newValue)) {
// Stacked progress bar
for (var i=0, n=newValue.length; i < n; i++) {
controller.addBar(controller.makeBar(newValue[i], oldValue[i], i));
}
} else {
// Simple bar
controller.addBar(controller.makeBar(newValue, oldValue));
}
}, true);

// Total percent listeners
scope.$watch('totalPercent', function(value) {
if (value >= 100) {
scope.onFull();
} else if (value <= 0) {
scope.onEmpty();
}
}, true);
templateUrl: 'template/progressbar/bar.html',
link: function(scope, element, attrs, progressCtrl) {
progressCtrl.addBar(scope, element);
}
};
})

.directive('progressbar', ['$transition', function($transition) {
.directive('progressbar', function() {
return {
restrict: 'EA',
replace: true,
transclude: true,
controller: 'ProgressController',
scope: {
width: '=',
old: '=',
type: '=',
animate: '='
value: '=',
type: '@'
},
templateUrl: 'template/progressbar/bar.html',
link: function(scope, element) {
scope.$watch('width', function(value) {
if (scope.animate) {
element.css('width', scope.old + '%');
$transition(element, {width: value + '%'});
} else {
element.css('width', value + '%');
}
});
templateUrl: 'template/progressbar/progressbar.html',
link: function(scope, element, attrs, progressCtrl) {
progressCtrl.addBar(scope, angular.element(element.children()[0]));
}
};
}]);
});

0 comments on commit 365573a

Please sign in to comment.