feat(DomController): organize dom reads/writes

This commit is contained in:
Adam Bradley
2016-11-29 10:27:07 -06:00
parent 0af494e613
commit cac71647f3
3 changed files with 85 additions and 10 deletions

View File

@ -10,8 +10,11 @@ import { HttpModule } from '@angular/http';
import { ActionSheetController } from './components/action-sheet/action-sheet'; import { ActionSheetController } from './components/action-sheet/action-sheet';
import { AlertController } from './components/alert/alert'; import { AlertController } from './components/alert/alert';
import { App } from './components/app/app'; import { App } from './components/app/app';
import { AppRootToken } from './components/app/app-root';
import { ClickBlock } from './util/click-block';
import { Config, ConfigToken, setupConfig } from './config/config'; import { Config, ConfigToken, setupConfig } from './config/config';
import { DeepLinker, setupDeepLinker } from './navigation/deep-linker'; import { DeepLinker, setupDeepLinker } from './navigation/deep-linker';
import { DomController } from './util/dom-controller';
import { Events, setupProvideEvents } from './util/events'; import { Events, setupProvideEvents } from './util/events';
import { Form } from './util/form'; import { Form } from './util/form';
import { GestureController } from './gestures/gesture-controller'; import { GestureController } from './gestures/gesture-controller';
@ -31,9 +34,7 @@ import { ToastController } from './components/toast/toast';
import { registerModeConfigs } from './config/mode-registry'; import { registerModeConfigs } from './config/mode-registry';
import { registerTransitions } from './transitions/transition-registry'; import { registerTransitions } from './transitions/transition-registry';
import { TransitionController } from './transitions/transition-controller'; import { TransitionController } from './transitions/transition-controller';
import { AppRootToken } from './components/app/app-root';
import { UrlSerializer, setupUrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer'; import { UrlSerializer, setupUrlSerializer, DeepLinkConfigToken } from './navigation/url-serializer';
import { ClickBlock } from './util/click-block';
/** /**
* Import Overlay Entry Components * Import Overlay Entry Components
*/ */
@ -51,6 +52,7 @@ import { ToastCmp } from './components/toast/toast-component';
* Export Providers * Export Providers
*/ */
export { Config, setupConfig, ConfigToken } from './config/config'; export { Config, setupConfig, ConfigToken } from './config/config';
export { DomController } from './util/dom-controller';
export { Platform, setupPlatform, UserAgentToken, DocumentDirToken, DocLangToken, NavigatorPlatformToken } from './platform/platform'; export { Platform, setupPlatform, UserAgentToken, DocumentDirToken, DocLangToken, NavigatorPlatformToken } from './platform/platform';
export { Haptic } from './util/haptic'; export { Haptic } from './util/haptic';
export { QueryParams, setupQueryParams, UrlToken } from './platform/query-params'; export { QueryParams, setupQueryParams, UrlToken } from './platform/query-params';
@ -102,13 +104,13 @@ export { ViewController } from './navigation/view-controller';
declarations: [ declarations: [
ActionSheetCmp, ActionSheetCmp,
AlertCmp, AlertCmp,
ClickBlock,
IONIC_DIRECTIVES, IONIC_DIRECTIVES,
LoadingCmp, LoadingCmp,
ModalCmp, ModalCmp,
PickerCmp, PickerCmp,
PopoverCmp, PopoverCmp,
ToastCmp, ToastCmp
ClickBlock
], ],
entryComponents: [ entryComponents: [
ActionSheetCmp, ActionSheetCmp,
@ -154,7 +156,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: registerTransitions, deps: [ Config ], multi: true }, { provide: APP_INITIALIZER, useFactory: registerTransitions, deps: [ Config ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform ], multi: true }, { provide: APP_INITIALIZER, useFactory: setupProvideEvents, deps: [ Platform, DomController ], multi: true },
{ provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, App, NgZone, GestureController ], multi: true }, { provide: APP_INITIALIZER, useFactory: setupTapClick, deps: [ Config, App, NgZone, GestureController ], multi: true },
// useClass // useClass
@ -167,10 +169,11 @@ export class IonicModule {
ActionSheetController, ActionSheetController,
AlertController, AlertController,
App, App,
DomController,
Events, Events,
Form, Form,
Haptic,
GestureController, GestureController,
Haptic,
Keyboard, Keyboard,
LoadingController, LoadingController,
Location, Location,

View File

@ -0,0 +1,71 @@
/**
* Adopted from FastDom
* https://github.com/wilsonpage/fastdom
* MIT License
*/
import { nativeRaf } from './dom';
import { removeArrayItem } from './util';
export class DomController {
private r: Function[] = [];
private w: Function[] = [];
private q: boolean;
read(fn: Function, ctx?: any): Function {
const task = !ctx ? fn : fn.bind(ctx);
this.r.push(task);
this.queue();
return task;
}
write(fn: Function, ctx?: any): Function {
const task = !ctx ? fn : fn.bind(ctx);
this.w.push(task);
this.queue();
return task;
}
cancel(task: any) {
return removeArrayItem(this.r, task) || removeArrayItem(this.w, task);
}
private queue() {
if (!this.q) {
this.q = true;
nativeRaf(timestamp => {
this.flush(timestamp);
});
}
}
private flush(timestamp: number) {
let err;
let task;
try {
// ******** DOM READS ****************
while (task = this.r.shift()) {
task(timestamp);
}
// ******** DOM WRITES ****************
while (task = this.w.shift()) {
task(timestamp);
}
} catch (e) {
err = e;
}
this.q = false;
if (this.r.length || this.w.length) {
this.queue();
}
if (err) {
throw err;
}
}
}

View File

@ -1,3 +1,4 @@
import { DomController } from '../util/dom-controller';
import { nativeTimeout, nativeRaf } from '../util/dom'; import { nativeTimeout, nativeRaf } from '../util/dom';
import { Platform } from '../platform/platform'; import { Platform } from '../platform/platform';
import { ScrollView } from '../util/scroll-view'; import { ScrollView } from '../util/scroll-view';
@ -109,7 +110,7 @@ export class Events {
/** /**
* @private * @private
*/ */
export function setupEvents(platform: Platform): Events { export function setupEvents(platform: Platform, dom: DomController): Events {
const events = new Events(); const events = new Events();
// start listening for resizes XXms after the app starts // start listening for resizes XXms after the app starts
@ -134,7 +135,7 @@ export function setupEvents(platform: Platform): Events {
let content = <HTMLElement>el.closest('.scroll-content'); let content = <HTMLElement>el.closest('.scroll-content');
if (content) { if (content) {
var scroll = new ScrollView(content); var scroll = new ScrollView(content, dom);
// We need to stop scrolling if it's happening and scroll up // We need to stop scrolling if it's happening and scroll up
content.style['WebkitBackfaceVisibility'] = 'hidden'; content.style['WebkitBackfaceVisibility'] = 'hidden';
@ -173,8 +174,8 @@ export function setupEvents(platform: Platform): Events {
/** /**
* @private * @private
*/ */
export function setupProvideEvents(platform: Platform) { export function setupProvideEvents(platform: Platform, dom: DomController) {
return function() { return function() {
return setupEvents(platform); return setupEvents(platform, dom);
}; };
} }