File
Metadata
selector |
onto-range-slider |
styleUrls |
range-slider.component.scss |
templateUrl |
range-slider.component.html |
Outputs
selectionChange
|
$event type: EventEmitter<any>
|
Methods
onResize
|
onResize()
|
Returns: void
|
draw
|
draw(splitvalue: number)
|
Returns: void
|
init
|
init()
|
Returns: void
|
update
|
update(rangemax: number)
|
Returns: void
|
Private sumRange
|
sumRange()
|
Returns: number
|
Public onSelectionChange
|
onSelectionChange()
|
Returns: void
|
Private updateSelection
|
updateSelection()
|
Returns: void
|
Private isInRange
|
isInRange(facet: SearchFacetModel)
|
Returns: boolean
|
Private parseInt
|
parseInt(value: string)
|
Returns: number
|
Private facetData
|
facetData: SearchFacetModel[]
|
Public maxElement
|
maxElement: any
|
Public maxSlider
|
maxSlider: any
|
Public maxValue
|
maxValue: any
|
Public minElement
|
minElement: any
|
Public minSlider
|
minSlider: any
|
Public minValue
|
minValue: any
|
Public selectedMax
|
selectedMax: any
|
Public selectedMin
|
selectedMin: any
|
Public slider
|
slider: any
|
Private thumbsize
|
thumbsize: number
|
Default value: 14
|
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
HostListener,
Input, OnDestroy,
OnInit,
Output,
ViewChild
} from '@angular/core';
import {SearchFacetModel} from '../../models/search-facet-model';
import {SelectedRange} from '../models/selected-range';
import {SearchRangeFacetGroupModel} from '../models/search-range-facet-group-model';
@Component({
selector: 'onto-range-slider',
templateUrl: './range-slider.component.html',
styleUrls: ['./range-slider.component.scss']
})
export class RangeSliderComponent implements OnInit, AfterViewInit, OnDestroy {
@Input()
public data: SearchRangeFacetGroupModel;
@ViewChild('minMaxSlider')
public slider: ElementRef;
@ViewChild('minSlider')
public minSlider: ElementRef;
@ViewChild('maxSlider')
public maxSlider: ElementRef;
@Output()
public selectionChange: EventEmitter<any> = new EventEmitter<any>();
@HostListener('window:resize', ['$event'])
onResize(): void {}
private facetData: SearchFacetModel[];
public sum: number;
private thumbsize = 14;
public minValue;
public maxValue;
public selectedMin;
public selectedMax;
public minElement;
public maxElement;
ngOnInit(): void {
this.facetData = [...this.data.facetGroupData];
this.facetData.sort((a, b) => {
try {
return this.parseInt(a.label) - this.parseInt(b.label);
} catch (e) {
throw new Error('Facet labels must represent numbers! ' + e.message);
}
});
this.minValue = this.facetData[0].label;
this.maxValue = this.facetData[this.facetData.length - 1].label;
this.selectedMin = this.minValue;
this.selectedMax = this.maxValue;
this.sum = this.sumRange();
this.updateSelection();
}
public ngAfterViewInit(): void {
this.minElement = this.minSlider.nativeElement;
this.maxElement = this.maxSlider.nativeElement;
this.init();
this.onResize = (): void => this.update(this.parseInt(this.maxElement.getAttribute('max')));
}
draw(splitvalue: number): void {
const thumbsize: any = this.parseInt(this.slider.nativeElement.getAttribute('data-thumbsize'));
const rangewidth = this.slider.nativeElement.clientWidth;
const rangemin = this.parseInt(this.slider.nativeElement.getAttribute('data-rangemin'));
const rangemax = this.parseInt(this.slider.nativeElement.getAttribute('data-rangemax'));
this.minElement.setAttribute('max', splitvalue);
this.maxElement.setAttribute('min', splitvalue);
this.minElement.style.width = this.parseInt(thumbsize + ((splitvalue - rangemin) / (rangemax - rangemin)) * (rangewidth - (2 * thumbsize))) + 'px';
this.maxElement.style.width = this.parseInt(thumbsize + ((rangemax - splitvalue) / (rangemax - rangemin)) * (rangewidth - (2 * thumbsize))) + 'px';
this.minElement.style.left = '0px';
this.maxElement.style.left = this.parseInt(this.minElement.style.width) + 'px';
// correct for 1 off at the end of the max slider
if (this.maxElement.value > (rangemax - 1)) {
this.maxElement.setAttribute('data-value', rangemax);
}
this.maxElement.value = this.maxElement.getAttribute('data-value');
this.minElement.value = this.minElement.getAttribute('data-value');
}
init(): void {
this.minElement.removeEventListener('input', () => this.update);
this.maxElement.removeEventListener('input', () => this.update);
const rangemin: any = this.parseInt(this.minElement.getAttribute('min'));
const rangemax: any = this.parseInt(this.maxElement.getAttribute('max'));
const avgvalue = (rangemin + rangemax) / 2;
this.minElement.setAttribute('data-value', rangemin);
this.maxElement.setAttribute('data-value', rangemax);
this.slider.nativeElement.setAttribute('data-rangemin', rangemin);
this.slider.nativeElement.setAttribute('data-rangemax', rangemax);
this.slider.nativeElement.setAttribute('data-thumbsize', this.thumbsize);
this.slider.nativeElement.setAttribute('data-rangewidth', this.slider.nativeElement.offsetWidth);
this.draw(avgvalue);
this.minElement.addEventListener('input', () => this.update(rangemax));
this.maxElement.addEventListener('input', () => this.update(rangemax));
}
update(rangemax: number): void {
// correction for min value calculation
let minvalue;
if (this.minElement.value > (rangemax - 1)) {
minvalue = Math.floor(this.minElement.value - 1);
} else {
minvalue = Math.floor(this.minElement.value);
}
// correction for max value calculation
let maxvalue;
if (this.maxElement.value > (rangemax - 1)) {
maxvalue = Math.ceil(this.maxElement.value);
} else {
maxvalue = Math.floor(this.maxElement.value);
}
this.minElement.setAttribute('data-value', minvalue);
this.maxElement.setAttribute('data-value', maxvalue);
this.selectedMin = minvalue;
this.selectedMax = maxvalue;
this.updateSelection();
this.sum = this.sumRange();
const avgvalue = Math.ceil((minvalue + maxvalue) / 2);
this.draw(avgvalue);
}
private sumRange(): number {
let sum = 0;
this.data.facetGroupData.forEach((facet) => {
if (this.isInRange(facet)) {
sum += facet.count;
}
});
return sum;
}
public onSelectionChange(): void {
this.selectionChange.emit(this.data.selectedRange);
}
private updateSelection(): void {
this.data.selectedRange = {
start: this.selectedMin,
end: this.selectedMax
} as SelectedRange;
this.onSelectionChange();
}
private isInRange(facet: SearchFacetModel): boolean {
const value = this.parseInt(facet.label);
return value >= this.parseInt(this.selectedMin) && value <= this.parseInt(this.selectedMax);
}
private parseInt(value: string): number {
try {
return parseInt(value);
} catch (e) {
throw new Error(`Parsing ${value} to number failed! ` + e.message);
}
}
public ngOnDestroy(): void {
this.onResize = function(): void {};
this.minElement.removeEventListener('input', () => this.update);
this.maxElement.removeEventListener('input', () => this.update);
}
}