mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
refactor(overlay): actionsheet/popup
This commit is contained in:
156
ionic/components/overlay/overlay-controller.ts
Normal file
156
ionic/components/overlay/overlay-controller.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
import {Component, View, NgZone, Injectable, Renderer} from 'angular2/angular2';
|
||||
|
||||
import {IonicApp} from '../app/app';
|
||||
import {Animation} from '../../animations/animation';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OverlayController {
|
||||
|
||||
constructor(app: IonicApp, zone: NgZone, renderer: Renderer) {
|
||||
this.app = app;
|
||||
this.zone = zone;
|
||||
this.renderer = renderer;
|
||||
this.refs = [];
|
||||
}
|
||||
|
||||
open(overlayType, componentType: Type, opts={}) {
|
||||
let resolve;
|
||||
let promise = new Promise(res => { resolve = res; });
|
||||
|
||||
if (!this.anchor) {
|
||||
console.error('<ion-overlay></ion-overlay> required in root component template to use: ' + overlayType);
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
try {
|
||||
this.anchor.append(componentType).then(ref => {
|
||||
let instance = ref.instance;
|
||||
|
||||
ref._z = ROOT_Z_INDEX;
|
||||
for (let i = 0; i < this.refs.length; i++) {
|
||||
if (this.refs[i]._z >= ref._z) {
|
||||
ref._z = this.refs[i]._z + 1;
|
||||
}
|
||||
}
|
||||
this.renderer.setElementStyle(ref.location, 'zIndex', ref._z);
|
||||
|
||||
util.extend(instance, opts);
|
||||
|
||||
ref._type = overlayType;
|
||||
ref._opts = opts;
|
||||
ref._handle = opts.handle || (overlayType + instance.zIndex);
|
||||
|
||||
this.add(ref);
|
||||
|
||||
instance.close = (opts={}) => {
|
||||
this.close(ref, opts);
|
||||
};
|
||||
|
||||
instance.onViewLoaded && instance.onViewLoaded();
|
||||
instance.onViewWillEnter && instance.onViewWillEnter();
|
||||
|
||||
let animation = Animation.create(ref.location.nativeElement, opts.enterAnimation);
|
||||
animation.before.addClass('show-overlay');
|
||||
|
||||
this.app.setEnabled(false, animation.duration());
|
||||
this.app.setTransitioning(true, animation.duration());
|
||||
|
||||
this.zone.runOutsideAngular(() => {
|
||||
|
||||
animation.play().then(() => {
|
||||
animation.dispose();
|
||||
|
||||
this.zone.run(() => {
|
||||
this.app.setEnabled(true);
|
||||
this.app.setTransitioning(false);
|
||||
instance.onViewDidEnter && instance.onViewDidEnter();
|
||||
resolve();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
close(ref, opts) {
|
||||
let resolve;
|
||||
let promise = new Promise(res => { resolve = res; });
|
||||
|
||||
let instance = ref.instance;
|
||||
instance.onViewWillLeave && instance.onViewWillLeave();
|
||||
instance.onViewWillUnload && instance.onViewWillUnload();
|
||||
|
||||
opts = util.extend(ref._opts, opts);
|
||||
let animation = Animation.create(ref.location.nativeElement, opts.leaveAnimation);
|
||||
animation.after.removeClass('show-overlay');
|
||||
|
||||
this.app.setEnabled(false, animation.duration());
|
||||
this.app.setTransitioning(true, animation.duration());
|
||||
|
||||
this.zone.runOutsideAngular(() => {
|
||||
|
||||
animation.play().then(() => {
|
||||
animation.dispose();
|
||||
|
||||
this.zone.run(() => {
|
||||
instance.onViewDidLeave && instance.onViewDidLeave();
|
||||
instance.onViewDidUnload && instance.onViewDidUnload();
|
||||
|
||||
this.app.setEnabled(true);
|
||||
this.app.setTransitioning(false);
|
||||
|
||||
this.remove(ref);
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
add(ref) {
|
||||
this.refs.push(ref);
|
||||
}
|
||||
|
||||
remove(ref) {
|
||||
util.array.remove(this.refs, ref);
|
||||
ref.dispose && ref.dispose();
|
||||
}
|
||||
|
||||
getByType(overlayType) {
|
||||
for (let i = this.overlays.length - 1; i >= 0; i--) {
|
||||
if (overlayType === this.overlays[i]._type) {
|
||||
return this.overlays[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getByHandle(handle, overlayType) {
|
||||
for (let i = this.overlays.length - 1; i >= 0; i--) {
|
||||
if (handle === this.overlays[i]._handle && overlayType === this.overlays[i]._type) {
|
||||
return this.overlays[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const ROOT_Z_INDEX = 1000;
|
||||
@@ -1,195 +1,27 @@
|
||||
import {Component, View, DirectiveBinding} from 'angular2/angular2';
|
||||
import {Component, View, ElementRef, DynamicComponentLoader} from 'angular2/angular2';
|
||||
|
||||
import {IonicApp} from '../app/app';
|
||||
import {Animation} from '../../animations/animation';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
|
||||
export class Overlay {
|
||||
|
||||
constructor(app: IonicApp) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
create(overlayType, componentType: Type, opts={}, context=null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let app = this.app;
|
||||
|
||||
let annotation = new Component({
|
||||
selector: 'ion-' + overlayType,
|
||||
host: {
|
||||
'[style.z-index]': 'zIndex',
|
||||
'class': overlayType
|
||||
}
|
||||
});
|
||||
let overlayComponentType = DirectiveBinding.createFromType(componentType, annotation);
|
||||
|
||||
// create a unique token that works as a cache key
|
||||
overlayComponentType.token = overlayType + componentType.name;
|
||||
|
||||
app.appendOverlay(overlayComponentType).then(ref => {
|
||||
let overlayRef = new OverlayRef(app, overlayType, opts, ref, context);
|
||||
overlayRef._open(opts).then(() => {
|
||||
resolve(overlayRef);
|
||||
});
|
||||
|
||||
}).catch(err => {
|
||||
console.error('Overlay appendOverlay:', err);
|
||||
reject(err);
|
||||
});
|
||||
|
||||
}).catch(err => {
|
||||
console.error('Overlay create:', err);
|
||||
});
|
||||
}
|
||||
|
||||
getByType(overlayType) {
|
||||
if (this.app) {
|
||||
for (let i = this.app.overlays.length - 1; i >= 0; i--) {
|
||||
if (overlayType === this.app.overlays[i]._type) {
|
||||
return this.app.overlays[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getByHandle(handle, overlayType) {
|
||||
if (this.app) {
|
||||
for (let i = this.app.overlays.length - 1; i >= 0; i--) {
|
||||
if (handle === this.app.overlays[i]._handle &&
|
||||
overlayType === this.app.overlays[i]._type) {
|
||||
return this.app.overlays[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class OverlayRef {
|
||||
constructor(app, overlayType, opts, ref, context) {
|
||||
this.app = app;
|
||||
|
||||
let overlayInstance = (ref && ref.instance);
|
||||
if (!overlayInstance) return;
|
||||
|
||||
if (context) {
|
||||
util.extend(ref.instance, context);
|
||||
}
|
||||
this._instance = overlayInstance;
|
||||
|
||||
overlayInstance.onViewLoaded && overlayInstance.onViewLoaded();
|
||||
|
||||
this.zIndex = ROOT_Z_INDEX;
|
||||
for (let i = 0; i < app.overlays.length; i++) {
|
||||
if (app.overlays[i].zIndex >= this.zIndex) {
|
||||
this.zIndex = app.overlays[i].zIndex + 1;
|
||||
}
|
||||
}
|
||||
overlayInstance.zIndex = this.zIndex;
|
||||
overlayInstance.overlayRef = this;
|
||||
overlayInstance.close = (instanceOpts) => {
|
||||
this.close(instanceOpts);
|
||||
};
|
||||
|
||||
this._elementRef = ref.location;
|
||||
this._type = overlayType;
|
||||
this._opts = opts;
|
||||
this._handle = opts.handle || this.zIndex;
|
||||
|
||||
this._dispose = () => {
|
||||
this._instance = null;
|
||||
ref.dispose && ref.dispose();
|
||||
util.array.remove(app.overlays, this);
|
||||
};
|
||||
|
||||
app.overlays.push(this);
|
||||
}
|
||||
|
||||
getElementRef() {
|
||||
return this._elementRef;
|
||||
}
|
||||
|
||||
_open(opts={}) {
|
||||
return new Promise(resolve => {
|
||||
let instance = this._instance || {};
|
||||
instance.onViewWillEnter && instance.onViewWillEnter();
|
||||
|
||||
let animationName = (opts && opts.animation) || this._opts.enterAnimation;
|
||||
let animation = Animation.create(this._elementRef.nativeElement, animationName);
|
||||
|
||||
animation.before.addClass('show-overlay');
|
||||
|
||||
this.app.setEnabled(false, animation.duration());
|
||||
this.app.setTransitioning(true, animation.duration());
|
||||
|
||||
this.app.zoneRunOutside(() => {
|
||||
|
||||
animation.play().then(() => {
|
||||
|
||||
this.app.zoneRun(() => {
|
||||
this.app.setEnabled(true);
|
||||
this.app.setTransitioning(false);
|
||||
animation.dispose();
|
||||
instance.onViewDidEnter && instance.onViewDidEnter();
|
||||
resolve();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
close(opts={}) {
|
||||
return new Promise(resolve => {
|
||||
let instance = this._instance || {};
|
||||
instance.onViewWillLeave && instance.onViewWillLeave();
|
||||
instance.onViewWillUnload && instance.onViewWillUnload();
|
||||
|
||||
let animationName = (opts && opts.animation) || this._opts.leaveAnimation;
|
||||
let animation = Animation.create(this._elementRef.nativeElement, animationName);
|
||||
|
||||
animation.after.removeClass('show-overlay');
|
||||
this.app.setEnabled(false, animation.duration());
|
||||
this.app.setTransitioning(true, animation.duration());
|
||||
|
||||
animation.play().then(() => {
|
||||
instance.onViewDidLeave && instance.onViewDidLeave();
|
||||
instance.onViewDidUnload && instance.onViewDidUnload();
|
||||
|
||||
this._dispose();
|
||||
|
||||
this.app.setEnabled(true);
|
||||
this.app.setTransitioning(false);
|
||||
animation.dispose();
|
||||
|
||||
resolve();
|
||||
})
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
import {OverlayController} from './overlay-controller';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'ion-overlays'
|
||||
selector: 'ion-overlay'
|
||||
})
|
||||
@View({
|
||||
template: ''
|
||||
})
|
||||
export class OverlaysContainer {
|
||||
constructor(app: IonicApp, elementRef: ElementRef, loader: DynamicComponentLoader) {
|
||||
export class OverlayAnchor {
|
||||
constructor(
|
||||
overlayCtrl: OverlayController,
|
||||
elementRef: ElementRef,
|
||||
loader: DynamicComponentLoader
|
||||
) {
|
||||
if (overlayCtrl.anchor) {
|
||||
throw ('An app should only have one <ion-overlays></ion-overlays>');
|
||||
}
|
||||
|
||||
this.elementRef = elementRef;
|
||||
this.loader = loader;
|
||||
app.overlayAnchor = this;
|
||||
overlayCtrl.anchor = this;
|
||||
}
|
||||
|
||||
append(componentType) {
|
||||
@@ -198,6 +30,3 @@ export class OverlaysContainer {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const ROOT_Z_INDEX = 1000;
|
||||
|
||||
Reference in New Issue
Block a user