a zip code crypto-currency system good for red ONLY

menu.js 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, Input, Output, Renderer, ViewChild, ViewEncapsulation, forwardRef } from '@angular/core';
  2. import { App } from '../app/app';
  3. import { Backdrop } from '../backdrop/backdrop';
  4. import { Config } from '../../config/config';
  5. import { Content } from '../content/content';
  6. import { DomController } from '../../platform/dom-controller';
  7. import { GESTURE_GO_BACK_SWIPE, GestureController, } from '../../gestures/gesture-controller';
  8. import { isRightSide, isTrueProperty } from '../../util/util';
  9. import { Keyboard } from '../../platform/keyboard';
  10. import { MenuContentGesture } from './menu-gestures';
  11. import { MenuController } from '../app/menu-controller';
  12. import { Nav } from '../nav/nav';
  13. import { Platform } from '../../platform/platform';
  14. import { UIEventManager } from '../../gestures/ui-event-manager';
  15. import { RootNode } from '../split-pane/split-pane';
  16. /**
  17. * @name Menu
  18. * @description
  19. * The Menu component is a navigation drawer that slides in from the side of the current
  20. * view. By default, it slides in from the left, but the side can be overridden. The menu
  21. * will be displayed differently based on the mode, however the display type can be changed
  22. * to any of the available [menu types](#menu-types). The menu element should be a sibling
  23. * to the app's content element. There can be any number of menus attached to the content.
  24. * These can be controlled from the templates, or programmatically using the [MenuController](../../app/MenuController).
  25. *
  26. * @usage
  27. *
  28. * ```html
  29. * <ion-menu [content]="mycontent">
  30. * <ion-content>
  31. * <ion-list>
  32. * <p>some menu content, could be list items</p>
  33. * </ion-list>
  34. * </ion-content>
  35. * </ion-menu>
  36. *
  37. * <ion-nav #mycontent [root]="rootPage"></ion-nav>
  38. * ```
  39. *
  40. * To add a menu to an app, the `<ion-menu>` element should be added as a sibling to the `ion-nav` it will belongs
  41. * to. A [local variable](https://angular.io/docs/ts/latest/guide/user-input.html#local-variables)
  42. * should be added to the `ion-nav` and passed to the `ion-menu`s `content` property.
  43. *
  44. * This tells the menu what it is bound to and what element to watch for gestures.
  45. * In the below example, `content` is using [property binding](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#property-binding)
  46. * because `mycontent` is a reference to the `<ion-nav>` element, and not a string.
  47. *
  48. *
  49. * ### Opening/Closing Menus
  50. *
  51. * There are several ways to open or close a menu. The menu can be **toggled** open or closed
  52. * from the template using the [MenuToggle](../MenuToggle) directive. It can also be
  53. * **closed** from the template using the [MenuClose](../MenuClose) directive. To display a menu
  54. * programmatically, inject the [MenuController](../MenuController) provider and call any of the
  55. * `MenuController` methods.
  56. *
  57. *
  58. * ### Menu Types
  59. *
  60. * The menu supports several display types: `overlay`, `reveal` and `push`. By default,
  61. * it will use the correct type based on the mode, but this can be changed. The default
  62. * type for both Material Design and Windows mode is `overlay`, and `reveal` is the default
  63. * type for iOS mode. The menu type can be changed in the app's [config](../../config/Config)
  64. * via the `menuType` property, or passed in the `type` property on the `<ion-menu>` element.
  65. * See [usage](#usage) below for examples of changing the menu type.
  66. *
  67. *
  68. * ### Navigation Bar Behavior
  69. *
  70. * If a [MenuToggle](../MenuToggle) button is added to the [Navbar](../../navbar/Navbar) of
  71. * a page, the button will only appear when the page it's in is currently a root page. The
  72. * root page is the initial page loaded in the app, or a page that has been set as the root
  73. * using the [setRoot](../../nav/NavController/#setRoot) method on the [NavController](../../nav/NavController).
  74. *
  75. * For example, say the application has two pages, `Page1` and `Page2`, and both have a
  76. * `MenuToggle` button in their navigation bars. Assume the initial page loaded into the app
  77. * is `Page1`, making it the root page. `Page1` will display the `MenuToggle` button, but once
  78. * `Page2` is pushed onto the navigation stack, the `MenuToggle` will not be displayed.
  79. *
  80. *
  81. * ### Persistent Menus
  82. *
  83. * Persistent menus display the [MenuToggle](../MenuToggle) button in the [Navbar](../../navbar/Navbar)
  84. * on all pages in the navigation stack. To make a menu persistent set `persistent` to `true` on the
  85. * `<ion-menu>` element. Note that this will only affect the `MenuToggle` button in the `Navbar` attached
  86. * to the `Menu` with `persistent` set to true, any other `MenuToggle` buttons will not be affected.
  87. * ### Menu Side
  88. *
  89. * By default, menus slide in from the left, but this can be overridden by passing `right`
  90. * to the `side` property:
  91. *
  92. * ```html
  93. * <ion-menu side="right" [content]="mycontent">...</ion-menu>
  94. * ```
  95. *
  96. *
  97. * ### Menu Type
  98. *
  99. * The menu type can be changed by passing the value to `type` on the `<ion-menu>`:
  100. *
  101. * ```html
  102. * <ion-menu type="overlay" [content]="mycontent">...</ion-menu>
  103. * ```
  104. *
  105. * It can also be set in the app's config. The below will set the menu type to
  106. * `push` for all modes, and then set the type to `overlay` for the `ios` mode.
  107. *
  108. * ```ts
  109. * // in NgModules
  110. *
  111. * imports: [
  112. * IonicModule.forRoot(MyApp,{
  113. * menuType: 'push',
  114. * platforms: {
  115. * ios: {
  116. * menuType: 'overlay',
  117. * }
  118. * }
  119. * })
  120. * ],
  121. * ```
  122. *
  123. *
  124. * ### Displaying the Menu
  125. *
  126. * To toggle a menu from the template, add a button with the `menuToggle`
  127. * directive anywhere in the page's template:
  128. *
  129. * ```html
  130. * <button ion-button menuToggle>Toggle Menu</button>
  131. * ```
  132. *
  133. * To close a menu, add the `menuClose` button. It can be added anywhere
  134. * in the content, or even the menu itself. Below it is added to the menu's
  135. * content:
  136. *
  137. * ```html
  138. * <ion-menu [content]="mycontent">
  139. * <ion-content>
  140. * <ion-list>
  141. * <ion-item menuClose detail-none>Close Menu</ion-item>
  142. * </ion-list>
  143. * </ion-content>
  144. * </ion-menu>
  145. * ```
  146. *
  147. * See the [MenuToggle](../MenuToggle) and [MenuClose](../MenuClose) docs
  148. * for more information on these directives.
  149. *
  150. * The menu can also be controlled from the Page by using the `MenuController`.
  151. * Inject the `MenuController` provider into the page and then call any of its
  152. * methods. In the below example, the `openMenu` method will open the menu
  153. * when it is called.
  154. *
  155. * ```ts
  156. * import { Component } from '@angular/core';
  157. * import { MenuController } from 'ionic-angular';
  158. *
  159. * @Component({...})
  160. * export class MyPage {
  161. * constructor(public menuCtrl: MenuController) {}
  162. *
  163. * openMenu() {
  164. * this.menuCtrl.open();
  165. * }
  166. * }
  167. * ```
  168. *
  169. * See the [MenuController](../../app/MenuController) API docs for all of the methods
  170. * and usage information.
  171. *
  172. *
  173. * @demo /docs/demos/src/menu/
  174. *
  175. * @see {@link /docs/components#menus Menu Component Docs}
  176. * @see {@link ../../app/MenuController MenuController API Docs}
  177. * @see {@link ../../nav/Nav Nav API Docs}
  178. * @see {@link ../../nav/NavController NavController API Docs}
  179. */
  180. export class Menu {
  181. constructor(_menuCtrl, _elementRef, _config, _plt, _renderer, _keyboard, _gestureCtrl, _domCtrl, _app) {
  182. this._menuCtrl = _menuCtrl;
  183. this._elementRef = _elementRef;
  184. this._config = _config;
  185. this._plt = _plt;
  186. this._renderer = _renderer;
  187. this._keyboard = _keyboard;
  188. this._gestureCtrl = _gestureCtrl;
  189. this._domCtrl = _domCtrl;
  190. this._app = _app;
  191. this._isSwipeEnabled = true;
  192. this._isAnimating = false;
  193. this._isPersistent = false;
  194. this._init = false;
  195. this._isPane = false;
  196. /**
  197. * @hidden
  198. */
  199. this.isOpen = false;
  200. /**
  201. * @hidden
  202. */
  203. this.isRightSide = false;
  204. /**
  205. * @output {event} Emitted when the menu is being dragged open.
  206. */
  207. this.ionDrag = new EventEmitter();
  208. /**
  209. * @output {event} Emitted when the menu has been opened.
  210. */
  211. this.ionOpen = new EventEmitter();
  212. /**
  213. * @output {event} Emitted when the menu has been closed.
  214. */
  215. this.ionClose = new EventEmitter();
  216. this._events = new UIEventManager(_plt);
  217. this._gestureBlocker = _gestureCtrl.createBlocker({
  218. disable: [GESTURE_GO_BACK_SWIPE]
  219. });
  220. this.side = 'start';
  221. }
  222. /**
  223. * @input {boolean} If true, the menu is enabled. Default `true`.
  224. */
  225. get enabled() {
  226. return this._isEnabled;
  227. }
  228. set enabled(val) {
  229. const isEnabled = isTrueProperty(val);
  230. this.enable(isEnabled);
  231. }
  232. /**
  233. * @input {string} Which side of the view the menu should be placed. Default `"left"`.
  234. */
  235. get side() {
  236. return this._side;
  237. }
  238. set side(val) {
  239. this.isRightSide = isRightSide(val, this._plt.isRTL);
  240. if (this.isRightSide) {
  241. this._side = 'right';
  242. }
  243. else {
  244. this._side = 'left';
  245. }
  246. }
  247. /**
  248. * @input {boolean} If true, swiping the menu is enabled. Default `true`.
  249. */
  250. get swipeEnabled() {
  251. return this._isSwipeEnabled;
  252. }
  253. set swipeEnabled(val) {
  254. const isEnabled = isTrueProperty(val);
  255. this.swipeEnable(isEnabled);
  256. }
  257. /**
  258. * @input {boolean} If true, the menu will persist on child pages.
  259. */
  260. get persistent() {
  261. return this._isPersistent;
  262. }
  263. set persistent(val) {
  264. this._isPersistent = isTrueProperty(val);
  265. }
  266. /**
  267. * @hidden
  268. */
  269. ngOnInit() {
  270. this._init = true;
  271. let content = this.content;
  272. this._cntEle = (content instanceof Node) ? content : content && content.getNativeElement && content.getNativeElement();
  273. // requires content element
  274. if (!this._cntEle) {
  275. return console.error('Menu: must have a [content] element to listen for drag events on. Example:\n\n<ion-menu [content]="content"></ion-menu>\n\n<ion-nav #content></ion-nav>');
  276. }
  277. this.setElementAttribute('side', this._side);
  278. // normalize the "type"
  279. if (!this.type) {
  280. this.type = this._config.get('menuType');
  281. }
  282. this.setElementAttribute('type', this.type);
  283. // add the gestures
  284. this._gesture = new MenuContentGesture(this._plt, this, this._gestureCtrl, this._domCtrl);
  285. // add menu's content classes
  286. this._cntEle.classList.add('menu-content');
  287. this._cntEle.classList.add('menu-content-' + this.type);
  288. let isEnabled = this._isEnabled;
  289. if (isEnabled === true || typeof isEnabled === 'undefined') {
  290. // check if more than one menu is on the same side
  291. isEnabled = !this._menuCtrl.getMenus().some(m => {
  292. return m.side === this.side && m.enabled;
  293. });
  294. }
  295. // register this menu with the app's menu controller
  296. this._menuCtrl._register(this);
  297. // mask it as enabled / disabled
  298. this.enable(isEnabled);
  299. }
  300. /**
  301. * @hidden
  302. */
  303. onBackdropClick(ev) {
  304. ev.preventDefault();
  305. ev.stopPropagation();
  306. this._menuCtrl.close();
  307. }
  308. /**
  309. * @hidden
  310. */
  311. _getType() {
  312. if (!this._type) {
  313. this._type = MenuController.create(this.type, this, this._plt);
  314. if (this._config.get('animate') === false) {
  315. this._type.ani.duration(0);
  316. }
  317. }
  318. return this._type;
  319. }
  320. /**
  321. * @hidden
  322. */
  323. setOpen(shouldOpen, animated = true) {
  324. // If the menu is disabled or it is currenly being animated, let's do nothing
  325. if ((shouldOpen === this.isOpen) || !this._canOpen() || this._isAnimating) {
  326. return Promise.resolve(this.isOpen);
  327. }
  328. return new Promise(resolve => {
  329. this._before();
  330. this._getType().setOpen(shouldOpen, animated, () => {
  331. this._after(shouldOpen);
  332. resolve(this.isOpen);
  333. });
  334. });
  335. }
  336. _forceClosing() {
  337. (void 0) /* assert */;
  338. this._isAnimating = true;
  339. this._getType().setOpen(false, false, () => {
  340. this._after(false);
  341. });
  342. }
  343. /**
  344. * @hidden
  345. */
  346. canSwipe() {
  347. return this._isSwipeEnabled &&
  348. !this._isAnimating &&
  349. this._canOpen() &&
  350. this._app.isEnabled();
  351. }
  352. /**
  353. * @hidden
  354. */
  355. isAnimating() {
  356. return this._isAnimating;
  357. }
  358. _swipeBeforeStart() {
  359. if (!this.canSwipe()) {
  360. (void 0) /* assert */;
  361. return;
  362. }
  363. this._before();
  364. }
  365. _swipeStart() {
  366. if (!this._isAnimating) {
  367. (void 0) /* assert */;
  368. return;
  369. }
  370. this._getType().setProgressStart(this.isOpen);
  371. }
  372. _swipeProgress(stepValue) {
  373. if (!this._isAnimating) {
  374. (void 0) /* assert */;
  375. return;
  376. }
  377. this._getType().setProgessStep(stepValue);
  378. const ionDrag = this.ionDrag;
  379. if (ionDrag.observers.length > 0) {
  380. ionDrag.emit(stepValue);
  381. }
  382. }
  383. _swipeEnd(shouldCompleteLeft, shouldCompleteRight, stepValue, velocity) {
  384. if (!this._isAnimating) {
  385. (void 0) /* assert */;
  386. return;
  387. }
  388. // user has finished dragging the menu
  389. const isRightSide = this.isRightSide;
  390. const isRTL = this._plt.isRTL;
  391. const opening = !this.isOpen;
  392. const shouldComplete = (opening)
  393. ? (isRightSide !== isRTL) ? shouldCompleteLeft : shouldCompleteRight
  394. : (isRightSide !== isRTL) ? shouldCompleteRight : shouldCompleteLeft;
  395. this._getType().setProgressEnd(shouldComplete, stepValue, velocity, (isOpen) => {
  396. (void 0) /* console.debug */;
  397. this._after(isOpen);
  398. });
  399. }
  400. _before() {
  401. (void 0) /* assert */;
  402. // this places the menu into the correct location before it animates in
  403. // this css class doesn't actually kick off any animations
  404. this.setElementClass('show-menu', true);
  405. this.backdrop.setElementClass('show-backdrop', true);
  406. this.resize();
  407. this._keyboard.close();
  408. this._isAnimating = true;
  409. }
  410. _after(isOpen) {
  411. (void 0) /* assert */;
  412. this._app.setEnabled(false, 100);
  413. // keep opening/closing the menu disabled for a touch more yet
  414. // only add listeners/css if it's enabled and isOpen
  415. // and only remove listeners/css if it's not open
  416. // emit opened/closed events
  417. this.isOpen = isOpen;
  418. this._isAnimating = false;
  419. this._events.unlistenAll();
  420. if (isOpen) {
  421. // Disable swipe to go back gesture
  422. this._gestureBlocker.block();
  423. this._cntEle.classList.add('menu-content-open');
  424. let callback = this.onBackdropClick.bind(this);
  425. this._events.listen(this._cntEle, 'click', callback, { capture: true });
  426. this._events.listen(this.backdrop.getNativeElement(), 'click', callback, { capture: true });
  427. this.ionOpen.emit(true);
  428. }
  429. else {
  430. // Enable swipe to go back gesture
  431. this._gestureBlocker.unblock();
  432. this._cntEle.classList.remove('menu-content-open');
  433. this.setElementClass('show-menu', false);
  434. this.backdrop.setElementClass('show-menu', false);
  435. this.ionClose.emit(true);
  436. }
  437. }
  438. /**
  439. * @hidden
  440. */
  441. open() {
  442. return this.setOpen(true);
  443. }
  444. /**
  445. * @hidden
  446. */
  447. close() {
  448. return this.setOpen(false);
  449. }
  450. /**
  451. * @hidden
  452. */
  453. resize() {
  454. const content = this.menuContent
  455. ? this.menuContent
  456. : this.menuNav;
  457. content && content.resize();
  458. }
  459. /**
  460. * @hidden
  461. */
  462. toggle() {
  463. return this.setOpen(!this.isOpen);
  464. }
  465. _canOpen() {
  466. return this._isEnabled && !this._isPane;
  467. }
  468. /**
  469. * @hidden
  470. */
  471. _updateState() {
  472. const canOpen = this._canOpen();
  473. // Close menu inmediately
  474. if (!canOpen && this.isOpen) {
  475. (void 0) /* assert */;
  476. // close if this menu is open, and should not be enabled
  477. this._forceClosing();
  478. }
  479. if (this._isEnabled && this._menuCtrl) {
  480. this._menuCtrl._setActiveMenu(this);
  481. }
  482. if (!this._init) {
  483. return;
  484. }
  485. const gesture = this._gesture;
  486. // only listen/unlisten if the menu has initialized
  487. if (canOpen && this._isSwipeEnabled && !gesture.isListening) {
  488. // should listen, but is not currently listening
  489. (void 0) /* console.debug */;
  490. gesture.listen();
  491. }
  492. else if (gesture.isListening && (!canOpen || !this._isSwipeEnabled)) {
  493. // should not listen, but is currently listening
  494. (void 0) /* console.debug */;
  495. gesture.unlisten();
  496. }
  497. if (this.isOpen || (this._isPane && this._isEnabled)) {
  498. this.resize();
  499. }
  500. (void 0) /* assert */;
  501. }
  502. /**
  503. * @hidden
  504. */
  505. enable(shouldEnable) {
  506. this._isEnabled = shouldEnable;
  507. this.setElementClass('menu-enabled', shouldEnable);
  508. this._updateState();
  509. return this;
  510. }
  511. /**
  512. * @internal
  513. */
  514. initPane() {
  515. return false;
  516. }
  517. /**
  518. * @internal
  519. */
  520. paneChanged(isPane) {
  521. this._isPane = isPane;
  522. this._updateState();
  523. }
  524. /**
  525. * @hidden
  526. */
  527. swipeEnable(shouldEnable) {
  528. this._isSwipeEnabled = shouldEnable;
  529. this._updateState();
  530. return this;
  531. }
  532. /**
  533. * @hidden
  534. */
  535. getNativeElement() {
  536. return this._elementRef.nativeElement;
  537. }
  538. /**
  539. * @hidden
  540. */
  541. getMenuElement() {
  542. return this.getNativeElement().querySelector('.menu-inner');
  543. }
  544. /**
  545. * @hidden
  546. */
  547. getContentElement() {
  548. return this._cntEle;
  549. }
  550. /**
  551. * @hidden
  552. */
  553. getBackdropElement() {
  554. return this.backdrop.getNativeElement();
  555. }
  556. /**
  557. * @hidden
  558. */
  559. width() {
  560. return this.getMenuElement().offsetWidth;
  561. }
  562. /**
  563. * @hidden
  564. */
  565. getMenuController() {
  566. return this._menuCtrl;
  567. }
  568. /**
  569. * @hidden
  570. */
  571. setElementClass(className, add) {
  572. this._renderer.setElementClass(this._elementRef.nativeElement, className, add);
  573. }
  574. /**
  575. * @hidden
  576. */
  577. setElementAttribute(attributeName, value) {
  578. this._renderer.setElementAttribute(this._elementRef.nativeElement, attributeName, value);
  579. }
  580. /**
  581. * @hidden
  582. */
  583. getElementRef() {
  584. return this._elementRef;
  585. }
  586. /**
  587. * @hidden
  588. */
  589. ngOnDestroy() {
  590. this._menuCtrl._unregister(this);
  591. this._events.destroy();
  592. this._gesture && this._gesture.destroy();
  593. this._type && this._type.destroy();
  594. this._gesture = null;
  595. this._type = null;
  596. this._cntEle = null;
  597. }
  598. }
  599. Menu.decorators = [
  600. { type: Component, args: [{
  601. selector: 'ion-menu',
  602. template: '<div class="menu-inner"><ng-content></ng-content></div>' +
  603. '<ion-backdrop></ion-backdrop>',
  604. host: {
  605. 'role': 'navigation'
  606. },
  607. changeDetection: ChangeDetectionStrategy.OnPush,
  608. encapsulation: ViewEncapsulation.None,
  609. providers: [{ provide: RootNode, useExisting: forwardRef(() => Menu) }]
  610. },] },
  611. ];
  612. /** @nocollapse */
  613. Menu.ctorParameters = () => [
  614. { type: MenuController, },
  615. { type: ElementRef, },
  616. { type: Config, },
  617. { type: Platform, },
  618. { type: Renderer, },
  619. { type: Keyboard, },
  620. { type: GestureController, },
  621. { type: DomController, },
  622. { type: App, },
  623. ];
  624. Menu.propDecorators = {
  625. 'backdrop': [{ type: ViewChild, args: [Backdrop,] },],
  626. 'menuContent': [{ type: ContentChild, args: [Content,] },],
  627. 'menuNav': [{ type: ContentChild, args: [Nav,] },],
  628. 'content': [{ type: Input },],
  629. 'id': [{ type: Input },],
  630. 'type': [{ type: Input },],
  631. 'enabled': [{ type: Input },],
  632. 'side': [{ type: Input },],
  633. 'swipeEnabled': [{ type: Input },],
  634. 'persistent': [{ type: Input },],
  635. 'maxEdgeStart': [{ type: Input },],
  636. 'ionDrag': [{ type: Output },],
  637. 'ionOpen': [{ type: Output },],
  638. 'ionClose': [{ type: Output },],
  639. };
  640. //# sourceMappingURL=menu.js.map