mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
Merge branch 'refactor-inputs'
This commit is contained in:
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user