mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Merge branch 'master' of github.com:driftyco/ionic2
This commit is contained in:
@@ -6,7 +6,7 @@ export * from 'ionic/components/blur/blur'
|
||||
export * from 'ionic/components/button/button'
|
||||
export * from 'ionic/components/checkbox/checkbox'
|
||||
export * from 'ionic/components/content/content'
|
||||
export * from 'ionic/components/form/input'
|
||||
export * from 'ionic/components/form/form'
|
||||
export * from 'ionic/components/icon/icon'
|
||||
export * from 'ionic/components/item/item'
|
||||
export * from 'ionic/components/item/item-group'
|
||||
|
||||
@@ -121,8 +121,8 @@ a[button] {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.padding > button[block]:first-child,
|
||||
.padding > [button][block]:first-child {
|
||||
[padding] > button[block]:first-child,
|
||||
[padding] > [button][block]:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {Component, View, Directive, ElementRef, Optional, NgControl} from 'angular2/angular2';
|
||||
import {Component, View, Directive, Optional, NgControl} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {IonInput} from '../form/input';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {IonicForm} from '../form/form';
|
||||
|
||||
/**
|
||||
* The checkbox is no different than the HTML checkbox input, except it's styled differently
|
||||
@@ -44,21 +43,14 @@ import {IonicConfig} from '../../config/config';
|
||||
'<ng-content></ng-content>' +
|
||||
'</ion-item-content>'
|
||||
})
|
||||
export class Checkbox extends Ion {
|
||||
/**
|
||||
* TODO
|
||||
* @param {ElementRef} elementRef TODO
|
||||
* @param {IonicConfig} ionicConfig TODO
|
||||
* @param {NgControl=} ngControl TODO
|
||||
*/
|
||||
export class Checkbox {
|
||||
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
config: IonicConfig,
|
||||
form: IonicForm,
|
||||
@Optional() ngControl: NgControl
|
||||
) {
|
||||
super(elementRef, config);
|
||||
this.tabIndex = 0;
|
||||
this.id = IonInput.nextId();
|
||||
this.form = form;
|
||||
form.register(this);
|
||||
|
||||
this.onChange = (_) => {};
|
||||
this.onTouched = (_) => {};
|
||||
@@ -72,8 +64,7 @@ export class Checkbox extends Ion {
|
||||
* TODO
|
||||
*/
|
||||
onInit() {
|
||||
super.onInit();
|
||||
this.labelId = 'label-' + this.id;
|
||||
this.labelId = 'label-' + this.inputId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,4 +112,8 @@ export class Checkbox extends Ion {
|
||||
* @param {Function} fn onTouched event handler.
|
||||
*/
|
||||
registerOnTouched(fn) { this.onTouched = fn; }
|
||||
|
||||
onDestroy() {
|
||||
this.form.deregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,35 +33,33 @@ scroll-content {
|
||||
$content-padding: 16px !default;
|
||||
|
||||
|
||||
.padding,
|
||||
[padding],
|
||||
.padding > scroll-content,
|
||||
[padding] > scroll-content {
|
||||
padding: $content-padding;
|
||||
}
|
||||
|
||||
.padding-top {
|
||||
[padding-top] {
|
||||
padding-top: $content-padding;
|
||||
}
|
||||
|
||||
.padding-right {
|
||||
[padding-right] {
|
||||
padding-right: $content-padding;
|
||||
}
|
||||
|
||||
.padding-bottom {
|
||||
[padding-bottom] {
|
||||
padding-bottom: $content-padding;
|
||||
}
|
||||
|
||||
.padding-left {
|
||||
[padding-left] {
|
||||
padding-left: $content-padding;
|
||||
}
|
||||
|
||||
.padding-vertical {
|
||||
[padding-vertical] {
|
||||
padding-top: $content-padding;
|
||||
padding-bottom: $content-padding;
|
||||
}
|
||||
|
||||
.padding-horizontal {
|
||||
[padding-horizontal] {
|
||||
padding-right: $content-padding;
|
||||
padding-left: $content-padding;
|
||||
}
|
||||
|
||||
@@ -5,35 +5,33 @@
|
||||
$content-padding-md: 16px !default;
|
||||
|
||||
|
||||
.padding,
|
||||
[padding],
|
||||
.padding > scroll-content,
|
||||
[padding] > scroll-content {
|
||||
padding: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-top {
|
||||
[padding-top] {
|
||||
padding-top: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-right {
|
||||
[padding-right] {
|
||||
padding-right: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-bottom {
|
||||
[padding-bottom] {
|
||||
padding-bottom: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-left {
|
||||
[padding-left] {
|
||||
padding-left: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-vertical {
|
||||
[padding-vertical] {
|
||||
padding-top: $content-padding-md;
|
||||
padding-bottom: $content-padding-md;
|
||||
}
|
||||
|
||||
.padding-horizontal {
|
||||
[padding-horizontal] {
|
||||
padding-right: $content-padding-md;
|
||||
padding-left: $content-padding-md;
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import {Component, Directive, View, Host, Attribute, ElementRef, forwardRef} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {IonInput} from './input';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
@Component({
|
||||
selector: 'focus-holder'
|
||||
})
|
||||
@View({
|
||||
template: '<input tabindex="999"><input tabindex="1001"><input tabindex="1002">',
|
||||
directives: [forwardRef(() => FocusInput)]
|
||||
})
|
||||
export class FocusHolder {
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
constructor() {
|
||||
this.i = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} inputType TODO
|
||||
*/
|
||||
setFocusHolder(inputType) {
|
||||
this.i[2].type = inputType;
|
||||
this.i[2].setFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} tabIndex TODO
|
||||
*/
|
||||
receivedFocus(tabIndex) {
|
||||
if (tabIndex === '999') {
|
||||
// focus on the previous input
|
||||
IonInput.focusPrevious();
|
||||
|
||||
} else if (tabIndex === '1001') {
|
||||
// focus on the next input
|
||||
IonInput.focusNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} input TODO
|
||||
*/
|
||||
register(input) {
|
||||
this.i.push(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'input',
|
||||
host: {
|
||||
'[type]': 'type',
|
||||
'(focus)': 'holder.receivedFocus(tabindex)',
|
||||
'(keydown)': 'keydown($event)'
|
||||
}
|
||||
})
|
||||
class FocusInput {
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
@Host() holder: FocusHolder,
|
||||
@Attribute('tabindex') tabindex: string
|
||||
) {
|
||||
this.elementRef = elementRef;
|
||||
this.holder = holder;
|
||||
this.tabindex = tabindex;
|
||||
this.holder.register(this);
|
||||
}
|
||||
|
||||
setFocus() {
|
||||
this.elementRef.nativeElement.focus();
|
||||
}
|
||||
|
||||
keydown(ev) {
|
||||
// prevent any keyboard typing when a holder has focus
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
get type() {
|
||||
// default to text type if unknown
|
||||
return this._t || 'text';
|
||||
}
|
||||
|
||||
set type(val) {
|
||||
this._t = val;
|
||||
}
|
||||
}
|
||||
235
ionic/components/form/form.ts
Normal file
235
ionic/components/form/form.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
import {Injectable, NgZone} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {raf} from '../../util/dom';
|
||||
|
||||
/**
|
||||
* The Input component is used to focus text input elements.
|
||||
*
|
||||
* The `focusNext()` and `focusPrevious()` methods make it easy to focus input elements across all devices.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-input>
|
||||
* <ion-label>Name</ion-label>
|
||||
* <input value="Name" type="text">
|
||||
* </ion-input>
|
||||
* ```
|
||||
*/
|
||||
@Injectable()
|
||||
export class IonicForm {
|
||||
|
||||
constructor(config: IonicConfig, zone: NgZone) {
|
||||
this._config = config;
|
||||
this._zone = zone;
|
||||
|
||||
this._inputs = [];
|
||||
this._ids = -1;
|
||||
this._focused = null;
|
||||
|
||||
zone.runOutsideAngular(() => {
|
||||
if (this._config.get('keyboardScrollAssist')) {
|
||||
this.initHolders(document);
|
||||
}
|
||||
|
||||
if (this._config.get('keyboardInputListener') !== false) {
|
||||
this.initKeyInput(document);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
initKeyInput(document) {
|
||||
/* Focus Outline
|
||||
* --------------------------------------------------
|
||||
* When a keydown event happens, from a tab key, then the
|
||||
* 'key-input' class is added to the body element so focusable
|
||||
* elements have an outline. On a mousedown or touchstart
|
||||
* event then the 'key-input' class is removed.
|
||||
*/
|
||||
|
||||
let isKeyInputEnabled = false;
|
||||
|
||||
function keyDown(ev) {
|
||||
if (!isKeyInputEnabled && ev.keyCode == 9) {
|
||||
isKeyInputEnabled = true;
|
||||
raf(enableKeyInput);
|
||||
}
|
||||
}
|
||||
|
||||
function pointerDown() {
|
||||
isKeyInputEnabled = false;
|
||||
raf(enableKeyInput);
|
||||
}
|
||||
|
||||
|
||||
function enableKeyInput() {
|
||||
document.body.classList[isKeyInputEnabled ? 'add' : 'remove']('key-input');
|
||||
|
||||
document.removeEventListener('mousedown', pointerDown);
|
||||
document.removeEventListener('touchstart', pointerDown);
|
||||
|
||||
if (isKeyInputEnabled) {
|
||||
document.addEventListener('mousedown', pointerDown);
|
||||
document.addEventListener('touchstart', pointerDown);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', keyDown);
|
||||
}
|
||||
|
||||
initHolders(document) {
|
||||
// raw DOM fun
|
||||
this._holder = document.createElement('focus-holder');
|
||||
|
||||
this._prev = document.createElement('input');
|
||||
this._prev.tabIndex = NO_FOCUS_TAB_INDEX;
|
||||
this._holder.appendChild(this._prev);
|
||||
|
||||
this._next = document.createElement('input');
|
||||
this._next.tabIndex = NO_FOCUS_TAB_INDEX;
|
||||
this._holder.appendChild(this._next);
|
||||
|
||||
this._temp = document.createElement('input');
|
||||
this._temp.tabIndex = NO_FOCUS_TAB_INDEX;
|
||||
this._holder.appendChild(this._temp);
|
||||
|
||||
document.body.appendChild(this._holder);
|
||||
|
||||
function preventDefault(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
this._prev.addEventListener('keydown', preventDefault);
|
||||
this._next.addEventListener('keydown', preventDefault);
|
||||
this._temp.addEventListener('keydown', preventDefault);
|
||||
|
||||
this._prev.addEventListener('focus', () => {
|
||||
this.focusPrevious();
|
||||
});
|
||||
|
||||
this._next.addEventListener('focus', () => {
|
||||
this.focusNext();
|
||||
});
|
||||
|
||||
let self = this;
|
||||
let resetTimer;
|
||||
function queueReset() {
|
||||
clearTimeout(resetTimer);
|
||||
|
||||
resetTimer = setTimeout(function() {
|
||||
self._zone.run(() => {
|
||||
self.resetInputs();
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
document.addEventListener('focusin', queueReset);
|
||||
document.addEventListener('focusout', queueReset);
|
||||
}
|
||||
|
||||
setFocusHolder(type) {
|
||||
if (this._temp) {
|
||||
this._temp.tabIndex = TEMP_TAB_INDEX;
|
||||
|
||||
this._temp.type = type || 'text';
|
||||
console.debug('setFocusHolder', this._temp.type);
|
||||
this._temp.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TODO} input TODO
|
||||
*/
|
||||
register(input) {
|
||||
console.debug('register input', input);
|
||||
|
||||
input.inputId = ++this._ids;
|
||||
input.tabIndex = NORMAL_FOCUS_TAB_INDEX;
|
||||
this._inputs.push(input);
|
||||
}
|
||||
|
||||
deregister(input) {
|
||||
console.debug('deregister input', input);
|
||||
|
||||
let index = this._inputs.indexOf(input);
|
||||
if (index > -1) {
|
||||
this._inputs.splice(index, 1);
|
||||
}
|
||||
if (input === this._focused) {
|
||||
this._focused = null;
|
||||
}
|
||||
}
|
||||
|
||||
resetInputs() {
|
||||
this._focused = null;
|
||||
|
||||
for (let i = 0, ii = this._inputs.length; i < ii; i++) {
|
||||
if (!this._focused && this._inputs[i].hasFocus) {
|
||||
this._focused = this._inputs[i];
|
||||
this._focused.tabIndex = ACTIVE_FOCUS_TAB_INDEX;
|
||||
|
||||
} else {
|
||||
this._inputs[i].tabIndex = NORMAL_FOCUS_TAB_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._temp) {
|
||||
this._temp.tabIndex = NO_FOCUS_TAB_INDEX;
|
||||
|
||||
if (this._focused) {
|
||||
// there's a focused input
|
||||
this._prev.tabIndex = PREV_TAB_INDEX;
|
||||
this._next.tabIndex = NEXT_TAB_INDEX;
|
||||
|
||||
} else {
|
||||
this._prev.tabIndex = this._next.tabIndex = NO_FOCUS_TAB_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the previous input element, if it exists.
|
||||
*/
|
||||
focusPrevious() {
|
||||
console.debug('focusPrevious');
|
||||
this.focusMove(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the next input element, if it exists.
|
||||
*/
|
||||
focusNext() {
|
||||
console.debug('focusNext');
|
||||
this.focusMove(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} inc TODO
|
||||
*/
|
||||
focusMove(inc) {
|
||||
let input = this._focused;
|
||||
if (input) {
|
||||
let index = this._inputs.indexOf(input);
|
||||
if (index > -1 && (index + inc) < this._inputs.length) {
|
||||
let siblingInput = this._inputs[index + inc];
|
||||
if (siblingInput) {
|
||||
siblingInput.initFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._focused.initFocus();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const NO_FOCUS_TAB_INDEX = -1;
|
||||
const NORMAL_FOCUS_TAB_INDEX = 0;
|
||||
const PREV_TAB_INDEX = 999;
|
||||
const ACTIVE_FOCUS_TAB_INDEX = 1000;
|
||||
const NEXT_TAB_INDEX = 1001;
|
||||
const TEMP_TAB_INDEX = 2000;
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import {Directive, ElementRef, Query, QueryList} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {IonicApp} from '../app/app';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
|
||||
|
||||
let inputRegistry = [];
|
||||
let inputItemIds = -1;
|
||||
let activeInput = null;
|
||||
let lastInput = null;
|
||||
|
||||
/**
|
||||
* The Input component is used to focus text input elements.
|
||||
*
|
||||
* The `focusNext()` and `focusPrevious()` methods make it easy to focus input elements across all devices.
|
||||
*
|
||||
* @usage
|
||||
* ```html
|
||||
* <ion-input>
|
||||
* <ion-label>Name</ion-label>
|
||||
* <input value="Name" type="text">
|
||||
* </ion-input>
|
||||
* ```
|
||||
*/
|
||||
export class IonInput extends Ion {
|
||||
/**
|
||||
* @param {TODO} input TODO
|
||||
*/
|
||||
static registerInput(input) {
|
||||
inputRegistry.push(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} input TODO
|
||||
*/
|
||||
static setAsLastInput(input) {
|
||||
lastInput = input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the previous input element, if it exists.
|
||||
*/
|
||||
static focusPrevious() {
|
||||
this.focusMove(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the next input element, if it exists.
|
||||
*/
|
||||
static focusNext() {
|
||||
this.focusMove(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} inc TODO
|
||||
*/
|
||||
static focusMove(inc) {
|
||||
let input = activeInput || lastInput;
|
||||
if (input) {
|
||||
|
||||
let index = inputRegistry.indexOf(input);
|
||||
if (index > -1 && (index + inc) < inputRegistry.length) {
|
||||
let siblingInput = inputRegistry[index + inc];
|
||||
siblingInput && siblingInput.initFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Number} The ID of the next input element.
|
||||
*/
|
||||
static nextId() {
|
||||
return ++inputItemIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
static clearTabIndexes() {
|
||||
for (let i = 0; i < inputRegistry.length; i++) {
|
||||
inputRegistry[i].tabIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -505,7 +505,7 @@ export class NavController extends Ion {
|
||||
* @private
|
||||
* TODO
|
||||
*/
|
||||
createViewComponetRef(type, hostProtoViewRef, viewContainer, viewCtrlBindings) {
|
||||
createViewComponentRef(type, hostProtoViewRef, viewContainer, viewCtrlBindings) {
|
||||
let bindings = this.bindings.concat(viewCtrlBindings);
|
||||
|
||||
// the same guts as DynamicComponentLoader.loadNextToLocation
|
||||
|
||||
@@ -195,11 +195,11 @@ export class Nav extends NavController {
|
||||
// the component being loaded is an <ion-tabs>
|
||||
// Tabs is essentially a pane, cuz it has its own navbar and content containers
|
||||
let contentContainerRef = this._viewManager.getViewContainer(this.anchorElementRef());
|
||||
let viewComponetRef = this.createViewComponetRef(componentType, hostProtoViewRef, contentContainerRef, this.getBindings(viewCtrl));
|
||||
viewComponetRef.instance._paneView = true;
|
||||
let viewComponentRef = this.createViewComponentRef(componentType, hostProtoViewRef, contentContainerRef, this.getBindings(viewCtrl));
|
||||
viewComponentRef.instance._paneView = true;
|
||||
|
||||
viewCtrl.disposals.push(() => {
|
||||
viewComponetRef.dispose();
|
||||
viewComponentRef.dispose();
|
||||
});
|
||||
|
||||
viewCtrl.onReady().then(() => {
|
||||
@@ -210,9 +210,9 @@ export class Nav extends NavController {
|
||||
// normal ion-view going into pane
|
||||
this.getPane(structure, viewCtrl, (pane) => {
|
||||
// add the content of the view into the pane's content area
|
||||
let viewComponetRef = this.createViewComponetRef(componentType, hostProtoViewRef, pane.contentContainerRef, this.getBindings(viewCtrl));
|
||||
let viewComponentRef = this.createViewComponentRef(componentType, hostProtoViewRef, pane.contentContainerRef, this.getBindings(viewCtrl));
|
||||
viewCtrl.disposals.push(() => {
|
||||
viewComponetRef.dispose();
|
||||
viewComponentRef.dispose();
|
||||
|
||||
// remove the pane if there are no view items left
|
||||
pane.totalViews--;
|
||||
@@ -226,10 +226,10 @@ export class Nav extends NavController {
|
||||
|
||||
// a new ComponentRef has been created
|
||||
// set the ComponentRef's instance to this ViewController
|
||||
viewCtrl.setInstance(viewComponetRef.instance);
|
||||
viewCtrl.setInstance(viewComponentRef.instance);
|
||||
|
||||
// remember the ElementRef to the content that was just created
|
||||
viewCtrl.viewElementRef(viewComponetRef.location);
|
||||
viewCtrl.viewElementRef(viewComponentRef.location);
|
||||
|
||||
// get the NavController's container for navbars, which is
|
||||
// the place this NavController will add each ViewController's navbar
|
||||
|
||||
@@ -1,42 +1,101 @@
|
||||
// import {
|
||||
// ddescribe,
|
||||
// describe,
|
||||
// xdescribe,
|
||||
// it,
|
||||
// iit,
|
||||
// xit,
|
||||
// expect,
|
||||
// beforeEach,
|
||||
// afterEach,
|
||||
// AsyncTestCompleter,
|
||||
// inject,
|
||||
// beforeEachBindings
|
||||
// } from 'angular2/test';
|
||||
|
||||
// import {Compiler} from 'angular2/angular2';
|
||||
|
||||
import {
|
||||
NavController,
|
||||
IonicConfig,
|
||||
Page,
|
||||
ViewController
|
||||
} from 'ionic/ionic';
|
||||
|
||||
|
||||
export function run() {
|
||||
describe("NavController", function(){
|
||||
beforeEach( function(){
|
||||
this.nav = new NavController(null, null, new IonicConfig(), null, null, null, null, null);
|
||||
describe("NavController", () => {
|
||||
let nav;
|
||||
|
||||
class FirstPage {}
|
||||
class SecondPage {}
|
||||
class ThirdPage {}
|
||||
|
||||
function mockTransitionFn(enteringView, leavingView, opts, cb) {
|
||||
let destroys = [];
|
||||
|
||||
nav._views.forEach(view => {
|
||||
if (view) {
|
||||
if (view.shouldDestroy) {
|
||||
destroys.push(view);
|
||||
|
||||
} else if (view.state === 2 && view.shouldCache) {
|
||||
view.shouldCache = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
destroys.forEach(view => {
|
||||
nav.remove(view);
|
||||
view.destroy();
|
||||
});
|
||||
cb();
|
||||
}
|
||||
|
||||
function mockCanGoBackFn() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// beforeEach(inject([Compiler], compiler => {
|
||||
beforeEach(() => {
|
||||
nav = new NavController(null, null, new IonicConfig(), null, null, null, null, null);
|
||||
});
|
||||
|
||||
it('should exist', function(){
|
||||
expect(this.nav).not.toBeUndefined();
|
||||
it('should exist', () => {
|
||||
expect(nav).not.toBeUndefined();
|
||||
});
|
||||
|
||||
describe("getActive", function(){
|
||||
it('should return null if there is no active view', function(){
|
||||
var active = this.nav.getActive();
|
||||
describe("getActive", () => {
|
||||
it('should return null if there is no active view', () => {
|
||||
var active = nav.getActive();
|
||||
expect(active).toBe(null);
|
||||
});
|
||||
|
||||
it('should return the first active page', function(){
|
||||
it('should return the first active page', () => {
|
||||
let activeView = new ViewController();
|
||||
activeView.state = 1; // ACTIVE_STATE
|
||||
|
||||
this.nav.add(activeView);
|
||||
var active = this.nav.getActive();
|
||||
nav.add(activeView);
|
||||
var active = nav.getActive();
|
||||
|
||||
expect(active).toBe(activeView);
|
||||
|
||||
let secondActiveView = new ViewController();
|
||||
secondActiveView.state = 1; // ACTIVE_STATE
|
||||
|
||||
nav.add(secondActiveView);
|
||||
active = nav.getActive();
|
||||
|
||||
expect(active).toBe(activeView);
|
||||
});
|
||||
});
|
||||
|
||||
describe("push", function(){
|
||||
it('should return a rejected Promise if componentType is falsy', function(done){
|
||||
describe("push", () => {
|
||||
it('should return a rejected Promise if componentType is falsy', done => {
|
||||
let s = jasmine.createSpy('success');
|
||||
let f = jasmine.createSpy('fail');
|
||||
|
||||
let promise = this.nav.push(undefined, {}, {});
|
||||
let promise = nav.push(undefined, {}, {});
|
||||
|
||||
promise.then(s, f).then(() => {
|
||||
expect(s).not.toHaveBeenCalled();
|
||||
@@ -45,21 +104,108 @@ export function run() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if componentType truthy, but is not a function', function(){
|
||||
let push = () => this.nav.push({}, {}, {});
|
||||
it('should throw an error if componentType truthy, but is not a function', () => {
|
||||
let push = () => nav.push({}, {}, {});
|
||||
expect(push).toThrow();
|
||||
|
||||
push = () => this.nav.push("string", {}, {});
|
||||
push = () => nav.push("string", {}, {});
|
||||
expect(push).toThrow();
|
||||
|
||||
push = () => this.nav.push(42, {}, {});
|
||||
push = () => nav.push(42, {}, {});
|
||||
expect(push).toThrow();
|
||||
|
||||
push = () => this.nav.push(true, {}, {});
|
||||
push = () => nav.push(true, {}, {});
|
||||
expect(push).toThrow();
|
||||
});
|
||||
|
||||
})
|
||||
});
|
||||
it('to add the pushed page to the nav stack', (done) => {
|
||||
expect(FirstPage).toBeDefined();
|
||||
expect(nav._views.length).toBe(0);
|
||||
|
||||
spyOn(nav, 'add').and.callThrough();
|
||||
|
||||
nav.transition = mockTransitionFn;
|
||||
nav.push(FirstPage, {}, {}).then(() => {
|
||||
expect(nav.add).toHaveBeenCalled();
|
||||
expect(nav._views.length).toBe(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setViews", () => {
|
||||
it('should return a resolved Promise if components is falsy', done => {
|
||||
let s = jasmine.createSpy('success');
|
||||
let f = jasmine.createSpy('fail');
|
||||
|
||||
let promise = nav.setViews();
|
||||
|
||||
promise.then(s, f).then(() => {
|
||||
expect(s).toHaveBeenCalled();
|
||||
expect(f).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('replace views with the supplied views', () => {
|
||||
let vc1 = new ViewController(),
|
||||
vc2 = new ViewController(),
|
||||
vc3 = new ViewController();
|
||||
nav._views = [vc1, vc2, vc3];
|
||||
let arr = [FirstPage, SecondPage, ThirdPage];
|
||||
|
||||
nav.transition = mockTransitionFn;
|
||||
nav.setViews(arr);
|
||||
|
||||
//_views[0] will be transitioned out of
|
||||
expect(nav._views[1].componentType).toBe(FirstPage);
|
||||
expect(nav._views[2].componentType).toBe(SecondPage);
|
||||
expect(nav._views[3].componentType).toBe(ThirdPage);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("insert", () => {
|
||||
it('insert page at the specified index', () => {
|
||||
nav._views = [{}, {}, {}];
|
||||
expect(nav._views[2].componentType).toBeUndefined();
|
||||
nav.insert(FirstPage, 2);
|
||||
expect(nav._views[2].componentType).toBe(FirstPage);
|
||||
});
|
||||
|
||||
it('push page if index >= _views.length', () => {
|
||||
nav._views = [{}, {}, {}];
|
||||
spyOn(nav, 'push').and.callThrough();
|
||||
nav.insert(FirstPage, 2);
|
||||
expect(nav.push).not.toHaveBeenCalled();
|
||||
|
||||
nav.transition = mockTransitionFn;
|
||||
nav.insert(FirstPage, 4);
|
||||
expect(nav._views[4].componentType).toBe(FirstPage);
|
||||
expect(nav.push).toHaveBeenCalled();
|
||||
|
||||
nav.insert(FirstPage, 10);
|
||||
expect(nav._views[5].componentType).toBe(FirstPage);
|
||||
expect(nav.push.calls.count()).toBe(2);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("setRoot", () => {
|
||||
it('remove previous views and set root', () => {
|
||||
let vc1 = new ViewController(),
|
||||
vc2 = new ViewController(),
|
||||
vc3 = new ViewController();
|
||||
nav._views = [vc1, vc2, vc3];
|
||||
expect(nav._views.length).toBe(3);
|
||||
|
||||
nav.transition = mockTransitionFn;
|
||||
nav.setRoot(FirstPage);
|
||||
//_views[0] will be transitioned out of
|
||||
expect(nav._views.length).toBe(2);
|
||||
expect(nav._views[1].componentType).toBe(FirstPage);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ export class ViewController {
|
||||
return done();
|
||||
}
|
||||
|
||||
// compile the componenet and create a ProtoViewRef
|
||||
// compile the component and create a ProtoViewRef
|
||||
navCtrl.compileView(this.componentType).then(hostProtoViewRef => {
|
||||
|
||||
// get the pane the NavController wants to use
|
||||
|
||||
@@ -15,8 +15,9 @@ $search-bar-ios-input-height: 28px !default;
|
||||
$search-bar-ios-input-placeholder-color: #9D9D9D !default;
|
||||
$search-bar-ios-input-text-color: #000 !default;
|
||||
$search-bar-ios-input-background-color: #FFFFFF !default;
|
||||
$search-bar-ios-input-transition: all 0.3s linear !default;
|
||||
//cubic-bezier(.25, .45, .05, 1)
|
||||
$search-bar-ios-input-transition: all 400ms cubic-bezier(.25, .45, .05, 1) !default;
|
||||
$search-bar-ios-cancel-transition: all 400ms cubic-bezier(.25, .45, .05, 1) !default;
|
||||
|
||||
$search-bar-ios-input-close-icon-color: #8F8E94 !default;
|
||||
$search-bar-ios-input-close-icon-svg: "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'><path fill='" + $search-bar-ios-input-close-icon-color + "' d='M403.1,108.9c-81.2-81.2-212.9-81.2-294.2,0s-81.2,212.9,0,294.2c81.2,81.2,212.9,81.2,294.2,0S484.3,190.1,403.1,108.9z M352,340.2L340.2,352l-84.4-84.2l-84,83.8L160,339.8l84-83.8l-84-83.8l11.8-11.8l84,83.8l84.4-84.2l11.8,11.8L267.6,256L352,340.2z'/></svg>" !default;
|
||||
$search-bar-ios-input-close-icon-size: 17px !default;
|
||||
@@ -88,19 +89,9 @@ $search-bar-ios-input-close-icon-size: 17px !default;
|
||||
|
||||
.search-bar-cancel {
|
||||
@extend button[clear];
|
||||
// transition: all 2s cubic-bezier(.25, .45, .05, 1);
|
||||
transition: $search-bar-ios-input-transition;
|
||||
transition-duration: 3s !important;
|
||||
margin-right: calc(-100%);
|
||||
// transform: translate3d(100px,0,0);
|
||||
// max-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.search-bar-cancel.left-align {
|
||||
max-width: initial;
|
||||
margin-right: 0;
|
||||
transition: $search-bar-ios-cancel-transition;
|
||||
padding-left: 8px;
|
||||
min-height: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,3 +69,7 @@ $search-bar-md-input-close-icon-size: 22px !default;
|
||||
right: 13px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.search-bar-cancel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,16 @@ export class SearchBar extends Ion {
|
||||
this.query = '';
|
||||
}
|
||||
|
||||
// Add the margin for iOS
|
||||
afterViewInit() {
|
||||
this.cancelButton = this.elementRef.nativeElement.querySelector('.search-bar-cancel');
|
||||
|
||||
if (this.cancelButton) {
|
||||
this.cancelWidth = this.cancelButton.offsetWidth;
|
||||
this.cancelButton.style.marginRight = "-" + this.cancelWidth + "px";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Much like ngModel, this is called from our valueAccessor for the attached
|
||||
* ControlDirective to update the value internally.
|
||||
@@ -99,10 +109,18 @@ export class SearchBar extends Ion {
|
||||
inputFocused() {
|
||||
this.isFocused = true;
|
||||
this.shouldLeftAlign = true;
|
||||
|
||||
if (this.cancelButton) {
|
||||
this.cancelButton.style.marginRight = "0px";
|
||||
}
|
||||
}
|
||||
inputBlurred() {
|
||||
this.isFocused = false;
|
||||
this.shouldLeftAlign = this.value.trim() != '';
|
||||
|
||||
if (this.cancelButton) {
|
||||
this.cancelButton.style.marginRight = "-" + this.cancelWidth + "px";
|
||||
}
|
||||
}
|
||||
|
||||
clearInput() {
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
<ion-search-bar ng-control="searchQuery" show-cancel="true"></ion-search-bar>
|
||||
<label> Search - Custom Cancel Button </label>
|
||||
<ion-search-bar ng-control="searchQuery" show-cancel="true" cancel-text="Done"></ion-search-bar>
|
||||
<label> Search - Custom Cancel Button Long Text</label>
|
||||
<ion-search-bar ng-control="searchQuery" show-cancel="true" cancel-text="I Am So Done"></ion-search-bar>
|
||||
<label> Search - Custom Cancel Action</label>
|
||||
<ion-search-bar ng-control="searchQuery" show-cancel="true" cancel-text="Done" [cancel-action]="myCancelAction"></ion-search-bar>
|
||||
</form>
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
forwardRef
|
||||
} from 'angular2/angular2';
|
||||
|
||||
import {Ion} from '../ion';
|
||||
import {IonInput} from '../form/input';
|
||||
import {IonicForm} from '../form/form';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {pointerCoord} from '../../util/dom';
|
||||
|
||||
@@ -109,7 +108,7 @@ class MediaSwitch {
|
||||
'</media-switch>',
|
||||
directives: [MediaSwitch]
|
||||
})
|
||||
export class Switch extends Ion {
|
||||
export class Switch {
|
||||
/**
|
||||
* TODO
|
||||
* @param {ElementRef} elementRef TODO
|
||||
@@ -117,24 +116,24 @@ export class Switch extends Ion {
|
||||
* @param {NgControl=} ngControl TODO
|
||||
*/
|
||||
constructor(
|
||||
form: IonicForm,
|
||||
elementRef: ElementRef,
|
||||
config: IonicConfig,
|
||||
@Optional() private ngControl: NgControl
|
||||
) {
|
||||
super(elementRef, config);
|
||||
let self = this;
|
||||
this.form = form;
|
||||
form.register(this);
|
||||
|
||||
self.id = IonInput.nextId();
|
||||
self.tabIndex = 0;
|
||||
self.lastTouch = 0;
|
||||
self.mode = config.get('mode');
|
||||
this.lastTouch = 0;
|
||||
this.mode = config.get('mode');
|
||||
|
||||
self.onChange = (_) => {};
|
||||
self.onTouched = (_) => {};
|
||||
this.onChange = (_) => {};
|
||||
this.onTouched = (_) => {};
|
||||
|
||||
if (ngControl) ngControl.valueAccessor = this;
|
||||
|
||||
|
||||
let self = this;
|
||||
function pointerMove(ev) {
|
||||
let currentX = pointerCoord(ev).x;
|
||||
|
||||
@@ -156,21 +155,20 @@ export class Switch extends Ion {
|
||||
}
|
||||
|
||||
this.addMoveListener = function() {
|
||||
this.switchEle.addEventListener('touchmove', pointerMove);
|
||||
this.switchEle.addEventListener('mousemove', pointerMove);
|
||||
self.switchEle.addEventListener('touchmove', pointerMove);
|
||||
self.switchEle.addEventListener('mousemove', pointerMove);
|
||||
elementRef.nativeElement.addEventListener('mouseout', pointerOut);
|
||||
};
|
||||
|
||||
this.removeMoveListener = function() {
|
||||
this.switchEle.removeEventListener('touchmove', pointerMove);
|
||||
this.switchEle.removeEventListener('mousemove', pointerMove);
|
||||
self.switchEle.removeEventListener('touchmove', pointerMove);
|
||||
self.switchEle.removeEventListener('mousemove', pointerMove);
|
||||
elementRef.nativeElement.removeEventListener('mouseout', pointerOut);
|
||||
};
|
||||
}
|
||||
|
||||
onInit() {
|
||||
super.onInit();
|
||||
this.labelId = 'label-' + this.id;
|
||||
this.labelId = 'label-' + this.inputId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,6 +232,7 @@ export class Switch extends Ion {
|
||||
onDestroy() {
|
||||
this.removeMoveListener();
|
||||
this.switchEle = this.addMoveListener = this.removeMoveListener = null;
|
||||
this.form.deregister(this);
|
||||
}
|
||||
|
||||
isDisabled(ev) {
|
||||
|
||||
@@ -155,17 +155,17 @@ export class Tab extends NavController {
|
||||
|
||||
loadContainer(componentType, hostProtoViewRef, viewCtrl, done) {
|
||||
|
||||
let viewComponetRef = this.createViewComponetRef(componentType, hostProtoViewRef, this.contentContainerRef, this.getBindings(viewCtrl));
|
||||
let viewComponentRef = this.createViewComponentRef(componentType, hostProtoViewRef, this.contentContainerRef, this.getBindings(viewCtrl));
|
||||
viewCtrl.disposals.push(() => {
|
||||
viewComponetRef.dispose();
|
||||
viewComponentRef.dispose();
|
||||
});
|
||||
|
||||
// a new ComponentRef has been created
|
||||
// set the ComponentRef's instance to this ViewController
|
||||
viewCtrl.setInstance(viewComponetRef.instance);
|
||||
viewCtrl.setInstance(viewComponentRef.instance);
|
||||
|
||||
// remember the ElementRef to the content that was just created
|
||||
viewCtrl.viewElementRef(viewComponetRef.location);
|
||||
viewCtrl.viewElementRef(viewComponentRef.location);
|
||||
|
||||
// get the NavController's container for navbars, which is
|
||||
// the place this NavController will add each ViewController's navbar
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {Directive, View, Host, Optional, ElementRef, Attribute, Query, QueryList, NgZone} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {IonInput} from '../form/input';
|
||||
import {IonicForm} from '../form/form';
|
||||
import {Label} from './label';
|
||||
import {Ion} from '../ion';
|
||||
import {IonicApp} from '../app/app';
|
||||
import {Content} from '../content/content';
|
||||
import * as dom from '../../util/dom';
|
||||
@@ -15,22 +14,18 @@ import {IonicPlatform} from '../../platform/platform';
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'ion-input',
|
||||
inputs: [
|
||||
'tabIndex'
|
||||
],
|
||||
host: {
|
||||
'(focus)': 'receivedFocus(true)',
|
||||
'(blur)': 'receivedFocus(false)',
|
||||
'(touchstart)': 'pointerStart($event)',
|
||||
'(touchend)': 'pointerEnd($event)',
|
||||
'(mouseup)': 'pointerEnd($event)',
|
||||
'[class.has-focus]': 'inputHasFocus',
|
||||
'[class.has-value]': 'inputHasValue',
|
||||
'[tabIndex]': 'activeTabIndex',
|
||||
'[class.has-focus]': 'hasFocus',
|
||||
'[class.has-value]': 'hasValue',
|
||||
'class': 'item'
|
||||
}
|
||||
})
|
||||
export class TextInput extends Ion {
|
||||
export class TextInput {
|
||||
/**
|
||||
* TODO
|
||||
* @param {ElementRef} elementRef TODO
|
||||
@@ -42,31 +37,30 @@ export class TextInput extends Ion {
|
||||
* @param {QueryList<Label>} labelQry TODO
|
||||
*/
|
||||
constructor(
|
||||
form: IonicForm,
|
||||
elementRef: ElementRef,
|
||||
config: IonicConfig,
|
||||
app: IonicApp,
|
||||
ngZone: NgZone,
|
||||
zone: NgZone,
|
||||
platform: IonicPlatform,
|
||||
@Optional() @Host() scrollView: Content
|
||||
) {
|
||||
super(elementRef, config);
|
||||
this.form = form;
|
||||
form.register(this);
|
||||
|
||||
this.app = app;
|
||||
this.elementRef = elementRef;
|
||||
this.zone = zone;
|
||||
this.platform = platform;
|
||||
|
||||
this.scrollView = scrollView;
|
||||
this.scrollAssist = config.get('keyboardScrollAssist');
|
||||
this.id = IonInput.nextId();
|
||||
IonInput.registerInput(this);
|
||||
|
||||
this.app = app;
|
||||
this.zone = ngZone;
|
||||
this.platform = platform;
|
||||
|
||||
this.keyboardHeight = this.config.get('keyboardHeight');
|
||||
this.keyboardHeight = config.get('keyboardHeight');
|
||||
}
|
||||
|
||||
registerInputElement(textInputElement) {
|
||||
registerInput(textInputElement) {
|
||||
this.input = textInputElement;
|
||||
this.type = textInputElement.type;
|
||||
textInputElement.tabIndex = -1;
|
||||
}
|
||||
|
||||
registerLabel(label) {
|
||||
@@ -77,17 +71,15 @@ export class TextInput extends Ion {
|
||||
* TODO
|
||||
*/
|
||||
onInit() {
|
||||
super.onInit();
|
||||
|
||||
if (this.input && this.label) {
|
||||
this.input.labelledBy = this.label.id = (this.label.id || 'label-' + this.id);
|
||||
this.input.labelledBy = this.label.id = (this.label.id || 'label-' + this.inputId);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
self.scrollMove = (ev) => {
|
||||
self.deregListeners();
|
||||
|
||||
if (self.inputHasFocus) {
|
||||
if (self.hasFocus) {
|
||||
self.tempFocusMove();
|
||||
}
|
||||
};
|
||||
@@ -119,7 +111,7 @@ export class TextInput extends Ion {
|
||||
|
||||
// focus this input if the pointer hasn't moved XX pixels
|
||||
// and the input doesn't already have focus
|
||||
if (!dom.hasPointerMoved(8, this.startCoord, endCoord) && !this.inputHasFocus) {
|
||||
if (!dom.hasPointerMoved(8, this.startCoord, endCoord) && !this.hasFocus) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
@@ -149,7 +141,6 @@ export class TextInput extends Ion {
|
||||
* TODO
|
||||
* @returns {TODO} TODO
|
||||
*/
|
||||
//TODO inconsistent return value, sometimes undefined
|
||||
initFocus() {
|
||||
let scrollView = this.scrollView;
|
||||
|
||||
@@ -327,12 +318,12 @@ export class TextInput extends Ion {
|
||||
setFocus() {
|
||||
this.zone.run(() => {
|
||||
// set focus on the input element
|
||||
this.input && this.input.setFocus();
|
||||
this.input && this.input.initFocus();
|
||||
|
||||
// ensure the body hasn't scrolled down
|
||||
document.body.scrollTop = 0;
|
||||
|
||||
IonInput.setAsLastInput(this);
|
||||
this.form.resetInputs();
|
||||
});
|
||||
|
||||
if (this.scrollAssist && this.scrollView) {
|
||||
@@ -343,25 +334,26 @@ export class TextInput extends Ion {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
tempFocusMove() {
|
||||
let focusHolder = this.app.focusHolder();
|
||||
focusHolder.setFocusHolder(this.type);
|
||||
this.form.setFocusHolder(this.type);
|
||||
}
|
||||
|
||||
get inputHasFocus() {
|
||||
get hasFocus() {
|
||||
return !!this.input && this.input.hasFocus;
|
||||
}
|
||||
|
||||
get inputHasValue() {
|
||||
get hasValue() {
|
||||
return !!this.input && this.input.hasValue;
|
||||
}
|
||||
|
||||
get activeTabIndex() {
|
||||
this.input.tabIndex = (this.inputHasFocus ? 1000 : -1);
|
||||
return -1;
|
||||
get tabIndex() {
|
||||
return this.input && this.input.tabIndex;
|
||||
}
|
||||
|
||||
set tabIndex(val) {
|
||||
if (this.input) {
|
||||
this.input.tabIndex = val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -369,7 +361,7 @@ export class TextInput extends Ion {
|
||||
* @param {boolean} receivedFocus TODO
|
||||
*/
|
||||
receivedFocus(receivedFocus) {
|
||||
if (receivedFocus && !this.inputHasFocus) {
|
||||
if (receivedFocus && !this.hasFocus) {
|
||||
this.initFocus();
|
||||
|
||||
} else {
|
||||
@@ -377,6 +369,11 @@ export class TextInput extends Ion {
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.deregListeners();
|
||||
this.form.deregister(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,31 +388,33 @@ export class TextInput extends Ion {
|
||||
host: {
|
||||
'[tabIndex]': 'tabIndex',
|
||||
'[attr.aria-labelledby]': 'labelledBy',
|
||||
'class': 'text-input input'
|
||||
'class': 'text-input'
|
||||
}
|
||||
})
|
||||
export class TextInputElement {
|
||||
/**
|
||||
* TODO
|
||||
* @param {string} type The value of the underlying element's type attribute.
|
||||
* @param {ElementRef} elementRef TODO
|
||||
* @param {IonicConfig} config TODO
|
||||
*/
|
||||
|
||||
constructor(
|
||||
form: IonicForm,
|
||||
@Attribute('type') type: string,
|
||||
elementRef: ElementRef,
|
||||
@Optional() textInput: TextInput
|
||||
@Optional() textInputWrapper: TextInput
|
||||
) {
|
||||
this.form = form;
|
||||
this.type = type;
|
||||
this.elementRef = elementRef;
|
||||
this.tabIndex = this.tabIndex || '';
|
||||
textInput && textInput.registerInputElement(this);
|
||||
this.tabIndex = 0;
|
||||
|
||||
if (textInputWrapper) {
|
||||
// it's within ionic's ion-input, let ion-input handle what's up
|
||||
textInputWrapper.registerInput(this);
|
||||
|
||||
} else {
|
||||
// not within ion-input
|
||||
form.register(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the input.
|
||||
*/
|
||||
setFocus() {
|
||||
initFocus() {
|
||||
this.elementRef.nativeElement.focus();
|
||||
}
|
||||
|
||||
@@ -424,7 +423,7 @@ export class TextInputElement {
|
||||
* @returns {boolean} true if the input has focus, otherwise false.
|
||||
*/
|
||||
get hasFocus() {
|
||||
return dom.hasFocus(this.elementRef);
|
||||
return dom.hasFocus(this.elementRef.nativeElement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,6 +433,10 @@ export class TextInputElement {
|
||||
get hasValue() {
|
||||
return (this.elementRef.nativeElement.value !== '');
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.form.deregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {IonicApp} from '../components/app/app';
|
||||
import {IonicConfig} from './config';
|
||||
import {IonicPlatform} from '../platform/platform';
|
||||
import {OverlayController} from '../components/overlay/overlay-controller';
|
||||
import {IonicForm} from '../components/form/form';
|
||||
import {ActionSheet} from '../components/action-sheet/action-sheet';
|
||||
import {Modal} from '../components/modal/modal';
|
||||
import {Popup} from '../components/popup/popup';
|
||||
@@ -24,15 +25,15 @@ export function ionicBindings(rootCmp, config) {
|
||||
config = new IonicConfig(config);
|
||||
}
|
||||
|
||||
let events = new Events();
|
||||
let tapClick = new TapClick(app, config, window, document);
|
||||
|
||||
platform.url(window.location.href);
|
||||
platform.userAgent(window.navigator.userAgent);
|
||||
platform.navigatorPlatform(window.navigator.platform);
|
||||
platform.load();
|
||||
config.setPlatform(platform);
|
||||
|
||||
let events = new Events();
|
||||
let tapClick = new TapClick(app, config, window, document);
|
||||
|
||||
setupDom(window, document, config, platform);
|
||||
bindEvents(window, document, platform, events);
|
||||
|
||||
@@ -45,6 +46,7 @@ export function ionicBindings(rootCmp, config) {
|
||||
bind(IonicPlatform).toValue(platform),
|
||||
bind(TapClick).toValue(tapClick),
|
||||
bind(Events).toValue(events),
|
||||
IonicForm,
|
||||
OverlayController,
|
||||
ActionSheet,
|
||||
Modal,
|
||||
@@ -92,10 +94,6 @@ function setupDom(window, document, config, platform) {
|
||||
bodyEle.classList.add('enable-hover');
|
||||
}
|
||||
|
||||
if (config.get('keyboardScrollAssist')) {
|
||||
// create focus holder
|
||||
}
|
||||
|
||||
/**
|
||||
* Hairline Shim
|
||||
* Add the "hairline" CSS class name to the body tag
|
||||
|
||||
@@ -14,7 +14,6 @@ export * from './platform/plugins'
|
||||
export * from './platform/storage'
|
||||
|
||||
export * from './util/click-block'
|
||||
export * from './util/focus'
|
||||
export * from './util/events'
|
||||
|
||||
export * from './animations/animation'
|
||||
|
||||
@@ -176,8 +176,12 @@ export function hasPointerMoved(threshold, startCoord, endCoord) {
|
||||
(Math.abs(startCoord.x - endCoord.x) > threshold || Math.abs(startCoord.y - endCoord.y) > threshold);
|
||||
}
|
||||
|
||||
export function isActive(ele) {
|
||||
return !!(ele && (document.activeElement === ele));
|
||||
}
|
||||
|
||||
export function hasFocus(ele) {
|
||||
return !!(ele && (document.activeElement === ele.nativeElement || document.activeElement === ele));
|
||||
return isActive(ele) && (ele.parentElement.querySelector(':focus') === ele);
|
||||
}
|
||||
|
||||
export function isTextInput(ele) {
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import {raf, ready} from './dom'
|
||||
|
||||
/* Focus Outline
|
||||
* --------------------------------------------------
|
||||
* When a keydown event happens, from a tab key, then the
|
||||
* 'key-input' class is added to the body element so focusable
|
||||
* elements have an outline. On a mousedown or touchstart
|
||||
* event then the 'key-input' class is removed.
|
||||
*/
|
||||
|
||||
|
||||
let isKeyInputEnabled = false
|
||||
|
||||
function keyDown(ev) {
|
||||
if (!isKeyInputEnabled && ev.keyCode == 9) {
|
||||
isKeyInputEnabled = true
|
||||
raf(enableKeyInput)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function enableKeyInput() {
|
||||
document.body.classList[isKeyInputEnabled ? 'add' : 'remove']('key-input')
|
||||
|
||||
if (isKeyInputEnabled) {
|
||||
document.addEventListener('mousedown', pointerDown)
|
||||
document.addEventListener('touchstart', pointerDown)
|
||||
|
||||
} else {
|
||||
document.removeEventListener('mousedown', pointerDown)
|
||||
document.removeEventListener('touchstart', pointerDown)
|
||||
}
|
||||
}
|
||||
|
||||
function pointerDown() {
|
||||
isKeyInputEnabled = false
|
||||
raf(enableKeyInput)
|
||||
}
|
||||
|
||||
|
||||
ready().then(function() {
|
||||
document.addEventListener('keydown', keyDown)
|
||||
})
|
||||
Reference in New Issue
Block a user