From f87d0452453825f121773dec27f3cfd921bd9588 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Tue, 16 Sep 2014 16:05:55 -0400 Subject: [PATCH] feat(linearProgress): Add linear progress indicator This linear progress directive displays a simple, animated loading bar. There are four display modes: determinate, indeterminate, buffer and query. Closes #187. Closes #296. Closes #286. --- config/build.config.js | 1 + src/base/_mixins.scss | 1 - src/components/linearProgress/README.md | 1 + .../linearProgress/_linearProgress.scss | 238 ++++++++++++++++++ .../linearProgress/demo1/index.html | 13 + src/components/linearProgress/demo1/script.js | 19 ++ src/components/linearProgress/demo1/style.css | 3 + .../linearProgress/linearProgress.js | 84 +++++++ .../linearProgress/linearProgress.spec.js | 4 + src/components/linearProgress/module.json | 10 + src/main.scss | 3 +- 11 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 src/components/linearProgress/README.md create mode 100644 src/components/linearProgress/_linearProgress.scss create mode 100644 src/components/linearProgress/demo1/index.html create mode 100644 src/components/linearProgress/demo1/script.js create mode 100644 src/components/linearProgress/demo1/style.css create mode 100644 src/components/linearProgress/linearProgress.js create mode 100644 src/components/linearProgress/linearProgress.spec.js create mode 100644 src/components/linearProgress/module.json diff --git a/config/build.config.js b/config/build.config.js index 1f187072bb7..f6ad91f31f4 100644 --- a/config/build.config.js +++ b/config/build.config.js @@ -92,6 +92,7 @@ module.exports = { 'src/components/toolbar/toolbar.js', 'src/components/whiteframe/whiteframe.js', 'src/components/divider/divider.js', + 'src/components/linearProgress/linearProgress.js', //Services 'src/services/decorators.js', diff --git a/src/base/_mixins.scss b/src/base/_mixins.scss index aeb1059f8f6..7e6db5f5cce 100644 --- a/src/base/_mixins.scss +++ b/src/base/_mixins.scss @@ -71,7 +71,6 @@ user-select: $val; } - @mixin keyframes($name) { @-webkit-keyframes #{$name} { @content; diff --git a/src/components/linearProgress/README.md b/src/components/linearProgress/README.md new file mode 100644 index 00000000000..721f395ba40 --- /dev/null +++ b/src/components/linearProgress/README.md @@ -0,0 +1 @@ +Linear progress bars, created with the `` directive. \ No newline at end of file diff --git a/src/components/linearProgress/_linearProgress.scss b/src/components/linearProgress/_linearProgress.scss new file mode 100644 index 00000000000..37f53e0d617 --- /dev/null +++ b/src/components/linearProgress/_linearProgress.scss @@ -0,0 +1,238 @@ +$bar-height:5px; + + material-linear-progress { + display: block; + width: 100%; + height: $bar-height; + + .container { + overflow: hidden; + position: relative; + height: 0; + background-color: $color-blue-100; + top: $bar-height; + @include transition(all .3s linear); + } + + .container.ready { + height: $bar-height; + top: 0; + } + + .bar { + height: $bar-height; + background-color: $color-blue-500; + position: absolute; + } + + .bar1, .bar2 { + @include transition(width 0.2s linear); + } + + &[mode=determinate] { + .bar1 { + display: none; + } + } + + &[mode=indeterminate] { + .bar1 { + left: 50%; + width: 10%; + @include animation(indeterminate1 5s infinite linear); + } + + .bar2 { + left: 0%; + width: 0%; + @include animation(indeterminate2 5s infinite linear); + } + } + + &[mode=buffer] { + .container { + background-color: transparent; + } + + .dashed:before { + content: ""; + display: block; + height: $bar-height; + width: 100%; + margin-top: 0px; + position: absolute; + background: radial-gradient(#d0d9ff 0%, #d0d9ff 20%, transparent 50%); + background-color: transparent; + background-size: 10px 10px; + background-position: 0px -23px; + @include animation(buffer 3s infinite linear); + } + + .bar1 { + background-color: $color-blue-100; + } + } + + &[mode=query] { + .bar2 { + left: 50%; + width: 10%; + @include animation(query .8s infinite cubic-bezier(0.390, 0.575, 0.565, 1.000)); + } + } +} + +@include keyframes(indeterminate1) { + 0% { + width: 0%; + left: 0%; + } + 10% { + width: 30%; + left: 100%; + } + 19.99% { + width: 30%; + left: 100%; + } + 20% { + width: 0%; + left: 0%; + } + 30% { + width: 80%; + left: 100%; + } + 30.01% { + width: 0%; + left: 0%; + } + 40% { + width: 5%; + left: 30%; + } + 50% { + width: 50%; + left: 100%; + } + 50.01% { + width: 0%; + left: 0%; + } + 60% { + width: 60%; + left: 20%; + } + 70% { + width: 5%; + left: 100%; + } + 70.01% { + width: 0%; + left: 0%; + } + 80% { + width: 50%; + left: 30%; + } + 90% { + width: 10%; + left: 80%; + } + 100% { + width: 20%; + left: 100%; + } +} + +@include keyframes(indeterminate2) { + 0% { + width: 0%; + left: 0%; + } + 10% { + width: 60%; + } + 19.99% { + width: 40%; + left: 100%; + } + 20% { + width: 0%; + left: 0%; + } + 25% { + width: 10%; + left: 10%; + } + 30% { + width: 40%; + left: 30%; + } + 40% { + width: 60%; + left: 100%; + } + 40.01% { + width: 0%; + left: 0%; + } + 50% { + width: 10%; + left: 40%; + } + 60% { + width: 30%; + left: 100%; + } + 60.01% { + width: 0%; + left: 0%; + } + 70% { + width: 10%; + left: 40%; + } + 80% { + width: 5%; + left: 100%; + } + 80.01% { + width: 0%; + left: 0%; + } + 90% { + width: 70%; + left: 10%; + } + 100% { + width: 10%; + left: 100%; + } +} + +@include keyframes(query) { + 0% { + width: 30%; + left: 70%; + } + 100% { + width: 0%; + left: 0%; + opacity: 0; + } +} + +@include keyframes(buffer) { + 0% { + opacity: 1; + background-position: 0px -23px; + } + 50% { + opacity: 0; + } + 100% { + opacity: 1; + background-position: -200px -23px; + } +} \ No newline at end of file diff --git a/src/components/linearProgress/demo1/index.html b/src/components/linearProgress/demo1/index.html new file mode 100644 index 00000000000..7eeb8c21866 --- /dev/null +++ b/src/components/linearProgress/demo1/index.html @@ -0,0 +1,13 @@ +
+

Determinate

+ + +

Indeterminate

+ + +

Buffer

+ + +

Query Indeterminate and Determinate

+ +
\ No newline at end of file diff --git a/src/components/linearProgress/demo1/script.js b/src/components/linearProgress/demo1/script.js new file mode 100644 index 00000000000..595a4c7f7a4 --- /dev/null +++ b/src/components/linearProgress/demo1/script.js @@ -0,0 +1,19 @@ +angular.module('linearProgressDemo1', ['ngMaterial']) + .controller('AppCtrl', ['$scope', '$interval', function($scope, $interval) { + $scope.mode = 'query'; + $scope.determinateValue = 30; + $scope.determinateValue2 = 30; + + $interval(function() { + $scope.determinateValue += 1; + $scope.determinateValue2 += 1.5; + if ($scope.determinateValue > 100) { + $scope.determinateValue = 30; + $scope.determinateValue2 = 30; + } + }, 100, 0, true); + + $interval(function() { + $scope.mode = ($scope.mode == 'query' ? 'determinate' : 'query'); + }, 7200, 0, true); + }]); \ No newline at end of file diff --git a/src/components/linearProgress/demo1/style.css b/src/components/linearProgress/demo1/style.css new file mode 100644 index 00000000000..76e6846d734 --- /dev/null +++ b/src/components/linearProgress/demo1/style.css @@ -0,0 +1,3 @@ +body { + padding: 20px; +} \ No newline at end of file diff --git a/src/components/linearProgress/linearProgress.js b/src/components/linearProgress/linearProgress.js new file mode 100644 index 00000000000..b89bd9fa3ee --- /dev/null +++ b/src/components/linearProgress/linearProgress.js @@ -0,0 +1,84 @@ +/** + * @ngdoc module + * @name material.components.linearProgress + * @description Linear Progress module! + */ +angular.module('material.components.linearProgress', [ + 'material.animations', + 'material.services.aria' +]) + .directive('materialLinearProgress', ['$timeout', MaterialLinearProgressDirective]); + +/** + * @ngdoc directive + * @name materialLinearProgress + * @module material.components.linearProgress + * @restrict E + * + * @description + * The linear 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. Each operation should only be represented by one activity indicator—for example, one refresh operation should not display both a refresh bar and an activity circle. + * + * 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} mode Select from one of four modes: determinate, indeterminate, buffer or query. + * @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0 + * @param {number=} secondaryValue In the buffer mode, this number represents the precentage of the secondary progress bar. Default: 0 + * + * @usage + * + * + * + * + * + * + * + * + * + * + * + */ +function MaterialLinearProgressDirective($timeout) { + return { + restrict: 'E', + template: '
' + + '
' + + '
' + + '
' + + '
', + link: function(scope, element, attr) { + var bar1 = angular.element(element[0].querySelector('.bar1')), + bar2 = angular.element(element[0].querySelector('.bar2')), + container = angular.element(element[0].querySelector('.container')); + + attr.$observe('value', function(value) { + bar2.css('width', clamp(value).toString() + '%'); + }); + + attr.$observe('secondaryvalue', function(value) { + bar1.css('width', clamp(value).toString() + '%'); + }); + + $timeout(function() { + container.addClass('ready'); + }); + } + }; +} + +// ********************************************************** +// Private Methods +// ********************************************************** + +function clamp(value) { + if (value > 100) { + return 100; + } + + if (value < 0) { + return 0; + } + + return value || 0; +} \ No newline at end of file diff --git a/src/components/linearProgress/linearProgress.spec.js b/src/components/linearProgress/linearProgress.spec.js new file mode 100644 index 00000000000..638626f8a88 --- /dev/null +++ b/src/components/linearProgress/linearProgress.spec.js @@ -0,0 +1,4 @@ +describe('materialLinearProgress', function() { + + +}); \ No newline at end of file diff --git a/src/components/linearProgress/module.json b/src/components/linearProgress/module.json new file mode 100644 index 00000000000..c42a785927e --- /dev/null +++ b/src/components/linearProgress/module.json @@ -0,0 +1,10 @@ +{ + "module": "material.components.linearProgress", + "name": "Linear Progress", + "demos": { + "demo1": { + "name": "Linear Progress Basic Usage", + "files": ["demo1/*"] + } + } +} \ No newline at end of file diff --git a/src/main.scss b/src/main.scss index 8936e05a808..ffa4a9465b7 100644 --- a/src/main.scss +++ b/src/main.scss @@ -30,4 +30,5 @@ "components/tabs/tabs", "components/list/list", "components/divider/divider", -"components/whiteframe/whiteframe"; +"components/whiteframe/whiteframe", +"components/linearProgress/linearProgress";