mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
wip
This commit is contained in:
106
ionic/animations/scroll-to.ts
Normal file
106
ionic/animations/scroll-to.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import {raf} from '../util/dom';
|
||||
|
||||
|
||||
export class ScrollTo {
|
||||
|
||||
constructor(ele, x, y, duration) {
|
||||
if (typeof ele === 'string') {
|
||||
// string query selector
|
||||
ele = document.querySelector(ele);
|
||||
}
|
||||
|
||||
if (ele) {
|
||||
if (ele.nativeElement) {
|
||||
// angular ElementRef
|
||||
ele = ele.nativeElement;
|
||||
}
|
||||
|
||||
if (ele.nodeType === 1) {
|
||||
this._el = ele;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start(x, y, duration, tolerance) {
|
||||
// scroll animation loop w/ easing
|
||||
// credit https://gist.github.com/dezinezync/5487119
|
||||
let self = this;
|
||||
|
||||
if (!self._el) {
|
||||
// invalid element
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
x = x || 0;
|
||||
y = y || 0;
|
||||
tolerance = tolerance || 0;
|
||||
|
||||
let ele = self._el;
|
||||
let fromY = ele.scrollTop;
|
||||
let fromX = ele.scrollLeft;
|
||||
|
||||
let xDistance = Math.abs(x - fromX);
|
||||
let yDistance = Math.abs(y - fromY);
|
||||
|
||||
if (yDistance <= tolerance && xDistance <= tolerance) {
|
||||
// prevent scrolling if already close to there
|
||||
this._el = ele = null;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let start = Date.now();
|
||||
|
||||
// start scroll loop
|
||||
self.isPlaying = true;
|
||||
raf(step);
|
||||
|
||||
// decelerating to zero velocity
|
||||
function easeOutCubic(t) {
|
||||
return (--t) * t * t + 1;
|
||||
}
|
||||
|
||||
// scroll loop
|
||||
function step() {
|
||||
let time = Math.min(1, ((Date.now() - start) / duration));
|
||||
|
||||
// where .5 would be 50% of time on a linear scale easedT gives a
|
||||
// fraction based on the easing method
|
||||
let easedT = easeOutCubic(time);
|
||||
|
||||
if (fromY != y) {
|
||||
ele.scrollTop = parseInt((easedT * (y - fromY)) + fromY, 10);
|
||||
}
|
||||
if (fromX != x) {
|
||||
ele.scrollLeft = parseInt((easedT * (x - fromX)) + fromX, 10);
|
||||
}
|
||||
|
||||
if (time < 1 && self.isPlaying) {
|
||||
raf(step);
|
||||
|
||||
} else if (!self.isPlaying) {
|
||||
// stopped
|
||||
this._el = ele = null;
|
||||
reject();
|
||||
|
||||
} else {
|
||||
// done
|
||||
this._el = ele = null;
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.isPlaying = false;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.stop();
|
||||
this._el = null;
|
||||
}
|
||||
|
||||
}
|
@ -8,8 +8,8 @@ export * from 'ionic/components/icon/icon'
|
||||
export * from 'ionic/components/item/item'
|
||||
export * from 'ionic/components/item/item-group'
|
||||
export * from 'ionic/components/form/form'
|
||||
export * from 'ionic/components/form/input/input'
|
||||
export * from 'ionic/components/form/label/label'
|
||||
export * from 'ionic/components/form/input'
|
||||
export * from 'ionic/components/form/label'
|
||||
export * from 'ionic/components/list/list'
|
||||
export * from 'ionic/components/modal/modal'
|
||||
export * from 'ionic/components/nav/nav'
|
||||
|
@ -11,6 +11,7 @@ import * as util from '../../util/util';
|
||||
// injectables
|
||||
import {ActionMenu} from '../action-menu/action-menu';
|
||||
import {Modal} from '../modal/modal';
|
||||
import {FocusHolder} from '../form/focus-holder';
|
||||
|
||||
|
||||
export class IonicApp {
|
||||
@ -29,6 +30,13 @@ export class IonicApp {
|
||||
this._zone = this.injector().get(NgZone);
|
||||
}
|
||||
|
||||
focusHolder(val) {
|
||||
if (arguments.length) {
|
||||
this._focusHolder = val;
|
||||
}
|
||||
return this._focusHolder;
|
||||
}
|
||||
|
||||
title(val) {
|
||||
document.title = val;
|
||||
}
|
||||
@ -206,6 +214,13 @@ export function ionicBootstrap(component, config, router) {
|
||||
bootstrap(component, injectableBindings).then(appRef => {
|
||||
app.load(appRef);
|
||||
|
||||
// append the focus holder if its needed
|
||||
if (config.setting('keyboardScrollAssist')) {
|
||||
app.appendComponent(FocusHolder).then(ref => {
|
||||
app.focusHolder(ref.instance);
|
||||
});
|
||||
}
|
||||
|
||||
router.load(window, app, config).then(() => {
|
||||
// resolve that the app has loaded
|
||||
resolve(app);
|
||||
|
@ -1,10 +1,11 @@
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
|
@ -90,7 +90,7 @@ $content-padding: 10px !default;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
z-index: $z-index-click-block;
|
||||
transform: translate3d(-9999px, 0px, 0px);
|
||||
transform: translate3d(-9999px, 0px, 0px);;
|
||||
|
||||
//background: red;
|
||||
//opacity: .3;
|
||||
|
@ -3,13 +3,17 @@ import {Component, View, ElementRef} from 'angular2/angular2';
|
||||
import {Ion} from '../ion';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {IonicComponent} from '../../config/annotations';
|
||||
import {ScrollTo} from '../../animations/scroll-to';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'ion-content',
|
||||
properties: [
|
||||
'parallax'
|
||||
]
|
||||
],
|
||||
host: {
|
||||
['[class.scroll-padding]']: 'scrollPadding'
|
||||
}
|
||||
})
|
||||
@View({
|
||||
template: '<div class="scroll-content"><content></content></div>'
|
||||
@ -17,6 +21,7 @@ import {IonicComponent} from '../../config/annotations';
|
||||
export class Content extends Ion {
|
||||
constructor(elementRef: ElementRef, ionicConfig: IonicConfig) {
|
||||
super(elementRef, ionicConfig);
|
||||
this.scrollPadding = false;
|
||||
}
|
||||
|
||||
onIonInit() {
|
||||
@ -32,4 +37,33 @@ export class Content extends Ion {
|
||||
this.scrollElement.removeEventListener('scroll', handler);
|
||||
}
|
||||
}
|
||||
|
||||
addTouchMoveListener(handler) {
|
||||
if(!this.scrollElement) { return; }
|
||||
|
||||
this.scrollElement.addEventListener('touchmove', handler);
|
||||
|
||||
return () => {
|
||||
this.scrollElement.removeEventListener('touchmove', handler);
|
||||
}
|
||||
}
|
||||
|
||||
scrollTo(x, y, duration, tolerance) {
|
||||
if (this._scrollTo) {
|
||||
this._scrollTo.dispose();
|
||||
}
|
||||
|
||||
this._scrollTo = new ScrollTo(this.scrollElement);
|
||||
|
||||
return this._scrollTo.start(x, y, duration, tolerance);
|
||||
}
|
||||
|
||||
get scrollPadding() {
|
||||
return this._sp;
|
||||
}
|
||||
|
||||
set scrollPadding(val) {
|
||||
this._sp = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
108
ionic/components/form/focus-holder.ts
Normal file
108
ionic/components/form/focus-holder.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import {Component, Directive, View, Parent, ElementRef, forwardRef} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import * as dom from '../../util/dom';
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {IonInput} from './form';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'focus-holder'
|
||||
})
|
||||
@View({
|
||||
template: '<input><input><input>',
|
||||
directives: [forwardRef(() => FocusInput)]
|
||||
})
|
||||
export class FocusHolder {
|
||||
constructor() {
|
||||
this.i = [];
|
||||
}
|
||||
|
||||
setFocusHolder(inputType) {
|
||||
IonInput.clearTabIndexes();
|
||||
|
||||
this.i[1].tabIndex = ACTIVE_TAB_INDEX;
|
||||
this.i[1].type = inputType;
|
||||
this.i[1].focus();
|
||||
}
|
||||
|
||||
setActiveInput(input) {
|
||||
IonInput.clearTabIndexes();
|
||||
|
||||
this.i[1].tabIndex = -1;
|
||||
|
||||
input.tabIndex = ACTIVE_TAB_INDEX;
|
||||
}
|
||||
|
||||
receivedFocus(tabIndex) {
|
||||
if (tabIndex === PREVIOUS_TAB_INDEX) {
|
||||
// they tabbed back one input
|
||||
// reset the focus to the center focus holder
|
||||
this.i[1].focus();
|
||||
|
||||
// focus on the previous input
|
||||
IonInput.focusPrevious();
|
||||
|
||||
} else if (tabIndex === NEXT_TAB_INDEX) {
|
||||
// they tabbed to the next input
|
||||
// reset the focus to the center focus holder
|
||||
this.i[1].focus();
|
||||
|
||||
// focus on the next input
|
||||
IonInput.focusNext();
|
||||
}
|
||||
}
|
||||
|
||||
register(input) {
|
||||
// register each of the focus holder inputs
|
||||
// assign them their correct tab indexes
|
||||
input.tabIndex = PREVIOUS_TAB_INDEX + this.i.length;
|
||||
this.i.push(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'input',
|
||||
properties: [
|
||||
'tabIndex'
|
||||
],
|
||||
host: {
|
||||
'[tabIndex]': 'tabIndex',
|
||||
'[type]': 'type',
|
||||
'(focus)': 'holder.receivedFocus(tabIndex)',
|
||||
'(keydown)': 'keydown($event)'
|
||||
}
|
||||
})
|
||||
class FocusInput {
|
||||
constructor(elementRef: ElementRef, @Parent() holder: FocusHolder) {
|
||||
this.elementRef = elementRef;
|
||||
holder.register(this);
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.elementRef.nativeElement.focus();
|
||||
}
|
||||
|
||||
keydown(ev) {
|
||||
// prevent any keyboard typing when a holder has focus
|
||||
if (ev.keyCode !== 9) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
get type() {
|
||||
// default to text type if unknown
|
||||
return this._t || 'text';
|
||||
}
|
||||
|
||||
set type(val) {
|
||||
this._t = val;
|
||||
}
|
||||
}
|
||||
|
||||
const PREVIOUS_TAB_INDEX = 999;
|
||||
const ACTIVE_TAB_INDEX = 1000;
|
||||
const NEXT_TAB_INDEX = 1001;
|
@ -1 +1,87 @@
|
||||
// form
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import * as dom from '../../util/dom';
|
||||
|
||||
let inputRegistry = [];
|
||||
let activeInput = null;
|
||||
let lastInput = null;
|
||||
|
||||
|
||||
export class IonInput {
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
app: IonicApp,
|
||||
scrollView: Content
|
||||
) {
|
||||
this.elementRef = elementRef;
|
||||
this.app = app;
|
||||
this.scrollView = scrollView;
|
||||
|
||||
inputRegistry.push(this);
|
||||
}
|
||||
|
||||
hasFocus() {
|
||||
return dom.hasFocus(this.elementRef);
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.setFocus();
|
||||
}
|
||||
|
||||
setFocus() {
|
||||
// TODO: How do you do this w/ NG2?
|
||||
this.elementRef.nativeElement.focus();
|
||||
}
|
||||
|
||||
setFocusHolder(type) {
|
||||
let focusHolder = this.app.focusHolder();
|
||||
focusHolder && focusHolder.setFocusHolder(type);
|
||||
}
|
||||
|
||||
isActiveInput(shouldBeActive) {
|
||||
if (shouldBeActive) {
|
||||
if (activeInput && activeInput !== lastInput) {
|
||||
lastInput = activeInput;
|
||||
}
|
||||
|
||||
activeInput = this;
|
||||
|
||||
let focusHolder = this.app.focusHolder();
|
||||
focusHolder && focusHolder.setActiveInput(activeInput);
|
||||
|
||||
} else if (activeInput === this) {
|
||||
lastInput = activeInput;
|
||||
activeInput = null;
|
||||
}
|
||||
}
|
||||
|
||||
sibling(inc) {
|
||||
let index = inputRegistry.indexOf(this);
|
||||
if (index > -1) {
|
||||
return inputRegistry[index + inc];
|
||||
}
|
||||
}
|
||||
|
||||
static focusPrevious() {
|
||||
this.focusMove(-1);
|
||||
}
|
||||
|
||||
static focusNext() {
|
||||
this.focusMove(1);
|
||||
}
|
||||
|
||||
static focusMove(inc) {
|
||||
let input = activeInput || lastInput;
|
||||
if (input) {
|
||||
let siblingInput = input.sibling(inc);
|
||||
siblingInput && siblingInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
static clearTabIndexes() {
|
||||
for (let i = 0; i < inputRegistry.length; i++) {
|
||||
inputRegistry[i].tabIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,28 @@ $item-input-padding: 6px 0 5px 0px;
|
||||
|
||||
ion-input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input.disable-focus,
|
||||
textarea.disable-focus,
|
||||
select.disable-focus {
|
||||
//pointer-events: none;
|
||||
}
|
||||
|
||||
focus-holder input {
|
||||
position: fixed;
|
||||
top: 1px;
|
||||
width: 9px;
|
||||
left: -9999px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.scroll-padding.scroll-padding .scroll-content {
|
||||
padding-bottom: 1000px;
|
||||
}
|
||||
|
||||
/*ion-input {
|
||||
display: block;
|
||||
|
||||
|
||||
position: relative;
|
||||
@ -28,3 +50,4 @@ ion-input {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
*/
|
198
ionic/components/form/input.ts
Normal file
198
ionic/components/form/input.ts
Normal file
@ -0,0 +1,198 @@
|
||||
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',
|
||||
'[class.disable-focus]': 'disableFocus'
|
||||
}
|
||||
})
|
||||
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, 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) {
|
||||
this.startCoord = dom.pointerCoord(ev);
|
||||
this.disableFocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
pointerEnd(ev) {
|
||||
if (this.scrollAssist) {
|
||||
let endCoord = dom.pointerCoord(ev);
|
||||
|
||||
if (this.startCoord && !dom.hasPointerMoved(20, this.startCoord, endCoord) && !this.hasFocus()) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
this.focus();
|
||||
|
||||
} else {
|
||||
this.disableFocus = false;
|
||||
}
|
||||
|
||||
this.startCoord = null;
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
let scrollView = this.scrollView;
|
||||
|
||||
if (scrollView && this.scrollAssist) {
|
||||
this.disableFocus = true;
|
||||
|
||||
// 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);
|
||||
|
||||
this.disableFocus = false;
|
||||
});
|
||||
|
||||
} else {
|
||||
// not inside of a scroll view, just focus it
|
||||
this.setFocus();
|
||||
this.disableFocus = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
receivedFocus(receivedFocus) {
|
||||
let self = this;
|
||||
let scrollView = self.scrollView;
|
||||
|
||||
self.isActiveInput(receivedFocus);
|
||||
|
||||
function touchMove(ev) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@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;
|
@ -1,12 +0,0 @@
|
||||
import {Component, Directive} from 'angular2/angular2';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-input'
|
||||
})
|
||||
export class Input {
|
||||
constructor() {
|
||||
//this.config = Button.config.invoke(this)
|
||||
console.log('INPUT');
|
||||
}
|
||||
}
|
7
ionic/components/form/label.ts
Normal file
7
ionic/components/form/label.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {Directive} from 'angular2/angular2';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-label'
|
||||
})
|
||||
export class Label {}
|
@ -1,10 +0,0 @@
|
||||
import {Component, Directive} from 'angular2/angular2';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-label'
|
||||
})
|
||||
export class Label {
|
||||
constructor() {
|
||||
}
|
||||
}
|
1
ionic/components/form/test/input/e2e.ts
Normal file
1
ionic/components/form/test/input/e2e.ts
Normal file
@ -0,0 +1 @@
|
||||
|
7
ionic/components/form/test/input/index.ts
Normal file
7
ionic/components/form/test/input/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {App} from 'ionic/ionic';
|
||||
|
||||
|
||||
@App({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class IonicApp {}
|
92
ionic/components/form/test/input/main.html
Normal file
92
ionic/components/form/test/input/main.html
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
<ion-toolbar><ion-title>Header</ion-title></ion-toolbar>
|
||||
|
||||
|
||||
<ion-content class="padding">
|
||||
|
||||
<ion-input>
|
||||
<input value="1" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="2" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="3" type="number">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<textarea>4</textarea>
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="5" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="6" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<textarea>7</textarea>
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="8" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="9" type="number">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<textarea>10</textarea>
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="11" type="text">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<input value="12" type="number">
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<textarea>13</textarea>
|
||||
</ion-input>
|
||||
|
||||
<ion-input>
|
||||
<textarea>14</textarea>
|
||||
</ion-input>
|
||||
|
||||
</ion-content>
|
||||
|
||||
|
||||
<ion-toolbar><ion-title>Footer</ion-title></ion-toolbar>
|
||||
|
||||
|
||||
<style>
|
||||
input, textarea {
|
||||
border: 1px solid red !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
focus-holder input:focus {
|
||||
background: red !important;
|
||||
}
|
||||
|
||||
focus-holder input:nth-child(1) {
|
||||
left: 200px !important;
|
||||
}
|
||||
|
||||
focus-holder input:nth-child(2) {
|
||||
left: 240px !important;
|
||||
}
|
||||
|
||||
focus-holder input:nth-child(3) {
|
||||
left: 280px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
List, Item, ItemGroup, ItemGroupTitle,
|
||||
Toolbar,
|
||||
Icon,
|
||||
Checkbox, Switch, Label, Input,
|
||||
Checkbox, Switch,
|
||||
Input, TextInput, InputLabel,
|
||||
Segment, SegmentButton, SegmentControlValueAccessor,
|
||||
RadioGroup, RadioButton, SearchBar,
|
||||
Nav, NavbarTemplate, Navbar, NavPush, NavPop,
|
||||
@ -50,13 +51,18 @@ export const IonicDirectives = [
|
||||
// Media
|
||||
forwardRef(() => Icon),
|
||||
|
||||
// Form elements
|
||||
// Form
|
||||
forwardRef(() => Segment),
|
||||
forwardRef(() => SegmentButton),
|
||||
forwardRef(() => SegmentControlValueAccessor),
|
||||
//Checkbox, Switch, Label, Input
|
||||
//Checkbox, Switch
|
||||
//RadioGroup, RadioButton, SearchBar,
|
||||
|
||||
// Input
|
||||
forwardRef(() => Input),
|
||||
forwardRef(() => TextInput),
|
||||
forwardRef(() => InputLabel),
|
||||
|
||||
// Nav
|
||||
forwardRef(() => Nav),
|
||||
forwardRef(() => NavbarTemplate),
|
||||
|
@ -33,8 +33,8 @@
|
||||
"components/content/content",
|
||||
"components/item/item",
|
||||
"components/form/form",
|
||||
"components/form/label/label",
|
||||
"components/form/input/input",
|
||||
"components/form/label",
|
||||
"components/form/input",
|
||||
"components/layout/layout",
|
||||
"components/list/list",
|
||||
"components/modal/modal",
|
||||
|
@ -71,7 +71,8 @@ Platform.register({
|
||||
settings: {
|
||||
mode: 'ios',
|
||||
viewTransition: 'ios',
|
||||
tapPolyfill: true
|
||||
tapPolyfill: true,
|
||||
keyboardScrollAssist: true
|
||||
},
|
||||
isMatch(p) {
|
||||
return p.isPlatform('ios', 'iphone|ipad|ipod');
|
||||
|
@ -3,6 +3,10 @@ const DEFAULT_EXPIRE = 330;
|
||||
let cbEle, fallbackTimerId;
|
||||
let isShowing = false;
|
||||
|
||||
function disableInput(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
function show(expire) {
|
||||
clearTimeout(fallbackTimerId);
|
||||
@ -18,6 +22,7 @@ function show(expire) {
|
||||
cbEle.className = 'click-block ' + CSS_CLICK_BLOCK;
|
||||
document.body.appendChild(cbEle);
|
||||
}
|
||||
cbEle.addEventListener('touchmove', disableInput);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +31,7 @@ function hide() {
|
||||
if (isShowing) {
|
||||
cbEle.classList.remove(CSS_CLICK_BLOCK);
|
||||
isShowing = false;
|
||||
cbEle.removeEventListener('touchmove', disableInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,3 +158,27 @@ export function windowLoad(callback) {
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
export function pointerCoord(ev) {
|
||||
// get coordinates for either a mouse click
|
||||
// or a touch depending on the given event
|
||||
let c = { x: 0, y: 0 };
|
||||
if (ev) {
|
||||
const touches = ev.touches && ev.touches.length ? ev.touches : [ev];
|
||||
const e = (ev.changedTouches && ev.changedTouches[0]) || touches[0];
|
||||
if (e) {
|
||||
c.x = e.clientX || e.pageX || 0;
|
||||
c.y = e.clientY || e.pageY || 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
export function hasPointerMoved(tolerance, startCoord, endCoord) {
|
||||
return Math.abs(startCoord.x - endCoord.x) > tolerance ||
|
||||
Math.abs(startCoord.y - endCoord.y) > tolerance;
|
||||
}
|
||||
|
||||
export function hasFocus(ele) {
|
||||
return !!(ele && (document.activeElement === ele.nativeElement || document.activeElement === ele));
|
||||
}
|
||||
|
@ -103,8 +103,8 @@ var tapEventListeners = {
|
||||
Platform.ready().then(config => {
|
||||
|
||||
if (config.setting('tapPolyfill')) {
|
||||
console.log('Tap.register, tapPolyfill')
|
||||
Tap.register(document);
|
||||
// console.log('Tap.register, tapPolyfill')
|
||||
// Tap.register(document);
|
||||
}
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user