Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 18bfae1

Browse files
crisbetoThomasBurleson
authored andcommitted
feat(progress): add the ability to disable the progressbars
* Adds support for `ngDisabled` to the `progressCircular` and `progressLinear` components. Hides the element and stops all rendering if the element is disabled. * Fixes a potential weird appearance in `progressCircular` if the animation time goes below 0. * Adds some missing coverage for the `$mdProgressCircularProvider`. Closes #7862
1 parent bbaa5b8 commit 18bfae1

File tree

9 files changed

+130
-44
lines changed

9 files changed

+130
-44
lines changed

src/components/progressCircular/demoBasicUsage/index.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ <h4>Theming</h4>
2626
colors.
2727
</p>
2828

29-
<div ng-show="vm.activated" layout="row" layout-sm="column" layout-align="space-around">
30-
<md-progress-circular class="md-hue-2" md-diameter="20px"></md-progress-circular>
31-
<md-progress-circular class="md-accent" md-diameter="40"></md-progress-circular>
32-
<md-progress-circular class="md-accent md-hue-1" md-diameter="60"></md-progress-circular>
33-
<md-progress-circular class="md-warn md-hue-3" md-diameter="70"></md-progress-circular>
34-
<md-progress-circular md-diameter="96"></md-progress-circular>
29+
<div layout="row" layout-sm="column" layout-align="space-around">
30+
<md-progress-circular ng-disabled="!vm.activated" class="md-hue-2" md-diameter="20px"></md-progress-circular>
31+
<md-progress-circular ng-disabled="!vm.activated" class="md-accent" md-diameter="40"></md-progress-circular>
32+
<md-progress-circular ng-disabled="!vm.activated" class="md-accent md-hue-1" md-diameter="60"></md-progress-circular>
33+
<md-progress-circular ng-disabled="!vm.activated" class="md-warn md-hue-3" md-diameter="70"></md-progress-circular>
34+
<md-progress-circular ng-disabled="!vm.activated" md-diameter="96"></md-progress-circular>
3535
</div>
3636
</md-content>
3737

@@ -42,12 +42,12 @@ <h4>Dark theme</h4>
4242
This is an example of the <b>&lt;md-progress-circular&gt;</b> component, with a dark theme.
4343
</p>
4444

45-
<div ng-show="vm.activated" layout="row" layout-sm="column" layout-align="space-around">
46-
<md-progress-circular class="md-hue-2" md-diameter="20px"></md-progress-circular>
47-
<md-progress-circular class="md-accent" md-diameter="40"></md-progress-circular>
48-
<md-progress-circular class="md-accent md-hue-1" md-diameter="60"></md-progress-circular>
49-
<md-progress-circular class="md-warn md-hue-3" md-diameter="70"></md-progress-circular>
50-
<md-progress-circular md-diameter="96"></md-progress-circular>
45+
<div layout="row" layout-sm="column" layout-align="space-around">
46+
<md-progress-circular ng-disabled="!vm.activated" class="md-hue-2" md-diameter="20px"></md-progress-circular>
47+
<md-progress-circular ng-disabled="!vm.activated" class="md-accent" md-diameter="40"></md-progress-circular>
48+
<md-progress-circular ng-disabled="!vm.activated" class="md-accent md-hue-1" md-diameter="60"></md-progress-circular>
49+
<md-progress-circular ng-disabled="!vm.activated" class="md-warn md-hue-3" md-diameter="70"></md-progress-circular>
50+
<md-progress-circular ng-disabled="!vm.activated" md-diameter="96"></md-progress-circular>
5151
</div>
5252
</md-content>
5353

src/components/progressCircular/js/progressCircularDirective.js

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
* should be a pixel-size value (eg '100'). If this attribute is
3030
* not present then a default value of '50px' is assumed.
3131
*
32+
* @param {boolean=} ng-disabled Determines whether to disable the progress element.
33+
*
3234
* @usage
3335
* <hljs lang="html">
3436
* <md-progress-circular md-mode="determinate" value="..."></md-progress-circular>
@@ -52,6 +54,7 @@ function MdProgressCircularDirective($$rAF, $window, $mdProgressCircular, $mdThe
5254
var DEGREE_IN_RADIANS = $window.Math.PI / 180;
5355
var MODE_DETERMINATE = 'determinate';
5456
var MODE_INDETERMINATE = 'indeterminate';
57+
var DISABLED_CLASS = '_md-progress-circular-disabled';
5558

5659
return {
5760
restrict: 'E',
@@ -76,7 +79,7 @@ function MdProgressCircularDirective($$rAF, $window, $mdProgressCircular, $mdThe
7679
var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE;
7780
var info = "Auto-adding the missing md-mode='{0}' to the ProgressCircular element";
7881

79-
$log.debug( $mdUtil.supplant(info, [mode]) );
82+
// $log.debug( $mdUtil.supplant(info, [mode]) );
8083
attrs.$set('mdMode', mode);
8184
} else {
8285
attrs.$set('mdMode', attrs.mdMode.trim());
@@ -87,38 +90,61 @@ function MdProgressCircularDirective($$rAF, $window, $mdProgressCircular, $mdThe
8790
};
8891

8992
function MdProgressCircularLink(scope, element, attrs) {
90-
var svg = angular.element(element[0].querySelector('svg'));
91-
var path = angular.element(element[0].querySelector('path'));
93+
var node = element[0];
94+
var svg = angular.element(node.querySelector('svg'));
95+
var path = angular.element(node.querySelector('path'));
9296
var startIndeterminate = $mdProgressCircular.startIndeterminate;
9397
var endIndeterminate = $mdProgressCircular.endIndeterminate;
9498
var rotationIndeterminate = 0;
9599
var lastAnimationId = 0;
96100
var interval;
97101

98102
$mdTheming(element);
103+
element.toggleClass(DISABLED_CLASS, attrs.hasOwnProperty('disabled'));
99104

100105
// If the mode is indeterminate, it doesn't need to
101106
// wait for the next digest. It can start right away.
102107
if(scope.mdMode === MODE_INDETERMINATE){
103108
startIndeterminateAnimation();
104109
}
105110

106-
scope.$watchGroup(['value', 'mdMode'], function(newValues, oldValues) {
107-
var mode = newValues[1];
111+
scope.$watchGroup(['value', 'mdMode', function() {
112+
var isDisabled = node.disabled;
108113

109-
if (mode !== MODE_DETERMINATE && mode !== MODE_INDETERMINATE) {
110-
mode = MODE_INDETERMINATE;
111-
attrs.$set('mdMode', mode);
114+
// Sometimes the browser doesn't return a boolean, in
115+
// which case we should check whether the attribute is
116+
// present.
117+
if (isDisabled === true || isDisabled === false){
118+
return isDisabled;
112119
}
120+
return angular.isDefined(element.attr('disabled'));
113121

114-
if (mode === MODE_INDETERMINATE) {
115-
startIndeterminateAnimation();
116-
} else {
117-
var newValue = clamp(newValues[0]);
122+
}], function(newValues, oldValues) {
123+
var mode = newValues[1];
124+
var isDisabled = newValues[2];
125+
var wasDisabled = oldValues[2];
126+
127+
if (isDisabled !== wasDisabled) {
128+
element.toggleClass(DISABLED_CLASS, !!isDisabled);
129+
}
118130

131+
if (isDisabled) {
119132
cleanupIndeterminateAnimation();
120-
element.attr('aria-valuenow', newValue);
121-
renderCircle(clamp(oldValues[0]), newValue);
133+
} else {
134+
if (mode !== MODE_DETERMINATE && mode !== MODE_INDETERMINATE) {
135+
mode = MODE_INDETERMINATE;
136+
attrs.$set('mdMode', mode);
137+
}
138+
139+
if (mode === MODE_INDETERMINATE) {
140+
startIndeterminateAnimation();
141+
} else {
142+
var newValue = clamp(newValues[0]);
143+
144+
cleanupIndeterminateAnimation();
145+
element.attr('aria-valuenow', newValue);
146+
renderCircle(clamp(oldValues[0]), newValue);
147+
}
122148
}
123149

124150
});
@@ -159,7 +185,7 @@ function MdProgressCircularDirective($$rAF, $window, $mdProgressCircular, $mdThe
159185
path.attr('d', getSvgArc(animateTo, diameter, pathDiameter, rotation));
160186
} else {
161187
$$rAF(function animation(now) {
162-
var currentTime = $window.Math.min((now || $mdUtil.now()) - startTime, animationDuration);
188+
var currentTime = $window.Math.max(0, $window.Math.min((now || $mdUtil.now()) - startTime, animationDuration));
163189

164190
path.attr('d', getSvgArc(
165191
ease(currentTime, animateFrom, changeInValue, animationDuration),

src/components/progressCircular/js/progressCircularProvider.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function MdProgressCircularProvider() {
4444
var progressConfig = {
4545
progressSize: 50,
4646
strokeWidth: 10,
47-
duration: 100,
47+
duration: 1000,
4848
easeFn: linearEase,
4949

5050
durationIndeterminate: 500,

src/components/progressCircular/progress-circular.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
md-progress-circular {
33
position: relative;
44

5+
&._md-progress-circular-disabled {
6+
visibility: hidden;
7+
}
8+
59
svg {
610
position: absolute;
711
overflow: visible;

src/components/progressCircular/progress-circular.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ describe('mdProgressCircular', function() {
9898
expect(path.css('stroke-width')).toBe(diameter / ratio + 'px');
9999
});
100100

101+
it('should hide the element if is disabled', function() {
102+
var element = buildIndicator(
103+
'<md-progress-circular disabled></md-progress-circular>'
104+
);
105+
106+
expect(element.hasClass('_md-progress-circular-disabled')).toBe(true);
107+
});
108+
101109
/**
102110
* Build a progressCircular
103111
*/
@@ -109,3 +117,19 @@ describe('mdProgressCircular', function() {
109117
}
110118

111119
});
120+
121+
describe('mdProgressCircularProvider', function() {
122+
beforeEach(function() {
123+
module('material.components.progressCircular', function($mdProgressCircularProvider) {
124+
$mdProgressCircularProvider.configure({
125+
progressSize: 1337,
126+
strokeWidth: 42
127+
});
128+
});
129+
});
130+
131+
it('should allow for the default options to be configured', inject(function($mdProgressCircular) {
132+
expect($mdProgressCircular.progressSize).toBe(1337);
133+
expect($mdProgressCircular.strokeWidth).toBe(42);
134+
}));
135+
});

src/components/progressLinear/demoBasicUsage/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ <h4 class="md-title">Buffer</h4>
2626
</p>
2727
<md-progress-linear class="md-warn" md-mode="buffer" value="{{vm.determinateValue}}"
2828
md-buffer-value="{{vm.determinateValue2}}"
29-
ng-show="vm.showList[0]"></md-progress-linear>
29+
ng-disabled="!vm.showList[0]"></md-progress-linear>
3030

3131
<h4 class="md-title">Query</h4>
3232

@@ -36,7 +36,7 @@ <h4 class="md-title">Query</h4>
3636
</p>
3737

3838
<div class="container" ng-class="{'visible' : !vm.activated}">
39-
<md-progress-linear md-mode="query" ng-show="vm.showList[1]"></md-progress-linear>
39+
<md-progress-linear md-mode="query" ng-disabled="!vm.showList[1]"></md-progress-linear>
4040
<div class="bottom-block">
4141
<span>Loading application libraries...</span>
4242
</div>

src/components/progressLinear/progress-linear.js

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ angular.module('material.components.progressLinear', [
4242
* then `md-mode="determinate"` would be auto-injected instead.
4343
* @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0
4444
* @param {number=} md-buffer-value In the buffer mode, this number represents the percentage of the secondary progress bar. Default: 0
45+
* @param {boolean=} ng-disabled Determines whether to disable the progress element.
4546
*
4647
* @usage
4748
* <hljs lang="html">
@@ -57,10 +58,11 @@ angular.module('material.components.progressLinear', [
5758
* </hljs>
5859
*/
5960
function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
60-
var MODE_DETERMINATE = "determinate",
61-
MODE_INDETERMINATE = "indeterminate",
62-
MODE_BUFFER = "buffer",
63-
MODE_QUERY = "query";
61+
var MODE_DETERMINATE = "determinate";
62+
var MODE_INDETERMINATE = "indeterminate";
63+
var MODE_BUFFER = "buffer";
64+
var MODE_QUERY = "query";
65+
var DISABLED_CLASS = "_md-progress-linear-disabled";
6466

6567
return {
6668
restrict: 'E',
@@ -71,7 +73,7 @@ function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
7173
'</div>',
7274
compile: compile
7375
};
74-
76+
7577
function compile(tElement, tAttrs, transclude) {
7678
tElement.attr('aria-valuemin', 0);
7779
tElement.attr('aria-valuemax', 100);
@@ -82,12 +84,16 @@ function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
8284
function postLink(scope, element, attr) {
8385
$mdTheming(element);
8486

85-
var lastMode, toVendorCSS = $mdUtil.dom.animator.toCss;
86-
var bar1 = angular.element(element[0].querySelector('._md-bar1')),
87-
bar2 = angular.element(element[0].querySelector('._md-bar2')),
88-
container = angular.element(element[0].querySelector('._md-container'));
87+
var lastMode;
88+
var isDisabled = attr.hasOwnProperty('disabled');
89+
var toVendorCSS = $mdUtil.dom.animator.toCss;
90+
var bar1 = angular.element(element[0].querySelector('._md-bar1'));
91+
var bar2 = angular.element(element[0].querySelector('._md-bar2'));
92+
var container = angular.element(element[0].querySelector('._md-container'));
8993

90-
element.attr('md-mode', mode());
94+
element
95+
.attr('md-mode', mode())
96+
.toggleClass(DISABLED_CLASS, isDisabled);
9197

9298
validateMode();
9399
watchAttributes();
@@ -107,6 +113,16 @@ function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
107113
animateIndicator(bar1, clamp(value));
108114
});
109115

116+
attr.$observe('disabled', function(value) {
117+
if (value === true || value === false) {
118+
isDisabled = value;
119+
} else {
120+
isDisabled = angular.isDefined(value);
121+
}
122+
123+
element.toggleClass(DISABLED_CLASS, !!isDisabled);
124+
});
125+
110126
attr.$observe('mdMode',function(mode){
111127
if (lastMode) container.removeClass( lastMode );
112128

@@ -133,10 +149,10 @@ function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
133149
var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE;
134150
var info = "Auto-adding the missing md-mode='{0}' to the ProgressLinear element";
135151

136-
$log.debug( $mdUtil.supplant(info, [mode]) );
152+
//$log.debug( $mdUtil.supplant(info, [mode]) );
137153

138154
element.attr("md-mode",mode);
139-
attr['mdMode'] = mode;
155+
attr.mdMode = mode;
140156
}
141157
}
142158

@@ -165,7 +181,7 @@ function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
165181
* percentage value (0-100).
166182
*/
167183
function animateIndicator(target, value) {
168-
if ( !mode() ) return;
184+
if ( isDisabled || !mode() ) return;
169185

170186
var to = $mdUtil.supplant("translateX({0}%) scale({1},1)", [ (value-100)/2, value/100 ]);
171187
var styles = toVendorCSS({ transform : to });

src/components/progressLinear/progress-linear.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ md-progress-linear {
99
padding-top: 0 !important;
1010
margin-bottom: 0 !important;
1111

12+
&._md-progress-linear-disabled {
13+
visibility: hidden;
14+
}
15+
1216
._md-container {
1317
display:block;
1418
position: relative;
@@ -83,7 +87,8 @@ md-progress-linear {
8387
}
8488
}
8589

86-
&.ng-hide {
90+
&.ng-hide
91+
._md-progress-linear-disabled & {
8792
animation: none;
8893

8994
._md-bar1 {

src/components/progressLinear/progress-linear.spec.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,15 @@ describe('mdProgressLinear', function() {
136136

137137
expect(bar2.style[$mdConstant.CSS.TRANSFORM]).toBeFalsy();
138138
}));
139+
140+
it('should hide the element if it is disabled', inject(function($compile, $rootScope) {
141+
var element = $compile('<div>' +
142+
'<md-progress-linear value="25" disabled>' +
143+
'</md-progress-linear>' +
144+
'</div>')($rootScope);
145+
146+
var progress = element.find('md-progress-linear').eq(0);
147+
148+
expect(progress.hasClass('_md-progress-linear-disabled')).toBe(true);
149+
}));
139150
});

0 commit comments

Comments
 (0)