Files
Adam Bradley acf12cdd15 refactor(menu): inject MenuController to control app menus
Menu has been improved to make it easier to open, close, toggle and
enable menus.
Instead of injecting `IonicApp` to find the menu component, you now
inject
`MenuController`.

Was:

```
constructor(app: IonicApp) {
  this.app = app;
}
openMenu() {
  this.app.getComponent('leftMenu').close();
}
```

Now:

To programmatically interact with any menu, you can inject the
`MenuController`
provider into any component or directive. This makes it easy get ahold
of and
control the correct menu instance. By default Ionic will find the app's
menu
without requiring a menu ID. An id attribute on an `<ion-menu>` is only
required
if there are multiple menus on the same side. If there are multiple
menus, but
on different sides, you can use the name of the side to get the correct
menu

If there's only one menu:

```
constructor(menu: MenuController) {
  this.menu = menu;
}
openMenu() {
  this.menu.close();
}
```

If there is a menu on the left and right side:

```
toggleMenu() {
  this.menu.toggle('left');
}
```

If there are multiple menus on the same side:

```
<ion-menu id="myMenuId" side="left">...</ion-menu>
<ion-menu id="otherMenuId" side="left">...</ion-menu>

closeMenu() {
  this.menu.close('myMenuId');
}
```
2016-02-04 16:47:05 -06:00

154 lines
4.2 KiB
TypeScript

import {Injectable, NgZone} from 'angular2/core';
import {Title} from 'angular2/platform/browser';
import {Config} from '../../config/config';
import {ClickBlock} from '../../util/click-block';
import {rafFrames} from '../../util/dom';
/**
* @private
* Component registry service. For more information on registering
* components see the [IdRef API reference](../id/IdRef/).
*/
@Injectable()
export class IonicApp {
private _titleSrv: Title = new Title();
private _title: string = '';
private _disTime: number = 0;
private _scrollTime: number = 0;
// Our component registry map
private components: {[id: string] : any} = {};
constructor(
private _config: Config,
private _clickBlock: ClickBlock,
private _zone: NgZone
) {}
/**
* Sets the document title.
* @param {string} val Value to set the document title to.
*/
setTitle(val: string) {
let self = this;
if (val !== self._title) {
self._title = val;
this._zone.runOutsideAngular(() => {
function setAppTitle() {
self._titleSrv.setTitle(self._title);
}
rafFrames(4, setAppTitle);
});
}
}
/**
* @private
* Sets if the app is currently enabled or not, meaning if it's
* available to accept new user commands. For example, this is set to `false`
* while views transition, a modal slides up, an action-sheet
* slides up, etc. After the transition completes it is set back to `true`.
* @param {bool} isEnabled
* @param {bool} fallback When `isEnabled` is set to `false`, this argument
* is used to set the maximum number of milliseconds that app will wait until
* it will automatically enable the app again. It's basically a fallback incase
* something goes wrong during a transition and the app wasn't re-enabled correctly.
*/
setEnabled(isEnabled: boolean, duration: number=700) {
this._disTime = (isEnabled ? 0 : Date.now() + duration);
if (duration > 32 || isEnabled) {
// only do a click block if the duration is longer than XXms
this._clickBlock.show(!isEnabled, duration + 64);
}
}
/**
* @private
* Boolean if the app is actively enabled or not.
* @return {bool}
*/
isEnabled(): boolean {
return (this._disTime < Date.now());
}
/**
* @private
*/
setScrolling() {
this._scrollTime = Date.now();
}
/**
* @private
* Boolean if the app is actively scrolling or not.
* @return {bool}
*/
isScrolling(): boolean {
return (this._scrollTime + 64 > Date.now());
}
/**
* @private
* Register a known component with a key, for easy lookups later.
* @param {string} id The id to use to register the component
* @param {Object} component The component to register
*/
register(id: string, component: any) {
this.components[id] = component;
}
/**
* @private
* Unregister a known component with a key.
* @param {string} id The id to use to unregister
*/
unregister(id: string) {
delete this.components[id];
}
/**
* @private
* Get a registered component with the given type (returns the first)
* @param {Object} cls the type to search for
* @return {Object} the matching component, or undefined if none was found
*/
getRegisteredComponent(cls: any): any {
for (let key in this.components) {
const component = this.components[key];
if (component instanceof cls) {
return component;
}
}
}
/**
* @private
* Get the component for the given key.
* @param {string} id TODO
* @return {Object} TODO
*/
getComponent(id: string): any {
// deprecated warning
if (/menu/i.test(id)) {
console.warn('Using app.getComponent(menuId) to control menus has been deprecated as of alpha55.\n' +
'Instead inject MenuController, for example:\n\n' +
'constructor(menu: MenuController) {\n' +
' this.menu = menu;\n' +
'}\n' +
'toggleMenu() {\n' +
' this.menu.toggle();\n' +
'}\n' +
'openRightMenu() {\n' +
' this.menu.open("right");\n' +
'}'
);
}
return this.components[id];
}
}