From 5cb8badde09e1f0426f28525215f60e6c9f6ae0e Mon Sep 17 00:00:00 2001 From: Justin DuJardin Date: Sun, 27 Dec 2015 10:58:54 -0800 Subject: [PATCH] feat(progress_linear): support buffer and query indicators and add tests --- examples/app.scss | 2 +- .../progress_linear/basic_usage.html | 27 +-- .../progress_linear/basic_usage.scss | 50 ++++++ .../components/progress_linear/basic_usage.ts | 47 +----- .../progress_linear/progress_linear.scss | 55 +++--- .../progress_linear/progress_linear.ts | 17 +- ng2-material/core/style/default-theme.scss | 2 +- .../progress_linear/progress_linear_spec.ts | 157 ++++++++++++++++++ 8 files changed, 265 insertions(+), 92 deletions(-) create mode 100644 examples/components/progress_linear/basic_usage.scss create mode 100644 test/components/progress_linear/progress_linear_spec.ts diff --git a/examples/app.scss b/examples/app.scss index ff7f3c4f..694a9ac4 100644 --- a/examples/app.scss +++ b/examples/app.scss @@ -6,8 +6,8 @@ $md-font-url: '../public/font/'; demos-app { md-content { + max-width: 800px; > section { - max-width: 800px; > h1 { margin-top: rem(6); margin-bottom: rem(6); diff --git a/examples/components/progress_linear/basic_usage.html b/examples/components/progress_linear/basic_usage.html index b876c399..fba86fb1 100644 --- a/examples/components/progress_linear/basic_usage.html +++ b/examples/components/progress_linear/basic_usage.html @@ -24,8 +24,8 @@

Buffer

For operations where the user wants to indicate some activity or loading from the server, use the buffer indicator:

- +

Query

@@ -34,30 +34,17 @@

Query

use the query indicator:

-
- +
+
Loading application libraries...
-
- -
- -

Query and Buffer progress linear indicators:

- - -
{{ activated ? 'On' : 'Off' }}
-
-
+

- Note: With the above switch -- which simply clears the mode in each <md-progress-linear - md-mode=""> element -- - developers now easily disable the animations and hide their progress indicators.

+ Hide indicators by adding a hidden attribute, or by binding to a dynamic value [hidden]="yourValue" +

diff --git a/examples/components/progress_linear/basic_usage.scss b/examples/components/progress_linear/basic_usage.scss new file mode 100644 index 00000000..9ca42d2e --- /dev/null +++ b/examples/components/progress_linear/basic_usage.scss @@ -0,0 +1,50 @@ +@import "../../../ng2-material/core/style/variables"; +@import "../../../ng2-material/core/style/theme-functions"; +@import "../../../ng2-material/core/style/default-theme"; + +body { + padding: 20px; +} + +h4 { + margin: 10px 0; +} + +md-progress-linear:not([mode=query]) { + padding-top: 10px; + margin-bottom: 20px; +} + +p.small > code { + font-size: 0.8em; +} + +.visible { + opacity: 0; + border: 2px solid white !important; +} + +.container { + display: block; + position: relative; + height: 100%; + width: 100%; + border: 2px solid md-color($md-primary, 100); + transition: opacity 0.1s linear; + border-top: 0px; +} + +.bottom-block { + display: block; + position: relative; + background-color: rgba(255, 235, 169, 0.25); + height: 85px; + width: 100%; +} + +.bottom-block > span { + display: inline-block; + margin-top: 10px; + padding: 25px; + font-size: 0.9em; +} diff --git a/examples/components/progress_linear/basic_usage.ts b/examples/components/progress_linear/basic_usage.ts index c0f2a4e9..9ce93539 100644 --- a/examples/components/progress_linear/basic_usage.ts +++ b/examples/components/progress_linear/basic_usage.ts @@ -2,17 +2,15 @@ import {View, Component} from 'angular2/core'; import {MATERIAL_DIRECTIVES} from 'ng2-material/all'; @Component({selector: 'progress-linear-basic-usage'}) -@View({templateUrl: 'examples/components/progress_linear/basic_usage.html', directives: [MATERIAL_DIRECTIVES]}) +@View({ + templateUrl: 'examples/components/progress_linear/basic_usage.html', + styleUrls: ['examples/components/progress_linear/basic_usage.css'], + directives: [MATERIAL_DIRECTIVES] +}) export default class ProgressLinearBasicUsage { - public modes: string[] = []; - public mode: string = 'query'; - public activated: boolean = true; public determinateValue: number = 30; public determinateValue2: number = 30; - private _counter: number = 0; - private _j: number = 0; - constructor() { // Iterate every 100ms, non-stop @@ -26,42 +24,7 @@ export default class ProgressLinearBasicUsage { if (this.determinateValue2 > 100) { this.determinateValue2 = 30; } - - // Incrementally start animation the five (5) Indeterminate, - // themed progress circular bars - - if ((this._j < 2) && !this.modes[this._j] && this.activated) { - this.modes[this._j] = (this._j === 0) ? 'buffer' : 'query'; - } - if (this._counter++ % 4 === 0) { - this._j++; - } - - // Show the indicator in the "Used within Containers" after 200ms delay - if (this._j === 2) { - this.mode = 'indeterminate'; - } }, 100, 0, true); - - setInterval(() => { - this.mode = (this.mode === 'query' ? 'determinate' : 'query'); - }, 7200, 0, true); - } - /** - * Turn off or on the 5 themed loaders - */ - toggleActivation() { - if (!this.activated) { - this.modes = [null,null,null,null,null]; - } - if (this.activated) { - this._j = this._counter = 0; - this.determinateValue = 30; - this.determinateValue2 = 30; - } - this.activated = !this.activated; - }; - } diff --git a/ng2-material/components/progress_linear/progress_linear.scss b/ng2-material/components/progress_linear/progress_linear.scss index df109154..2ea5b1c1 100644 --- a/ng2-material/components/progress_linear/progress_linear.scss +++ b/ng2-material/components/progress_linear/progress_linear.scss @@ -1,5 +1,4 @@ @import "../../core/style/variables"; - // TODO(jelbourn): This goes away. @import "../../core/style/default-theme"; @@ -10,6 +9,10 @@ md-progress-linear { width: 100%; height: $progress-linear-bar-height; + &[hidden] { + display: none; + } + *, *:before { box-sizing: border-box; } @@ -18,7 +21,7 @@ md-progress-linear { overflow: hidden; position: relative; height: $progress-linear-bar-height; - top: $progress-linear-bar-height; + //top: $progress-linear-bar-height; transform: translate(0, 5px) scale(1, 0); transition: all .3s linear; } @@ -37,13 +40,13 @@ md-progress-linear { transition: all 0.2s linear; } - &[mode="determinate"] { + &[mode=determinate] { .md-progress-linear-bar1 { display: none; } } - &[mode="indeterminate"] { + &[mode=indeterminate] { .md-progress-linear-bar1 { animation: indeterminate1 4s infinite linear; } @@ -53,7 +56,7 @@ md-progress-linear { } } - &[mode="buffer"] { + &[mode=buffer] { .md-progress-linear-container { background-color: transparent !important; } @@ -72,7 +75,10 @@ md-progress-linear { } } - &[mode="query"] { + &[mode=query] { + .md-progress-linear-bar1 { + display: none; + } .md-progress-linear-bar2 { animation: query .8s infinite cubic-bezier(0.390, 0.575, 0.565, 1.000); } @@ -152,7 +158,7 @@ md-progress-linear { 0% { transform: translateX(-50%) scale(0, 1); } - 25.99%{ + 25.99% { transform: translateX(-50%) scale(0, 1); } 28% { @@ -209,35 +215,42 @@ md-progress-linear { } } - // THEME md-progress-linear { .md-progress-linear-container { background-color: md-color($md-primary, 100); } - .md-progress-linear-bar { background-color: md-color($md-primary); } - &.md-warn .md-progress-linear-container { - background-color: md-color($md-warn, 100); - } - - &.md-warn .md-progress-linear-bar { - background-color: md-color($md-warn); - } - - &.md-accent .md-progress-linear-container { - background-color: md-color($md-accent, 100); + &.md-warn { + .md-progress-linear-container { + background-color: md-color($md-warn, 100); + } + .md-progress-linear-bar { + background-color: md-color($md-warn); + } } - &.md-accent .md-progress-linear-bar { - background-color: md-color($md-accent); + &.md-accent { + .md-progress-linear-container { + background-color: md-color($md-accent, 100); + } + .md-progress-linear-bar { + background-color: md-color($md-accent); + } } &[mode=buffer] { + background-color: transparent !important; + transition: all 0.2s linear; + .md-progress-linear-display:before { + display: block; + animation: buffer 3s infinite linear; + } + &.md-primary { .md-progress-linear-bar1 { background-color: md-color($md-primary, 100); diff --git a/ng2-material/components/progress_linear/progress_linear.ts b/ng2-material/components/progress_linear/progress_linear.ts index 5162607d..4a4a5baf 100644 --- a/ng2-material/components/progress_linear/progress_linear.ts +++ b/ng2-material/components/progress_linear/progress_linear.ts @@ -6,7 +6,7 @@ import {Input} from 'angular2/core'; /** Different display / behavior modes for progress_linear. */ @CONST() -class ProgressMode { +export class ProgressMode { @CONST() static DETERMINATE = 'determinate'; @CONST() static INDETERMINATE = 'indeterminate'; @CONST() static BUFFER = 'buffer'; @@ -15,12 +15,13 @@ class ProgressMode { @Component({ selector: 'md-progress-linear', - inputs: ['value', 'bufferValue'], + inputs: ['value', 'bufferValue', 'mode'], host: { 'role': 'progressbar', 'aria-valuemin': '0', 'aria-valuemax': '100', - '[attr.aria-valuenow]': 'value' + '[attr.aria-valuenow]': 'value', + '[attr.mode]': 'mode' } }) @View({ @@ -76,15 +77,17 @@ export class MdProgressLinear implements OnChanges { ngOnChanges(_) { // If the mode does not use a value, or if there is no value, do nothing. - if (this.mode === ProgressMode.QUERY || this.mode === ProgressMode.INDETERMINATE || - isBlank(this.value)) { + if (this.mode === ProgressMode.QUERY || this.mode === ProgressMode.INDETERMINATE) { return; } - this.primaryBarTransform = this.transformForValue(this.value); + if (!isBlank(this.value)) { + this.primaryBarTransform = this.transformForValue(this.value); + } + // The bufferValue is only used in buffer mode. - if (this.mode === ProgressMode.BUFFER) { + if (this.mode === ProgressMode.BUFFER && !isBlank(this.bufferValue)) { this.secondaryBarTransform = this.transformForValue(this.bufferValue); } } diff --git a/ng2-material/core/style/default-theme.scss b/ng2-material/core/style/default-theme.scss index 1e4009bb..77275c33 100644 --- a/ng2-material/core/style/default-theme.scss +++ b/ng2-material/core/style/default-theme.scss @@ -9,5 +9,5 @@ $md-is-dark-theme: false; $md-primary: md-palette($md-indigo, 500, 100, 700, $md-contrast-palettes); $md-accent: md-palette($md-pink, 500, 300, 700, $md-contrast-palettes); $md-background: md-palette($md-grey, 500, 0, 600, $md-contrast-palettes); -$md-warn: md-palette($md-red, 500, 300, 800, $md-contrast-palettes); +$md-warn: md-palette($md-red, 500, 100, 700, $md-contrast-palettes); $md-foreground: if($md-is-dark-theme, $md-dark-theme-foreground, $md-light-theme-foreground); diff --git a/test/components/progress_linear/progress_linear_spec.ts b/test/components/progress_linear/progress_linear_spec.ts new file mode 100644 index 00000000..71a6bd8c --- /dev/null +++ b/test/components/progress_linear/progress_linear_spec.ts @@ -0,0 +1,157 @@ +import { + AsyncTestCompleter, + TestComponentBuilder, + beforeEach, + beforeEachProviders, + describe, + expect, + inject, + it, +} from 'angular2/testing_internal'; +import {DebugElement} from 'angular2/src/core/debug/debug_element'; +import {Component, View, provide} from 'angular2/core'; +import {UrlResolver} from 'angular2/compiler'; +import {TestUrlResolver} from '../../test_url_resolver'; +import {MdTab, MdTabs} from '../../../ng2-material/components/tabs/tabs'; +import {MATERIAL_PROVIDERS} from '../../../ng2-material/all'; +import {ComponentFixture} from "angular2/testing"; +import {CORE_DIRECTIVES} from "angular2/common"; +import {findChildrenByAttribute,findChildrenByTag,findChildByTag} from "../../util"; +import {TimerWrapper} from "angular2/src/facade/async"; +import {Ink} from "../../../ng2-material/core/util/ink"; +import {MdProgressLinear, ProgressMode} from "../../../ng2-material/components/progress_linear/progress_linear"; + + +export function main() { + + interface IProgressFixture { + fixture:ComponentFixture; + progress:MdProgressLinear; + debug:DebugElement; + } + @Component({selector: 'test-app'}) + @View({ + directives: [CORE_DIRECTIVES, MdProgressLinear], + template: `` + }) + class TestComponent { + value: number = 25; + bufferValue: number = 50; + blankValue:number; + modeDeterminate:string = ProgressMode.DETERMINATE; + modeIndeterminate:string = ProgressMode.INDETERMINATE; + modeBuffer:string = ProgressMode.BUFFER; + modeQuery:string = ProgressMode.QUERY; + } + + describe('Progress Linear', () => { + let builder: TestComponentBuilder; + + function setup(template: string = null): Promise { + let prep = template === null ? + builder.createAsync(TestComponent) : + builder.overrideTemplate(TestComponent, template).createAsync(TestComponent); + return prep.then((fixture: ComponentFixture) => { + fixture.detectChanges(); + let debug = findChildByTag(fixture.debugElement, 'md-progress-linear'); + let component = debug.componentInstance; + return { + fixture: fixture, + progress: component, + debug: debug + }; + }).catch(console.error.bind(console)); + } + + beforeEachProviders(() => [ + MATERIAL_PROVIDERS, + provide(UrlResolver, {useValue: new TestUrlResolver()}), + ]); + beforeEach(inject([TestComponentBuilder], (tcb) => { + builder = tcb; + })); + + describe('md-progress-linear', () => { + + describe('value', () => { + it('should be blank until specified', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.value).toBeUndefined(); + async.done(); + }); + })); + it('should set from binding', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.value).toBe(25); + async.done(); + }); + })); + it('should do nothing with undefined value', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.value).toBeUndefined(); + async.done(); + }); + })); + + }); + + describe('mode', () => { + it('should default to determinate', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.mode).toBe(ProgressMode.DETERMINATE); + async.done(); + }); + })); + it('should set from attribute', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.mode).toBe(ProgressMode.INDETERMINATE); + async.done(); + }); + })); + it('should set from binding', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.mode).toBe(ProgressMode.QUERY); + async.done(); + }); + })); + + }); + + describe('bufferValue', () => { + it('should be blank until specified', inject([AsyncTestCompleter], (async) => { + setup(``).then((api: IProgressFixture) => { + expect(api.progress.bufferValue).toBeUndefined(); + async.done(); + }); + })); + it('should set from binding', inject([AsyncTestCompleter], (async) => { + let template = ` + ` + setup(template).then((api: IProgressFixture) => { + expect(api.progress.bufferValue).toBe(50); + async.done(); + }); + })); + it('should do nothing with undefined value', inject([AsyncTestCompleter], (async) => { + let template = ` + `; + setup(template).then((api: IProgressFixture) => { + expect(api.progress.bufferValue).toBeUndefined(); + async.done(); + }); + })); + + }); + + + }); + }); + + +} +