mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
refactor(overlay): actionsheet/popup
This commit is contained in:
@ -6,10 +6,11 @@
|
|||||||
* The ActionSheet is a modal menu with options to select based on an action.
|
* The ActionSheet is a modal menu with options to select based on an action.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {View, Injectable, NgFor, NgIf} from 'angular2/angular2';
|
import {Component, View, Injectable, NgFor, NgIf} from 'angular2/angular2';
|
||||||
|
|
||||||
|
import {OverlayController} from '../overlay/overlay-controller';
|
||||||
|
import {IonicConfig} from '../../config/config';
|
||||||
import {Icon} from '../icon/icon';
|
import {Icon} from '../icon/icon';
|
||||||
import {Overlay} from '../overlay/overlay';
|
|
||||||
import {Animation} from '../../animations/animation';
|
import {Animation} from '../../animations/animation';
|
||||||
import * as util from 'ionic/util';
|
import * as util from 'ionic/util';
|
||||||
|
|
||||||
@ -52,6 +53,9 @@ import * as util from 'ionic/util';
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ion-action-sheet'
|
||||||
|
})
|
||||||
@View({
|
@View({
|
||||||
template:
|
template:
|
||||||
'<backdrop (click)="_cancel()" tappable disable-activated></backdrop>' +
|
'<backdrop (click)="_cancel()" tappable disable-activated></backdrop>' +
|
||||||
@ -76,30 +80,42 @@ import * as util from 'ionic/util';
|
|||||||
'</action-sheet-wrapper>',
|
'</action-sheet-wrapper>',
|
||||||
directives: [NgFor, NgIf, Icon]
|
directives: [NgFor, NgIf, Icon]
|
||||||
})
|
})
|
||||||
class ActionSheetDirective {
|
class ActionSheetCmp {
|
||||||
|
|
||||||
_cancel() {
|
_cancel() {
|
||||||
this.cancel && this.cancel();
|
this.cancel && this.cancel();
|
||||||
return this.overlayRef.close();
|
return this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
_destructive() {
|
_destructive() {
|
||||||
let shouldClose = this.destructiveButtonClicked();
|
let shouldClose = this.destructiveButtonClicked();
|
||||||
if (shouldClose === true) {
|
if (shouldClose === true) {
|
||||||
return this.overlayRef.close();
|
return this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_buttonClicked(index) {
|
_buttonClicked(index) {
|
||||||
let shouldClose = this.buttonClicked(index);
|
let shouldClose = this.buttonClicked(index);
|
||||||
if (shouldClose === true) {
|
if (shouldClose === true) {
|
||||||
return this.overlayRef.close();
|
return this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ActionSheet extends Overlay {
|
export class ActionSheet {
|
||||||
|
|
||||||
|
constructor(ctrl: OverlayController, config: IonicConfig) {
|
||||||
|
this.ctrl = ctrl;
|
||||||
|
this._defaults = {
|
||||||
|
enterAnimation: config.get('actionSheetEnter'),
|
||||||
|
leaveAnimation: config.get('actionSheetLeave'),
|
||||||
|
cancelIcon: config.get('actionSheetCancelIcon'),
|
||||||
|
destructiveIcon: config.get('actionSheetDestructiveIcon')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and open a new Action Sheet. This is the
|
* Create and open a new Action Sheet. This is the
|
||||||
* public API, and most often you will only use ActionSheet.open()
|
* public API, and most often you will only use ActionSheet.open()
|
||||||
@ -108,25 +124,18 @@ export class ActionSheet extends Overlay {
|
|||||||
* @return {Promise} Promise that resolves when the action sheet is open.
|
* @return {Promise} Promise that resolves when the action sheet is open.
|
||||||
*/
|
*/
|
||||||
open(opts={}) {
|
open(opts={}) {
|
||||||
let config = this.config;
|
return this.ctrl.open(OVERLAY_TYPE, ActionSheetCmp, util.extend(this._defaults, opts));
|
||||||
let defaults = {
|
|
||||||
enterAnimation: config.get('actionSheetEnter'),
|
|
||||||
leaveAnimation: config.get('actionSheetLeave'),
|
|
||||||
cancelIcon: config.get('actionSheetCancelIcon'),
|
|
||||||
destructiveIcon: config.get('actionSheetDestructiveIcon')
|
|
||||||
};
|
|
||||||
|
|
||||||
let context = util.extend(defaults, opts);
|
|
||||||
|
|
||||||
return this.create(OVERLAY_TYPE, ActionSheetDirective, context, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
* @returns {TODO} TODO
|
* @returns {TODO} TODO
|
||||||
*/
|
*/
|
||||||
get() {
|
get(handle) {
|
||||||
return this.getByType(OVERLAY_TYPE);
|
if (handle) {
|
||||||
|
return this.ctrl.getByHandle(handle, OVERLAY_TYPE);
|
||||||
|
}
|
||||||
|
return this.ctrl.getByType(OVERLAY_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
<ion-content padding>
|
<ion-content padding>
|
||||||
<button (click)="openMenu()">Open Action Sheet</button>
|
<button (click)="openMenu()">Open Action Sheet</button>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-overlay></ion-overlay>
|
||||||
|
@ -129,18 +129,4 @@ export class IonicApp {
|
|||||||
return this.components[id];
|
return this.components[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create and append the given component into the root
|
|
||||||
* element of the app.
|
|
||||||
*
|
|
||||||
* @param {TODO} componentType the component to create and insert
|
|
||||||
* @return {Promise} Promise that resolves with the ContainerRef created
|
|
||||||
*/
|
|
||||||
appendOverlay(componentType: Type) {
|
|
||||||
if (!this.overlayAnchor) {
|
|
||||||
throw ('<ion-overlays></ion-overlays> must be added to your root component\'s template');
|
|
||||||
}
|
|
||||||
return this.overlayAnchor.append(componentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import {Injectable} from 'angular2/angular2';
|
import {Injectable} from 'angular2/angular2';
|
||||||
|
|
||||||
import {Overlay} from '../overlay/overlay';
|
import {IonicApp} from '../app/app';
|
||||||
|
import {IonicConfig} from '../../config/config';
|
||||||
|
import {OverlayController} from '../overlay/overlay-controller';
|
||||||
import {Animation} from '../../animations/animation';
|
import {Animation} from '../../animations/animation';
|
||||||
import * as util from 'ionic/util';
|
import * as util from 'ionic/util';
|
||||||
|
|
||||||
@ -28,7 +30,14 @@ import * as util from 'ionic/util';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Modal extends Overlay {
|
export class Modal {
|
||||||
|
|
||||||
|
constructor(app: IonicApp, config: IonicConfig) {
|
||||||
|
// super(app, {
|
||||||
|
// enterAnimation: config.get('modalEnter') || 'modal-slide-in',
|
||||||
|
// leaveAnimation: config.get('modalLeave') || 'modal-slide-out',
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
@ -37,12 +46,7 @@ export class Modal extends Overlay {
|
|||||||
* @returns {TODO} TODO
|
* @returns {TODO} TODO
|
||||||
*/
|
*/
|
||||||
open(ComponentType: Type, opts={}) {
|
open(ComponentType: Type, opts={}) {
|
||||||
let defaults = {
|
return this.create(OVERLAY_TYPE, ComponentType, opts);
|
||||||
enterAnimation: this.config.get('modalEnter') || 'modal-slide-in',
|
|
||||||
leaveAnimation: this.config.get('modalLeave') || 'modal-slide-out',
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.create(OVERLAY_TYPE, ComponentType, util.extend(defaults, opts));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,7 +171,7 @@ export class NavController extends Ion {
|
|||||||
|
|
||||||
// the active view is going to be the leaving one (if one exists)
|
// the active view is going to be the leaving one (if one exists)
|
||||||
let leavingView = this.getActive() || new ViewController();
|
let leavingView = this.getActive() || new ViewController();
|
||||||
leavingView.shouldCache = (util.isBoolean(opts.cacheleavingView) ? opts.cacheleavingView : true);
|
leavingView.shouldCache = (util.isBoolean(opts.cacheLeavingView) ? opts.cacheLeavingView : true);
|
||||||
leavingView.shouldDestroy = !leavingView.shouldCache;
|
leavingView.shouldDestroy = !leavingView.shouldCache;
|
||||||
if (leavingView.shouldDestroy) {
|
if (leavingView.shouldDestroy) {
|
||||||
leavingView.willUnload();
|
leavingView.willUnload();
|
||||||
@ -215,7 +215,7 @@ export class NavController extends Ion {
|
|||||||
// get the active view and set that it is staged to be leaving
|
// get the active view and set that it is staged to be leaving
|
||||||
// was probably the one popped from the stack
|
// was probably the one popped from the stack
|
||||||
let leavingView = this.getActive() || new ViewController();
|
let leavingView = this.getActive() || new ViewController();
|
||||||
leavingView.shouldCache = (util.isBoolean(opts.cacheleavingView) ? opts.cacheleavingView : false);
|
leavingView.shouldCache = (util.isBoolean(opts.cacheLeavingView) ? opts.cacheLeavingView : false);
|
||||||
leavingView.shouldDestroy = !leavingView.shouldCache;
|
leavingView.shouldDestroy = !leavingView.shouldCache;
|
||||||
if (leavingView.shouldDestroy) {
|
if (leavingView.shouldDestroy) {
|
||||||
leavingView.willUnload();
|
leavingView.willUnload();
|
||||||
@ -341,7 +341,7 @@ export class NavController extends Ion {
|
|||||||
opts.animate = opts.animate || false;
|
opts.animate = opts.animate || false;
|
||||||
|
|
||||||
// ensure leaving views are not cached, and should be destroyed
|
// ensure leaving views are not cached, and should be destroyed
|
||||||
opts.cacheleavingView = false;
|
opts.cacheLeavingView = false;
|
||||||
|
|
||||||
// get the views to auto remove without having to do a transiton for each
|
// get the views to auto remove without having to do a transiton for each
|
||||||
// the last view (the currently active one) will do a normal transition out
|
// the last view (the currently active one) will do a normal transition out
|
||||||
|
@ -14,8 +14,6 @@ export class ViewController {
|
|||||||
this.state = 0;
|
this.state = 0;
|
||||||
this.disposals = [];
|
this.disposals = [];
|
||||||
|
|
||||||
this._nbItms = [];
|
|
||||||
|
|
||||||
this.navbarTemplateRef = null;
|
this.navbarTemplateRef = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {OverlayController} from './overlay-controller';
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-overlays'
|
selector: 'ion-overlay'
|
||||||
})
|
})
|
||||||
@View({
|
@View({
|
||||||
template: ''
|
template: ''
|
||||||
})
|
})
|
||||||
export class OverlaysContainer {
|
export class OverlayAnchor {
|
||||||
constructor(app: IonicApp, elementRef: ElementRef, loader: DynamicComponentLoader) {
|
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.elementRef = elementRef;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
app.overlayAnchor = this;
|
overlayCtrl.anchor = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
append(componentType) {
|
append(componentType) {
|
||||||
@ -198,6 +30,3 @@ export class OverlaysContainer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const ROOT_Z_INDEX = 1000;
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {FORM_DIRECTIVES, NgControl, NgControlGroup,
|
import {FORM_DIRECTIVES, NgControl, NgControlGroup,
|
||||||
Component, View, Injectable, NgClass, NgIf, NgFor} from 'angular2/angular2';
|
Component, View, ElementRef, Injectable, NgClass, NgIf, NgFor} from 'angular2/angular2';
|
||||||
|
|
||||||
import {Overlay} from '../overlay/overlay';
|
import {OverlayController} from '../overlay/overlay-controller';
|
||||||
|
import {IonicConfig} from '../../config/config';
|
||||||
import {Animation} from '../../animations/animation';
|
import {Animation} from '../../animations/animation';
|
||||||
import {Ion} from '../ion';
|
|
||||||
import * as util from 'ionic/util';
|
import * as util from 'ionic/util';
|
||||||
|
|
||||||
|
|
||||||
@ -63,25 +63,27 @@ import * as util from 'ionic/util';
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Popup extends Overlay {
|
export class Popup {
|
||||||
|
|
||||||
|
constructor(ctrl: OverlayController, config: IonicConfig) {
|
||||||
|
this.ctrl = ctrl;
|
||||||
|
this._defaults = {
|
||||||
|
enterAnimation: config.get('popupPopIn'),
|
||||||
|
leaveAnimation: config.get('popupPopOut'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
* @param {TODO} opts TODO
|
* @param {TODO} opts TODO
|
||||||
* @returns {object} A promise
|
* @returns {object} A promise
|
||||||
*/
|
*/
|
||||||
popup(opts) {
|
open(opts) {
|
||||||
return new Promise((resolve, reject)=> {
|
return new Promise((resolve, reject)=> {
|
||||||
let config = this.config;
|
|
||||||
let defaults = {
|
|
||||||
enterAnimation: config.get('popupPopIn'),
|
|
||||||
leaveAnimation: config.get('popupPopOut'),
|
|
||||||
};
|
|
||||||
|
|
||||||
opts.promiseResolve = resolve;
|
opts.promiseResolve = resolve;
|
||||||
opts.promiseReject = reject;
|
opts.promiseReject = reject;
|
||||||
|
|
||||||
return this.create(OVERLAY_TYPE, StandardPopup, defaults, opts);
|
return this.ctrl.open(OVERLAY_TYPE, PopupCmp, util.extend(this._defaults, opts));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +130,7 @@ export class Popup extends Overlay {
|
|||||||
]
|
]
|
||||||
}, opts);
|
}, opts);
|
||||||
|
|
||||||
return this.popup(opts);
|
return this.open(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,7 +184,7 @@ export class Popup extends Overlay {
|
|||||||
cancelButton, okButton
|
cancelButton, okButton
|
||||||
]
|
]
|
||||||
}, opts);
|
}, opts);
|
||||||
return this.popup(opts);
|
return this.open(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,7 +245,7 @@ export class Popup extends Overlay {
|
|||||||
]
|
]
|
||||||
}, opts);
|
}, opts);
|
||||||
|
|
||||||
return this.popup(opts);
|
return this.open(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,7 +266,7 @@ const OVERLAY_TYPE = 'popup';
|
|||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-popup-default'
|
selector: 'ion-popup'
|
||||||
})
|
})
|
||||||
@View({
|
@View({
|
||||||
template:
|
template:
|
||||||
@ -285,19 +287,22 @@ const OVERLAY_TYPE = 'popup';
|
|||||||
directives: [FORM_DIRECTIVES, NgClass, NgIf, NgFor]
|
directives: [FORM_DIRECTIVES, NgClass, NgIf, NgFor]
|
||||||
})
|
})
|
||||||
|
|
||||||
class StandardPopup {
|
class PopupCmp {
|
||||||
constructor(popup: Popup) {
|
|
||||||
this.popup = popup;
|
constructor(elementRef: ElementRef) {
|
||||||
|
this.elementRef = elementRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
onInit() {
|
onInit() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.element = this.overlayRef.getElementRef().nativeElement;
|
// TODO: make more better, no DOM BS
|
||||||
this.promptInput = this.element.querySelector('input');
|
this.promptInput = this.elementRef.nativeElement.querySelector('input');
|
||||||
if (this.promptInput) {
|
if (this.promptInput) {
|
||||||
this.promptInput.value = '';
|
this.promptInput.value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonTapped(button, event) {
|
buttonTapped(button, event) {
|
||||||
let promptValue = this.promptInput && this.promptInput.value;
|
let promptValue = this.promptInput && this.promptInput.value;
|
||||||
|
|
||||||
@ -314,20 +319,22 @@ class StandardPopup {
|
|||||||
// Resolve with the prompt value
|
// Resolve with the prompt value
|
||||||
this.promiseResolve(promptValue);
|
this.promiseResolve(promptValue);
|
||||||
}
|
}
|
||||||
return this.overlayRef.close();
|
return this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_cancel(event) {
|
_cancel(event) {
|
||||||
this.cancel && this.cancel(event);
|
this.cancel && this.cancel(event);
|
||||||
|
|
||||||
if (!event.defaultPrevented) {
|
if (!event.defaultPrevented) {
|
||||||
this.promiseReject();
|
this.promiseReject();
|
||||||
return this.overlayRef.close();
|
return this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PopupAnimation extends Animation {
|
class PopupAnimation extends Animation {
|
||||||
constructor(element) {
|
constructor(element) {
|
||||||
super(element);
|
super(element);
|
||||||
@ -342,13 +349,14 @@ class PopupAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animations for modals
|
* Animations for popups
|
||||||
*/
|
*/
|
||||||
class PopupPopIn extends PopupAnimation {
|
class PopupPopIn extends PopupAnimation {
|
||||||
constructor(element) {
|
constructor(element) {
|
||||||
super(element);
|
super(element);
|
||||||
this.wrapper.fromTo('opacity', '0', '1')
|
this.wrapper.fromTo('opacity', '0.01', '1')
|
||||||
this.wrapper.fromTo('scale', '1.1', '1');
|
this.wrapper.fromTo('scale', '1.1', '1');
|
||||||
|
|
||||||
this.backdrop.fromTo('opacity', '0', '0.3')
|
this.backdrop.fromTo('opacity', '0', '0.3')
|
||||||
@ -370,7 +378,7 @@ Animation.register('popup-pop-out', PopupPopOut);
|
|||||||
class PopupMdPopIn extends PopupPopIn {
|
class PopupMdPopIn extends PopupPopIn {
|
||||||
constructor(element) {
|
constructor(element) {
|
||||||
super(element);
|
super(element);
|
||||||
this.backdrop.fromTo('opacity', '0', '0.5')
|
this.backdrop.fromTo('opacity', '0.01', '0.5')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Animation.register('popup-md-pop-in', PopupMdPopIn);
|
Animation.register('popup-md-pop-in', PopupMdPopIn);
|
||||||
|
@ -14,3 +14,5 @@
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
|
<ion-overlay></ion-overlay>
|
||||||
|
@ -4,6 +4,7 @@ import {ROUTER_BINDINGS, HashLocationStrategy, LocationStrategy} from 'angular2/
|
|||||||
import {IonicApp} from '../components/app/app';
|
import {IonicApp} from '../components/app/app';
|
||||||
import {IonicConfig} from './config';
|
import {IonicConfig} from './config';
|
||||||
import {IonicPlatform} from '../platform/platform';
|
import {IonicPlatform} from '../platform/platform';
|
||||||
|
import {OverlayController} from '../components/overlay/overlay-controller';
|
||||||
import {ActionSheet} from '../components/action-sheet/action-sheet';
|
import {ActionSheet} from '../components/action-sheet/action-sheet';
|
||||||
import {Modal} from '../components/modal/modal';
|
import {Modal} from '../components/modal/modal';
|
||||||
import {Popup} from '../components/popup/popup';
|
import {Popup} from '../components/popup/popup';
|
||||||
@ -40,6 +41,7 @@ export function ionicBindings(configSettings) {
|
|||||||
bind(IonicPlatform).toValue(platform),
|
bind(IonicPlatform).toValue(platform),
|
||||||
bind(TapClick).toValue(tapClick),
|
bind(TapClick).toValue(tapClick),
|
||||||
bind(Events).toValue(events),
|
bind(Events).toValue(events),
|
||||||
|
OverlayController,
|
||||||
ActionSheet,
|
ActionSheet,
|
||||||
Modal,
|
Modal,
|
||||||
Popup,
|
Popup,
|
||||||
|
@ -49,13 +49,17 @@ export function IonicDirective(config) {
|
|||||||
*/
|
*/
|
||||||
export function IonicComponent(config) {
|
export function IonicComponent(config) {
|
||||||
return function(cls) {
|
return function(cls) {
|
||||||
var annotations = Reflect.getMetadata('annotations', cls) || [];
|
return makeComponent(cls, appendConfig(cls, config));
|
||||||
annotations.push(new Component(appendConfig(cls, config)));
|
|
||||||
Reflect.defineMetadata('annotations', annotations, cls);
|
|
||||||
return cls;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function makeComponent(cls, config) {
|
||||||
|
var annotations = Reflect.getMetadata('annotations', cls) || [];
|
||||||
|
annotations.push(new Component(config));
|
||||||
|
Reflect.defineMetadata('annotations', annotations, cls);
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
|
||||||
function appendConfig(cls, config) {
|
function appendConfig(cls, config) {
|
||||||
config.host = config.host || {};
|
config.host = config.host || {};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {CORE_DIRECTIVES, FORM_DIRECTIVES, forwardRef} from 'angular2/angular2'
|
import {CORE_DIRECTIVES, FORM_DIRECTIVES, forwardRef} from 'angular2/angular2'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
OverlayAnchor,
|
||||||
Menu, MenuToggle, MenuClose,
|
Menu, MenuToggle, MenuClose,
|
||||||
Button, Content, Scroll, Refresher,
|
Button, Content, Scroll, Refresher,
|
||||||
Slides, Slide, SlideLazy,
|
Slides, Slide, SlideLazy,
|
||||||
@ -29,6 +30,7 @@ export const IONIC_DIRECTIVES = [
|
|||||||
FORM_DIRECTIVES,
|
FORM_DIRECTIVES,
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
|
forwardRef(() => OverlayAnchor),
|
||||||
forwardRef(() => Menu),
|
forwardRef(() => Menu),
|
||||||
forwardRef(() => MenuToggle),
|
forwardRef(() => MenuToggle),
|
||||||
forwardRef(() => MenuClose),
|
forwardRef(() => MenuClose),
|
||||||
|
Reference in New Issue
Block a user