Headless CMS and Content Managment Hub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

187 lines
4.9 KiB

/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Component, ElementRef, forwardRef, Input, Renderer2, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from '@app/framework/internal';
export const SQX_SLIDER_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderComponent), multi: true
};
@Component({
selector: 'sqx-slider',
styleUrls: ['./slider.component.scss'],
templateUrl: './slider.component.html',
providers: [SQX_SLIDER_CONTROL_VALUE_ACCESSOR]
})
export class SliderComponent implements ControlValueAccessor {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
private windowMouseMoveListener: Function | null = null;
private windowMouseUpListener: Function | null = null;
private centerStartOffset = 0;
private lastValue: number;
private value: number;
private isDragging = false;
public isDisabled = false;
@ViewChild('bar')
public bar: ElementRef;
@ViewChild('thumb')
public thumb: ElementRef;
@Input()
public min = 0;
@Input()
public max = 100;
@Input()
public step = 1;
constructor(private readonly renderer: Renderer2) { }
public writeValue(value: number) {
this.lastValue = this.value = Types.isNumber(value) ? value : 0;
this.updateThumbPosition();
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public onBarMouseClick(event: MouseEvent): boolean {
if (this.windowMouseMoveListener) {
return true;
}
const relativeValue = this.getRelativeX(event);
this.value = Math.round((relativeValue * (this.max - this.min) + this.min) / this.step) * this.step;
this.updateThumbPosition();
this.updateTouched();
this.updateValue();
return false;
}
public onThumbMouseDown(event: MouseEvent): boolean {
this.centerStartOffset = event.offsetX - this.thumb.nativeElement.clientWidth * 0.5;
this.windowMouseMoveListener =
this.renderer.listen('window', 'mousemove', (e: MouseEvent) => {
this.onMouseMove(e);
});
this.windowMouseUpListener =
this.renderer.listen('window', 'mouseup', () => {
this.onMouseUp();
});
this.renderer.addClass(this.thumb.nativeElement, 'focused');
this.isDragging = true;
return false;
}
private onMouseMove(event: MouseEvent): boolean {
if (!this.isDragging) {
return true;
}
const relativeValue = this.getRelativeX(event);
this.value = Math.round((relativeValue * (this.max - this.min) + this.min) / this.step) * this.step;
this.updateThumbPosition();
this.updateTouched();
return false;
}
private onMouseUp(): boolean {
this.updateValue();
setTimeout(() => {
this.releaseMouseHandlers();
this.renderer.removeClass(this.thumb.nativeElement, 'focused');
}, 10);
this.centerStartOffset = 0;
this.isDragging = false;
return false;
}
private getRelativeX(event: MouseEvent): number {
const parentOffsetX = this.getParentX(event, this.bar.nativeElement) - this.centerStartOffset;
const parentWidth = this.bar.nativeElement.clientWidth;
const relativeValue = Math.min(1, Math.max(0, (parentOffsetX - this.centerStartOffset) / parentWidth));
return relativeValue;
}
private getParentX(e: any, container: any): number {
const rect = container.getBoundingClientRect();
const x =
!!e.touches ?
e.touches[0].pageX :
e.pageX;
return x - rect.left;
}
private updateTouched() {
this.callTouched();
}
private updateValue() {
if (this.lastValue !== this.value) {
this.lastValue = this.value;
this.callChange(this.value);
}
}
private updateThumbPosition() {
const relativeValue = Math.min(1, Math.max(0, (this.value - this.min) / (this.max - this.min)));
this.renderer.setStyle(this.thumb.nativeElement, 'left', relativeValue * 100 + '%');
}
private releaseMouseHandlers() {
if (this.windowMouseMoveListener) {
this.windowMouseMoveListener();
this.windowMouseMoveListener = null;
}
if (this.windowMouseUpListener) {
this.windowMouseUpListener();
this.windowMouseUpListener = null;
}
this.isDragging = false;
}
}