@@ -8,7 +8,7 @@ import {MenuContentGesture, MenuTargetGesture} from './menu-gestures';
88import { Gesture } from '../../gestures/gesture' ;
99import { MenuController } from './menu-controller' ;
1010import { MenuType } from './menu-types' ;
11- import { isFalseProperty } from '../../util/util' ;
11+ import { isTrueProperty } from '../../util/util' ;
1212
1313
1414/**
@@ -17,12 +17,11 @@ import {isFalseProperty} from '../../util/util';
1717@Component ( {
1818 selector : 'ion-menu' ,
1919 host : {
20- 'role' : 'navigation' ,
21- '[attr.side]' : 'side' ,
22- '[attr.type]' : 'type' ,
23- '[attr.swipeEnabled]' : 'swipeEnabled'
20+ 'role' : 'navigation'
2421 } ,
25- template : '<ng-content></ng-content><div tappable disable-activated class="backdrop"></div>' ,
22+ template :
23+ '<ng-content></ng-content>' +
24+ '<div tappable disable-activated class="backdrop"></div>' ,
2625 directives : [ forwardRef ( ( ) => MenuBackdrop ) ]
2726} )
2827export class Menu extends Ion {
@@ -32,23 +31,16 @@ export class Menu extends Ion {
3231 private _menuGesture : Gesture ;
3332 private _type : MenuType ;
3433 private _resizeUnreg : Function ;
35-
34+ private _isEnabled : boolean = true ;
35+ private _isSwipeEnabled : boolean = true ;
36+ private _isListening : boolean = false ;
37+ private _init : boolean = false ;
3638
3739 /**
3840 * @private
3941 */
4042 isOpen : boolean = false ;
4143
42- /**
43- * @private
44- */
45- isEnabled : boolean = true ;
46-
47- /**
48- * @private
49- */
50- isSwipeEnabled : boolean = true ;
51-
5244 /**
5345 * @private
5446 */
@@ -83,7 +75,28 @@ export class Menu extends Ion {
8375 /**
8476 * @private
8577 */
86- @Input ( ) swipeEnabled : any ;
78+ @Input ( )
79+ get enabled ( ) : boolean {
80+ return this . _isEnabled ;
81+ }
82+
83+ set enabled ( val : boolean ) {
84+ this . _isEnabled = isTrueProperty ( val ) ;
85+ this . _setListeners ( ) ;
86+ }
87+
88+ /**
89+ * @private
90+ */
91+ @Input ( )
92+ get swipeEnabled ( ) : boolean {
93+ return this . _isSwipeEnabled ;
94+ }
95+
96+ set swipeEnabled ( val : boolean ) {
97+ this . _isSwipeEnabled = isTrueProperty ( val ) ;
98+ this . _setListeners ( ) ;
99+ }
87100
88101 /**
89102 * @private
@@ -112,6 +125,8 @@ export class Menu extends Ion {
112125 */
113126 ngOnInit ( ) {
114127 let self = this ;
128+ self . _init = true ;
129+
115130 let content = self . content ;
116131 self . _cntEle = ( content instanceof Node ) ? content : content && content . getNativeElement && content . getNativeElement ( ) ;
117132
@@ -132,23 +147,29 @@ export class Menu extends Ion {
132147 }
133148 self . _renderer . setElementAttribute ( self . _elementRef . nativeElement , 'type' , self . type ) ;
134149
135- // add the gesture listeners
136- self . _zone . runOutsideAngular ( function ( ) {
137- self . _cntGesture = new MenuContentGesture ( self , self . getContentElement ( ) ) ;
138- self . _menuGesture = new MenuTargetGesture ( self , self . getNativeElement ( ) ) ;
139-
140- self . onContentClick = function ( ev : UIEvent ) {
141- if ( self . isEnabled ) {
142- ev . preventDefault ( ) ;
143- ev . stopPropagation ( ) ;
144- self . close ( ) ;
145- }
146- } ;
147- } ) ;
150+ // add the gestures
151+ self . _cntGesture = new MenuContentGesture ( self , self . getContentElement ( ) ) ;
152+ self . _menuGesture = new MenuTargetGesture ( self , self . getNativeElement ( ) ) ;
148153
149- if ( isFalseProperty ( self . swipeEnabled ) ) {
150- self . isSwipeEnabled = false ;
154+ // register listeners if this menu is enabled
155+ // check if more than one menu is on the same side
156+ let hasEnabledSameSideMenu = self . _menuCtrl . getMenus ( ) . some ( m => {
157+ return m . side === self . side && m . enabled ;
158+ } ) ;
159+ if ( hasEnabledSameSideMenu ) {
160+ // auto-disable if another menu on the same side is already enabled
161+ self . _isEnabled = false ;
151162 }
163+ self . _setListeners ( ) ;
164+
165+ // create a reusable click handler on this instance, but don't assign yet
166+ self . onContentClick = function ( ev : UIEvent ) {
167+ if ( self . _isEnabled ) {
168+ ev . preventDefault ( ) ;
169+ ev . stopPropagation ( ) ;
170+ self . close ( ) ;
171+ }
172+ } ;
152173
153174 self . _cntEle . classList . add ( 'menu-content' ) ;
154175 self . _cntEle . classList . add ( 'menu-content-' + self . type ) ;
@@ -157,6 +178,34 @@ export class Menu extends Ion {
157178 self . _menuCtrl . register ( self ) ;
158179 }
159180
181+ /**
182+ * @private
183+ */
184+ private _setListeners ( ) {
185+ let self = this ;
186+
187+ if ( self . _init ) {
188+ // only listen/unlisten if the menu has initialized
189+
190+ if ( self . _isEnabled && self . _isSwipeEnabled && ! self . _isListening ) {
191+ // should listen, but is not currently listening
192+ console . debug ( 'menu, gesture listen' , self . side ) ;
193+ self . _zone . runOutsideAngular ( function ( ) {
194+ self . _cntGesture . listen ( ) ;
195+ self . _menuGesture . listen ( ) ;
196+ } ) ;
197+ self . _isListening = true ;
198+
199+ } else if ( self . _isListening && ( ! self . _isEnabled || ! self . _isSwipeEnabled ) ) {
200+ // should not listen, but is currently listening
201+ console . debug ( 'menu, gesture unlisten' , self . side ) ;
202+ self . _cntGesture . unlisten ( ) ;
203+ self . _menuGesture . unlisten ( ) ;
204+ self . _isListening = false ;
205+ }
206+ }
207+ }
208+
160209 /**
161210 * @private
162211 */
@@ -176,7 +225,7 @@ export class Menu extends Ion {
176225 * @param {boolean } shouldOpen If the Menu is open or not.
177226 * @return {Promise } returns a promise once set
178227 */
179- setOpen ( shouldOpen ) : Promise < boolean > {
228+ setOpen ( shouldOpen : boolean ) : Promise < boolean > {
180229 // _isPrevented is used to prevent unwanted opening/closing after swiping open/close
181230 // or swiping open the menu while pressing down on the menuToggle button
182231 if ( ( shouldOpen && this . isOpen ) || this . _isPrevented ( ) ) {
@@ -198,7 +247,7 @@ export class Menu extends Ion {
198247 */
199248 setProgressStart ( ) {
200249 // user started swiping the menu open/close
201- if ( this . _isPrevented ( ) || ! this . isEnabled || ! this . isSwipeEnabled ) return ;
250+ if ( this . _isPrevented ( ) || ! this . _isEnabled || ! this . _isSwipeEnabled ) return ;
202251
203252 this . _before ( ) ;
204253 this . _getType ( ) . setProgressStart ( this . isOpen ) ;
@@ -209,7 +258,7 @@ export class Menu extends Ion {
209258 */
210259 setProgessStep ( stepValue : number ) {
211260 // user actively dragging the menu
212- if ( this . isEnabled && this . isSwipeEnabled ) {
261+ if ( this . _isEnabled && this . _isSwipeEnabled ) {
213262 this . _prevent ( ) ;
214263 this . _getType ( ) . setProgessStep ( stepValue ) ;
215264 this . opening . next ( stepValue ) ;
@@ -221,7 +270,7 @@ export class Menu extends Ion {
221270 */
222271 setProgressEnd ( shouldComplete : boolean , currentStepValue : number ) {
223272 // user has finished dragging the menu
224- if ( this . isEnabled && this . isSwipeEnabled ) {
273+ if ( this . _isEnabled && this . _isSwipeEnabled ) {
225274 this . _prevent ( ) ;
226275 this . _getType ( ) . setProgressEnd ( shouldComplete , currentStepValue , ( isOpen ) => {
227276 console . debug ( 'menu, progress end' , this . side ) ;
@@ -236,7 +285,7 @@ export class Menu extends Ion {
236285 private _before ( ) {
237286 // this places the menu into the correct location before it animates in
238287 // this css class doesn't actually kick off any animations
239- if ( this . isEnabled ) {
288+ if ( this . _isEnabled ) {
240289 this . getNativeElement ( ) . classList . add ( 'show-menu' ) ;
241290 this . getBackdropElement ( ) . classList . add ( 'show-backdrop' ) ;
242291
@@ -252,7 +301,7 @@ export class Menu extends Ion {
252301 // keep opening/closing the menu disabled for a touch more yet
253302 // only add listeners/css if it's enabled and isOpen
254303 // and only remove listeners/css if it's not open
255- if ( ( this . isEnabled && isOpen ) || ! isOpen ) {
304+ if ( ( this . _isEnabled && isOpen ) || ! isOpen ) {
256305 this . _prevent ( ) ;
257306
258307 this . isOpen = isOpen ;
@@ -318,7 +367,7 @@ export class Menu extends Ion {
318367 * @return {Menu } Returns the instance of the menu, which is useful for chaining.
319368 */
320369 enable ( shouldEnable : boolean ) : Menu {
321- this . isEnabled = shouldEnable ;
370+ this . enabled = shouldEnable ;
322371 if ( ! shouldEnable && this . isOpen ) {
323372 this . close ( ) ;
324373 }
@@ -331,7 +380,7 @@ export class Menu extends Ion {
331380 * @return {Menu } Returns the instance of the menu, which is useful for chaining.
332381 */
333382 swipeEnable ( shouldEnable : boolean ) : Menu {
334- this . isSwipeEnabled = shouldEnable ;
383+ this . swipeEnabled = shouldEnable ;
335384 return this ;
336385 }
337386
0 commit comments