Skip to content

Fix (slider): Update slider position and ticks when the min and max #1598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/demo-app/slider/slider-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ <h1>Default Slider</h1>
{{slidey.value}}

<h1>Slider with Min and Max</h1>
<md-slider min="5" max="7" #slider2></md-slider>
<input [(ngModel)]="min">
<md-slider [min]="min" [max]="max" tick-interval="5" #slider2></md-slider>
{{slider2.value}}
<input [(ngModel)]="max">

<h1>Disabled Slider</h1>
<md-slider disabled #slider3></md-slider>
Expand Down
2 changes: 2 additions & 0 deletions src/demo-app/slider/slider-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ import {Component} from '@angular/core';
export class SliderDemo {
demo: number;
val: number = 50;
min: number = 0;
max: number = 100;
}
44 changes: 42 additions & 2 deletions src/lib/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,18 +249,23 @@ describe('MdSlider', () => {
let sliderDimensions: ClientRect;
let trackFillElement: HTMLElement;
let thumbElement: HTMLElement;
let tickContainerElement: HTMLElement;
let testComponent: SliderWithMinAndMax;

beforeEach(() => {
fixture = TestBed.createComponent(SliderWithMinAndMax);
fixture.detectChanges();

sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
testComponent = fixture.debugElement.componentInstance;
sliderNativeElement = sliderDebugElement.nativeElement;
sliderInstance = sliderDebugElement.injector.get(MdSlider);
sliderTrackElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track');
sliderDimensions = sliderTrackElement.getBoundingClientRect();
trackFillElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track-fill');
thumbElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-thumb-position');
tickContainerElement =
<HTMLElement>sliderNativeElement.querySelector('.md-slider-tick-container');
});

it('should set the default values from the attributes', () => {
Expand Down Expand Up @@ -312,7 +317,39 @@ describe('MdSlider', () => {
// The closest snap is at the halfway point on the slider.
expect(thumbDimensions.left).toBe(sliderDimensions.left + sliderDimensions.width * 0.5);
expect(trackFillDimensions.width).toBe(thumbPosition);
});

it('should adjust thumb and ticks when min changes', () => {
testComponent.min = -2;
fixture.detectChanges();

let trackFillDimensions = trackFillElement.getBoundingClientRect();
let tickContainerDimensions = tickContainerElement.getBoundingClientRect();

expect(trackFillDimensions.width).toBe(sliderDimensions.width * 6 / 8);
expect(tickContainerDimensions.width)
.toBe(sliderDimensions.width - sliderDimensions.width * 6 / 8);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we also need to check that the linear gradient background for the ticks has been updated (since the tick interval will have changed).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

expect(tickContainerElement.style.background)
.toContain(`repeating-linear-gradient(to right, black, black 2px, transparent 2px, ` +
`transparent ${sliderDimensions.width * 6 / 8 - 1}px)`);
});

it('should adjust thumb and ticks when max changes', () => {
testComponent.min = -2;
fixture.detectChanges();

testComponent.max = 10;
fixture.detectChanges();

let trackFillDimensions = trackFillElement.getBoundingClientRect();
let tickContainerDimensions = tickContainerElement.getBoundingClientRect();

expect(trackFillDimensions.width).toBe(sliderDimensions.width * 6 / 12);
expect(tickContainerDimensions.width)
.toBe(sliderDimensions.width - sliderDimensions.width * 6 / 12);
expect(tickContainerElement.style.background)
.toContain(`repeating-linear-gradient(to right, black, black 2px, transparent 2px, ` +
`transparent ${sliderDimensions.width * 6 / 12 - 1}px)`);
});
});

Expand Down Expand Up @@ -689,11 +726,14 @@ class StandardSlider { }
class DisabledSlider { }

@Component({
template: `<md-slider min="4" max="6"></md-slider>`,
template: `<md-slider [min]="min" [max]="max" tick-interval="6"></md-slider>`,
styles: [noTransitionStyle],
encapsulation: ViewEncapsulation.None
})
class SliderWithMinAndMax { }
class SliderWithMinAndMax {
min = 4;
max = 6;
}

@Component({
template: `<md-slider value="26"></md-slider>`
Expand Down
19 changes: 16 additions & 3 deletions src/lib/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
if (!this._isInitialized) {
this.value = this._min;
}
this.snapThumbToValue();
this._updateTickSeparation();
}

@Input()
Expand All @@ -136,6 +138,8 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {

set max(v: number) {
this._max = Number(v);
this.snapThumbToValue();
this._updateTickSeparation();
}

@Input()
Expand Down Expand Up @@ -276,6 +280,9 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
* is set to something other than a number or 'auto', nothing happens.
*/
private _updateTickSeparation() {
if (!this._sliderDimensions) {
return;
}
if (this._tickInterval == 'auto') {
this._updateAutoTickSeparation();
} else if (Number(this._tickInterval)) {
Expand Down Expand Up @@ -428,8 +435,10 @@ export class SliderRenderer {
* Draws ticks onto the tick container.
*/
drawTicks(tickSeparation: number) {
let sliderTrackContainer =
<HTMLElement>this._sliderElement.querySelector('.md-slider-track-container');
let tickContainerWidth = sliderTrackContainer.getBoundingClientRect().width;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the size calculation for the tick container change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was checking the width of the same container whose width it was setting. This wasn't a problem before since it never changed after initialization, but now it can change.

let tickContainer = <HTMLElement>this._sliderElement.querySelector('.md-slider-tick-container');
let tickContainerWidth = tickContainer.getBoundingClientRect().width;
// An extra element for the last tick is needed because the linear gradient cannot be told to
// always draw a tick at the end of the gradient. To get around this, there is a second
// container for ticks that has a single tick mark on the very right edge.
Expand All @@ -443,10 +452,14 @@ export class SliderRenderer {
lastTickContainer.style.background = `linear-gradient(to left, black, black 2px, transparent ` +
`2px, transparent)`;

// If the second to last tick is too close (a separation of less than half the normal
// separation), don't show it by decreasing the width of the tick container element.
if (tickContainerWidth % tickSeparation < (tickSeparation / 2)) {
// If the second to last tick is too close (a separation of less than half the normal
// separation), don't show it by decreasing the width of the tick container element.
tickContainer.style.width = tickContainerWidth - tickSeparation + 'px';
} else {
// If there is enough space for the second-to-last tick, restore the default width of the
// tick container.
tickContainer.style.width = '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment here like

// If there is enough space for the second-to-last tick, restore the default width of the tick container.

}
}
}
Expand Down