mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
235 lines
6.3 KiB
TypeScript
235 lines
6.3 KiB
TypeScript
import {Component, View, bootstrap, ElementRef, NgZone, bind, DynamicComponentLoader, Injector} from 'angular2/angular2';
|
|
import {routerInjectables, HashLocationStrategy, LocationStrategy, Router} from 'angular2/router';
|
|
|
|
import {IonicConfig} from '../../config/config';
|
|
import {Platform} from '../../platform/platform';
|
|
import * as util from '../../util/util';
|
|
|
|
// injectables
|
|
import {ActionMenu} from '../action-menu/action-menu';
|
|
import {Modal} from '../modal/modal';
|
|
import {Popup} from '../popup/popup';
|
|
import {FocusHolder} from '../form/focus-holder';
|
|
|
|
|
|
export class IonicApp {
|
|
|
|
constructor() {
|
|
this.overlays = [];
|
|
|
|
// Our component registry map
|
|
this.components = {};
|
|
}
|
|
|
|
load(appRef) {
|
|
this.ref(appRef);
|
|
this._zone = appRef.injector.get(NgZone);
|
|
}
|
|
|
|
focusHolder(val) {
|
|
if (arguments.length) {
|
|
this._focusHolder = val;
|
|
}
|
|
return this._focusHolder;
|
|
}
|
|
|
|
title(val) {
|
|
document.title = val;
|
|
}
|
|
|
|
ref(val) {
|
|
if (arguments.length) {
|
|
this._ref = val;
|
|
}
|
|
return this._ref;
|
|
}
|
|
|
|
get injector() {
|
|
return this._ref.injector;
|
|
}
|
|
|
|
zoneRun(fn) {
|
|
this._zone.run(fn);
|
|
}
|
|
|
|
/**
|
|
* Register a known component with a key, for easy lookups later.
|
|
*/
|
|
register(key, component) {
|
|
this.components[key] = component;
|
|
// TODO(mlynch): We need to track the lifecycle of this component to remove it onDehydrate
|
|
}
|
|
|
|
/**
|
|
* Get the component for the given key.
|
|
*/
|
|
getComponent(key) {
|
|
return this.components[key];
|
|
}
|
|
|
|
/**
|
|
* Create and append the given component into the root
|
|
* element of the app.
|
|
*
|
|
* @param Component the component to create and insert
|
|
* @return Promise that resolves with the ContainerRef created
|
|
*/
|
|
appendComponent(componentType: Type, context=null) {
|
|
return this.rootAnchor.append(componentType);
|
|
}
|
|
|
|
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-ios_8
|
|
platformClass += '_' + platformVersion.major;
|
|
bodyEle.classList.add(platformClass);
|
|
|
|
// platform-ios_8_3
|
|
bodyEle.classList.add(platformClass + '_' + platformVersion.minor);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* 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';
|
|
document.body.appendChild(hairlineEle);
|
|
|
|
if (hairlineEle.offsetHeight === 1) {
|
|
document.body.classList.add('hairlines');
|
|
}
|
|
document.body.removeChild(hairlineEle);
|
|
}
|
|
|
|
bodyEle.setAttribute('mode', config.setting('mode'));
|
|
}
|
|
|
|
isRTL(val) {
|
|
if (arguments.length) {
|
|
this._rtl = val;
|
|
}
|
|
return this._rtl;
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
}, 2000);
|
|
|
|
return app;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'root-anchor'
|
|
})
|
|
@View({
|
|
template: ''
|
|
})
|
|
class RootAnchor {
|
|
constructor(app: IonicApp, elementRef: ElementRef, loader: DynamicComponentLoader) {
|
|
this.elementRef = elementRef;
|
|
this.loader = loader;
|
|
app.rootAnchor = this;
|
|
}
|
|
|
|
append(componentType) {
|
|
return this.loader.loadNextToLocation(componentType, this.elementRef).catch(err => {
|
|
console.error(err)
|
|
});
|
|
}
|
|
}
|
|
|
|
export function ionicBootstrap(rootComponentType, config) {
|
|
return new Promise(resolve => {
|
|
try {
|
|
// get the user config, or create one if wasn't passed in
|
|
if (typeof config !== IonicConfig) {
|
|
config = new IonicConfig(config);
|
|
}
|
|
|
|
// 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);
|
|
|
|
// TODO: probs need a better way to inject global injectables
|
|
let actionMenu = new ActionMenu(app, config);
|
|
let modal = new Modal(app, config);
|
|
let popup = new Popup(app, config);
|
|
|
|
// add injectables that will be available to all child components
|
|
let appBindings = Injector.resolve([
|
|
bind(IonicApp).toValue(app),
|
|
bind(IonicConfig).toValue(config),
|
|
bind(ActionMenu).toValue(actionMenu),
|
|
bind(Modal).toValue(modal),
|
|
bind(Popup).toValue(popup),
|
|
routerInjectables,
|
|
bind(LocationStrategy).toClass(HashLocationStrategy)
|
|
]);
|
|
|
|
bootstrap(rootComponentType, appBindings).then(appRef => {
|
|
app.load(appRef);
|
|
|
|
// Adding a anchor to add overlays off of...huh??
|
|
let elementRefs = appRef._hostComponent.hostView._view.elementRefs;
|
|
let lastElementRef = elementRefs[1];
|
|
let injector = lastElementRef.parentView._view.rootElementInjectors[0]._injector;
|
|
let loader = injector.get(DynamicComponentLoader);
|
|
loader.loadNextToLocation(RootAnchor, lastElementRef).then(() => {
|
|
// append the focus holder if its needed
|
|
if (config.setting('keyboardScrollAssist')) {
|
|
app.appendComponent(FocusHolder).then(ref => {
|
|
app.focusHolder(ref.instance);
|
|
});
|
|
}
|
|
}).catch(err => {
|
|
console.error(err)
|
|
});
|
|
|
|
resolve(app);
|
|
|
|
}).catch(err => {
|
|
console.error('ionicBootstrap', err);
|
|
});
|
|
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|