import { Component , ElementRef , EventEmitter , HostListener , Input , OnChanges , OnInit , Output , SimpleChanges , ViewChild } from '@angular/core' ; import { Utilities } from './utilities' ; @ Component ( { selector : 'biger-progress' , templateUrl : './progress.component.html' , styleUrls : [ './progress.component.scss' ] } ) export class ProgressComponent extends Utilities implements OnInit , OnChanges { private sliderModel = [ 0 , 0 , 0 ] ; private sliderWidth = 0 ; private totalDiff = 100 ; private startClientX = 0 ; private startPosition = 0 ; private minValue : number ; private maxValue : number ; private minSelected : number ; private maxSelected : number ; private sliderInitiated = false ; public handlerX = 0 ; public isHandlerActive = false ; public isTouchEventStart = false ; public isMouseEventStart = false ; public currentHandlerIndex = 0 ; private initValue = 0 ; private currentValue = 0 ; constructor ( ) { super ( ) ; } @ Input ( 'min' ) set setMinValue ( value ) { if ( ! isNaN ( value ) ) { this . minValue = Number ( value ) ; } } @ Input ( 'max' ) set setMaxValue ( value ) { if ( ! isNaN ( value ) ) { this . maxValue = Number ( value ) ; } } @ Input ( 'value' ) set setCurrentValue ( value ) { if ( ! isNaN ( value ) && this . currentValue !== Number ( value ) ) { this . currentValue = Number ( value ) ; } } @ Output ( ) readonly change = new EventEmitter < number > ( ) ; @ ViewChild ( 'bar' , { static : true } ) bar : ElementRef < HTMLDivElement > ; ngOnInit ( ) { this . initializeSlider ( ) ; } ngOnChanges ( changes ) { if ( this . sliderInitiated ) { this . resetModel ( ) ; } } public initializeSlider ( ) { try { this . sliderWidth = this . bar . nativeElement . offsetWidth ; this . sliderInitiated = true ; } catch ( e ) { console . error ( e ) ; } } private resetModel ( ) { this . validateSliderValues ( ) ; this . sliderModel = [ this . currentValue - this . initValue , 100 - this . currentValue , 0 ] ; requestAnimationFrame ( this . setHandlerPosition . bind ( this , true ) ) ; } private validateSliderValues ( ) { if ( this . isNullOrEmpty ( this . minValue ) || this . isNullOrEmpty ( this . maxValue ) ) { this . updateCurrentValue ( 0 ) ; } else if ( this . minValue > this . maxValue ) { this . updateCurrentValue ( 0 ) ; } else { this . initValue = this . minValue ; if ( this . isNullOrEmpty ( this . minSelected ) || this . minSelected < this . minValue || this . minSelected > this . maxValue ) { this . minSelected = this . minValue ; } if ( this . isNullOrEmpty ( this . maxSelected ) || this . maxSelected < this . minValue || this . maxSelected > this . maxValue ) { this . maxSelected = this . maxValue ; } if ( this . minSelected > this . maxSelected ) { this . minSelected = this . minValue ; this . maxSelected = this . maxValue ; } } } private updateCurrentValue ( value ) { this . minSelected = this . currentValue = value ; this . change . emit ( this . currentValue ) ; } private setHandlerPosition ( privateChange = false ) { if ( ! privateChange ) { this . updateCurrentValue ( this . initValue + this . currentValue ) ; } this . handlerX = this . currentValue ; } private setModelValue ( value ) { this . sliderModel [ 0 ] = value ; this . currentValue = value ; } @ HostListener ( 'document:mouseup' ) @ HostListener ( 'document:panend' ) setHandlerActiveOff ( ) { this . isMouseEventStart = false ; this . isTouchEventStart = false ; this . isHandlerActive = false ; } public setHandlerActive ( event ) { event . preventDefault ( ) ; if ( ! this . isNullOrEmpty ( event . clientX ) ) { this . startClientX = event . clientX ; this . isMouseEventStart = true ; this . isTouchEventStart = false ; } else if ( ! this . isNullOrEmpty ( event . deltaX ) ) { this . startClientX = event . deltaX ; this . isTouchEventStart = true ; this . isMouseEventStart = false ; } if ( this . isMouseEventStart || this . isTouchEventStart ) { this . startPosition = this . sliderModel [ 0 ] ; this . isHandlerActive = true ; } } public onBarClick ( event ) { const size = this . bar . nativeElement . clientWidth ; const val = event . clientX ; const { left } = this . bar . nativeElement . getBoundingClientRect ( ) ; const offset = Math . abs ( val - left ) ; const model = Math . round ( ( offset / size ) * ( this . maxValue - this . minValue ) ) + this . minValue ; this . setModelValue ( model ) ; requestAnimationFrame ( this . setHandlerPosition . bind ( this , false ) ) ; } public handlerSliding ( event ) { if ( ( this . isMouseEventStart && event . clientX ) || ( this . isTouchEventStart && event . deltaX ) ) { const movedX = Math . round ( ( ( event . clientX || event . deltaX ) - this . startClientX ) / this . sliderWidth * this . totalDiff ) ; const model = this . startPosition + movedX ; if ( model >= this . minValue && model <= this . maxValue ) { this . setModelValue ( model ) ; requestAnimationFrame ( this . setHandlerPosition . bind ( this , false ) ) ; } } } }