diff --git a/src/components/progress-circle/progress-circle.spec.ts b/src/components/progress-circle/progress-circle.spec.ts index 9d83d11d0cbf..7a9aaf02da91 100644 --- a/src/components/progress-circle/progress-circle.spec.ts +++ b/src/components/progress-circle/progress-circle.spec.ts @@ -42,18 +42,36 @@ describe('MdProgressCircular', () => { }); }); - it('should define a default value for the value attribute', (done: () => void) => { + it('should define a default value of undefined for the value attribute', (done: () => void) => { builder .overrideTemplate(TestApp, '') .createAsync(TestApp) .then((fixture) => { fixture.detectChanges(); let progressElement = getChildDebugElement(fixture.debugElement, 'md-progress-circle'); - expect(progressElement.componentInstance.value).toBe(0); + expect(progressElement.componentInstance.value).toBeUndefined(); done(); }); }); + it('should set the value to undefined when the mode is set to indeterminate', + (done: () => void) => { + builder + .overrideTemplate(TestApp, ``) + .createAsync(TestApp) + .then((fixture) => { + let progressElement = getChildDebugElement(fixture.debugElement, 'md-progress-circle'); + fixture.debugElement.componentInstance.mode = 'determinate'; + fixture.detectChanges(); + expect(progressElement.componentInstance.value).toBe(50); + fixture.debugElement.componentInstance.mode = 'indeterminate'; + fixture.detectChanges(); + expect(progressElement.componentInstance.value).toBe(undefined); + done(); + }); + }); + it('should clamp the value of the progress between 0 and 100', (done: () => void) => { builder .overrideTemplate(TestApp, '') diff --git a/src/components/progress-circle/progress-circle.ts b/src/components/progress-circle/progress-circle.ts index 6cb6d2676ec2..2a32e005f267 100644 --- a/src/components/progress-circle/progress-circle.ts +++ b/src/components/progress-circle/progress-circle.ts @@ -35,8 +35,8 @@ type EasingFn = (currentTime: number, startValue: number, selector: 'md-progress-circle', host: { 'role': 'progressbar', - 'aria-valuemin': '0', - 'aria-valuemax': '100', + '[attr.aria-valuemin]': 'ariaValueMin', + '[attr.aria-valuemax]': 'ariaValueMax', }, templateUrl: 'progress-circle.html', styleUrls: ['progress-circle.css'], @@ -49,6 +49,22 @@ export class MdProgressCircle implements OnDestroy { /** The id of the indeterminate interval. */ private _interdeterminateInterval: number; + /** + * Values for aria max and min are only defined as numbers when in a determinate mode. We do this + * because voiceover does not report the progress indicator as indeterminate if the aria min + * and/or max value are number values. + * + * @internal + */ + get ariaValueMin() { + return this.mode == 'determinate' ? 0 : null; + } + + /** @internal */ + get ariaValueMax() { + return this.mode == 'determinate' ? 100 : null; + } + /** @internal */ get interdeterminateInterval() { return this._interdeterminateInterval; @@ -79,19 +95,21 @@ export class MdProgressCircle implements OnDestroy { /** * Value of the progress circle. * - * Input:number, defaults to 0. + * Input:number * _value is bound to the host as the attribute aria-valuenow. */ - private _value: number = 0; + private _value: number; @Input() @HostBinding('attr.aria-valuenow') get value() { - return this._value; + if (this.mode == 'determinate') { + return this._value; + } } set value(v: number) { - if (v) { + if (v && this.mode == 'determinate') { let newValue = clamp(v); - this._animateCircle(this.value, newValue, linearEase, DURATION_DETERMINATE, 0); + this._animateCircle((this.value || 0), newValue, linearEase, DURATION_DETERMINATE, 0); this._value = newValue; } } @@ -206,6 +224,7 @@ export class MdProgressCircle implements OnDestroy { selector: 'md-spinner', host: { 'role': 'progressbar', + 'mode': 'indeterminate', }, templateUrl: 'progress-circle.html', styleUrls: ['progress-circle.css'],