Skip to content

Use slide gesture on the slider instead of drag gesture #905

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 1 commit into from
Jul 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
2 changes: 1 addition & 1 deletion src/components/slider/slider.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="md-slider-wrapper">
<div class="md-slider-container"
[class.md-slider-dragging]="isDragging"
[class.md-slider-sliding]="isSliding"
[class.md-slider-active]="isActive">
<div class="md-slider-track-container">
<div class="md-slider-track"></div>
Expand Down
6 changes: 3 additions & 3 deletions src/components/slider/slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ md-slider *::after {
}

/**
* Holds the isActive and isDragging classes as well as helps with positioning the children.
* Holds the isActive and isSliding classes as well as helps with positioning the children.
* Cannot be merged with .md-slider-wrapper.
*/
.md-slider-container {
Expand Down Expand Up @@ -130,8 +130,8 @@ md-slider *::after {
border-color: md-color($md-accent);
}

.md-slider-dragging .md-slider-thumb-position,
.md-slider-dragging .md-slider-track-fill {
.md-slider-sliding .md-slider-thumb-position,
.md-slider-sliding .md-slider-track-fill {
transition: none;
cursor: default;
}
Expand Down
114 changes: 57 additions & 57 deletions src/components/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,22 @@ describe('MdSlider', () => {
expect(sliderInstance.value).toBe(19);
});

it('should update the value on a drag', () => {
it('should update the value on a slide', () => {
expect(sliderInstance.value).toBe(0);
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.89, gestureConfig);
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.89, gestureConfig);
// The expected value is 89 from: percentage * difference of max and min.
expect(sliderInstance.value).toBe(89);
});

it('should set the value as min when dragging before the track', () => {
it('should set the value as min when sliding before the track', () => {
expect(sliderInstance.value).toBe(0);
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, -1.33, gestureConfig);
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, -1.33, gestureConfig);
expect(sliderInstance.value).toBe(0);
});

it('should set the value as max when dragging past the track', () => {
it('should set the value as max when sliding past the track', () => {
expect(sliderInstance.value).toBe(0);
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 1.75, gestureConfig);
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 1.75, gestureConfig);
expect(sliderInstance.value).toBe(100);
});

Expand Down Expand Up @@ -116,9 +116,9 @@ describe('MdSlider', () => {
expect(thumbDimensions.left).toBe(sliderDimensions.width * 0.5 + sliderDimensions.left);
});

it('should update the track fill on drag', () => {
it('should update the track fill on slide', () => {
expect(trackFillDimensions.width).toBe(0);
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.86, gestureConfig);
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.86, gestureConfig);

trackFillDimensions = trackFillElement.getBoundingClientRect();
thumbDimensions = thumbElement.getBoundingClientRect();
Expand All @@ -130,11 +130,11 @@ describe('MdSlider', () => {
expect(Math.round(trackFillDimensions.width)).toBe(Math.round(thumbPosition));
});

it('should update the thumb position on drag', () => {
it('should update the thumb position on slide', () => {
expect(thumbDimensions.left).toBe(sliderDimensions.left);
// The drag event also truncates the position passed in, so 50% is used here as well to
// The slide event also truncates the position passed in, so 50% is used here as well to
// ensure the ability to calculate the expected position.
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.5, gestureConfig);
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.5, gestureConfig);

thumbDimensions = thumbElement.getBoundingClientRect();
expect(thumbDimensions.left).toBe(sliderDimensions.width * 0.5 + sliderDimensions.left);
Expand Down Expand Up @@ -165,19 +165,19 @@ describe('MdSlider', () => {
expect(containerElement.classList).not.toContain('md-slider-active');
});

it('should add and remove the md-slider-dragging class when dragging', () => {
it('should add and remove the md-slider-sliding class when sliding', () => {
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
expect(containerElement.classList).not.toContain('md-slider-dragging');
expect(containerElement.classList).not.toContain('md-slider-sliding');

dispatchDragStartEvent(sliderNativeElement, 0, gestureConfig);
dispatchSlideStartEvent(sliderNativeElement, 0, gestureConfig);
fixture.detectChanges();

expect(containerElement.classList).toContain('md-slider-dragging');
expect(containerElement.classList).toContain('md-slider-sliding');

dispatchDragEndEvent(sliderNativeElement, 0.34, gestureConfig);
dispatchSlideEndEvent(sliderNativeElement, 0.34, gestureConfig);
fixture.detectChanges();

expect(containerElement.classList).not.toContain('md-slider-dragging');
expect(containerElement.classList).not.toContain('md-slider-sliding');
});
});

Expand Down Expand Up @@ -208,9 +208,9 @@ describe('MdSlider', () => {
expect(sliderInstance.value).toBe(0);
});

it('should not change the value on drag when disabled', () => {
it('should not change the value on slide when disabled', () => {
expect(sliderInstance.value).toBe(0);
dispatchDragEvent(sliderNativeElement, sliderNativeElement, 0, 0.5, gestureConfig);
dispatchSlideEvent(sliderNativeElement, sliderNativeElement, 0, 0.5, gestureConfig);
expect(sliderInstance.value).toBe(0);
});

Expand All @@ -224,14 +224,14 @@ describe('MdSlider', () => {
expect(containerElement.classList).not.toContain('md-slider-active');
});

it('should not add the md-slider-dragging class on drag when disabled', () => {
it('should not add the md-slider-sliding class on slide when disabled', () => {
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
expect(containerElement.classList).not.toContain('md-slider-dragging');
expect(containerElement.classList).not.toContain('md-slider-sliding');

dispatchDragStartEvent(sliderNativeElement, 0.46, gestureConfig);
dispatchSlideStartEvent(sliderNativeElement, 0.46, gestureConfig);
fixture.detectChanges();

expect(containerElement.classList).not.toContain('md-slider-dragging');
expect(containerElement.classList).not.toContain('md-slider-sliding');
});
});

Expand Down Expand Up @@ -274,8 +274,8 @@ describe('MdSlider', () => {
expect(sliderInstance.value).toBe(value);
});

it('should set the correct value on drag', () => {
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.62, gestureConfig);
it('should set the correct value on slide', () => {
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.62, gestureConfig);
// Computed by multiplying the difference between the min and the max by the percentage from
// the click and adding that to the minimum.
let value = Math.round(4 + (0.62 * (6 - 4)));
Expand All @@ -295,11 +295,11 @@ describe('MdSlider', () => {
expect(Math.round(trackFillDimensions.width)).toBe(Math.round(thumbPosition));
});

it('should snap the thumb and fill to the nearest value on drag', () => {
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.74, gestureConfig);
it('should snap the thumb and fill to the nearest value on slide', () => {
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.74, gestureConfig);
fixture.detectChanges();

dispatchDragEndEvent(sliderNativeElement, 0.74, gestureConfig);
dispatchSlideEndEvent(sliderNativeElement, 0.74, gestureConfig);
fixture.detectChanges();

let trackFillDimensions = trackFillElement.getBoundingClientRect();
Expand Down Expand Up @@ -343,8 +343,8 @@ describe('MdSlider', () => {
expect(sliderInstance.value).toBe(92);
});

it('should set the correct value on drag', () => {
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.32, gestureConfig);
it('should set the correct value on slide', () => {
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.32, gestureConfig);
expect(sliderInstance.value).toBe(32);
});
});
Expand Down Expand Up @@ -396,18 +396,18 @@ describe('MdSlider', () => {
expect(Math.round(trackFillDimensions.width)).toBe(Math.round(thumbPosition));
});

it('should set the correct step value on drag', () => {
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.07, gestureConfig);
it('should set the correct step value on slide', () => {
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.07, gestureConfig);
fixture.detectChanges();

expect(sliderInstance.value).toBe(0);
});

it('should snap the thumb and fill to a step on drag', () => {
dispatchDragEvent(sliderTrackElement, sliderNativeElement, 0, 0.88, gestureConfig);
it('should snap the thumb and fill to a step on slide', () => {
dispatchSlideEvent(sliderTrackElement, sliderNativeElement, 0, 0.88, gestureConfig);
fixture.detectChanges();

dispatchDragEndEvent(sliderNativeElement, 0.88, gestureConfig);
dispatchSlideEndEvent(sliderNativeElement, 0.88, gestureConfig);
fixture.detectChanges();

let trackFillDimensions = trackFillElement.getBoundingClientRect();
Expand Down Expand Up @@ -489,62 +489,62 @@ function dispatchClickEvent(element: HTMLElement, percentage: number): void {
}

/**
* Dispatches a drag event from an element.
* Dispatches a slide event from an element.
* @param trackElement The track element from which the event location will be calculated.
* @param containerElement The container element from which the event will be dispatched.
* @param startPercent The percentage of the slider where the drag will begin.
* @param endPercent The percentage of the slider where the drag will end.
* @param gestureConfig The gesture config for the test to handle emitting the drag events.
* @param startPercent The percentage of the slider where the slide will begin.
* @param endPercent The percentage of the slider where the slide will end.
* @param gestureConfig The gesture config for the test to handle emitting the slide events.
*/
function dispatchDragEvent(trackElement: HTMLElement, containerElement: HTMLElement,
startPercent: number, endPercent: number,
gestureConfig: TestGestureConfig): void {
function dispatchSlideEvent(trackElement: HTMLElement, containerElement: HTMLElement,
startPercent: number, endPercent: number,
gestureConfig: TestGestureConfig): void {
let dimensions = trackElement.getBoundingClientRect();
let startX = dimensions.left + (dimensions.width * startPercent);
let endX = dimensions.left + (dimensions.width * endPercent);

gestureConfig.emitEventForElement('dragstart', containerElement, {
// The actual event has a center with an x value that the drag listener is looking for.
gestureConfig.emitEventForElement('slidestart', containerElement, {
// The actual event has a center with an x value that the slide listener is looking for.
center: { x: startX },
// The event needs a source event with a prevent default so we fake one.
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
});

gestureConfig.emitEventForElement('drag', containerElement, {
gestureConfig.emitEventForElement('slide', containerElement, {
center: { x: endX },
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
});
}

/**
* Dispatches a dragstart event from an element.
* Dispatches a slidestart event from an element.
* @param element The element from which the event will be dispatched.
* @param startPercent The percentage of the slider where the drag will begin.
* @param gestureConfig The gesture config for the test to handle emitting the drag events.
* @param startPercent The percentage of the slider where the slide will begin.
* @param gestureConfig The gesture config for the test to handle emitting the slide events.
*/
function dispatchDragStartEvent(element: HTMLElement, startPercent: number,
gestureConfig: TestGestureConfig): void {
function dispatchSlideStartEvent(element: HTMLElement, startPercent: number,
gestureConfig: TestGestureConfig): void {
let dimensions = element.getBoundingClientRect();
let x = dimensions.left + (dimensions.width * startPercent);

gestureConfig.emitEventForElement('dragstart', element, {
gestureConfig.emitEventForElement('slidestart', element, {
center: { x: x },
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
});
}

/**
* Dispatches a dragend event from an element.
* Dispatches a slideend event from an element.
* @param element The element from which the event will be dispatched.
* @param endPercent The percentage of the slider where the drag will end.
* @param gestureConfig The gesture config for the test to handle emitting the drag events.
* @param endPercent The percentage of the slider where the slide will end.
* @param gestureConfig The gesture config for the test to handle emitting the slide events.
*/
function dispatchDragEndEvent(element: HTMLElement, endPercent: number,
gestureConfig: TestGestureConfig): void {
function dispatchSlideEndEvent(element: HTMLElement, endPercent: number,
gestureConfig: TestGestureConfig): void {
let dimensions = element.getBoundingClientRect();
let x = dimensions.left + (dimensions.width * endPercent);

gestureConfig.emitEventForElement('dragend', element, {
gestureConfig.emitEventForElement('slideend', element, {
center: { x: x },
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
});
Expand Down
32 changes: 16 additions & 16 deletions src/components/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import {applyCssTransform} from '@angular2-material/core/style/apply-transform';
host: {
'tabindex': '0',
'(click)': 'onClick($event)',
'(drag)': 'onDrag($event)',
'(dragstart)': 'onDragStart($event)',
'(dragend)': 'onDragEnd()',
'(slide)': 'onSlide($event)',
'(slidestart)': 'onSlideStart($event)',
'(slideend)': 'onSlideEnd()',
'(window:resize)': 'onResize()',
'(blur)': 'onBlur()',
},
Expand Down Expand Up @@ -51,14 +51,14 @@ export class MdSlider implements AfterContentInit {
@Input() step: number = 1;

/**
* Whether or not the thumb is currently being dragged.
* Whether or not the thumb is sliding.
* Used to determine if there should be a transition for the thumb and fill track.
* TODO: internal
*/
isDragging: boolean = false;
isSliding: boolean = false;

/**
* Whether or not the slider is active (clicked or is being dragged).
* Whether or not the slider is active (clicked or sliding).
* Used to shrink and grow the thumb as according to the Material Design spec.
* TODO: internal
*/
Expand Down Expand Up @@ -128,45 +128,45 @@ export class MdSlider implements AfterContentInit {
}

this.isActive = true;
this.isDragging = false;
this.isSliding = false;
this._renderer.addFocus();
this.updateValueFromPosition(event.clientX);
this.snapToValue();
}

/** TODO: internal */
onDrag(event: HammerInput) {
onSlide(event: HammerInput) {
if (this.disabled) {
return;
}

// Prevent the drag from selecting anything else.
// Prevent the slide from selecting anything else.
event.preventDefault();
this.updateValueFromPosition(event.center.x);
}

/** TODO: internal */
onDragStart(event: HammerInput) {
onSlideStart(event: HammerInput) {
if (this.disabled) {
return;
}

event.preventDefault();
this.isDragging = true;
this.isSliding = true;
this.isActive = true;
this._renderer.addFocus();
this.updateValueFromPosition(event.center.x);
}

/** TODO: internal */
onDragEnd() {
this.isDragging = false;
this.snapToValue();
onSlideEnd() {
this.isSliding = false;
this.snapToValue();
}

/** TODO: internal */
onResize() {
this.isDragging = true;
this.isSliding = true;
this._sliderDimensions = this._renderer.getSliderDimensions();
// Skip updating the value and position as there is no new placement.
this._renderer.updateThumbAndFillPosition(this._percent, this._sliderDimensions.width);
Expand All @@ -180,7 +180,7 @@ export class MdSlider implements AfterContentInit {
/**
* When the value changes without a physical position, the percentage needs to be recalculated
* independent of the physical location.
* This is also used to move the thumb to a snapped value once dragging is done.
* This is also used to move the thumb to a snapped value once sliding is done.
*/
updatePercentFromValue() {
this._percent = (this.value - this.min) / (this.max - this.min);
Expand Down