ionic-angular
Version:
A powerful framework for building mobile and progressive web apps with JavaScript and Angular 2
326 lines • 11 kB
JavaScript
import { Directive, ElementRef, EventEmitter, HostListener, Output, Renderer } from '@angular/core';
import { NgControl } from '@angular/forms';
import { Config } from '../../config/config';
import { Platform } from '../../platform/platform';
/**
* @hidden
*/
export class NativeInput {
/**
* @param {?} _elementRef
* @param {?} _renderer
* @param {?} config
* @param {?} _plt
* @param {?} ngControl
*/
constructor(_elementRef, _renderer, config, _plt, ngControl) {
this._elementRef = _elementRef;
this._renderer = _renderer;
this._plt = _plt;
this.ngControl = ngControl;
this.focusChange = new EventEmitter();
this.valueChange = new EventEmitter();
this.keydown = new EventEmitter();
this._clone = config.getBoolean('inputCloning', false);
this._blurring = config.getBoolean('inputBlurring', false);
}
/**
* @param {?} ev
* @return {?}
*/
_change(ev) {
this.valueChange.emit(ev.target.value);
}
/**
* @param {?} ev
* @return {?}
*/
_keyDown(ev) {
if (ev) {
ev.target && this.keydown.emit(ev.target.value);
}
}
/**
* @return {?}
*/
_focus() {
var /** @type {?} */ self = this;
self.focusChange.emit(true);
if (self._blurring) {
// automatically blur input if:
// 1) this input has focus
// 2) the newly tapped document element is not an input
(void 0) /* console.debug */;
var /** @type {?} */ unregTouchEnd = this._plt.registerListener(this._plt.doc(), 'touchend', (ev) => {
var /** @type {?} */ tapped = (ev.target);
if (tapped && self.element()) {
if (tapped.tagName !== 'INPUT' && tapped.tagName !== 'TEXTAREA' && !tapped.classList.contains('input-cover')) {
self.element().blur();
}
}
}, {
capture: true,
zone: false
});
self._unrefBlur = function () {
(void 0) /* console.debug */;
unregTouchEnd();
};
}
}
/**
* @return {?}
*/
_blur() {
this.focusChange.emit(false);
this.hideFocus(false);
this._unrefBlur && this._unrefBlur();
this._unrefBlur = null;
}
/**
* @param {?} val
* @return {?}
*/
labelledBy(val) {
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'aria-labelledby', val);
}
/**
* @param {?} val
* @return {?}
*/
isDisabled(val) {
this._renderer.setElementAttribute(this._elementRef.nativeElement, 'disabled', val ? '' : null);
}
/**
* @return {?}
*/
setFocus() {
// let's set focus to the element
// but only if it does not already have focus
if (this._plt.getActiveElement() !== this.element()) {
this.element().focus();
}
}
/**
* @param {?} shouldFocus
* @param {?} inputRelativeY
* @return {?}
*/
beginFocus(shouldFocus, inputRelativeY) {
if (this._relocated !== shouldFocus) {
const /** @type {?} */ focusedInputEle = this.element();
if (shouldFocus) {
// we should focus into this element
if (this._clone) {
// this platform needs the input to be cloned
// this allows for the actual input to receive the focus from
// the user's touch event, but before it receives focus, it
// moves the actual input to a location that will not screw
// up the app's layout, and does not allow the native browser
// to attempt to scroll the input into place (messing up headers/footers)
// the cloned input fills the area of where native input should be
// while the native input fakes out the browser by relocating itself
// before it receives the actual focus event
cloneInputComponent(this._plt, focusedInputEle);
// move the native input to a location safe to receive focus
// according to the browser, the native input receives focus in an
// area which doesn't require the browser to scroll the input into place
((focusedInputEle.style))[this._plt.Css.transform] = `translate3d(-9999px,${inputRelativeY}px,0)`;
focusedInputEle.style.opacity = '0';
}
// let's now set focus to the actual native element
// at this point it is safe to assume the browser will not attempt
// to scroll the input into view itself (screwing up headers/footers)
this.setFocus();
}
else {
// should remove the focus
if (this._clone) {
// should remove the cloned node
removeClone(this._plt, focusedInputEle);
}
}
this._relocated = shouldFocus;
}
}
/**
* @param {?} shouldHideFocus
* @return {?}
*/
hideFocus(shouldHideFocus) {
let /** @type {?} */ focusedInputEle = this.element();
(void 0) /* console.debug */;
if (shouldHideFocus) {
cloneInputComponent(this._plt, focusedInputEle);
((focusedInputEle.style))[this._plt.Css.transform] = 'scale(0)';
}
else {
removeClone(this._plt, focusedInputEle);
}
}
/**
* @param {?} val
* @return {?}
*/
setValue(val) {
this._elementRef.nativeElement['value'] = val;
}
/**
* @return {?}
*/
getValue() {
return this.element().value;
}
/**
* @param {?} val
* @return {?}
*/
setMin(val) {
this._elementRef.nativeElement['min'] = val;
}
/**
* @param {?} val
* @return {?}
*/
setMax(val) {
this._elementRef.nativeElement['max'] = val;
}
/**
* @param {?} val
* @return {?}
*/
setStep(val) {
this._elementRef.nativeElement['step'] = val;
}
/**
* @param {?} cssClass
* @param {?} shouldAdd
* @return {?}
*/
setElementClass(cssClass, shouldAdd) {
this._renderer.setElementClass(this._elementRef.nativeElement, cssClass, shouldAdd);
}
/**
* @return {?}
*/
element() {
return this._elementRef.nativeElement;
}
/**
* @return {?}
*/
ngOnDestroy() {
this._unrefBlur && this._unrefBlur();
}
}
NativeInput.decorators = [
{ type: Directive, args: [{
selector: '.text-input'
},] },
];
/**
* @nocollapse
*/
NativeInput.ctorParameters = () => [
{ type: ElementRef, },
{ type: Renderer, },
{ type: Config, },
{ type: Platform, },
{ type: NgControl, },
];
NativeInput.propDecorators = {
'focusChange': [{ type: Output },],
'valueChange': [{ type: Output },],
'keydown': [{ type: Output },],
'_change': [{ type: HostListener, args: ['input', ['$event'],] },],
'_keyDown': [{ type: HostListener, args: ['keydown', ['$event'],] },],
'_focus': [{ type: HostListener, args: ['focus',] },],
'_blur': [{ type: HostListener, args: ['blur',] },],
};
function NativeInput_tsickle_Closure_declarations() {
/** @type {?} */
NativeInput.decorators;
/**
* @nocollapse
* @type {?}
*/
NativeInput.ctorParameters;
/** @type {?} */
NativeInput.propDecorators;
/** @type {?} */
NativeInput.prototype._relocated;
/** @type {?} */
NativeInput.prototype._clone;
/** @type {?} */
NativeInput.prototype._blurring;
/** @type {?} */
NativeInput.prototype._unrefBlur;
/** @type {?} */
NativeInput.prototype.focusChange;
/** @type {?} */
NativeInput.prototype.valueChange;
/** @type {?} */
NativeInput.prototype.keydown;
/** @type {?} */
NativeInput.prototype._elementRef;
/** @type {?} */
NativeInput.prototype._renderer;
/** @type {?} */
NativeInput.prototype._plt;
/** @type {?} */
NativeInput.prototype.ngControl;
}
/**
* @param {?} plt
* @param {?} srcNativeInputEle
* @return {?}
*/
function cloneInputComponent(plt, srcNativeInputEle) {
// given a native <input> or <textarea> element
// find its parent wrapping component like <ion-input> or <ion-textarea>
// then clone the entire component
const /** @type {?} */ srcComponentEle = (srcNativeInputEle.closest('ion-input,ion-textarea'));
if (srcComponentEle) {
// DOM READ
const /** @type {?} */ srcTop = srcComponentEle.offsetTop;
const /** @type {?} */ srcLeft = srcComponentEle.offsetLeft;
const /** @type {?} */ srcWidth = srcComponentEle.offsetWidth;
const /** @type {?} */ srcHeight = srcComponentEle.offsetHeight;
// DOM WRITE
// not using deep clone so we don't pull in unnecessary nodes
const /** @type {?} */ clonedComponentEle = (srcComponentEle.cloneNode(false));
clonedComponentEle.classList.add('cloned-input');
clonedComponentEle.setAttribute('aria-hidden', 'true');
clonedComponentEle.style.pointerEvents = 'none';
clonedComponentEle.style.position = 'absolute';
clonedComponentEle.style.top = srcTop + 'px';
clonedComponentEle.style.left = srcLeft + 'px';
clonedComponentEle.style.width = srcWidth + 'px';
clonedComponentEle.style.height = srcHeight + 'px';
const /** @type {?} */ clonedNativeInputEle = (srcNativeInputEle.cloneNode(false));
clonedNativeInputEle.value = srcNativeInputEle.value;
clonedNativeInputEle.tabIndex = -1;
clonedComponentEle.appendChild(clonedNativeInputEle);
srcComponentEle.parentNode.appendChild(clonedComponentEle);
srcComponentEle.style.pointerEvents = 'none';
}
((srcNativeInputEle.style))[plt.Css.transform] = 'scale(0)';
}
/**
* @param {?} plt
* @param {?} srcNativeInputEle
* @return {?}
*/
function removeClone(plt, srcNativeInputEle) {
const /** @type {?} */ srcComponentEle = (srcNativeInputEle.closest('ion-input,ion-textarea'));
if (srcComponentEle && srcComponentEle.parentElement) {
const /** @type {?} */ clonedInputEles = srcComponentEle.parentElement.querySelectorAll('.cloned-input');
for (var /** @type {?} */ i = 0; i < clonedInputEles.length; i++) {
clonedInputEles[i].parentNode.removeChild(clonedInputEles[i]);
}
srcComponentEle.style.pointerEvents = '';
}
((srcNativeInputEle.style))[plt.Css.transform] = '';
srcNativeInputEle.style.opacity = '';
}
//# sourceMappingURL=native-input.js.map