fix(): ensure that bindings fore core are being loaded.

This commit is contained in:
Josh Thomas
2017-05-18 13:56:47 -05:00
parent 4003b6f62b
commit d4f45b5a07
4 changed files with 249 additions and 0 deletions

View File

@ -0,0 +1,124 @@
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
/**
* @hidden
*/
@Directive({
selector: 'ion-toggle',
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: BooleanInput, multi: true }],
})
export class BooleanInput {
id: string;
_labelId: string;
_chg: Function;
_tch: Function;
_dis: Function;
@Output() ionChange: EventEmitter<any> = new EventEmitter<any>();
@Output() ionFocus: EventEmitter<any> = new EventEmitter<any>();
@Output() ionBlur: EventEmitter<any> = new EventEmitter<any>();
constructor(public _el: ElementRef) {}
/**
* @input {boolean} If true, the element is selected.
*/
@Input()
get checked(): boolean {
return this._el.nativeElement.checked;
}
set checked(val: boolean) {
this._el.nativeElement.checked = val;
}
/**
* @input {boolean} If true, the user cannot interact with this element.
*/
@Input()
get disabled(): boolean {
return this._el.nativeElement.disabled;
}
set disabled(val: boolean) {
this._el.nativeElement.disabled = val;
}
/**
* @input {string}
*/
@Input()
get value(): string {
return this._el.nativeElement.value;
}
set value(val: string) {
this._el.nativeElement.value = val;
}
/**
* @hidden
*/
@HostListener('$ionChange', ['$event'])
_onChange(ev: any) {
ev.stopPropagation();
this._chg && this._chg(ev.detail.checked);
this._tch && this._tch();
this.ionChange.emit(this);
}
/**
* @hidden
*/
@HostListener('$ionFocus', ['$event'])
_onFocus(ev: any) {
ev.stopPropagation();
this.ionFocus.emit(this);
}
/**
* @hidden
*/
@HostListener('$ionBlur', ['$event'])
_onBlur(ev: any) {
ev.stopPropagation();
this.ionBlur.emit(this);
}
/**
* @hidden
*/
writeValue(val: any) {
if (this.checked !== val) {
this.checked = val;
}
}
/**
* @hidden
*/
registerOnChange(fn: any) {
this._chg = fn;
}
/**
* @hidden
*/
registerOnTouched(fn: any) {
this._tch = fn;
}
/**
* @hidden
*/
registerOnDisabledChange(fn: any) {
this._dis = fn;
}
/**
* @hidden
*/
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
}
}

View File

@ -0,0 +1,122 @@
import { Config } from '../../../config/config';
import { DomController } from '../../../platform/dom-controller';
import { NgZone } from '@angular/core';
import { Platform } from '../../../platform/platform';
/**
* @hidden
*/
export function setupCore(config: Config, plt: Platform, domCtrl: DomController, zone: NgZone) {
return function() {
const win: any = plt.win();
const doc = plt.doc();
const ionic: any = win['Ionic'];
if (!ionic || !ionic['staticDir']) {
// window.Ionic should already exist and
// window.Ionic.staticDir should have been added to the
// main bundle referencing the static www build directory
return;
}
// same controllers are used by ionic core
ionic['ConfigCtrl'] = config;
// keep core and angular dom reads/writes *nsync
ionic['DomCtrl'] = domCtrl;
// next tick controller created here so that it can
// be created to run outside of angular
ionic['QueueCtrl'] = getQueueController(win, zone);
// keep core and angular dom reads/writes *nsync
ionic['eventNameFn'] = function(eventName: string) {
return '$' + eventName;
};
// build up a path for the exact ionic core javascript file this browser needs
var pathItems: string[] = ['core'];
if (!('attachShadow' in Element.prototype)) {
// browser requires the shadow dom polyfill
pathItems.push('sd');
}
if (!win.customElements) {
// browser requires the custom elements polyfill
pathItems.push('ce');
}
// request the ionic core file this browser needs
var s = doc.createElement('script');
s.src = `${ionic['staticDir']}ionic.${pathItems.join('.')}.js`;
doc.head.appendChild(s);
return {};
};
}
function getQueueController(win: any, zone: NgZone) {
const hostScheduleDefer: Function = win['requestIdleCallback'];
const callbacks: Function[] = [];
let pending = false;
function doWork(deadlineObj: any) {
// let's see if we've got time to take care of things
while (deadlineObj.timeRemaining() > 1 && callbacks.length > 0) {
// do some work while within the allowed time
// shift the array and fire off the callbacks from the beginning
// once we run out of time or callbacks we'll stop
callbacks.shift()();
}
// check to see if we still have work to do
if (pending = (callbacks.length > 0)) {
// everyone just settle down now
// we already don't have time to do anything in this callback
// let's throw the next one in a requestAnimationFrame
// so we can just simmer down for a bit
zone.runOutsideAngular(() => {
requestAnimationFrame(flush);
});
}
}
function flush() {
// always force a bunch of callbacks to run, but still have
// a throttle on how many can run in a certain time
const start = performance.now();
while (callbacks.length > 0 && (performance.now() - start < 4)) {
callbacks.shift()();
}
if (pending = (callbacks.length > 0)) {
// still more to do yet, but we've run out of time
// let's let thing cool off and try again after a raf
zone.runOutsideAngular(() => {
hostScheduleDefer(doWork);
});
}
}
function add(cb: Function) {
// add the work to the end of the callbacks
callbacks.push(cb);
if (!pending) {
// not already pending work to do, so let's tee it up
pending = true;
zone.runOutsideAngular(() => {
hostScheduleDefer(doWork);
});
}
}
return {
add: add,
flush: flush
};
}

View File

@ -122,6 +122,7 @@ export { NavController } from './navigation/nav-controller';
export { NavControllerBase } from './navigation/nav-controller-base'; export { NavControllerBase } from './navigation/nav-controller-base';
export { NavParams } from './navigation/nav-params'; export { NavParams } from './navigation/nav-params';
export { NavLink, NavOptions, DeepLinkConfig, DeepLinkMetadata, DeepLinkMetadataFactory } from './navigation/nav-util'; export { NavLink, NavOptions, DeepLinkConfig, DeepLinkMetadata, DeepLinkMetadataFactory } from './navigation/nav-util';
export { setupCore } from './bindings/angular/providers/ionic-core';
export { TapClick, setupTapClick, isActivatable } from './tap-click/tap-click'; export { TapClick, setupTapClick, isActivatable } from './tap-click/tap-click';
export { UrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer'; export { UrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer';
export { ViewController } from './navigation/view-controller'; export { ViewController } from './navigation/view-controller';

View File

@ -31,6 +31,7 @@ import { ModuleLoader, provideModuleLoader, setupPreloading, LAZY_LOADED_TOKEN }
import { NgModuleLoader } from './util/ng-module-loader'; import { NgModuleLoader } from './util/ng-module-loader';
import { Platform, setupPlatform } from './platform/platform'; import { Platform, setupPlatform } from './platform/platform';
import { PlatformConfigToken, providePlatformConfigs } from './platform/platform-registry'; import { PlatformConfigToken, providePlatformConfigs } from './platform/platform-registry';
import { setupCore } from './bindings/angular/providers/ionic-core';
import { TapClick, setupTapClick } from './tap-click/tap-click'; import { TapClick, setupTapClick } from './tap-click/tap-click';
import { registerModeConfigs } from './config/mode-registry'; import { registerModeConfigs } from './config/mode-registry';
import { TransitionController } from './transitions/transition-controller'; import { TransitionController } from './transitions/transition-controller';
@ -395,6 +396,7 @@ export class IonicModule {
// useFactory: ionic app initializers // useFactory: ionic app initializers
{ provide: APP_INITIALIZER, useFactory: registerModeConfigs, deps: [ Config ], multi: true }, { provide: APP_INITIALIZER, useFactory: registerModeConfigs, deps: [ Config ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupCore, deps: [ Config, Platform, DomController, NgZone ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform, DomController ], multi: true }, { provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform, DomController ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, Platform, DomController, App, GestureController ], multi: true }, { provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, Platform, DomController, App, GestureController ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupPreloading, deps: [ Config, DeepLinkConfigToken, ModuleLoader, NgZone ], multi: true }, { provide: APP_INITIALIZER, useFactory: setupPreloading, deps: [ Config, DeepLinkConfigToken, ModuleLoader, NgZone ], multi: true },