mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(platform): add backbutton event
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {getQuerystring, assign} from '../util/util';
|
||||
import {ready, windowDimensions, flushDimensionCache} from '../util/dom';
|
||||
import {Config} from '../config/config';
|
||||
import {EventEmitter} from 'angular2/core';
|
||||
import {getQuerystring} from '../util/util';
|
||||
import {ready, windowDimensions, flushDimensionCache} from '../util/dom';
|
||||
|
||||
/**
|
||||
* @name Platform
|
||||
@@ -25,7 +26,7 @@ import {Config} from '../config/config';
|
||||
*/
|
||||
export class Platform {
|
||||
private _platforms: Array<string>;
|
||||
private _versions: any = {};
|
||||
private _versions: {[name: string]: PlatformVersion} = {};
|
||||
private _dir: string;
|
||||
private _lang: string;
|
||||
private _url: string;
|
||||
@@ -35,14 +36,8 @@ export class Platform {
|
||||
private _onResizes: Array<Function> = [];
|
||||
private _readyPromise: Promise<any>;
|
||||
private _readyResolve: any;
|
||||
private _engineReady: any;
|
||||
private _resizeTm: any;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
platformOverride: string;
|
||||
|
||||
constructor(platforms = []) {
|
||||
this._platforms = platforms;
|
||||
this._readyPromise = new Promise(res => { this._readyResolve = res; } );
|
||||
@@ -124,7 +119,7 @@ export class Platform {
|
||||
|
||||
|
||||
/**
|
||||
* Returns an object containing information about the paltform
|
||||
* Returns an object containing information about the platforms.
|
||||
*
|
||||
* ```
|
||||
* import {Platform} from 'ionic-angular';
|
||||
@@ -132,8 +127,7 @@ export class Platform {
|
||||
* @Page({...})
|
||||
* export MyPage {
|
||||
* constructor(platform: Platform) {
|
||||
* this.platform = platform;
|
||||
* console.log(this.platform.versions());
|
||||
* console.log(platform.versions());
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
@@ -142,12 +136,7 @@ export class Platform {
|
||||
* @returns {object} An object with various platform info
|
||||
*
|
||||
*/
|
||||
versions(platformName: string): any {
|
||||
if (arguments.length) {
|
||||
// get a specific platform's version
|
||||
return this._versions[platformName];
|
||||
}
|
||||
|
||||
versions(): {[name: string]: PlatformVersion} {
|
||||
// get all the platforms that have a valid parsed version
|
||||
return this._versions;
|
||||
}
|
||||
@@ -155,7 +144,7 @@ export class Platform {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
version(): any {
|
||||
version(): PlatformVersion {
|
||||
for (let platformName in this._versions) {
|
||||
if (this._versions[platformName]) {
|
||||
return this._versions[platformName];
|
||||
@@ -165,7 +154,11 @@ export class Platform {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise when the platform is ready and native functionality can be called
|
||||
* Returns a promise when the platform is ready and native functionality
|
||||
* can be called. If the app is running from within a web browser, then
|
||||
* the promise will resolve when the DOM is ready. When the app is running
|
||||
* from an application engine such as Cordova, then the promise
|
||||
* will resolve when Cordova triggers the `deviceready` event.
|
||||
*
|
||||
* ```
|
||||
* import {Platform} from 'ionic-angular';
|
||||
@@ -173,39 +166,37 @@ export class Platform {
|
||||
* @Page({...})
|
||||
* export MyPage {
|
||||
* constructor(platform: Platform) {
|
||||
* this.platform = platform;
|
||||
* this.platform.ready().then(() => {
|
||||
* platform.ready().then(() => {
|
||||
* console.log('Platform ready');
|
||||
* // The platform is now ready, execute any native code you want
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @returns {promise} Returns a promsie when device ready has fired
|
||||
* @returns {promise}
|
||||
*/
|
||||
ready(): Promise<any> {
|
||||
// this is the default if it's not replaced by the engine
|
||||
// if there was no custom ready method from the engine
|
||||
// then use the default DOM ready
|
||||
return this._readyPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
prepareReady(config: Config) {
|
||||
let self = this;
|
||||
triggerReady() {
|
||||
this._readyResolve();
|
||||
}
|
||||
|
||||
function resolve() {
|
||||
self._readyResolve(config);
|
||||
}
|
||||
|
||||
if (this._engineReady) {
|
||||
// the engine provide a ready promise, use this instead
|
||||
this._engineReady(resolve);
|
||||
|
||||
} else {
|
||||
// there is no custom ready method from the engine
|
||||
// use the default dom ready
|
||||
ready(resolve);
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
prepareReady() {
|
||||
// this is the default prepareReady if it's not replaced by the engine
|
||||
// if there was no custom ready method from the engine
|
||||
// then use the default DOM ready
|
||||
ready(this.triggerReady.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,31 +267,30 @@ export class Platform {
|
||||
// Methods meant to be overridden by the engine
|
||||
// **********************************************
|
||||
// Provided NOOP methods so they do not error when
|
||||
// called by engines (the browser) doesn't provide them
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
on() {}
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onHardwareBackButton() {}
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
registerBackButtonAction() {}
|
||||
// called by engines (the browser)that do not provide them
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
exitApp() {}
|
||||
|
||||
// Events meant to be triggered by the engine
|
||||
// **********************************************
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
fullScreen() {}
|
||||
backButton: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
showStatusBar() {}
|
||||
pause: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
resume: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
|
||||
// Getter/Setter Methods
|
||||
@@ -427,21 +417,21 @@ export class Platform {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static register(platformConfig) {
|
||||
static register(platformConfig: PlatformConfig) {
|
||||
platformRegistry[platformConfig.name] = platformConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static registry(): any {
|
||||
static registry() {
|
||||
return platformRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
static get(platformName: string): any {
|
||||
static get(platformName: string): PlatformConfig {
|
||||
return platformRegistry[platformName] || {};
|
||||
}
|
||||
|
||||
@@ -513,15 +503,13 @@ export class Platform {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
load(platformOverride?: string) {
|
||||
let rootPlatformNode = null;
|
||||
let engineNode = null;
|
||||
load(config: Config) {
|
||||
let rootPlatformNode: PlatformNode;
|
||||
let enginePlatformNode: PlatformNode;
|
||||
let self = this;
|
||||
|
||||
this.platformOverride = platformOverride;
|
||||
|
||||
// figure out the most specific platform and active engine
|
||||
let tmpPlatform = null;
|
||||
let tmpPlatform: PlatformNode;
|
||||
for (let platformName in platformRegistry) {
|
||||
|
||||
tmpPlatform = this.matchPlatform(platformName);
|
||||
@@ -532,7 +520,7 @@ export class Platform {
|
||||
if (tmpPlatform.isEngine) {
|
||||
// because it matched then this should be the active engine
|
||||
// you cannot have more than one active engine
|
||||
engineNode = tmpPlatform;
|
||||
enginePlatformNode = tmpPlatform;
|
||||
|
||||
} else if (!rootPlatformNode || tmpPlatform.depth > rootPlatformNode.depth) {
|
||||
// only find the root node for platforms that are not engines
|
||||
@@ -553,20 +541,13 @@ export class Platform {
|
||||
if (rootPlatformNode) {
|
||||
|
||||
// check if we found an engine node (cordova/node-webkit/etc)
|
||||
if (engineNode) {
|
||||
if (enginePlatformNode) {
|
||||
// add the engine to the first in the platform hierarchy
|
||||
// the original rootPlatformNode now becomes a child
|
||||
// of the engineNode, which is not the new root
|
||||
engineNode.child = rootPlatformNode;
|
||||
rootPlatformNode.parent = engineNode;
|
||||
rootPlatformNode = engineNode;
|
||||
|
||||
// add any events which the engine would provide
|
||||
// for example, Cordova provides its own ready event
|
||||
let engineMethods = engineNode.methods();
|
||||
engineMethods._engineReady = engineMethods.ready;
|
||||
delete engineMethods.ready;
|
||||
assign(this, engineMethods);
|
||||
enginePlatformNode.child = rootPlatformNode;
|
||||
rootPlatformNode.parent = enginePlatformNode;
|
||||
rootPlatformNode = enginePlatformNode;
|
||||
}
|
||||
|
||||
let platformNode = rootPlatformNode;
|
||||
@@ -585,12 +566,14 @@ export class Platform {
|
||||
|
||||
platformNode = rootPlatformNode;
|
||||
while (platformNode) {
|
||||
platformNode.initialize(this, config);
|
||||
|
||||
// set the array of active platforms with
|
||||
// the last one in the array the most important
|
||||
this._platforms.push(platformNode.name());
|
||||
this._platforms.push(platformNode.name);
|
||||
|
||||
// get the platforms version if a version parser was provided
|
||||
this._versions[platformNode.name()] = platformNode.version(this);
|
||||
this._versions[platformNode.name] = platformNode.version(this);
|
||||
|
||||
// go to the next platform child
|
||||
platformNode = platformNode.child;
|
||||
@@ -605,7 +588,7 @@ export class Platform {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
matchPlatform(platformName: string): any {
|
||||
private matchPlatform(platformName: string): PlatformNode {
|
||||
// build a PlatformNode and assign config data to it
|
||||
// use it's getRoot method to build up its hierarchy
|
||||
// depending on which platforms match
|
||||
@@ -640,24 +623,24 @@ function insertSuperset(platformNode: PlatformNode) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class PlatformNode {
|
||||
private c;
|
||||
private c: PlatformConfig;
|
||||
|
||||
parent: PlatformNode;
|
||||
child: PlatformNode;
|
||||
name: string;
|
||||
isEngine: boolean;
|
||||
depth: number;
|
||||
|
||||
constructor(platformName: string) {
|
||||
this.c = Platform.get(platformName);
|
||||
this.name = platformName;
|
||||
this.isEngine = this.c.isEngine;
|
||||
}
|
||||
|
||||
name(): string {
|
||||
return this.c.name;
|
||||
}
|
||||
|
||||
settings(): any {
|
||||
return this.c.settings || {};
|
||||
}
|
||||
@@ -666,22 +649,15 @@ class PlatformNode {
|
||||
return this.c.superset;
|
||||
}
|
||||
|
||||
methods(): any {
|
||||
return this.c.methods || {};
|
||||
}
|
||||
|
||||
isMatch(p: Platform): boolean {
|
||||
if (p.platformOverride && !this.isEngine) {
|
||||
return (p.platformOverride === this.c.name);
|
||||
|
||||
} else if (!this.c.isMatch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.c.isMatch(p);
|
||||
return this.c.isMatch && this.c.isMatch(p) || false;
|
||||
}
|
||||
|
||||
version(p: Platform): any {
|
||||
initialize(platform: Platform, config: Config) {
|
||||
this.c.initialize && this.c.initialize(platform, config);
|
||||
}
|
||||
|
||||
version(p: Platform): PlatformVersion {
|
||||
if (this.c.versionParser) {
|
||||
let v = this.c.versionParser(p);
|
||||
if (v) {
|
||||
@@ -699,7 +675,7 @@ class PlatformNode {
|
||||
getRoot(p: Platform): PlatformNode {
|
||||
if (this.isMatch(p)) {
|
||||
|
||||
let parents = this.getSubsetParents(this.name());
|
||||
let parents = this.getSubsetParents(this.name);
|
||||
|
||||
if (!parents.length) {
|
||||
return this;
|
||||
@@ -742,5 +718,23 @@ class PlatformNode {
|
||||
|
||||
}
|
||||
|
||||
let platformRegistry = {};
|
||||
let platformDefault = null;
|
||||
let platformRegistry: {[name: string]: PlatformConfig} = {};
|
||||
let platformDefault: string = null;
|
||||
|
||||
export interface PlatformConfig {
|
||||
name?: string;
|
||||
isEngine?: boolean;
|
||||
initialize?: Function;
|
||||
isMatch?: Function;
|
||||
superset?: string;
|
||||
subsets?: string[];
|
||||
settings?: any;
|
||||
versionParser?: any;
|
||||
}
|
||||
|
||||
export interface PlatformVersion {
|
||||
str?: string;
|
||||
num?: number;
|
||||
major?: number;
|
||||
minor?: number
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Platform} from './platform';
|
||||
import {Config} from '../config/config';
|
||||
import {windowLoad} from '../util/dom';
|
||||
|
||||
const win: any = window;
|
||||
@@ -166,16 +167,38 @@ Platform.register({
|
||||
Platform.register({
|
||||
name: 'cordova',
|
||||
isEngine: true,
|
||||
methods: {
|
||||
ready: function(resolve) {
|
||||
function isReady() {
|
||||
doc.removeEventListener('deviceready', isReady);
|
||||
resolve();
|
||||
}
|
||||
initialize: function(p: Platform, config: Config) {
|
||||
|
||||
// prepare a custom "ready" for cordova "deviceready"
|
||||
p.prepareReady = function() {
|
||||
// 1) ionic bootstrapped
|
||||
windowLoad(function() {
|
||||
doc.addEventListener('deviceready', isReady);
|
||||
// 2) window onload triggered or completed
|
||||
doc.addEventListener('deviceready', () => {
|
||||
// 3) cordova deviceready event triggered
|
||||
|
||||
// add cordova listeners to fire platform events
|
||||
doc.addEventListener('backbutton', function() {
|
||||
p.backButton.emit(null);
|
||||
});
|
||||
// doc.addEventListener('pause', function() {
|
||||
// p.pause.emit(null);
|
||||
// });
|
||||
// doc.addEventListener('resume', function() {
|
||||
// p.resume.emit(null);
|
||||
// });
|
||||
|
||||
// cordova has fully loaded and we've added listeners
|
||||
p.triggerReady();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// cordova has its own exitApp method
|
||||
p.exitApp = function() {
|
||||
win.navigator.app.exitApp();
|
||||
};
|
||||
|
||||
},
|
||||
isMatch(): boolean {
|
||||
return !!(win.cordova || win.PhoneGap || win.phonegap);
|
||||
|
||||
@@ -5,22 +5,13 @@ export function run() {
|
||||
it('should set core as the fallback', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent('idk');
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('ios')).toEqual(false);
|
||||
expect(platform.is('core')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should set android via platformOverride, despite ios user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(IPAD_UA);
|
||||
platform.load('android');
|
||||
|
||||
expect(platform.is('android')).toEqual(true);
|
||||
expect(platform.is('ios')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should get case insensitive querystring value', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?KEY=value');
|
||||
@@ -35,48 +26,10 @@ export function run() {
|
||||
expect(platform.query('key')).toEqual('value');
|
||||
});
|
||||
|
||||
it('should set ios via platformOverride, despite android querystring', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=android');
|
||||
platform.load('ios');
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
expect(platform.is('ios')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should set windows via platformOverride, despite android querystring', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=android');
|
||||
platform.load('windows');
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('windows')).toEqual(true);
|
||||
expect(platform.is('ios')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should set ios via platformOverride', () => {
|
||||
let platform = new Platform();
|
||||
platform.load('ios');
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
expect(platform.is('ios')).toEqual(true);
|
||||
});
|
||||
|
||||
it('should set android via platformOverride', () => {
|
||||
let platform = new Platform();
|
||||
platform.load('android');
|
||||
|
||||
expect(platform.is('android')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
expect(platform.is('ios')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should set windows via querystring', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=windows');
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
@@ -87,7 +40,7 @@ export function run() {
|
||||
it('should set ios via querystring', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=ios');
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
@@ -99,7 +52,7 @@ export function run() {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=windows');
|
||||
platform.setUserAgent(ANDROID_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('windows')).toEqual(true);
|
||||
@@ -110,7 +63,7 @@ export function run() {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=ios');
|
||||
platform.setUserAgent(ANDROID_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('android')).toEqual(false);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
@@ -120,7 +73,7 @@ export function run() {
|
||||
it('should set android via querystring', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=android');
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('android')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
@@ -131,7 +84,7 @@ export function run() {
|
||||
let platform = new Platform();
|
||||
platform.setUrl('/?ionicplatform=android');
|
||||
platform.setUserAgent(IPHONE_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('android')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
@@ -141,7 +94,7 @@ export function run() {
|
||||
it('should set windows via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(WINDOWS_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(true);
|
||||
@@ -152,7 +105,7 @@ export function run() {
|
||||
it('should set windows8 via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(WINDOWS8_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(true);
|
||||
@@ -163,7 +116,7 @@ export function run() {
|
||||
it('should set windows7 via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(WINDOWS7_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(true);
|
||||
@@ -174,7 +127,7 @@ export function run() {
|
||||
it('should set android via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(ANDROID_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
@@ -185,7 +138,7 @@ export function run() {
|
||||
it('should set iphone via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(IPHONE_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
@@ -198,7 +151,7 @@ export function run() {
|
||||
it('should set ipad via user agent', () => {
|
||||
let platform = new Platform();
|
||||
platform.setUserAgent(IPAD_UA);
|
||||
platform.load();
|
||||
platform.load(null);
|
||||
|
||||
expect(platform.is('mobile')).toEqual(true);
|
||||
expect(platform.is('windows')).toEqual(false);
|
||||
|
||||
Reference in New Issue
Block a user