123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*!
- * Angular Material Design
- * https://github.com/angular/material
- * @license MIT
- * v0.11.4
- */
- (function( window, angular, undefined ){
- "use strict";
- /**
- * @ngdoc module
- * @name material.components.progressCircular
- * @description Circular Progress module!
- */
- angular.module('material.components.progressCircular', [
- 'material.core'
- ])
- .directive('mdProgressCircular', MdProgressCircularDirective);
- /**
- * @ngdoc directive
- * @name mdProgressCircular
- * @module material.components.progressCircular
- * @restrict E
- *
- * @description
- * The circular progress directive is used to make loading content in your app as delightful and
- * painless as possible by minimizing the amount of visual change a user sees before they can view
- * and interact with content.
- *
- * 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.
- *
- * 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.
- *
- * @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
- * may be a percentage (eg '25%') or a pixel-size value (eg '48'). If this attribute is
- * not present then a default value of '48px' is assumed.
- *
- * @usage
- * <hljs lang="html">
- * <md-progress-circular md-mode="determinate" value="..."></md-progress-circular>
- *
- * <md-progress-circular md-mode="determinate" ng-value="..."></md-progress-circular>
- *
- * <md-progress-circular md-mode="determinate" value="..." md-diameter="100"></md-progress-circular>
- *
- * <md-progress-circular md-mode="indeterminate"></md-progress-circular>
- * </hljs>
- */
- function MdProgressCircularDirective($mdTheming, $mdUtil, $log) {
- var DEFAULT_PROGRESS_SIZE = 100;
- var DEFAULT_SCALING = 0.5;
- var MODE_DETERMINATE = "determinate",
- MODE_INDETERMINATE = "indeterminate";
- return {
- restrict: 'E',
- scope : true,
- template:
- // The progress 'circle' is composed of two half-circles: the left side and the right
- // side. Each side has CSS applied to 'fill-in' the half-circle to the appropriate progress.
- '<div class="md-spinner-wrapper">' +
- '<div class="md-inner">' +
- '<div class="md-gap"></div>' +
- '<div class="md-left">' +
- '<div class="md-half-circle"></div>' +
- '</div>' +
- '<div class="md-right">' +
- '<div class="md-half-circle"></div>' +
- '</div>' +
- '</div>' +
- '</div>',
- compile: compile
- };
- function compile(tElement) {
- // The javascript in this file is mainly responsible for setting the correct aria attributes.
- // The animation of the progress spinner is done entirely with just CSS.
- tElement.attr('aria-valuemin', 0);
- tElement.attr('aria-valuemax', 100);
- tElement.attr('role', 'progressbar');
- return postLink;
- }
- function postLink(scope, element, attr) {
- $mdTheming(element);
- var circle = element;
- var spinnerWrapper = angular.element(element.children()[0]);
- var lastMode, toVendorCSS = $mdUtil.dom.animator.toCss;
- element.attr('md-mode', mode());
- updateScale();
- validateMode();
- watchAttributes();
- /**
- * 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;
- }
- });
- }
- /**
- * 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()])
- }));
- }
- /**
- * 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";
- $log.debug( $mdUtil.supplant(info, [mode]) );
- element.attr("md-mode",mode);
- attr['mdMode'] = mode;
- }
- }
- var leftC, rightC, gap;
- /**
- * Manually animate the Determinate indicator based on the specified
- * percentage value (0-100).
- *
- * Note: this animation was previously done using SCSS.
- * - generated 54K of styles
- * - 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'));
- var gapStyles = removeEmptyValues({
- borderBottomColor: (value <= 50) ? "transparent !important" : "",
- transition: (value <= 50) ? "" : "borderBottomColor 0.1s linear"
- }),
- leftStyles = removeEmptyValues({
- transition: (value <= 50) ? "transform 0.1s linear" : "",
- transform: $mdUtil.supplant("rotate({0}deg)", [value <= 50 ? 135 : (((value - 50) / 50 * 180) + 135)])
- }),
- rightStyles = removeEmptyValues({
- transition: (value >= 50) ? "transform 0.1s linear" : "",
- transform: $mdUtil.supplant("rotate({0}deg)", [value >= 50 ? 45 : (value / 50 * 180 - 135)])
- });
- leftC.css(toVendorCSS(leftStyles));
- rightC.css(toVendorCSS(rightStyles));
- gap.css(toVendorCSS(gapStyles));
- }
- /**
- * We will scale the progress circle based on the default diameter.
- *
- * Determine the diameter percentage (defaults to 100%)
- * May be express as float, percentage, or integer
- */
- function getDiameterRatio() {
- if ( !attr.mdDiameter ) return DEFAULT_SCALING;
- var match = /([0-9]*)%/.exec(attr.mdDiameter);
- var value = Math.max(0, (match && match[1]/100) || parseFloat(attr.mdDiameter));
- // 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 || "").trim();
- if ( value ) {
- switch(value) {
- case MODE_DETERMINATE :
- case MODE_INDETERMINATE :
- break;
- default:
- value = undefined;
- break;
- }
- }
- return value;
- }
- }
- /**
- * Clamps the value to be between 0 and 100.
- * @param {number} value The value to clamp.
- * @returns {number}
- */
- function clamp(value) {
- return Math.max(0, Math.min(value || 0, 100));
- }
- function removeEmptyValues(target) {
- for (var key in target) {
- if (target.hasOwnProperty(key)) {
- if ( target[key] == "" ) delete target[key];
- }
- }
- return target;
- }
- }
- MdProgressCircularDirective.$inject = ["$mdTheming", "$mdUtil", "$log"];
- })(window, window.angular);
|