Skip to content

Commit

Permalink
fix(progressLinear, progressCircular): sync logic, fix linear animati…
Browse files Browse the repository at this point in the history
…ons, 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.
  • Loading branch information
ThomasBurleson committed Sep 3, 2015
1 parent ffbcff3 commit d74f93a
Show file tree
Hide file tree
Showing 13 changed files with 654 additions and 258 deletions.
5 changes: 2 additions & 3 deletions src/components/autocomplete/autocomplete.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,14 @@ md-autocomplete {
&.md-menu-showing {
z-index: $z-index-backdrop + 1;
}
md-progress-linear[md-mode=indeterminate] {
md-progress-linear .md-mode-indeterminate {
position: absolute;
bottom: 0; left: 0; width: 100%;
top: 20px; left: 0; width: 100%;
height: 3px;
transition: none;

.md-container {
transition: none;
top: auto;
height: 3px;
}
&.ng-enter {
Expand Down
92 changes: 54 additions & 38 deletions src/components/progressCircular/demoBasicUsage/index.html
Original file line number Diff line number Diff line change
@@ -1,43 +1,59 @@
<div ng-controller="AppCtrl as vm" layout="column" layout-margin style="padding:25px;">

<h4 style="margin-top:10px">Determinate</h4>
<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>
<div layout="row" layout-sm="column" layout-align="space-around">
<md-progress-circular md-mode="determinate" value="{{vm.determinateValue}}"></md-progress-circular>
</div>

<h4>Indeterminate</h4>
<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>
<div layout="row" layout-sm="column" layout-align="space-around">
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
</div>

<h4>Theming </h4>

<p>
Your current theme colors can be used to easily colorize your progress indicator with `md-warn` or `md-accent` colors.
To easily hide a <b>&lt;md-progress-circular&gt;</b> component, simply set the <b>md-mode</b> to "" or null.
</p>
<div layout="row" layout-sm="column" layout-align="space-around" >
<md-progress-circular class="md-hue-2" md-mode="{{vm.modes[0]}}" md-diameter="20px" ></md-progress-circular>
<md-progress-circular class="md-accent" md-mode="{{vm.modes[1]}}" md-diameter="40" ></md-progress-circular>
<md-progress-circular class="md-accent md-hue-1" md-mode="{{vm.modes[2]}}" md-diameter="60" ></md-progress-circular>
<md-progress-circular class="md-warn md-hue-3" md-mode="{{vm.modes[3]}}" md-diameter="70"></md-progress-circular>
<md-progress-circular md-mode="{{vm.modes[4]}}" md-diameter="96"></md-progress-circular>
</div>

<div layout="row" id="loaders">

<p style="margin-right: 20px">Show Progress Circular Indicators: </p>

<h5>Off</h5>
<md-switch
ng-model="vm.activated"
ng-change="vm.toggleActivation()"
aria-label="Toggle Progress Circular Indicators">
<h5>On</h5>
</md-switch>
</div>
<h4 style="margin-top:10px">Determinate</h4>

<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>

<div layout="row" layout-sm="column" layout-align="space-around">
<md-progress-circular md-mode="determinate" value="{{vm.determinateValue}}"></md-progress-circular>
</div>

<h4>Indeterminate</h4>

<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>

<div layout="row" layout-sm="column" layout-align="space-around">
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
</div>

<h4>Theming </h4>

<p>
Your current theme colors can be used to easily colorize your progress indicator with `md-warn` or `md-accent`
colors.
To easily hide a <b>&lt;md-progress-circular&gt;</b> component, simply set the <b>md-mode</b> to "" or null.
</p>

<div layout="row" layout-sm="column" layout-align="space-around">
<md-progress-circular class="md-hue-2" md-mode="{{vm.modes[0]}}" md-diameter="20px"></md-progress-circular>
<md-progress-circular class="md-accent" md-mode="{{vm.modes[1]}}" md-diameter="40"></md-progress-circular>
<md-progress-circular class="md-accent md-hue-1" md-mode="{{vm.modes[2]}}" md-diameter="60"></md-progress-circular>
<md-progress-circular class="md-warn md-hue-3" md-mode="{{vm.modes[3]}}" md-diameter="70"></md-progress-circular>
<md-progress-circular md-mode="{{vm.modes[4]}}" md-diameter="96"></md-progress-circular>
</div>


<hr ng-class="{'visible' : vm.activated}">

<div layout="row" id="loaders">

<p>Progress Circular Indicators: </p>

<h5>Off</h5>
<md-switch
ng-model="vm.activated"
ng-change="vm.toggleActivation()"
aria-label="Toggle Progress Circular Indicators">
<h5>On</h5>
</md-switch>
</div>

<p class="small">
Note: With above switch -- that simply clears the md-mode in each <code>&lt;md-progress-linear md-mode=""&gt;</code>
element --
developers can easily disable the animations and hide their progress indicators.
</p>

</div>
26 changes: 26 additions & 0 deletions src/components/progressCircular/demoBasicUsage/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,29 @@ md-progress-circular {
#loaders > h5 {
padding-top: 8px;
}

#loaders > p {
margin-right: 20px;
}


p.small {
font-size: 0.8em;
margin-top: -18px;
}


hr {
width: 100%;
margin-top: 20px;
border-color: rgba(221, 221, 177, 0.1);
}

p.small > code {
font-size: 0.8em;
}


.visible {
border-color: rgba(221, 221, 177, 0);
}
114 changes: 82 additions & 32 deletions src/components/progressCircular/progress-circular.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ angular.module('material.components.progressCircular', [
* not necessary to expose what's happening behind the scenes and how long it will take, use an
* indeterminate indicator.
*
* @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**.<br/>
* Note: if the `md-mode` value is undefined or not 1 of the two (2) valid modes, then `.ng-hide`
* @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**.
*
* Note: if the `md-mode` value is set as undefined or specified as not 1 of the two (2) valid modes, then `.ng-hide`
* will be auto-applied as a style to the component.
*
* Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute.
* If `value=""` is also specified, however, then `md-mode="determinate"` would be auto-injected instead.
* @param {number=} value In determinate mode, this number represents the percentage of the
* circular progress. Default: 0
* @param {number=} md-diameter This specifies the diamter of the circular progress. The value
Expand All @@ -46,7 +50,7 @@ angular.module('material.components.progressCircular', [
* <md-progress-circular md-mode="indeterminate"></md-progress-circular>
* </hljs>
*/
function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
function MdProgressCircularDirective($mdTheming, $mdUtil, $log) {
var DEFAULT_PROGRESS_SIZE = 100;
var DEFAULT_SCALING = 0.5;

Expand Down Expand Up @@ -87,43 +91,68 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
function postLink(scope, element, attr) {
$mdTheming(element);

var circle = element[0];
var circle = element;
var spinnerWrapper = angular.element(element.children()[0]);

var lastMode, toVendorCSS = $mdUtil.dom.animator.toCss;

// Update size/scaling of the progress indicator
// Watch the "value" and "md-mode" attributes
updateScale();
validateMode();
watchAttributes();

circle.style[$mdConstant.CSS.TRANSFORM] = 'scale(' + getDiameterRatio() + ')';

attr.$observe('value', function(value) {
var percentValue = clamp(value);
element.attr('aria-valuenow', percentValue);

if (attr.mdMode == "determinate") {
animateIndicator(percentValue);
}
});
/**
* Watch the value and md-mode attributes
*/
function watchAttributes() {
attr.$observe('value', function(value) {
var percentValue = clamp(value);
element.attr('aria-valuenow', percentValue);

if (mode() == MODE_DETERMINATE) {
animateIndicator(percentValue);
}
});
attr.$observe('mdMode',function(mode){
switch( mode ) {
case MODE_DETERMINATE:
case MODE_INDETERMINATE:
spinnerWrapper.removeClass('ng-hide');
spinnerWrapper.removeClass( lastMode );
spinnerWrapper.addClass( lastMode = "md-mode-" + mode );
break;
default:
spinnerWrapper.removeClass( lastMode );
spinnerWrapper.addClass('ng-hide');
lastMode = undefined;
break;
}
});
}

attr.$observe('mdMode',function(mode){
switch( mode ) {
case MODE_DETERMINATE:
case MODE_INDETERMINATE:
spinnerWrapper.removeClass('ng-hide');
/**
* Update size/scaling of the progress indicator
* Watch the "value" and "md-mode" attributes
*/
function updateScale() {
circle.css(toVendorCSS({
transform : $mdUtil.supplant('scale( {0} )',[getDiameterRatio()])
}));
}

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

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

break;
default:
spinnerWrapper.addClass('ng-hide');
element.attr("md-mode",mode);
attr['mdMode'] = mode;
}
});
}

var leftC, rightC, gap;

Expand All @@ -136,6 +165,8 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
* - use attribute selectors which had poor performances in IE
*/
function animateIndicator(value) {
if ( !mode() ) return;

leftC = leftC || angular.element(element[0].querySelector('.md-left > .md-half-circle'));
rightC = rightC || angular.element(element[0].querySelector('.md-right > .md-half-circle'));
gap = gap || angular.element(element[0].querySelector('.md-gap'));
Expand All @@ -146,7 +177,7 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
}),
leftStyles = removeEmptyValues({
transition: (value <= 50) ? "transform 0.1s linear" : "",
transform: $mdUtil.supplant("rotate({0}deg)", [value <= 50 ? 135 : ((((value - 50) / 50) * 180) + 135)])
transform: $mdUtil.supplant("rotate({0}deg)", [value <= 50 ? 135 : (((value - 50) / 50 * 180) + 135)])
}),
rightStyles = removeEmptyValues({
transition: (value >= 50) ? "transform 0.1s linear" : "",
Expand Down Expand Up @@ -174,6 +205,25 @@ function MdProgressCircularDirective($mdConstant, $mdTheming, $mdUtil) {
// should return ratio; DEFAULT_PROGRESS_SIZE === 100px is default size
return (value > 1) ? value / DEFAULT_PROGRESS_SIZE : value;
}

/**
* Is the md-mode a valid option?
*/
function mode() {
var value = attr.mdMode;
if ( value ) {
switch(value) {
case MODE_DETERMINATE :
case MODE_INDETERMINATE :
break;
default:
value = undefined;
break;
}
}
return value;
}

}

/**
Expand Down
Loading

0 comments on commit d74f93a

Please sign in to comment.