Skip to content

Commit cac378f

Browse files
manucorporatadamdbradley
authored andcommitted
fix(menu): only one menu can be opened at a time
fixes #6826
1 parent 6e9eb93 commit cac378f

File tree

9 files changed

+90
-62
lines changed

9 files changed

+90
-62
lines changed

src/animations/animation.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,12 @@ export class Animation {
289289
var self = this;
290290
var i: number;
291291

292+
let dur = this._dur;
292293
if (isDefined(opts.duration)) {
293-
self._dur = opts.duration;
294+
dur = opts.duration;
294295
}
295296

296-
console.debug('Animation, play, duration', self._dur, 'easing', self._easing);
297+
console.debug('Animation, play, duration', dur, 'easing', this._easing);
297298

298299
// always default that an animation does not tween
299300
// a tween requires that an Animation class has an element
@@ -313,7 +314,7 @@ export class Animation {
313314
// ensure all past transition end events have been cleared
314315
self._clearAsync();
315316

316-
if (self._dur > 30) {
317+
if (dur > 30) {
317318
// this animation has a duration, so it should animate
318319
// place all the elements with their FROM properties
319320

@@ -328,7 +329,7 @@ export class Animation {
328329
// set the async TRANSITION END event
329330
// and run onFinishes when the transition ends
330331
// ******** DOM WRITE ****************
331-
self._asyncEnd(self._dur, true);
332+
self._asyncEnd(dur, true);
332333

333334
// begin each animation when everything is rendered in their place
334335
// and the transition duration/easing is ready to go

src/components/app/test/animations/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {ionicBootstrap, Config, Animation} from '../../../../../src';
66
templateUrl: 'main.html'
77
})
88
class E2EPage {
9-
duration;
10-
easing;
9+
duration: string;
10+
easing: string;
1111

1212
constructor(config: Config) {
1313
this.duration = '1000';

src/components/menu/menu-controller.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ export class MenuController {
125125
open(menuId?: string): Promise<boolean> {
126126
let menu = this.get(menuId);
127127
if (menu) {
128+
let openedMenu = this.getOpen();
129+
if (openedMenu && menu !== openedMenu) {
130+
openedMenu.setOpen(false, false);
131+
}
128132
return menu.open();
129133
}
130134

@@ -147,7 +151,7 @@ export class MenuController {
147151

148152
} else {
149153
// find the menu that is open
150-
menu = this._menus.find(m => m.isOpen);
154+
menu = this.getOpen();
151155
}
152156

153157
if (menu) {
@@ -158,11 +162,6 @@ export class MenuController {
158162
return Promise.resolve(false);
159163
}
160164

161-
tempDisable(temporarilyDisable: boolean) {
162-
this._menus.forEach(menu => {
163-
menu.tempDisable(temporarilyDisable);
164-
});
165-
}
166165

167166
/**
168167
* Toggle the menu. If it's closed, it will open, and if opened, it
@@ -173,6 +172,10 @@ export class MenuController {
173172
toggle(menuId?: string): Promise<boolean> {
174173
let menu = this.get(menuId);
175174
if (menu) {
175+
let openedMenu = this.getOpen();
176+
if (openedMenu && menu !== openedMenu) {
177+
openedMenu.setOpen(false, false);
178+
}
176179
return menu.toggle();
177180
}
178181
return Promise.resolve(false);
@@ -229,7 +232,7 @@ export class MenuController {
229232
* provided, then it'll try to find the menu using the menu's `id`
230233
* property. If a menu is not found then it'll return `null`.
231234
* @param {string} [menuId] Optionally get the menu by its id, or side.
232-
* @return {Menu} Returns the instance of the menu if found, otherwise `null`.
235+
* @return {Menu} Returns the instance of the menu if found, otherwise `null`.
233236
*/
234237
get(menuId?: string): Menu {
235238
var menu: Menu;
@@ -252,12 +255,21 @@ export class MenuController {
252255

253256
// return the first enabled menu
254257
menu = this._menus.find(m => m.enabled);
255-
if (menu) return menu;
258+
if (menu) {
259+
return menu;
260+
}
256261

257262
// get the first menu in the array, if one exists
258263
return (this._menus.length ? this._menus[0] : null);
259264
}
260265

266+
/**
267+
* @return {Menu} Returns the instance of the menu already opened, otherwise `null`.
268+
*/
269+
getOpen(): Menu {
270+
return this._menus.find(m => m.isOpen);
271+
}
272+
261273

262274
/**
263275
* @return {Array<Menu>} Returns an array of all menu instances.

src/components/menu/menu-gestures.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ export class MenuContentGesture extends SlideEdgeGesture {
2424

2525
canStart(ev: any): boolean {
2626
let menu = this.menu;
27-
return (
28-
menu.enabled &&
29-
menu.swipeEnabled &&
30-
(menu.isOpen || super.canStart(ev))
31-
);
27+
if (!menu.enabled || !menu.swipeEnabled) {
28+
return false;
29+
}
30+
if (menu.isOpen) {
31+
return true;
32+
} else if (menu.getMenuController().getOpen()) {
33+
return false;
34+
}
35+
return super.canStart(ev);
3236
}
3337

3438
// Set CSS, then wait one frame for it to apply before sliding starts

src/components/menu/menu-types.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@ export class MenuType {
1515
ani: Animation = new Animation();
1616
isOpening: boolean;
1717

18-
setOpen(shouldOpen: boolean, done: Function) {
19-
this.ani
20-
.onFinish(done, true)
21-
.reverse(!shouldOpen)
22-
.play();
18+
setOpen(shouldOpen: boolean, animated: boolean, done: Function) {
19+
let ani = this.ani
20+
.onFinish(done, true)
21+
.reverse(!shouldOpen);
22+
if (animated) {
23+
ani.play();
24+
} else {
25+
ani.play({ duration: 0 });
26+
}
2327
}
2428

2529
setProgressStart(isOpen: boolean) {

src/components/menu/menu.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ export class Menu extends Ion {
198198
private _isSwipeEnabled: boolean = true;
199199
private _isPers: boolean = false;
200200
private _init: boolean = false;
201-
private _prevEnabled: boolean;
202201

203202
/**
204203
* @private
@@ -414,7 +413,7 @@ export class Menu extends Ion {
414413
/**
415414
* @private
416415
*/
417-
setOpen(shouldOpen: boolean): Promise<boolean> {
416+
setOpen(shouldOpen: boolean, animated: boolean = true): Promise<boolean> {
418417
// _isPrevented is used to prevent unwanted opening/closing after swiping open/close
419418
// or swiping open the menu while pressing down on the MenuToggle button
420419
if ((shouldOpen && this.isOpen) || this._isPrevented()) {
@@ -424,7 +423,7 @@ export class Menu extends Ion {
424423
this._before();
425424

426425
return new Promise(resolve => {
427-
this._getType().setOpen(shouldOpen, () => {
426+
this._getType().setOpen(shouldOpen, animated, () => {
428427
this._after(shouldOpen);
429428
resolve(this.isOpen);
430429
});
@@ -515,21 +514,6 @@ export class Menu extends Ion {
515514
}
516515
}
517516

518-
/**
519-
* @private
520-
*/
521-
tempDisable(temporarilyDisable: boolean) {
522-
if (temporarilyDisable) {
523-
this._prevEnabled = this._isEnabled;
524-
this._getType().setProgessStep(0);
525-
this.enable(false);
526-
527-
} else {
528-
this.enable(this._prevEnabled);
529-
this._after(false);
530-
}
531-
}
532-
533517
private _prevent() {
534518
// used to prevent unwanted opening/closing after swiping open/close
535519
// or swiping open the menu while pressing down on the MenuToggle
@@ -613,6 +597,13 @@ export class Menu extends Ion {
613597
return this.backdrop.getNativeElement();
614598
}
615599

600+
/**
601+
* @private
602+
*/
603+
getMenuController(): MenuController {
604+
return this._menuCtrl;
605+
}
606+
616607
/**
617608
* @private
618609
*/

src/components/menu/test/basic/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ class E2EPage {
6767
});
6868
}
6969

70+
openRightMenu() {
71+
this.menu.open('right');
72+
}
73+
74+
openLeftMenu() {
75+
this.menu.open('left');
76+
}
77+
7078
onDrag(ev: any) {
7179
console.log('Menu is being dragged', ev);
7280
}

src/components/menu/test/basic/main.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
{{p.title}}
1515
</button>
1616

17+
<button ion-item (click)="openRightMenu()">
18+
Open Right Menu
19+
</button>
20+
1721
<button ion-item menuClose="left" class="e2eCloseLeftMenu" detail-none>
1822
Close Menu
1923
</button>
@@ -90,6 +94,10 @@
9094
{{p.title}}
9195
</button>
9296

97+
<button ion-item (click)="openLeftMenu()">
98+
Open Left Menu
99+
</button>
100+
93101
<button ion-item menuClose="right" class="e2eCloseRightMenu" detail-none>
94102
Close Menu
95103
</button>

src/components/modal/test/basic/index.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ActionSheetController, App, Config, ionicBootstrap, ModalController, Na
66
@Injectable()
77
class SomeComponentProvider {
88
constructor(private config: Config) {
9-
console.log('SomeComponentProvider constructor')
9+
console.log('SomeComponentProvider constructor');
1010
}
1111

1212
getName() {
@@ -17,7 +17,7 @@ class SomeComponentProvider {
1717
@Injectable()
1818
class SomeAppProvider {
1919
constructor(private config: Config) {
20-
console.log('SomeAppProvider constructor')
20+
console.log('SomeAppProvider constructor');
2121
}
2222

2323
getData() {
@@ -84,7 +84,7 @@ class E2EPage {
8484
}
8585

8686
presentModalWithInputs() {
87-
let modal = this.modalCtrl.create(ModalWithInputs);
87+
let modal = this.modalCtrl.create(ModalWithInputs);
8888
modal.onDidDismiss((data: any) => {
8989
console.log('Modal with inputs data:', data);
9090
});
@@ -98,7 +98,7 @@ class E2EPage {
9898
});
9999
}
100100

101-
presentNavigableModal(){
101+
presentNavigableModal() {
102102
this.modalCtrl.create(NavigableModal).present();
103103
}
104104
}
@@ -139,10 +139,10 @@ class NavigableModal {
139139
`
140140
})
141141
class NavigableModal2 {
142-
constructor(private navController:NavController) {
142+
constructor(private navController: NavController) {
143143
}
144144

145-
submit(){
145+
submit() {
146146
this.navController.pop();
147147
}
148148
}
@@ -188,23 +188,23 @@ class ModalPassData {
188188
this.viewCtrl.dismiss(this.data);
189189
}
190190

191-
ionViewLoaded(){
191+
ionViewLoaded() {
192192
console.log('ModalPassData ionViewLoaded fired');
193193
}
194194

195-
ionViewWillEnter(){
195+
ionViewWillEnter() {
196196
console.log('ModalPassData ionViewWillEnter fired');
197197
}
198198

199-
ionViewDidEnter(){
199+
ionViewDidEnter() {
200200
console.log('ModalPassData ionViewDidEnter fired');
201201
}
202202

203-
ionViewWillLeave(){
203+
ionViewWillLeave() {
204204
console.log('ModalPassData ionViewWillLeave fired');
205205
}
206206

207-
ionViewDidLeave(){
207+
ionViewDidLeave() {
208208
console.log('ModalPassData ionViewDidLeave fired');
209209
}
210210
}
@@ -375,10 +375,10 @@ class ContactUs {
375375
})
376376
class ModalFirstPage {
377377

378-
private items:any[];
378+
private items: any[];
379379
constructor(private nav: NavController, private app: App, private actionSheetCtrl: ActionSheetController) {
380380
this.items = [];
381-
for ( let i = 0; i < 50; i++ ){
381+
for ( let i = 0; i < 50; i++ ) {
382382
this.items.push({
383383
value: (i + 1)
384384
});
@@ -387,7 +387,7 @@ class ModalFirstPage {
387387

388388
push() {
389389
let page = ModalSecondPage;
390-
let params = { id: 8675309, myData: [1,2,3,4] };
390+
let params = { id: 8675309, myData: [1, 2, 3, 4] };
391391

392392
this.nav.push(page, params);
393393
}
@@ -396,15 +396,15 @@ class ModalFirstPage {
396396
this.app.getRootNav().pop();
397397
}
398398

399-
ionViewLoaded(){
399+
ionViewLoaded() {
400400
console.log('ModalFirstPage ionViewLoaded fired');
401401
}
402402

403-
ionViewWillEnter(){
403+
ionViewWillEnter() {
404404
console.log('ModalFirstPage ionViewWillEnter fired');
405405
}
406406

407-
ionViewDidEnter(){
407+
ionViewDidEnter() {
408408
console.log('ModalFirstPage ionViewDidEnter fired');
409409
}
410410

@@ -477,15 +477,15 @@ class ModalSecondPage {
477477
console.log('Second page params:', params);
478478
}
479479

480-
ionViewLoaded(){
480+
ionViewLoaded() {
481481
console.log('ModalSecondPage ionViewLoaded');
482482
}
483483

484-
ionViewWillEnter(){
484+
ionViewWillEnter() {
485485
console.log('ModalSecondPage ionViewWillEnter');
486486
}
487487

488-
ionViewDidEnter(){
488+
ionViewDidEnter() {
489489
console.log('ModalSecondPage ionViewDidEnter');
490490
}
491491
}

0 commit comments

Comments
 (0)