Skip to content

Commit 97cb36b

Browse files
ThomasBurlesonkennethcachia
authored andcommitted
fix(progressLinear, progressCircular): sync logic, fix linear animations, perf upgrades
synchronize progressLinear with similar logic used in progressCircular. * improve animation performances * watch md-mode for changes * refactor animation SCSS * enable hiding and no-animations with undefined/empty md-mode attributes * for both indicators, use `display:inline-block;` * update demos with enable switch * fix query mode * update Select to use enhanced progressCircular component * fix autocomplete styling of progress-linear.md-mode-indeterminate * auto-inject md-mode attribute if missing * use 'determinate' if value attribute is defined * otherwise use 'indeterminate' * $log.debug() notify user (via $log.debug) of injection * add API doc details regarding md-mode auto-injection * fix tests BREAKING-CHANGES Before: ```css md-progress-linear { display: block; } md-progress-circular { // display not set // position not set } ``` ```css md-progress-linear { display: block; position: relative; } md-progress-circular { display: block; position: relative; } ``` Fixes angular#4421. Fixes angular#4409. Fixes angular#2540. Fixes angular#2364. Fixes angular#1926. Fixes angular#3802. Closes angular#4454.
1 parent 6d33f91 commit 97cb36b

File tree

13 files changed

+654
-258
lines changed

13 files changed

+654
-258
lines changed

src/components/autocomplete/autocomplete.scss

+2-3
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,14 @@ md-autocomplete {
7171
&.md-menu-showing {
7272
z-index: $z-index-backdrop + 1;
7373
}
74-
md-progress-linear[md-mode=indeterminate] {
74+
md-progress-linear .md-mode-indeterminate {
7575
position: absolute;
76-
bottom: 0; left: 0; width: 100%;
76+
top: 20px; left: 0; width: 100%;
7777
height: 3px;
7878
transition: none;
7979

8080
.md-container {
8181
transition: none;
82-
top: auto;
8382
height: 3px;
8483
}
8584
&.ng-enter {
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,59 @@
11
<div ng-controller="AppCtrl as vm" layout="column" layout-margin style="padding:25px;">
22

3-
<h4 style="margin-top:10px">Determinate</h4>
4-
<p>For operations where the percentage of the operation completed can be determined, use a determinate indicator. They give users a quick sense of how long an operation will take.</p>
5-
<div layout="row" layout-sm="column" layout-align="space-around">
6-
<md-progress-circular md-mode="determinate" value="{{vm.determinateValue}}"></md-progress-circular>
7-
</div>
8-
9-
<h4>Indeterminate</h4>
10-
<p>For operations where the user is asked to wait a moment while something finishes up, and it's not necessary to expose what's happening behind the scenes and how long it will take, use an indeterminate indicator.</p>
11-
<div layout="row" layout-sm="column" layout-align="space-around">
12-
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
13-
</div>
14-
15-
<h4>Theming </h4>
16-
17-
<p>
18-
Your current theme colors can be used to easily colorize your progress indicator with `md-warn` or `md-accent` colors.
19-
To easily hide a <b>&lt;md-progress-circular&gt;</b> component, simply set the <b>md-mode</b> to "" or null.
20-
</p>
21-
<div layout="row" layout-sm="column" layout-align="space-around" >
22-
<md-progress-circular class="md-hue-2" md-mode="{{vm.modes[0]}}" md-diameter="20px" ></md-progress-circular>
23-
<md-progress-circular class="md-accent" md-mode="{{vm.modes[1]}}" md-diameter="40" ></md-progress-circular>
24-
<md-progress-circular class="md-accent md-hue-1" md-mode="{{vm.modes[2]}}" md-diameter="60" ></md-progress-circular>
25-
<md-progress-circular class="md-warn md-hue-3" md-mode="{{vm.modes[3]}}" md-diameter="70"></md-progress-circular>
26-
<md-progress-circular md-mode="{{vm.modes[4]}}" md-diameter="96"></md-progress-circular>
27-
</div>
28-
29-
<div layout="row" id="loaders">
30-
31-
<p style="margin-right: 20px">Show Progress Circular Indicators: </p>
32-
33-
<h5>Off</h5>
34-
<md-switch
35-
ng-model="vm.activated"
36-
ng-change="vm.toggleActivation()"
37-
aria-label="Toggle Progress Circular Indicators">
38-
<h5>On</h5>
39-
</md-switch>
40-
</div>
3+
<h4 style="margin-top:10px">Determinate</h4>
414

5+
<p>For operations where the percentage of the operation completed can be determined, use a determinate indicator. They
6+
give users a quick sense of how long an operation will take.</p>
7+
8+
<div layout="row" layout-sm="column" layout-align="space-around">
9+
<md-progress-circular md-mode="determinate" value="{{vm.determinateValue}}"></md-progress-circular>
10+
</div>
11+
12+
<h4>Indeterminate</h4>
13+
14+
<p>For operations where the user is asked to wait a moment while something finishes up, and it's not necessary to
15+
expose what's happening behind the scenes and how long it will take, use an indeterminate indicator.</p>
16+
17+
<div layout="row" layout-sm="column" layout-align="space-around">
18+
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
19+
</div>
20+
21+
<h4>Theming </h4>
22+
23+
<p>
24+
Your current theme colors can be used to easily colorize your progress indicator with `md-warn` or `md-accent`
25+
colors.
26+
To easily hide a <b>&lt;md-progress-circular&gt;</b> component, simply set the <b>md-mode</b> to "" or null.
27+
</p>
28+
29+
<div layout="row" layout-sm="column" layout-align="space-around">
30+
<md-progress-circular class="md-hue-2" md-mode="{{vm.modes[0]}}" md-diameter="20px"></md-progress-circular>
31+
<md-progress-circular class="md-accent" md-mode="{{vm.modes[1]}}" md-diameter="40"></md-progress-circular>
32+
<md-progress-circular class="md-accent md-hue-1" md-mode="{{vm.modes[2]}}" md-diameter="60"></md-progress-circular>
33+
<md-progress-circular class="md-warn md-hue-3" md-mode="{{vm.modes[3]}}" md-diameter="70"></md-progress-circular>
34+
<md-progress-circular md-mode="{{vm.modes[4]}}" md-diameter="96"></md-progress-circular>
35+
</div>
36+
37+
38+
<hr ng-class="{'visible' : vm.activated}">
39+
40+
<div layout="row" id="loaders">
41+
42+
<p>Progress Circular Indicators: </p>
43+
44+
<h5>Off</h5>
45+
<md-switch
46+
ng-model="vm.activated"
47+
ng-change="vm.toggleActivation()"
48+
aria-label="Toggle Progress Circular Indicators">
49+
<h5>On</h5>
50+
</md-switch>
51+
</div>
52+
53+
<p class="small">
54+
Note: With above switch -- that simply clears the md-mode in each <code>&lt;md-progress-linear md-mode=""&gt;</code>
55+
element --
56+
developers can easily disable the animations and hide their progress indicators.
57+
</p>
4258

4359
</div>

src/components/progressCircular/demoBasicUsage/style.css

+26
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,29 @@ md-progress-circular {
2020
#loaders > h5 {
2121
padding-top: 8px;
2222
}
23+
24+
#loaders > p {
25+
margin-right: 20px;
26+
}
27+
28+
29+
p.small {
30+
font-size: 0.8em;
31+
margin-top: -18px;
32+
}
33+
34+
35+
hr {
36+
width: 100%;
37+
margin-top: 20px;
38+
border-color: rgba(221, 221, 177, 0.1);
39+
}
40+
41+
p.small > code {
42+
font-size: 0.8em;
43+
}
44+
45+
46+
.visible {
47+
border-color: rgba(221, 221, 177, 0);
48+
}

src/components/progressCircular/progress-circular.js

+82-32
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ angular.module('material.components.progressCircular', [
2626
* not necessary to expose what's happening behind the scenes and how long it will take, use an
2727
* indeterminate indicator.
2828
*
29-
* @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**.<br/>
30-
* Note: if the `md-mode` value is undefined or not 1 of the two (2) valid modes, then `.ng-hide`
29+
* @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**.
30+
*
31+
* Note: if the `md-mode` value is set as undefined or specified as not 1 of the two (2) valid modes, then `.ng-hide`
3132
* will be auto-applied as a style to the component.
33+
*
34+
* Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute.
35+
* If `value=""` is also specified, however, then `md-mode="determinate"` would be auto-injected instead.
3236
* @param {number=} value In determinate mode, this number represents the percentage of the
3337
* circular progress. Default: 0
3438
* @param {number=} md-diameter This specifies the diamter of the circular progress. The value
@@ -46,7 +50,7 @@ angular.module('material.components.progressCircular', [
4650
* <md-progress-circular md-mode="indeterminate"></md-progress-circular>
4751
* </hljs>
4852
*/
49-
function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
53+
function MdProgressCircularDirective($mdTheming, $mdUtil, $log) {
5054
var DEFAULT_PROGRESS_SIZE = 100;
5155
var DEFAULT_SCALING = 0.5;
5256

@@ -87,43 +91,68 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
8791
function postLink(scope, element, attr) {
8892
$mdTheming(element);
8993

90-
var circle = element[0];
94+
var circle = element;
9195
var spinnerWrapper = angular.element(element.children()[0]);
92-
9396
var lastMode, toVendorCSS = $mdUtil.dom.animator.toCss;
9497

95-
// Update size/scaling of the progress indicator
96-
// Watch the "value" and "md-mode" attributes
98+
updateScale();
99+
validateMode();
100+
watchAttributes();
97101

98-
circle.style[$mdConstant.CSS.TRANSFORM] = 'scale(' + getDiameterRatio() + ')';
99-
100-
attr.$observe('value', function(value) {
101-
var percentValue = clamp(value);
102-
element.attr('aria-valuenow', percentValue);
103-
104-
if (attr.mdMode == "determinate") {
105-
animateIndicator(percentValue);
106-
}
107-
});
102+
/**
103+
* Watch the value and md-mode attributes
104+
*/
105+
function watchAttributes() {
106+
attr.$observe('value', function(value) {
107+
var percentValue = clamp(value);
108+
element.attr('aria-valuenow', percentValue);
109+
110+
if (mode() == MODE_DETERMINATE) {
111+
animateIndicator(percentValue);
112+
}
113+
});
114+
attr.$observe('mdMode',function(mode){
115+
switch( mode ) {
116+
case MODE_DETERMINATE:
117+
case MODE_INDETERMINATE:
118+
spinnerWrapper.removeClass('ng-hide');
119+
spinnerWrapper.removeClass( lastMode );
120+
spinnerWrapper.addClass( lastMode = "md-mode-" + mode );
121+
break;
122+
default:
123+
spinnerWrapper.removeClass( lastMode );
124+
spinnerWrapper.addClass('ng-hide');
125+
lastMode = undefined;
126+
break;
127+
}
128+
});
129+
}
108130

109-
attr.$observe('mdMode',function(mode){
110-
switch( mode ) {
111-
case MODE_DETERMINATE:
112-
case MODE_INDETERMINATE:
113-
spinnerWrapper.removeClass('ng-hide');
131+
/**
132+
* Update size/scaling of the progress indicator
133+
* Watch the "value" and "md-mode" attributes
134+
*/
135+
function updateScale() {
136+
circle.css(toVendorCSS({
137+
transform : $mdUtil.supplant('scale( {0} )',[getDiameterRatio()])
138+
}));
139+
}
114140

115-
// Inject class selector instead of attribute selector
116-
// (@see layout.js changes for IE performance issues)
141+
/**
142+
* Auto-defaults the mode to either `determinate` or `indeterminate` mode; if not specified
143+
*/
144+
function validateMode() {
145+
if ( angular.isUndefined(attr.mdMode) ) {
146+
var hasValue = angular.isDefined(attr.value);
147+
var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE;
148+
var info = "Auto-adding the missing md-mode='{0}' to the ProgressCircular element";
117149

118-
if ( lastMode ) spinnerWrapper.removeClass( lastMode );
119-
lastMode = "md-mode-" + mode;
120-
if ( lastMode ) spinnerWrapper.addClass( lastMode );
150+
$log.debug( $mdUtil.supplant(info, [mode]) );
121151

122-
break;
123-
default:
124-
spinnerWrapper.addClass('ng-hide');
152+
element.attr("md-mode",mode);
153+
attr['mdMode'] = mode;
125154
}
126-
});
155+
}
127156

128157
var leftC, rightC, gap;
129158

@@ -136,6 +165,8 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
136165
* - use attribute selectors which had poor performances in IE
137166
*/
138167
function animateIndicator(value) {
168+
if ( !mode() ) return;
169+
139170
leftC = leftC || angular.element(element[0].querySelector('.md-left > .md-half-circle'));
140171
rightC = rightC || angular.element(element[0].querySelector('.md-right > .md-half-circle'));
141172
gap = gap || angular.element(element[0].querySelector('.md-gap'));
@@ -146,7 +177,7 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
146177
}),
147178
leftStyles = removeEmptyValues({
148179
transition: (value <= 50) ? "transform 0.1s linear" : "",
149-
transform: $mdUtil.supplant("rotate({0}deg)", [value <= 50 ? 135 : ((((value - 50) / 50) * 180) + 135)])
180+
transform: $mdUtil.supplant("rotate({0}deg)", [value <= 50 ? 135 : (((value - 50) / 50 * 180) + 135)])
150181
}),
151182
rightStyles = removeEmptyValues({
152183
transition: (value >= 50) ? "transform 0.1s linear" : "",
@@ -174,6 +205,25 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
174205
// should return ratio; DEFAULT_PROGRESS_SIZE === 100px is default size
175206
return (value > 1) ? value / DEFAULT_PROGRESS_SIZE : value;
176207
}
208+
209+
/**
210+
* Is the md-mode a valid option?
211+
*/
212+
function mode() {
213+
var value = attr.mdMode;
214+
if ( value ) {
215+
switch(value) {
216+
case MODE_DETERMINATE :
217+
case MODE_INDETERMINATE :
218+
break;
219+
default:
220+
value = undefined;
221+
break;
222+
}
223+
}
224+
return value;
225+
}
226+
177227
}
178228

179229
/**

0 commit comments

Comments
 (0)