igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
268 lines (215 loc) • 6.74 kB
text/typescript
import {
Component,
Input,
HostListener,
ElementRef,
HostBinding,
Output,
EventEmitter,
OnInit,
OnDestroy,
TemplateRef
} from '@angular/core';
import { takeUntil } from 'rxjs/operators';
import { SliderHandle } from '../slider.common';
import { Subject } from 'rxjs';
import { IgxDirectionality } from '../../services/direction/directionality';
import { NgClass } from '@angular/common';
/**
* @hidden
*/
export class IgxSliderThumbComponent implements OnInit, OnDestroy {
public value: any;
public continuous: boolean;
public thumbLabelVisibilityDuration;
public disabled: boolean;
public onPan: Subject<number>;
public stepDistance: number;
public step: number;
public templateRef: TemplateRef<any>;
public context: any;
public type: SliderHandle;
public deactiveState: boolean;
public thumbValueChange = new EventEmitter<number>();
public thumbChange = new EventEmitter<any>();
public hoverChange = new EventEmitter<boolean>();
public tabindex = 0;
public zIndex = 0;
public focused = false;
public get thumbFromClass() {
return this.type === SliderHandle.FROM;
}
public get thumbToClass() {
return this.type === SliderHandle.TO;
}
public get thumbFromActiveClass() {
return this.type === SliderHandle.FROM && this._isActive;
}
public get thumbToActiveClass() {
return this.type === SliderHandle.TO && this._isActive;
}
public get thumbFromDisabledClass() {
return this.type === SliderHandle.FROM && this.disabled;
}
public get thumbToDisabledClass() {
return this.type === SliderHandle.TO && this.disabled;
}
public get thumbFromPressedClass() {
return this.type === SliderHandle.FROM && this.isActive && this._isPressed;
}
public get thumbToPressedClass() {
return this.type === SliderHandle.TO && this.isActive && this._isPressed;
}
public get getDotClass() {
return {
'igx-slider-thumb-from__dot': this.type === SliderHandle.FROM,
'igx-slider-thumb-to__dot': this.type === SliderHandle.TO
};
}
public isActive = false;
public get nativeElement() {
return this._elementRef.nativeElement;
}
public get destroy(): Subject<boolean> {
return this._destroy$;
}
private _isActive = false;
private _isPressed = false;
private _destroy$ = new Subject<boolean>();
private get thumbPositionX() {
const thumbBounderies = this.nativeElement.getBoundingClientRect();
const thumbCenter = (thumbBounderies.right - thumbBounderies.left) / 2;
return thumbBounderies.left + thumbCenter;
}
constructor(private _elementRef: ElementRef, private _dir: IgxDirectionality) { }
public onPointerEnter() {
this.focused = false;
this.hoverChange.emit(true);
}
public onPointerLeave() {
this.hoverChange.emit(false);
}
public onKeyUp(event: KeyboardEvent) {
event.stopPropagation();
this.focused = true;
}
public onKeyDown(event: KeyboardEvent) {
if (this.disabled) {
return;
}
let increment = 0;
const stepWithDir = (rtl: boolean) => rtl ? this.step * -1 : this.step;
if (event.key.endsWith('Left')) {
increment = stepWithDir(!this._dir.rtl);
} else if (event.key.endsWith('Right')) {
increment = stepWithDir(this._dir.rtl);
} else {
return;
}
this.thumbChange.emit();
this.thumbValueChange.emit(increment);
}
public onBlur() {
this.isActive = false;
this.zIndex = 0;
this.focused = false;
}
public onFocusListener() {
this.isActive = true;
this.zIndex = 1;
}
/**
* @hidden
*/
public ngOnInit() {
this.onPan
.pipe(takeUntil(this._destroy$))
.subscribe(mouseX =>
this.updateThumbValue(mouseX)
);
}
/**
* @hidden
*/
public ngOnDestroy() {
this._destroy$.next(true);
this._destroy$.complete();
}
/**
* Show thumb label and ripple.
*/
public showThumbIndicators() {
this.toggleThumbIndicators(true);
}
/**
* Hide thumb label and ripple.
*/
public hideThumbIndicators() {
this.toggleThumbIndicators(false);
}
private updateThumbValue(mouseX: number) {
const updateValue = this.calculateTrackUpdate(mouseX);
if (this.isActive && updateValue !== 0) {
this.thumbValueChange.emit(updateValue);
}
}
private calculateTrackUpdate(mouseX: number): number {
const scaleX = this._dir.rtl ? this.thumbPositionX - mouseX : mouseX - this.thumbPositionX;
const stepDistanceCenter = this.stepDistance / 2;
// If the thumb scale range (slider update) is less thàn a half step,
// the position stays the same.
const scaleXPositive = Math.abs(scaleX);
if (scaleXPositive < stepDistanceCenter) {
return 0;
}
return this.stepToProceed(scaleX, this.stepDistance);
}
private stepToProceed(scaleX, stepDist) {
return Math.round(scaleX / stepDist) * this.step;
}
private toggleThumbIndicators(visible: boolean) {
this._isPressed = visible;
if (this.continuous || this.deactiveState) {
this._isActive = false;
} else {
this._isActive = visible;
}
}
}