diff --git a/ionic/components/action-menu/action-menu.js b/ionic/components/action-menu/action-menu.js index b193665892..9d81e94d13 100644 --- a/ionic/components/action-menu/action-menu.js +++ b/ionic/components/action-menu/action-menu.js @@ -1,3 +1,11 @@ +/** +* @ngdoc service +* @name ActionMenu +* @module ionic +* @description +* The ActionMenu is a modal menu with options to select based on an action. +*/ + import {NgIf, NgFor, DynamicComponentLoader, ComponentLaoder, ElementRef, ComponentRef, onDestroy, DomRenderer} from 'angular2/angular2'; import {bind, Injector} from 'angular2/di'; import {Promise} from 'angular2/src/facade/async'; @@ -10,12 +18,153 @@ import {Parent} from 'angular2/src/core/annotations_impl/visibility'; import {Item, Icon} from 'ionic/ionic' import {Ionic} from 'ionic/components/app/app' import {IonicComponent} from 'ionic/config/component' -import {raf, ready} from 'ionic/util/dom' +import {raf, rafPromise, ready} from 'ionic/util/dom' import * as util from 'ionic/util' import {Animation} from 'ionic/animations/animation'; +@Component({ + selector: 'ion-action-menu' +}) +@View({ + template: ` +
+
+
+
+
{{options.titleText}}
+ + +
+
+ +
+
+
+
`, + directives: [Item,Icon, NgIf, NgFor] +}) +export class ActionMenu { + constructor(elementRef: ElementRef) { + this.domElement = elementRef.domElement + this.config = ActionMenu.config.invoke(this) + this.wrapperEl = this.domElement.querySelector('.action-menu-wrapper'); + + this.options = { + destructiveButtonClicked: util.noop, + buttonClicked: util.noop, + cancel: util.noop + }; + + console.log('ActionMenu: Component Created', this.domElement); + } + + /** + * Close the ActionMenu. + * + * @return Promise that resolves when the action menu is closed. + */ + close() { + return new Promise(resolve => { + raf(() => { + var backdrop = this.domElement.children[0].classList.remove('active'); + var slideOut = Animation.create(this.wrapperEl, 'action-menu-slide-out'); + + slideOut.play().then(() => { + this.wrapperEl.classList.remove('action-menu-up'); + this._clean(); + resolve(); + }) + }); + }); + } + + /** + * Open the Action Menu + * + * @return Promise that resolves when the action menu is open. + */ + open() { + return new Promise(resolve => { + raf(() => { + var backdrop = this.domElement.children[0].classList.add('active'); + var slideIn = Animation.create(this.wrapperEl, 'action-menu-slide-in'); + + slideIn.play().then(() => { + this.wrapperEl.classList.add('action-menu-up'); + resolve(); + }) + }); + }); + } + + /** + * Set the options (as in show()) + * + * @param opts the options to set + */ + setOptions(opts) { + util.extend(this.options, opts); + } + + /** + * Create and open a new Action Menu. This is the + * public API, and most often you will only use ActionMenu.open() + * + * @return Promise that resolves when the action menu is open. + */ + static open(opts) { + console.log('Opening menu', opts, Ionic); + + var promise = new Promise(resolve => { + ActionMenu._inject().then((ref) => { + let actionMenu = ref.instance; + actionMenu.ref = ref; + actionMenu.setOptions(opts); + actionMenu.open(); + resolve(actionMenu); + }); + }) + + return promise; + } + + static _inject() { + return Ionic.appendToRoot(ActionMenu); + } + + _clean() { + this.ref.dispose(); + } + + _cancel() { + this.options.cancel(); + this.close().then(() => { + }); + } + + + _destructiveButtonClicked() { + let shouldClose = this.options.destructiveButtonClicked(); + if(shouldClose === true) { + return this.close() + } + } + + _buttonClicked(index) { + let shouldClose = this.options.buttonClicked(index); + if(shouldClose === true) { + return this.close() + } + } +} + +new IonicComponent(ActionMenu, {}) + +/** + * Animations for action sheet + */ class ActionMenuSlideIn extends Animation { constructor(element) { super(element); @@ -38,90 +187,4 @@ class ActionMenuSlideOut extends Animation { .to('translateY', '100%'); } } -Animation.register('action-menu-slide-out', ActionMenuSlideIn); - -@Component({ - selector: 'ion-action-menu' -}) -@View({ - template: ` -
-
-
-
-
{{titleText}}
- - -
-
- -
-
-
-
`, - directives: [Item,Icon, NgIf, NgFor] -}) -export class ActionMenu { - constructor(elementRef: ElementRef) { - this.domElement = elementRef.domElement - this.config = ActionMenu.config.invoke(this) - - this.wrapperEl = this.domElement.querySelector('.action-menu-wrapper'); - - console.log('ActionMenu: Component Created', this.domElement); - } - - close() { - raf(() => { - var backdrop = this.domElement.children[0].classList.remove('active'); - var slideOut = Animation.create(this.wrapperEl, 'action-menu-slide-out'); - - return slideOut.play().then(() => { - this.wrapperEl.classList.remove('action-menu-up'); - }) - }); - } - - open() { - raf(() => { - var backdrop = this.domElement.children[0].classList.add('active'); - var slideIn = Animation.create(this.wrapperEl, 'action-menu-slide-in'); - - return slideIn.play().then(() => { - this.wrapperEl.classList.add('action-menu-up'); - }) - }); - } - - setOptions(opts) { - util.extend(this, opts); - } - - // Overridden by options - destructiveButtonClicked() {} - buttonClicked(index) {} - cancel() {} - - static open(opts) { - console.log('Opening menu', opts, Ionic); - - var promise = new Promise(resolve => { - ActionMenu._inject().then((actionMenu) => { - actionMenu.setOptions(opts); - setTimeout(() => { - actionMenu.open(); - }) - resolve(actionMenu); - }); - }) - - return promise; - } - - static _inject() { - return Ionic.appendToRoot(ActionMenu); - } - -} - -new IonicComponent(ActionMenu, {}) +Animation.register('action-menu-slide-out', ActionMenuSlideOut); diff --git a/ionic/components/action-menu/test/basic/index.js b/ionic/components/action-menu/test/basic/index.js index 38207bd45a..e1d17a2ec4 100644 --- a/ionic/components/action-menu/test/basic/index.js +++ b/ionic/components/action-menu/test/basic/index.js @@ -32,8 +32,12 @@ class IonicApp { // add cancel code.. console.log('Canceled'); }, + destructiveButtonClicked: () => { + console.log('Destructive clicked'); + }, buttonClicked: function(index) { console.log('Button clicked', index); + if(index == 1) { return false; } return true; } }).then(actionMenu => { diff --git a/ionic/components/app/app.js b/ionic/components/app/app.js index 48ec0c1970..3d30f4a2f3 100644 --- a/ionic/components/app/app.js +++ b/ionic/components/app/app.js @@ -22,6 +22,13 @@ class IonicAppRoot { return this.rootElementRef; } + /** + * Create and append the given component into the root + * element of the app. + * + * @param Component the ComponentClass to create and insert + * @return Promise that resolves with the ContainerRef created + */ appendToRoot(Component: Type) { var appRef = Ionic.getAppRef(); var injector = appRef.injector; @@ -39,7 +46,7 @@ class IonicAppRoot { console.log('Injected and created', containerRef); - resolve(containerRef.instance, containerRef.location); + resolve(containerRef);//containerRef.instance, containerRef.location); }); }); diff --git a/ionic/util/dom.js b/ionic/util/dom.js index 083f52f611..951f084dd8 100644 --- a/ionic/util/dom.js +++ b/ionic/util/dom.js @@ -1,3 +1,5 @@ +// Use Angular's promise which doesn't swallow exceptions +import {Promise} from 'angular2/src/facade/async'; const nativeRaf = window.requestAnimationFrame || window.webkitRequestAnimationFrame ||