You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
6.7 KiB

  1. /*!
  2. * Angular Material Design
  3. * https://github.com/angular/material
  4. * @license MIT
  5. * v1.1.1
  6. */
  7. (function( window, angular, undefined ){
  8. "use strict";
  9. /**
  10. * @ngdoc module
  11. * @name material.components.progressLinear
  12. * @description Linear Progress module!
  13. */
  14. MdProgressLinearDirective.$inject = ["$mdTheming", "$mdUtil", "$log"];
  15. angular.module('material.components.progressLinear', [
  16. 'material.core'
  17. ])
  18. .directive('mdProgressLinear', MdProgressLinearDirective);
  19. /**
  20. * @ngdoc directive
  21. * @name mdProgressLinear
  22. * @module material.components.progressLinear
  23. * @restrict E
  24. *
  25. * @description
  26. * The linear progress directive is used to make loading content
  27. * in your app as delightful and painless as possible by minimizing
  28. * the amount of visual change a user sees before they can view
  29. * and interact with content.
  30. *
  31. * Each operation should only be represented by one activity indicator
  32. * For example: one refresh operation should not display both a
  33. * refresh bar and an activity circle.
  34. *
  35. * For operations where the percentage of the operation completed
  36. * can be determined, use a determinate indicator. They give users
  37. * a quick sense of how long an operation will take.
  38. *
  39. * For operations where the user is asked to wait a moment while
  40. * something finishes up, and its not necessary to expose what's
  41. * happening behind the scenes and how long it will take, use an
  42. * indeterminate indicator.
  43. *
  44. * @param {string} md-mode Select from one of four modes: determinate, indeterminate, buffer or query.
  45. *
  46. * Note: if the `md-mode` value is set as undefined or specified as 1 of the four (4) valid modes, then `indeterminate`
  47. * will be auto-applied as the mode.
  48. *
  49. * Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute. If `value=""` is also specified, however,
  50. * then `md-mode="determinate"` would be auto-injected instead.
  51. * @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0
  52. * @param {number=} md-buffer-value In the buffer mode, this number represents the percentage of the secondary progress bar. Default: 0
  53. * @param {boolean=} ng-disabled Determines whether to disable the progress element.
  54. *
  55. * @usage
  56. * <hljs lang="html">
  57. * <md-progress-linear md-mode="determinate" value="..."></md-progress-linear>
  58. *
  59. * <md-progress-linear md-mode="determinate" ng-value="..."></md-progress-linear>
  60. *
  61. * <md-progress-linear md-mode="indeterminate"></md-progress-linear>
  62. *
  63. * <md-progress-linear md-mode="buffer" value="..." md-buffer-value="..."></md-progress-linear>
  64. *
  65. * <md-progress-linear md-mode="query"></md-progress-linear>
  66. * </hljs>
  67. */
  68. function MdProgressLinearDirective($mdTheming, $mdUtil, $log) {
  69. var MODE_DETERMINATE = "determinate";
  70. var MODE_INDETERMINATE = "indeterminate";
  71. var MODE_BUFFER = "buffer";
  72. var MODE_QUERY = "query";
  73. var DISABLED_CLASS = "_md-progress-linear-disabled";
  74. return {
  75. restrict: 'E',
  76. template: '<div class="md-container">' +
  77. '<div class="md-dashed"></div>' +
  78. '<div class="md-bar md-bar1"></div>' +
  79. '<div class="md-bar md-bar2"></div>' +
  80. '</div>',
  81. compile: compile
  82. };
  83. function compile(tElement, tAttrs, transclude) {
  84. tElement.attr('aria-valuemin', 0);
  85. tElement.attr('aria-valuemax', 100);
  86. tElement.attr('role', 'progressbar');
  87. return postLink;
  88. }
  89. function postLink(scope, element, attr) {
  90. $mdTheming(element);
  91. var lastMode;
  92. var isDisabled = attr.hasOwnProperty('disabled');
  93. var toVendorCSS = $mdUtil.dom.animator.toCss;
  94. var bar1 = angular.element(element[0].querySelector('.md-bar1'));
  95. var bar2 = angular.element(element[0].querySelector('.md-bar2'));
  96. var container = angular.element(element[0].querySelector('.md-container'));
  97. element
  98. .attr('md-mode', mode())
  99. .toggleClass(DISABLED_CLASS, isDisabled);
  100. validateMode();
  101. watchAttributes();
  102. /**
  103. * Watch the value, md-buffer-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. if (mode() != MODE_QUERY) animateIndicator(bar2, percentValue);
  110. });
  111. attr.$observe('mdBufferValue', function(value) {
  112. animateIndicator(bar1, clamp(value));
  113. });
  114. attr.$observe('disabled', function(value) {
  115. if (value === true || value === false) {
  116. isDisabled = !!value;
  117. } else {
  118. isDisabled = angular.isDefined(value);
  119. }
  120. element.toggleClass(DISABLED_CLASS, isDisabled);
  121. container.toggleClass(lastMode, !isDisabled);
  122. });
  123. attr.$observe('mdMode', function(mode) {
  124. if (lastMode) container.removeClass( lastMode );
  125. switch( mode ) {
  126. case MODE_QUERY:
  127. case MODE_BUFFER:
  128. case MODE_DETERMINATE:
  129. case MODE_INDETERMINATE:
  130. container.addClass( lastMode = "md-mode-" + mode );
  131. break;
  132. default:
  133. container.addClass( lastMode = "md-mode-" + MODE_INDETERMINATE );
  134. break;
  135. }
  136. });
  137. }
  138. /**
  139. * Auto-defaults the mode to either `determinate` or `indeterminate` mode; if not specified
  140. */
  141. function validateMode() {
  142. if ( angular.isUndefined(attr.mdMode) ) {
  143. var hasValue = angular.isDefined(attr.value);
  144. var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE;
  145. var info = "Auto-adding the missing md-mode='{0}' to the ProgressLinear element";
  146. //$log.debug( $mdUtil.supplant(info, [mode]) );
  147. element.attr("md-mode", mode);
  148. attr.mdMode = mode;
  149. }
  150. }
  151. /**
  152. * Is the md-mode a valid option?
  153. */
  154. function mode() {
  155. var value = (attr.mdMode || "").trim();
  156. if ( value ) {
  157. switch(value) {
  158. case MODE_DETERMINATE:
  159. case MODE_INDETERMINATE:
  160. case MODE_BUFFER:
  161. case MODE_QUERY:
  162. break;
  163. default:
  164. value = MODE_INDETERMINATE;
  165. break;
  166. }
  167. }
  168. return value;
  169. }
  170. /**
  171. * Manually set CSS to animate the Determinate indicator based on the specified
  172. * percentage value (0-100).
  173. */
  174. function animateIndicator(target, value) {
  175. if ( isDisabled || !mode() ) return;
  176. var to = $mdUtil.supplant("translateX({0}%) scale({1},1)", [ (value-100)/2, value/100 ]);
  177. var styles = toVendorCSS({ transform : to });
  178. angular.element(target).css( styles );
  179. }
  180. }
  181. /**
  182. * Clamps the value to be between 0 and 100.
  183. * @param {number} value The value to clamp.
  184. * @returns {number}
  185. */
  186. function clamp(value) {
  187. return Math.max(0, Math.min(value || 0, 100));
  188. }
  189. }
  190. })(window, window.angular);