mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
204 lines
5.1 KiB
TypeScript
204 lines
5.1 KiB
TypeScript
import {Directive, View, Parent, Ancestor, Optional, ElementRef, Attribute, forwardRef} from 'angular2/angular2';
|
|
|
|
import {IonicDirective} from '../../config/annotations';
|
|
import {IonicConfig} from '../../config/config';
|
|
import {IonInput} from './form';
|
|
import {Ion} from '../ion';
|
|
import {IonicApp} from '../app/app';
|
|
import {Content} from '../content/content';
|
|
import {ClickBlock} from '../../util/click-block';
|
|
import * as dom from '../../util/dom';
|
|
import {Platform} from '../../platform/platform';
|
|
|
|
|
|
@IonicDirective({
|
|
selector: 'ion-input'
|
|
})
|
|
export class Input extends Ion {
|
|
|
|
constructor(
|
|
elementRef: ElementRef,
|
|
ionicConfig: IonicConfig
|
|
) {
|
|
super(elementRef, ionicConfig);
|
|
this.id = ++inputIds;
|
|
}
|
|
|
|
onInit() {
|
|
if (this.input) {
|
|
this.input.id = 'input-' + this.id;
|
|
}
|
|
if (this.label) {
|
|
this.label.id = 'label-' + this.id;
|
|
this.input.labelledBy = this.label.id;
|
|
}
|
|
}
|
|
|
|
registerInput(directive) {
|
|
this.input = directive;
|
|
}
|
|
|
|
registerLabel(directive) {
|
|
this.label = directive;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Directive({
|
|
selector: 'textarea,input[type=text],input[type=password],input[type=number],input[type=search],input[type=email],input[type=url]',
|
|
property: [
|
|
'tabIndex'
|
|
],
|
|
host: {
|
|
'[tabIndex]': 'tabIndex',
|
|
'(focus)': 'receivedFocus(true)',
|
|
'(blur)': 'receivedFocus(false)',
|
|
'(touchstart)': 'pointerStart($event)',
|
|
'(touchend)': 'pointerEnd($event)',
|
|
'(mousedown)': 'pointerStart($event)',
|
|
'(mouseup)': 'pointerEnd($event)',
|
|
'[attr.id]': 'id',
|
|
'[attr.aria-labelledby]': 'labelledBy'
|
|
}
|
|
})
|
|
export class TextInput extends IonInput {
|
|
constructor(
|
|
@Optional() @Parent() container: Input,
|
|
@Optional() @Ancestor() scrollView: Content,
|
|
@Attribute('type') type: string,
|
|
elementRef: ElementRef,
|
|
app: IonicApp,
|
|
config: IonicConfig
|
|
) {
|
|
super(elementRef, config, app, scrollView);
|
|
|
|
if (container) {
|
|
container.registerInput(this);
|
|
this.container = container;
|
|
}
|
|
|
|
this.type = type;
|
|
this.elementRef = elementRef;
|
|
this.tabIndex = this.tabIndex || '';
|
|
|
|
this.scrollAssist = config.setting('keyboardScrollAssist');
|
|
}
|
|
|
|
pointerStart(ev) {
|
|
if (this.scrollAssist) {
|
|
// remember where the touchstart/mousedown started
|
|
this.startCoord = dom.pointerCoord(ev);
|
|
this.pressStart = Date.now();
|
|
}
|
|
}
|
|
|
|
pointerEnd(ev) {
|
|
if (this.scrollAssist) {
|
|
|
|
// get where the touchend/mouseup ended
|
|
let endCoord = dom.pointerCoord(ev);
|
|
|
|
// focus this input if the pointer hasn't moved XX pixels
|
|
// and the input doesn't already have focus
|
|
if (this.startCoord && !dom.hasPointerMoved(20, this.startCoord, endCoord) && !this.hasFocus()) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
|
|
this.focus();
|
|
}
|
|
|
|
this.startCoord = this.pressStart = null;
|
|
}
|
|
}
|
|
|
|
focus() {
|
|
let scrollView = this.scrollView;
|
|
|
|
if (scrollView && this.scrollAssist) {
|
|
// this input is inside of a scroll view
|
|
// scroll the input to the top
|
|
let inputY = this.elementRef.nativeElement.offsetTop - 8;
|
|
|
|
// do not allow any clicks while it's scrolling
|
|
ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 200);
|
|
|
|
// used to put a lot of padding on the bottom of the scroll view
|
|
scrollView.scrollPadding = true;
|
|
|
|
// temporarily move the focus to the focus holder so the browser
|
|
// doesn't freak out while it's trying to get the input in place
|
|
this.setFocusHolder(this.type);
|
|
|
|
// scroll the input into place
|
|
scrollView.scrollTo(0, inputY, SCROLL_INTO_VIEW_DURATION, 8).then(() => {
|
|
// the scroll view is in the correct position now
|
|
// give the native input the focus
|
|
this.setFocus();
|
|
|
|
// all good, allow clicks again
|
|
ClickBlock(false);
|
|
});
|
|
|
|
} else {
|
|
// not inside of a scroll view, just focus it
|
|
this.setFocus();
|
|
}
|
|
|
|
}
|
|
|
|
receivedFocus(receivedFocus) {
|
|
console.log('receivedFocus: ', receivedFocus)
|
|
let self = this;
|
|
let scrollView = self.scrollView;
|
|
|
|
self.isActiveInput(receivedFocus);
|
|
|
|
function touchMove(ev) {
|
|
console.log('touchMove')
|
|
if (!self.isPressHold()) {
|
|
self.setFocusHolder(self.type);
|
|
self.deregTouchMove();
|
|
}
|
|
}
|
|
|
|
if (scrollView && this.scrollAssist) {
|
|
if (receivedFocus) {
|
|
// when the input has focus, then the focus holder
|
|
// should not be able to be focused
|
|
self.deregTouchMove = scrollView && scrollView.addTouchMoveListener(touchMove);
|
|
|
|
} else {
|
|
// the input no longer has focus
|
|
self.deregTouchMove && self.deregTouchMove();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
isPressHold() {
|
|
console.log('pressStart:', this.pressStart, ' pressStart + 500 < now:', this.pressStart + 500 < Date.now())
|
|
return this.pressStart && (this.pressStart + 500 < Date.now());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Directive({
|
|
selector: 'label',
|
|
host: {
|
|
'[attr.id]': 'id'
|
|
}
|
|
})
|
|
export class InputLabel {
|
|
constructor(@Optional() @Parent() container: Input) {
|
|
if (container) {
|
|
container.registerLabel(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
const SCROLL_INTO_VIEW_DURATION = 500;
|
|
|
|
let inputIds = -1;
|