mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
rename Platform to IonicPlatform
Make IonicPlatform an injectable. Closes #99
This commit is contained in:
@@ -2,7 +2,7 @@ import {Component, View, bootstrap, ElementRef, NgZone, bind, DynamicComponentLo
|
||||
import {ROUTER_BINDINGS, HashLocationStrategy, LocationStrategy, Router} from 'angular2/router';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {IonicPlatform, Platform} from '../../platform/platform';
|
||||
import * as util from '../../util/util';
|
||||
|
||||
// injectables
|
||||
@@ -180,50 +180,6 @@ export class IonicApp {
|
||||
return this.rootAnchor.append(componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param {Element} bodyEle the body element
|
||||
* @param {TODO} platform TODO
|
||||
* @param {TODO} config TODO
|
||||
*/
|
||||
applyBodyCss(bodyEle, platform, config) {
|
||||
let versions = platform.versions();
|
||||
platform.platforms().forEach(platformName => {
|
||||
// platform-ios
|
||||
let platformClass = 'platform-' + platformName;
|
||||
bodyEle.classList.add(platformClass);
|
||||
|
||||
let platformVersion = versions[platformName];
|
||||
if (platformVersion) {
|
||||
// platform-ios9
|
||||
platformClass += platformVersion.major;
|
||||
bodyEle.classList.add(platformClass);
|
||||
|
||||
// platform-ios9_3
|
||||
bodyEle.classList.add(platformClass + '_' + platformVersion.minor);
|
||||
}
|
||||
});
|
||||
|
||||
bodyEle.classList.add(config.setting('mode'));
|
||||
|
||||
/**
|
||||
* Hairline Shim
|
||||
* Add the "hairline" CSS class name to the body tag
|
||||
* if the browser supports subpixels.
|
||||
*/
|
||||
if (window.devicePixelRatio >= 2) {
|
||||
var hairlineEle = document.createElement('div');
|
||||
hairlineEle.style.border = '.5px solid transparent';
|
||||
bodyEle.appendChild(hairlineEle);
|
||||
|
||||
if (hairlineEle.offsetHeight === 1) {
|
||||
bodyEle.classList.add('hairlines');
|
||||
}
|
||||
bodyEle.removeChild(hairlineEle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If val is defined, specifies whether app text is RTL. If val is undefined
|
||||
* returns whether app text is RTL.
|
||||
@@ -240,26 +196,6 @@ export class IonicApp {
|
||||
|
||||
}
|
||||
|
||||
function initApp(window, document, config) {
|
||||
// create the base IonicApp
|
||||
let app = new IonicApp();
|
||||
app.isRTL(document.documentElement.getAttribute('dir') == 'rtl');
|
||||
|
||||
// load all platform data
|
||||
// Platform is a global singleton
|
||||
Platform.url(window.location.href);
|
||||
Platform.userAgent(window.navigator.userAgent);
|
||||
Platform.navigatorPlatform(window.navigator.platform);
|
||||
Platform.load(config);
|
||||
|
||||
setTimeout(() => {
|
||||
// start listening for resizes XXms after the app starts
|
||||
window.addEventListener('resize', Platform.winResize);
|
||||
}, 2500);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'root-anchor'
|
||||
})
|
||||
@@ -280,6 +216,38 @@ class RootAnchor {
|
||||
}
|
||||
}
|
||||
|
||||
function initApp(window, document, config, platform) {
|
||||
// create the base IonicApp
|
||||
let app = new IonicApp();
|
||||
app.isRTL(document.dir == 'rtl');
|
||||
|
||||
// load all platform data
|
||||
platform.url(window.location.href);
|
||||
platform.userAgent(window.navigator.userAgent);
|
||||
platform.navigatorPlatform(window.navigator.platform);
|
||||
platform.load(config);
|
||||
|
||||
// copy default platform settings into the user config platform settings
|
||||
// user config platform settings should override default platform settings
|
||||
config.setPlatform(platform);
|
||||
|
||||
// config and platform settings have been figured out
|
||||
// apply the correct CSS to the app
|
||||
applyBodyCss(document.body, config, platform);
|
||||
|
||||
// prepare the ready promise to fire....when ready
|
||||
platform.prepareReady(config);
|
||||
|
||||
setTimeout(function() {
|
||||
// start listening for resizes XXms after the app starts
|
||||
window.addEventListener('resize', function() {
|
||||
platform.winResize();
|
||||
});
|
||||
}, 2500);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
@@ -295,19 +263,10 @@ export function ionicBootstrap(rootComponentType, config) {
|
||||
config = new IonicConfig(config);
|
||||
}
|
||||
|
||||
let platform = new IonicPlatform(window);
|
||||
|
||||
// create the base IonicApp
|
||||
let app = initApp(window, document, config);
|
||||
|
||||
// copy default platform settings into the user config platform settings
|
||||
// user config platform settings should override default platform settings
|
||||
config.setPlatform(Platform);
|
||||
|
||||
// config and platform settings have been figured out
|
||||
// apply the correct CSS to the app
|
||||
app.applyBodyCss(document.body, Platform, config);
|
||||
|
||||
// prepare the ready promise to fire....when ready
|
||||
Platform.prepareReady(config);
|
||||
let app = initApp(window, document, config, platform);
|
||||
|
||||
// TODO: probs need a better way to inject global injectables
|
||||
let activator = new Activator(app, config, window, document);
|
||||
@@ -319,6 +278,7 @@ export function ionicBootstrap(rootComponentType, config) {
|
||||
let appBindings = Injector.resolve([
|
||||
bind(IonicApp).toValue(app),
|
||||
bind(IonicConfig).toValue(config),
|
||||
bind(IonicPlatform).toValue(platform),
|
||||
bind(Activator).toValue(activator),
|
||||
bind(ActionMenu).toValue(actionMenu),
|
||||
bind(Modal).toValue(modal),
|
||||
@@ -357,3 +317,42 @@ export function ionicBootstrap(rootComponentType, config) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applyBodyCss(bodyEle, config, platform) {
|
||||
let versions = platform.versions();
|
||||
platform.platforms().forEach(platformName => {
|
||||
// platform-ios
|
||||
let platformClass = 'platform-' + platformName;
|
||||
bodyEle.classList.add(platformClass);
|
||||
|
||||
let platformVersion = versions[platformName];
|
||||
if (platformVersion) {
|
||||
// platform-ios9
|
||||
platformClass += platformVersion.major;
|
||||
bodyEle.classList.add(platformClass);
|
||||
|
||||
// platform-ios9_3
|
||||
bodyEle.classList.add(platformClass + '_' + platformVersion.minor);
|
||||
}
|
||||
});
|
||||
|
||||
// set the mode class name
|
||||
// ios
|
||||
bodyEle.classList.add(config.setting('mode'));
|
||||
|
||||
/**
|
||||
* Hairline Shim
|
||||
* Add the "hairline" CSS class name to the body tag
|
||||
* if the browser supports subpixels.
|
||||
*/
|
||||
if (window.devicePixelRatio >= 2) {
|
||||
var hairlineEle = document.createElement('div');
|
||||
hairlineEle.style.border = '.5px solid transparent';
|
||||
bodyEle.appendChild(hairlineEle);
|
||||
|
||||
if (hairlineEle.offsetHeight === 1) {
|
||||
bodyEle.classList.add('hairlines');
|
||||
}
|
||||
bodyEle.removeChild(hairlineEle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import {Component, Directive, View, Host, Attribute, ElementRef, forwardRef} from 'angular2/angular2';
|
||||
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import * as dom from '../../util/dom';
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {IonInput} from './input';
|
||||
|
||||
/**
|
||||
@@ -15,7 +13,7 @@ import {IonInput} from './input';
|
||||
template: '<input tabindex="999"><input tabindex="1001"><input tabindex="1002">',
|
||||
directives: [forwardRef(() => FocusInput)]
|
||||
})
|
||||
export class FocusHolder {
|
||||
export class FocusHolder {
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {IonicConfig} from '../config/config';
|
||||
import {Platform} from '../platform/platform';
|
||||
import * as util from 'ionic/util';
|
||||
import {isArray} from 'ionic/util';
|
||||
import * as dom from 'ionic/util/dom';
|
||||
|
||||
|
||||
/**
|
||||
@@ -47,27 +47,6 @@ export class Ion {
|
||||
}
|
||||
}
|
||||
|
||||
getDelegate(delegateName) {
|
||||
let cls = this.constructor;
|
||||
|
||||
if (cls.delegates) {
|
||||
let cases = cls.delegates[delegateName] || [];
|
||||
|
||||
for (let i = 0; i < cases.length; i++) {
|
||||
let delegateCase = cases[i];
|
||||
if (util.isArray(delegateCase)) {
|
||||
let [ check, DelegateConstructor ] = delegateCase;
|
||||
if (check(this)) {
|
||||
return new DelegateConstructor(this);
|
||||
}
|
||||
|
||||
} else {
|
||||
return new delegateCase(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getElementRef() {
|
||||
return this.elementRef;
|
||||
}
|
||||
@@ -76,12 +55,16 @@ export class Ion {
|
||||
return this.elementRef.nativeElement;
|
||||
}
|
||||
|
||||
getDimensions() {
|
||||
return dom.getDimensions(this.elementRef.nativeElement);
|
||||
}
|
||||
|
||||
width() {
|
||||
return Platform.getDimensions(this).w;
|
||||
return this.getDimensions().width;
|
||||
}
|
||||
|
||||
height() {
|
||||
return Platform.getDimensions(this).h;
|
||||
return this.getDimensions().height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {App, IonicView, IonicApp, IonicConfig, Platform} from 'ionic/ionic';
|
||||
import {App, IonicView, IonicApp, IonicConfig, IonicPlatform} from 'ionic/ionic';
|
||||
import {Modal, ActionMenu, NavController, NavParams, Animation} from 'ionic/ionic';
|
||||
|
||||
|
||||
@@ -7,27 +7,27 @@ import {Modal, ActionMenu, NavController, NavParams, Animation} from 'ionic/ioni
|
||||
})
|
||||
class MyAppCmp {
|
||||
|
||||
constructor(modal: Modal, app: IonicApp, ionicConfig: IonicConfig) {
|
||||
constructor(modal: Modal, app: IonicApp, config: IonicConfig, platform: IonicPlatform) {
|
||||
this.modal = modal;
|
||||
|
||||
console.log('platforms', Platform.platforms());
|
||||
console.log('mode', ionicConfig.setting('mode'));
|
||||
console.log('platforms', platform.platforms());
|
||||
console.log('mode', config.setting('mode'));
|
||||
|
||||
console.log('core', Platform.is('core'))
|
||||
console.log('cordova', Platform.is('cordova'))
|
||||
console.log('mobile', Platform.is('mobile'))
|
||||
console.log('ipad', Platform.is('ipad'))
|
||||
console.log('iphone', Platform.is('iphone'))
|
||||
console.log('phablet', Platform.is('phablet'))
|
||||
console.log('tablet', Platform.is('tablet'))
|
||||
console.log('ios', Platform.is('ios'))
|
||||
console.log('android', Platform.is('android'))
|
||||
console.log('windows phone', Platform.is('windowsphone'))
|
||||
console.log('core', platform.is('core'))
|
||||
console.log('cordova', platform.is('cordova'))
|
||||
console.log('mobile', platform.is('mobile'))
|
||||
console.log('ipad', platform.is('ipad'))
|
||||
console.log('iphone', platform.is('iphone'))
|
||||
console.log('phablet', platform.is('phablet'))
|
||||
console.log('tablet', platform.is('tablet'))
|
||||
console.log('ios', platform.is('ios'))
|
||||
console.log('android', platform.is('android'))
|
||||
console.log('windows phone', platform.is('windowsphone'))
|
||||
|
||||
console.log('isRTL', app.isRTL())
|
||||
|
||||
Platform.ready().then(() => {
|
||||
console.log('Platform.ready')
|
||||
platform.ready().then(() => {
|
||||
console.log('platform.ready')
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -13,25 +13,25 @@ import {raf, ready, CSS} from 'ionic/util/dom';
|
||||
* Place it as the first child of your ionContent or ionScroll element.
|
||||
*
|
||||
* When refreshing is complete, call `refresher.complete()` from your controller.
|
||||
*
|
||||
*
|
||||
* @usage
|
||||
* ```ts
|
||||
* <ion-refresher (starting)="doStarting()" (refresh)="doRefresh($event, refresher)" (pulling)="doPulling($event, amt)">
|
||||
*
|
||||
*
|
||||
*
|
||||
* doRefresh(refresher) {
|
||||
* console.log('Refreshing!', refresher);
|
||||
*
|
||||
*
|
||||
* setTimeout(() => {
|
||||
* console.log('Pull to refresh complete!', refresher);
|
||||
* refresher.complete();
|
||||
* })
|
||||
* }
|
||||
*
|
||||
*
|
||||
* doStarting() {
|
||||
* console.log('Pull started!');
|
||||
* }
|
||||
*
|
||||
*
|
||||
* doPulling(amt) {
|
||||
* console.log('You have pulled', amt);
|
||||
* }
|
||||
@@ -326,15 +326,6 @@ export class Refresher {
|
||||
this.startY = parseInt(e.touches[0].screenY, 10);
|
||||
}
|
||||
|
||||
// kitkat fix for touchcancel events http://updates.html5rocks.com/2014/05/A-More-Compatible-Smoother-Touch
|
||||
/*
|
||||
if (ionic.Platform.isAndroid() && ionic.Platform.version() === 4.4 && scrollHost.scrollTop === 0) {
|
||||
isDragging = true;
|
||||
e.preventDefault();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// how far have we dragged so far?
|
||||
this.deltaY = parseInt(e.touches[0].screenY, 10) - this.startY;
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {Directive, Attribute, NgZone} from 'angular2/angular2'
|
||||
|
||||
import {Platform} from '../../platform/platform';
|
||||
import {IonicPlatform} from '../../platform/platform';
|
||||
|
||||
|
||||
class DisplayWhen {
|
||||
|
||||
constructor(conditions, ngZone) {
|
||||
constructor(conditions, platform, ngZone) {
|
||||
this.isMatch = false;
|
||||
this.platform = platform;
|
||||
|
||||
if (!conditions) return;
|
||||
|
||||
@@ -15,7 +16,7 @@ class DisplayWhen {
|
||||
// check if its one of the matching platforms first
|
||||
// a platform does not change during the life of an app
|
||||
for (let i = 0; i < this.conditions.length; i++) {
|
||||
if (this.conditions[i] && Platform.is(this.conditions[i])) {
|
||||
if (this.conditions[i] && platform.is(this.conditions[i])) {
|
||||
this.isMatch = true;
|
||||
return;
|
||||
}
|
||||
@@ -23,7 +24,7 @@ class DisplayWhen {
|
||||
|
||||
if ( this.orientation() ) {
|
||||
// add window resize listener
|
||||
Platform.onResize(() => {
|
||||
platform.onResize(() => {
|
||||
ngZone.run(() => {
|
||||
this.orientation();
|
||||
});
|
||||
@@ -35,18 +36,16 @@ class DisplayWhen {
|
||||
|
||||
orientation() {
|
||||
for (let i = 0; i < this.conditions.length; i++) {
|
||||
var condition = this.conditions[i];
|
||||
|
||||
if (condition == 'portrait') {
|
||||
this.isMatch = Platform.isPortrait();
|
||||
if (this.conditions[i] == 'portrait') {
|
||||
this.isMatch = this.platform.isPortrait();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (condition == 'landscape') {
|
||||
this.isMatch = Platform.isLandscape();
|
||||
if (this.conditions[i] == 'landscape') {
|
||||
this.isMatch = this.platform.isLandscape();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +68,10 @@ export class ShowWhen extends DisplayWhen {
|
||||
*/
|
||||
constructor(
|
||||
@Attribute('show-when') showWhen: string,
|
||||
platform: IonicPlatform,
|
||||
ngZone: NgZone
|
||||
) {
|
||||
super(showWhen, ngZone);
|
||||
super(showWhen, platform, ngZone);
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
@@ -97,9 +97,10 @@ export class HideWhen extends DisplayWhen {
|
||||
*/
|
||||
constructor(
|
||||
@Attribute('hide-when') hideWhen: string,
|
||||
platform: IonicPlatform,
|
||||
ngZone: NgZone
|
||||
) {
|
||||
super(hideWhen, ngZone);
|
||||
super(hideWhen, platform, ngZone);
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
|
||||
@@ -8,7 +8,6 @@ import {DragGesture} from 'ionic/gestures/drag-gesture';
|
||||
import {IonicComponent, IonicDirective} from '../../config/annotations';
|
||||
import {IonicConfig} from '../../config/config';
|
||||
import {dom} from 'ionic/util';
|
||||
import {Platform} from 'ionic/platform/platform';
|
||||
import {CSS} from '../../util/dom';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import {TextInput} from 'ionic/ionic';
|
||||
export function run() {
|
||||
|
||||
it('should scroll, top and bottom below safe area, no room to scroll', () => {
|
||||
|
||||
let inputOffsetTop = 350;
|
||||
let inputOffsetHeight = 35;
|
||||
let scrollViewDimensions = {
|
||||
@@ -13,16 +12,16 @@ export function run() {
|
||||
scrollHeight: 700
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(-178.5);
|
||||
expect(scrollData.scrollTo).toBe(208.5);
|
||||
expect(scrollData.scrollPadding).toBe(523.5);
|
||||
expect(scrollData.scrollAmount).toBe(-205);
|
||||
expect(scrollData.scrollTo).toBe(235);
|
||||
expect(scrollData.scrollPadding).toBe(550);
|
||||
});
|
||||
|
||||
it('should scroll, top and bottom below safe area, room to scroll', () => {
|
||||
|
||||
let inputOffsetTop = 350;
|
||||
let inputOffsetHeight = 35;
|
||||
let scrollViewDimensions = {
|
||||
@@ -32,11 +31,12 @@ export function run() {
|
||||
scrollHeight: 1000
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(-178.5);
|
||||
expect(scrollData.scrollTo).toBe(208.5);
|
||||
expect(scrollData.scrollAmount).toBe(-205);
|
||||
expect(scrollData.scrollTo).toBe(235);
|
||||
expect(scrollData.scrollPadding).toBe(0);
|
||||
});
|
||||
|
||||
@@ -51,8 +51,9 @@ export function run() {
|
||||
scrollHeight: 700
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(150);
|
||||
expect(scrollData.scrollTo).toBe(100);
|
||||
@@ -70,12 +71,13 @@ export function run() {
|
||||
scrollHeight: 700
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(-80);
|
||||
expect(scrollData.scrollTo).toBe(100);
|
||||
expect(scrollData.scrollPadding).toBe(523.5);
|
||||
expect(scrollData.scrollPadding).toBe(550);
|
||||
});
|
||||
|
||||
it('should scroll, top in safe, bottom below safe, below more than top in, enough padding', () => {
|
||||
@@ -87,8 +89,9 @@ export function run() {
|
||||
scrollTop: 0,
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(-20);
|
||||
expect(scrollData.scrollTo).toBe(20);
|
||||
@@ -104,11 +107,12 @@ export function run() {
|
||||
scrollTop: 0,
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
|
||||
expect(scrollData.scrollAmount).toBe(-153.5);
|
||||
expect(scrollData.scrollTo).toBe(153.5);
|
||||
expect(scrollData.scrollAmount).toBe(-180);
|
||||
expect(scrollData.scrollTo).toBe(180);
|
||||
expect(scrollData.scrollPadding).toBe(0);
|
||||
});
|
||||
|
||||
@@ -122,8 +126,9 @@ export function run() {
|
||||
keyboardTop: 400
|
||||
};
|
||||
let keyboardHeight = 400;
|
||||
let platformHeight = 800;
|
||||
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, platformHeight);
|
||||
expect(scrollData.noScroll).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ 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';
|
||||
import {IonicPlatform} from '../../platform/platform';
|
||||
|
||||
|
||||
/**
|
||||
@@ -104,6 +104,7 @@ export class TextInput extends Ion {
|
||||
config: IonicConfig,
|
||||
app: IonicApp,
|
||||
ngZone: NgZone,
|
||||
platform: IonicPlatform,
|
||||
@Optional() @Host() scrollView: Content,
|
||||
@Query(TextInputElement) inputQry: QueryList<TextInputElement>,
|
||||
@Query(Label) labelQry: QueryList<Label>
|
||||
@@ -117,8 +118,11 @@ export class TextInput extends Ion {
|
||||
|
||||
this.app = app;
|
||||
this.zone = ngZone;
|
||||
this.platform = platform;
|
||||
this.inputQry = inputQry;
|
||||
this.labelQry = labelQry;
|
||||
|
||||
this.keyboardHeight = this.config.setting('keyboardHeight');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,9 +217,7 @@ export class TextInput extends Ion {
|
||||
// find out if text input should be manually scrolled into view
|
||||
let ele = this.elementRef.nativeElement;
|
||||
|
||||
let keyboardHeight = this.config.setting('keyboardHeight');
|
||||
|
||||
let scrollData = TextInput.getScollData(ele.offsetTop, ele.offsetHeight, scrollView.getDimensions(), keyboardHeight);
|
||||
let scrollData = TextInput.getScollData(ele.offsetTop, ele.offsetHeight, scrollView.getDimensions(), this.keyboardHeight, this.platform.height());
|
||||
if (scrollData.noScroll) {
|
||||
// the text input is in a safe position that doesn't require
|
||||
// it to be scrolled into view, just set focus now
|
||||
@@ -261,14 +263,14 @@ export class TextInput extends Ion {
|
||||
* @param {TODO} keyboardHeight TODO
|
||||
* @returns {TODO} TODO
|
||||
*/
|
||||
static getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight) {
|
||||
static getScollData(inputOffsetTop, inputOffsetHeight, scrollViewDimensions, keyboardHeight, plaformHeight) {
|
||||
// compute input's Y values relative to the body
|
||||
let inputTop = (inputOffsetTop + scrollViewDimensions.contentTop - scrollViewDimensions.scrollTop);
|
||||
let inputBottom = (inputTop + inputOffsetHeight);
|
||||
|
||||
// compute the safe area which is the viewable content area when the soft keyboard is up
|
||||
let safeAreaTop = scrollViewDimensions.contentTop;
|
||||
let safeAreaHeight = Platform.height() - keyboardHeight - safeAreaTop;
|
||||
let safeAreaHeight = plaformHeight - keyboardHeight - safeAreaTop;
|
||||
safeAreaHeight /= 2;
|
||||
let safeAreaBottom = safeAreaTop + safeAreaHeight;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ export class IonicConfig {
|
||||
// or it was from the default platform configs
|
||||
// in that order
|
||||
if (isFunction(settings[arg0])) {
|
||||
settings[arg0] = settings[arg0]();
|
||||
settings[arg0] = settings[arg0](this._platform);
|
||||
}
|
||||
return settings[arg0];
|
||||
|
||||
@@ -139,6 +139,8 @@ export class IonicConfig {
|
||||
* @param {Object} platform The platform
|
||||
*/
|
||||
setPlatform(platform) {
|
||||
this._platform = platform;
|
||||
|
||||
// get the array of active platforms, which also knows the hierarchy,
|
||||
// with the last one the most important
|
||||
this._platforms = platform.platforms();
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as Rx from 'rx';
|
||||
|
||||
import * as util from 'ionic/util';
|
||||
import {NativePlugin} from '../plugin';
|
||||
import {Platform} from '../../platform/platform';
|
||||
|
||||
|
||||
@NativePlugin({
|
||||
name: 'Device Motion',
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as Rx from 'rx';
|
||||
|
||||
import * as util from 'ionic/util';
|
||||
import {NativePlugin} from '../plugin';
|
||||
import {Platform} from '../../platform/platform';
|
||||
|
||||
|
||||
@NativePlugin({
|
||||
name: 'Device Orientation',
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as Rx from 'rx';
|
||||
|
||||
import * as util from 'ionic/util';
|
||||
import {NativePlugin} from '../plugin';
|
||||
import {Platform} from '../../platform/platform';
|
||||
|
||||
|
||||
@NativePlugin({
|
||||
name: 'Device',
|
||||
@@ -20,9 +20,7 @@ export class Device {
|
||||
return this.ifPlugin(window.device, () => {
|
||||
return device;
|
||||
}, () => {
|
||||
return {
|
||||
name: Platform.platforms().join(',')
|
||||
}
|
||||
return {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,9 +69,7 @@ export class Device {
|
||||
this.ifPlugin(window.device, () => {
|
||||
return device.name;
|
||||
}, () => {
|
||||
return {
|
||||
name: Platform.name()
|
||||
}
|
||||
return 'unknown'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,14 @@ import * as dom from '../util/dom';
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
export class PlatformCtrl {
|
||||
export class IonicPlatform {
|
||||
|
||||
constructor() {
|
||||
constructor(window) {
|
||||
this._window = window;
|
||||
this._settings = {};
|
||||
this._platforms = [];
|
||||
this._versions = {};
|
||||
this._registry = {};
|
||||
this._default = null;
|
||||
this._onResizes = [];
|
||||
this._dimensions = {};
|
||||
this._dimIds = 0;
|
||||
|
||||
this._readyPromise = new Promise(res => { this._readyResolve = res; } );
|
||||
}
|
||||
@@ -67,6 +64,7 @@ export class PlatformCtrl {
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* TODO
|
||||
* @param {TODO} config TODO
|
||||
* @returns {TODO} TODO
|
||||
@@ -89,24 +87,6 @@ export class PlatformCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @returns {TODO} TODO
|
||||
*/
|
||||
domReady() {
|
||||
// convenience method so its easy to access on Platform
|
||||
return dom.ready.apply(this, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @returns {TODO} TODO
|
||||
*/
|
||||
windowLoad() {
|
||||
// convenience method so its easy to access on Platform
|
||||
return dom.windowLoad.apply(this, arguments);
|
||||
}
|
||||
|
||||
|
||||
// Methods meant to be overridden by the engine
|
||||
// **********************************************
|
||||
@@ -152,16 +132,16 @@ export class PlatformCtrl {
|
||||
|
||||
width() {
|
||||
if (!this._w) {
|
||||
this._w = window.innerWidth;
|
||||
this._h = window.innerHeight;
|
||||
this._w = this._window.innerWidth;
|
||||
this._h = this._window.innerHeight;
|
||||
}
|
||||
return this._w;
|
||||
}
|
||||
|
||||
height() {
|
||||
if (!this._h) {
|
||||
this._w = window.innerWidth;
|
||||
this._h = window.innerHeight;
|
||||
this._w = this._window.innerWidth;
|
||||
this._h = this._window.innerHeight;
|
||||
}
|
||||
return this._h;
|
||||
}
|
||||
@@ -175,14 +155,16 @@ export class PlatformCtrl {
|
||||
}
|
||||
|
||||
winResize() {
|
||||
clearTimeout(Platform._resizeTimer);
|
||||
let self = this;
|
||||
clearTimeout(self._resizeTimer);
|
||||
|
||||
Platform._resizeTimer = setTimeout(() => {
|
||||
Platform.flushDimensions();
|
||||
self._resizeTimer = setTimeout(() => {
|
||||
this._w = this._h = 0;
|
||||
dom.flushDimensionCache();
|
||||
|
||||
for (let i = 0; i < Platform._onResizes.length; i++) {
|
||||
for (let i = 0; i < self._onResizes.length; i++) {
|
||||
try {
|
||||
Platform._onResizes[i]();
|
||||
self._onResizes[i]();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -195,53 +177,33 @@ export class PlatformCtrl {
|
||||
this._onResizes.push(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element offsetWidth and offsetHeight. Values are cached to
|
||||
* reduce DOM reads, and reset on a window resize.
|
||||
* @param {TODO} platformConfig TODO
|
||||
*/
|
||||
getDimensions(component) {
|
||||
// cache
|
||||
if (!component._dimId) {
|
||||
component._dimId = ++this._dimIds;
|
||||
}
|
||||
|
||||
let dimensions = this._dimensions[component._dimId];
|
||||
if (!dimensions) {
|
||||
let ele = component.getNativeElement();
|
||||
|
||||
dimensions = this._dimensions[component._dimId] = {
|
||||
w: ele.offsetWidth,
|
||||
h: ele.offsetHeight
|
||||
};
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
flushDimensions() {
|
||||
this._dimensions = {};
|
||||
this._w = this._h = 0;
|
||||
}
|
||||
|
||||
|
||||
// Registry
|
||||
// Platform Registry
|
||||
// **********************************************
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} platformConfig TODO
|
||||
*/
|
||||
register(platformConfig) {
|
||||
this._registry[platformConfig.name] = platformConfig;
|
||||
static register(platformConfig) {
|
||||
platformRegistry[platformConfig.name] = platformConfig;
|
||||
}
|
||||
|
||||
registry() {
|
||||
return this._registry;
|
||||
static registry() {
|
||||
return platformRegistry;
|
||||
}
|
||||
|
||||
setDefault(platformName) {
|
||||
this._default = platformName;
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} platformName TODO
|
||||
* @returns {string} TODO
|
||||
*/
|
||||
static get(platformName) {
|
||||
return platformRegistry[platformName] || {};
|
||||
}
|
||||
|
||||
static setDefault(platformName) {
|
||||
platformDefault = platformName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +276,7 @@ export class PlatformCtrl {
|
||||
|
||||
// figure out the most specific platform and active engine
|
||||
let tmpPlatform = null;
|
||||
for (let platformName in this._registry) {
|
||||
for (let platformName in platformRegistry) {
|
||||
|
||||
tmpPlatform = this.matchPlatform(platformName);
|
||||
if (tmpPlatform) {
|
||||
@@ -336,7 +298,7 @@ export class PlatformCtrl {
|
||||
}
|
||||
|
||||
if (!rootPlatformNode) {
|
||||
rootPlatformNode = new PlatformNode(this._default);
|
||||
rootPlatformNode = new PlatformNode(platformDefault);
|
||||
}
|
||||
|
||||
// build a Platform instance filled with the
|
||||
@@ -423,15 +385,6 @@ export class PlatformCtrl {
|
||||
return this._settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* @param {TODO} platformName TODO
|
||||
* @returns {string} TODO
|
||||
*/
|
||||
get(platformName) {
|
||||
return this._registry[platformName] || {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function insertSuperset(platformNode) {
|
||||
@@ -453,7 +406,7 @@ function insertSuperset(platformNode) {
|
||||
class PlatformNode {
|
||||
|
||||
constructor(platformName) {
|
||||
this.c = Platform.get(platformName);
|
||||
this.c = IonicPlatform.get(platformName);
|
||||
this.isEngine = this.c.isEngine;
|
||||
}
|
||||
|
||||
@@ -543,13 +496,13 @@ class PlatformNode {
|
||||
}
|
||||
|
||||
getSubsetParents(subsetPlatformName) {
|
||||
let registry = Platform.registry();
|
||||
let platformRegistry = IonicPlatform.registry();
|
||||
|
||||
let parentPlatformNames = [];
|
||||
let platform = null;
|
||||
|
||||
for (let platformName in registry) {
|
||||
platform = registry[platformName];
|
||||
for (let platformName in platformRegistry) {
|
||||
platform = platformRegistry[platformName];
|
||||
|
||||
if (platform.subsets && platform.subsets.indexOf(subsetPlatformName) > -1) {
|
||||
parentPlatformNames.push(platformName);
|
||||
@@ -561,4 +514,6 @@ class PlatformNode {
|
||||
|
||||
}
|
||||
|
||||
export let Platform = new PlatformCtrl();
|
||||
|
||||
let platformRegistry = {};
|
||||
let platformDefault = null;
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import {Platform} from './platform';
|
||||
import {IonicPlatform} from './platform';
|
||||
import {windowLoad} from '../util/dom';
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'core',
|
||||
settings: {
|
||||
mode: 'ios',
|
||||
keyboardHeight: 290,
|
||||
}
|
||||
});
|
||||
Platform.setDefault('core');
|
||||
IonicPlatform.setDefault('core');
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'mobile'
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'phablet',
|
||||
isMatch(p) {
|
||||
let smallest = Math.min(p.width(), p.height());
|
||||
@@ -27,7 +28,7 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'tablet',
|
||||
isMatch(p) {
|
||||
let smallest = Math.min(p.width(), p.height());
|
||||
@@ -38,7 +39,7 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'android',
|
||||
superset: 'mobile',
|
||||
subsets: [
|
||||
@@ -60,7 +61,7 @@ Platform.register({
|
||||
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'ios',
|
||||
superset: 'mobile',
|
||||
subsets: [
|
||||
@@ -69,11 +70,11 @@ Platform.register({
|
||||
],
|
||||
settings: {
|
||||
mode: 'ios',
|
||||
tapPolyfill: function() {
|
||||
return /iphone|ipad|ipod/i.test(Platform.navigatorPlatform());
|
||||
tapPolyfill: function(p) {
|
||||
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
||||
},
|
||||
keyboardScrollAssist: function() {
|
||||
return /iphone|ipad|ipod/i.test(Platform.navigatorPlatform());
|
||||
keyboardScrollAssist: function(p) {
|
||||
return /iphone|ipad|ipod/i.test(p.navigatorPlatform());
|
||||
},
|
||||
keyboardHeight: 290,
|
||||
},
|
||||
@@ -86,7 +87,7 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'ipad',
|
||||
superset: 'tablet',
|
||||
settings: {
|
||||
@@ -98,7 +99,7 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'iphone',
|
||||
subsets: [
|
||||
'phablet'
|
||||
@@ -109,7 +110,7 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'windowsphone',
|
||||
superset: 'mobile',
|
||||
subsets: [
|
||||
@@ -128,17 +129,21 @@ Platform.register({
|
||||
});
|
||||
|
||||
|
||||
Platform.register({
|
||||
IonicPlatform.register({
|
||||
name: 'cordova',
|
||||
isEngine: true,
|
||||
methods: {
|
||||
ready: function(resolve) {
|
||||
Platform.windowLoad(() => {
|
||||
document.addEventListener("deviceready", resolve);
|
||||
function isReady() {
|
||||
document.removeEventListener('deviceready', isReady);
|
||||
resolve();
|
||||
}
|
||||
windowLoad(function() {
|
||||
document.addEventListener('deviceready', isReady);
|
||||
});
|
||||
}
|
||||
},
|
||||
isMatch(p) {
|
||||
isMatch() {
|
||||
return !!(window.cordova || window.PhoneGap || window.phonegap);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -196,25 +196,58 @@ export function hasFocusedTextInput() {
|
||||
}
|
||||
|
||||
export function closest(el, selector) {
|
||||
var matchesFn;
|
||||
var matchesFn;
|
||||
|
||||
// find vendor prefix
|
||||
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
|
||||
if (typeof document.body[fn] == 'function') {
|
||||
matchesFn = fn;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
|
||||
// traverse parents
|
||||
while (el!==null) {
|
||||
parent = el.parentElement;
|
||||
if (parent!==null && parent[matchesFn](selector)) {
|
||||
return parent;
|
||||
}
|
||||
el = parent;
|
||||
// find vendor prefix
|
||||
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
|
||||
if (typeof document.body[fn] == 'function') {
|
||||
matchesFn = fn;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
|
||||
return null;
|
||||
// traverse parents
|
||||
while (el!==null) {
|
||||
parent = el.parentElement;
|
||||
if (parent!==null && parent[matchesFn](selector)) {
|
||||
return parent;
|
||||
}
|
||||
el = parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the element offsetWidth and offsetHeight. Values are cached
|
||||
* to reduce DOM reads. Cache is cleared on a window resize.
|
||||
* @param {TODO} ele TODO
|
||||
*/
|
||||
export function getDimensions(ele) {
|
||||
if (!ele.ionicId) {
|
||||
ele.ionicId = ++ionicElementIds;
|
||||
if (ele.ionicId % 200) {
|
||||
// periodically flush dimensions
|
||||
flushDimensionCache();
|
||||
}
|
||||
}
|
||||
|
||||
let dimensions = elementDimensions[ele.ionicId];
|
||||
if (!dimensions) {
|
||||
dimensions = elementDimensions[ele.ionicId] = {
|
||||
width: ele.offsetWidth,
|
||||
height: ele.offsetHeight
|
||||
};
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
export function flushDimensionCache() {
|
||||
elementDimensions = {};
|
||||
}
|
||||
|
||||
let elementDimensions = {};
|
||||
let ionicElementIds = 0;
|
||||
|
||||
Reference in New Issue
Block a user