Merge branch 'refactor-inputs'

This commit is contained in:
Manuel Mtz-Almeida
2017-04-05 20:00:39 +02:00
36 changed files with 1137 additions and 974 deletions

View File

@ -1,16 +1,15 @@
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, Input, OnDestroy, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnDestroy, Optional, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { clamp, isPresent, isTrueProperty } from '../../util/util';
import { clamp, isTrueProperty } from '../../util/util';
import { Config } from '../../config/config';
import { DomController } from '../../platform/dom-controller';
import { Form } from '../../util/form';
import { Haptic } from '../../tap-click/haptic';
import { Ion } from '../ion';
import { BaseInput } from '../../util/base-input';
import { Item } from '../item/item';
import { Platform } from '../../platform/platform';
import { PointerCoordinates, pointerCoord } from '../../util/dom';
import { TimeoutDebouncer } from '../../util/debouncer';
import { UIEventManager } from '../../gestures/ui-event-manager';
@ -112,13 +111,11 @@ export const RANGE_VALUE_ACCESSOR: any = {
providers: [RANGE_VALUE_ACCESSOR],
encapsulation: ViewEncapsulation.None,
})
export class Range extends Ion implements AfterViewInit, ControlValueAccessor, OnDestroy {
export class Range extends BaseInput<any> implements AfterViewInit, ControlValueAccessor, OnDestroy {
_dual: boolean;
_pin: boolean;
_disabled: boolean = false;
_pressed: boolean;
_lblId: string;
_fn: Function;
_activeB: boolean;
_rect: ClientRect;
@ -141,21 +138,10 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
_barL: string;
_barR: string;
_debouncer: TimeoutDebouncer = new TimeoutDebouncer(0);
_events: UIEventManager;
@ViewChild('slider') public _slider: ElementRef;
/**
* @hidden
*/
value: any;
/**
* @hidden
*/
id: string;
/**
* @input {number} Minimum integer value of the range. Defaults to `0`.
*/
@ -245,19 +231,6 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
this._dual = isTrueProperty(val);
}
/**
* @input {boolean} If true, the user cannot interact with this element.
*/
@Input()
get disabled(): boolean {
return this._disabled;
}
set disabled(val: boolean) {
this._disabled = val = isTrueProperty(val);
const item = this._item;
item && item.setElementClass('item-range-disabled', val);
}
/**
* Returns the ratio of the knob's is current location, which is a number
* between `0` and `1`. If two knobs are used, this property represents
@ -282,25 +255,10 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
return null;
}
/**
* @output {Range} Emitted when the range selector drag starts.
*/
@Output() ionFocus: EventEmitter<Range> = new EventEmitter<Range>();
/**
* @output {Range} Emitted when the range value changes.
*/
@Output() ionChange: EventEmitter<Range> = new EventEmitter<Range>();
/**
* @output {Range} Emitted when the range selector drag ends.
*/
@Output() ionBlur: EventEmitter<Range> = new EventEmitter<Range>();
constructor(
private _form: Form,
form: Form,
private _haptic: Haptic,
@Optional() private _item: Item,
@Optional() item: Item,
config: Config,
private _plt: Platform,
elementRef: ElementRef,
@ -308,21 +266,16 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
private _dom: DomController,
private _cd: ChangeDetectorRef
) {
super(config, elementRef, renderer, 'range');
super(config, elementRef, renderer, 'range', 0, form, item, null);
this._events = new UIEventManager(_plt);
_form.register(this);
if (_item) {
this.id = 'rng-' + _item.registerInput('range');
this._lblId = 'lbl-' + _item.id;
_item.setElementClass('item-range', true);
}
}
/**
* @hidden
*/
ngAfterViewInit() {
this._initialize();
// add touchstart/mousedown listeners
this._events.pointerEvents({
element: this._slider.nativeElement,
@ -346,7 +299,7 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
}
// trigger ionFocus event
this.ionFocus.emit(this);
this._fireFocus();
// prevent default so scrolling does not happen
ev.preventDefault();
@ -375,38 +328,40 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
/** @internal */
_pointerMove(ev: UIEvent) {
if (!this._disabled) {
// prevent default so scrolling does not happen
ev.preventDefault();
ev.stopPropagation();
// update the active knob's position
const hasChanged = this._update(pointerCoord(ev), this._rect, true);
if (hasChanged && this._snaps) {
// trigger a haptic selection changed event
// if this is a snap range
this._haptic.gestureSelectionChanged();
}
if (this._disabled) {
return;
}
// prevent default so scrolling does not happen
ev.preventDefault();
ev.stopPropagation();
// update the active knob's position
const hasChanged = this._update(pointerCoord(ev), this._rect, true);
if (hasChanged && this._snaps) {
// trigger a haptic selection changed event
// if this is a snap range
this._haptic.gestureSelectionChanged();
}
}
/** @internal */
_pointerUp(ev: UIEvent) {
if (!this._disabled) {
// prevent default so scrolling does not happen
ev.preventDefault();
ev.stopPropagation();
if (this._disabled) {
return;
}
// prevent default so scrolling does not happen
ev.preventDefault();
ev.stopPropagation();
// update the active knob's position
this._update(pointerCoord(ev), this._rect, false);
// update the active knob's position
this._update(pointerCoord(ev), this._rect, false);
// trigger a haptic end
this._haptic.gestureSelectionEnd();
// trigger a haptic end
this._haptic.gestureSelectionEnd();
// trigger ionBlur event
this.ionBlur.emit(this);
}
// trigger ionBlur event
this._fireBlur();
}
/** @internal */
@ -447,27 +402,24 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
}
// value has been updated
let value;
if (this._dual) {
// dual knobs have an lower and upper value
if (!this.value) {
// ensure we're always updating the same object
this.value = {};
}
this.value.lower = Math.min(this._valA, this._valB);
this.value.upper = Math.max(this._valA, this._valB);
value = {
lower: Math.min(this._valA, this._valB),
upper: Math.max(this._valA, this._valB)
};
console.debug(`range, updateKnob: ${ratio}, lower: ${this.value.lower}, upper: ${this.value.upper}`);
} else {
// single knob only has one value
this.value = this._valA;
value = this._valA;
console.debug(`range, updateKnob: ${ratio}, value: ${this.value}`);
}
this._debouncer.debounce(() => {
this.onChange(this.value);
this.ionChange.emit(this);
});
// Update input value
this.value = value;
return true;
}
@ -566,70 +518,40 @@ export class Range extends Ion implements AfterViewInit, ControlValueAccessor, O
return clamp(0, value, 1);
}
/**
* @hidden
*/
writeValue(val: any) {
if (isPresent(val)) {
this.value = val;
if (this._dual) {
this._valA = val.lower;
this._valB = val.upper;
this._ratioA = this._valueToRatio(val.lower);
this._ratioB = this._valueToRatio(val.upper);
} else {
this._valA = val;
this._ratioA = this._valueToRatio(val);
}
this._updateBar();
_inputNormalize(val: any): any {
if (this._dual) {
return val;
} else {
val = parseFloat(val);
return isNaN(val) ? undefined : val;
}
}
/**
* @hidden
*/
registerOnChange(fn: Function): void {
this._fn = fn;
this.onChange = (val: any) => {
fn(val);
this.onTouched();
};
}
_inputUpdated() {
const val = this.value;
if (this._dual) {
this._valA = val.lower;
this._valB = val.upper;
this._ratioA = this._valueToRatio(val.lower);
this._ratioB = this._valueToRatio(val.upper);
/**
* @hidden
*/
registerOnTouched(fn: any) { this.onTouched = fn; }
} else {
this._valA = val;
this._ratioA = this._valueToRatio(val);
}
/**
* @hidden
*/
onChange(val: any) {
// used when this input does not have an ngModel or formControlName
this.onTouched();
this._updateBar();
this._cd.detectChanges();
}
/**
* @hidden
*/
onTouched() { }
/**
* @hidden
*/
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
}
/**
* @hidden
*/
ngOnDestroy() {
this._form.deregister(this);
super.ngOnDestroy();
this._events.destroy();
}
}