Skip to content

Commit 5311336

Browse files
committed
fix(menu): rtl support
1 parent 51d5079 commit 5311336

File tree

16 files changed

+129
-138
lines changed

16 files changed

+129
-138
lines changed

src/components/app/menu-controller.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ export class MenuController {
248248
// there could be more than one menu on the same side
249249
// so first try to get the enabled one
250250
menu = this._menus.find(m => m.side === menuId && m.enabled);
251-
if (menu) return menu;
251+
if (menu) {
252+
return menu;
253+
}
252254

253255
// didn't find a menu side that is enabled
254256
// so try to get the first menu side found

src/components/app/menu-interface.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Animation } from '../../animations/animation';
2-
3-
export type Side = 'left' | 'right' | 'start' | 'end';
2+
import { Side } from '../../util/util';
43

54
export interface Menu {
65
setOpen(shouldOpen: boolean, animated: boolean): Promise<boolean>;
@@ -13,6 +12,7 @@ export interface Menu {
1312
enabled: boolean;
1413
side: Side;
1514
id: string;
15+
isRightSide: boolean;
1616
isAnimating(): boolean;
1717
width(): number;
1818
getContentElement(): HTMLElement;

src/components/item/item-options.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Directive, ElementRef, EventEmitter, Input, Output, Renderer } from '@angular/core';
22

33
import { Platform } from '../../platform/platform';
4-
import { ITEM_SIDE_FLAG_LEFT, ITEM_SIDE_FLAG_RIGHT, ItemSliding } from './item-sliding';
4+
import { Side, isRightSide } from '../../util/util';
5+
import { ItemSliding } from './item-sliding';
56

67
/**
78
* @name ItemOptions
@@ -33,7 +34,7 @@ export class ItemOptions {
3334
* @input {string} The side the option button should be on. Defaults to `"right"`.
3435
* If you have multiple `ion-item-options`, a side must be provided for each.
3536
*/
36-
@Input() side: string;
37+
@Input() side: Side;
3738

3839
/**
3940
* @output {event} Emitted when the item has been fully swiped.
@@ -49,17 +50,8 @@ export class ItemOptions {
4950
/**
5051
* @hidden
5152
*/
52-
getSides(): number {
53-
switch (this.side) {
54-
case 'left':
55-
return ITEM_SIDE_FLAG_LEFT;
56-
case 'right':
57-
return ITEM_SIDE_FLAG_RIGHT;
58-
case 'start':
59-
return this._plt.isRTL() ? ITEM_SIDE_FLAG_RIGHT : ITEM_SIDE_FLAG_LEFT;
60-
default: // end
61-
return this._plt.isRTL() ? ITEM_SIDE_FLAG_LEFT : ITEM_SIDE_FLAG_RIGHT;
62-
}
53+
isRightSide(): boolean {
54+
return isRightSide(this.side, this._plt.isRTL);
6355
}
6456

6557
/**

src/components/item/item-sliding.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import { ItemOptions } from './item-options';
1010
const SWIPE_MARGIN = 30;
1111
const ELASTIC_FACTOR = 0.55;
1212

13-
export const ITEM_SIDE_FLAG_NONE = 0;
14-
export const ITEM_SIDE_FLAG_LEFT = 1 << 0;
15-
export const ITEM_SIDE_FLAG_RIGHT = 1 << 1;
16-
export const ITEM_SIDE_FLAG_BOTH = ITEM_SIDE_FLAG_LEFT | ITEM_SIDE_FLAG_RIGHT;
13+
const ITEM_SIDE_FLAG_NONE = 0;
14+
const ITEM_SIDE_FLAG_LEFT = 1 << 0;
15+
const ITEM_SIDE_FLAG_RIGHT = 1 << 1;
16+
const ITEM_SIDE_FLAG_BOTH = ITEM_SIDE_FLAG_LEFT | ITEM_SIDE_FLAG_RIGHT;
1717

1818

1919
const enum SlidingState {
@@ -121,6 +121,7 @@ const enum SlidingState {
121121
encapsulation: ViewEncapsulation.None
122122
})
123123
export class ItemSliding {
124+
124125
private _openAmount: number = 0;
125126
private _startX: number = 0;
126127
private _optsWidthRightSide: number = 0;
@@ -166,7 +167,8 @@ export class ItemSliding {
166167
private _dom: DomController,
167168
private _renderer: Renderer,
168169
private _elementRef: ElementRef,
169-
private _zone: NgZone) {
170+
private _zone: NgZone
171+
) {
170172
list && list.containsSlidingItem(true);
171173
_elementRef.nativeElement.$ionComponent = this;
172174
this.setElementClass('item-wrapper', true);
@@ -180,13 +182,13 @@ export class ItemSliding {
180182
this._leftOptions = this._rightOptions = null;
181183

182184
for (var item of itemOptions.toArray()) {
183-
var side = item.getSides();
184-
if (side === ITEM_SIDE_FLAG_LEFT) {
185-
this._leftOptions = item;
186-
} else {
185+
if (item.isRightSide()) {
187186
this._rightOptions = item;
187+
sides |= ITEM_SIDE_FLAG_RIGHT;
188+
} else {
189+
this._leftOptions = item;
190+
sides |= ITEM_SIDE_FLAG_LEFT;
188191
}
189-
sides |= item.getSides();
190192
}
191193
this._optsDirty = true;
192194
this._sides = sides;
@@ -203,7 +205,7 @@ export class ItemSliding {
203205
* @hidden
204206
*/
205207
getSlidingPercent(): number {
206-
let openAmount = this._openAmount;
208+
const openAmount = this._openAmount;
207209
if (openAmount > 0) {
208210
return openAmount / this._optsWidthRightSide;
209211
} else if (openAmount < 0) {
@@ -272,9 +274,9 @@ export class ItemSliding {
272274

273275
// Check if the drag didn't clear the buttons mid-point
274276
// and we aren't moving fast enough to swipe open
275-
let isResetDirection = (this._openAmount > 0) === !(velocity < 0);
276-
let isMovingFast = Math.abs(velocity) > 0.3;
277-
let isOnCloseZone = Math.abs(this._openAmount) < Math.abs(restingPoint / 2);
277+
const isResetDirection = (this._openAmount > 0) === !(velocity < 0);
278+
const isMovingFast = Math.abs(velocity) > 0.3;
279+
const isOnCloseZone = Math.abs(this._openAmount) < Math.abs(restingPoint / 2);
278280
if (swipeShouldReset(isResetDirection, isMovingFast, isOnCloseZone)) {
279281
restingPoint = 0;
280282
}
@@ -330,14 +332,14 @@ export class ItemSliding {
330332

331333
} else {
332334
if (openAmount > 0) {
333-
let state = (openAmount >= (this._optsWidthRightSide + SWIPE_MARGIN))
335+
var state = (openAmount >= (this._optsWidthRightSide + SWIPE_MARGIN))
334336
? SlidingState.Right | SlidingState.SwipeRight
335337
: SlidingState.Right;
336338

337339
this._setState(state);
338340

339341
} else if (openAmount < 0) {
340-
let state = (openAmount <= (-this._optsWidthLeftSide - SWIPE_MARGIN))
342+
var state = (openAmount <= (-this._optsWidthLeftSide - SWIPE_MARGIN))
341343
? SlidingState.Left | SlidingState.SwipeLeft
342344
: SlidingState.Left;
343345

src/components/menu/menu-gestures.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class MenuContentGesture extends SlideEdgeGesture {
3333
}
3434

3535
canStart(ev: any): boolean {
36-
let menu = this.menu;
36+
const menu = this.menu;
3737
if (!menu.canSwipe()) {
3838
return false;
3939
}
@@ -57,21 +57,21 @@ export class MenuContentGesture extends SlideEdgeGesture {
5757
}
5858

5959
onSlide(slide: SlideData, ev: any) {
60-
let z = (this.menu.side === 'right' ? slide.min : slide.max);
61-
let stepValue = (slide.distance / z);
60+
const z = (this.menu.isRightSide ? slide.min : slide.max);
61+
const stepValue = (slide.distance / z);
6262

6363
this.menu._swipeProgress(stepValue);
6464
}
6565

6666
onSlideEnd(slide: SlideData, ev: any) {
67-
let z = (this.menu.side === 'right' ? slide.min : slide.max);
68-
let currentStepValue = (slide.distance / z);
69-
let velocity = slide.velocity;
67+
let z = (this.menu.isRightSide ? slide.min : slide.max);
68+
const currentStepValue = (slide.distance / z);
69+
const velocity = slide.velocity;
7070
z = Math.abs(z * 0.5);
71-
let shouldCompleteRight = (velocity >= 0)
71+
const shouldCompleteRight = (velocity >= 0)
7272
&& (velocity > 0.2 || slide.delta > z);
7373

74-
let shouldCompleteLeft = (velocity <= 0)
74+
const shouldCompleteLeft = (velocity <= 0)
7575
&& (velocity < -0.2 || slide.delta < -z);
7676

7777
console.debug('menu gesture, onSlideEnd', this.menu.side,
@@ -88,24 +88,26 @@ export class MenuContentGesture extends SlideEdgeGesture {
8888
}
8989

9090
getElementStartPos(slide: SlideData, ev: any) {
91-
if (this.menu.side === 'right') {
92-
return this.menu.isOpen ? slide.min : slide.max;
91+
const menu = this.menu;
92+
if (menu.isRightSide) {
93+
return menu.isOpen ? slide.min : slide.max;
9394
}
9495
// left menu
95-
return this.menu.isOpen ? slide.max : slide.min;
96+
return menu.isOpen ? slide.max : slide.min;
9697
}
9798

98-
getSlideBoundaries(): {min: number, max: number} {
99-
if (this.menu.side === 'right') {
99+
getSlideBoundaries(): { min: number, max: number } {
100+
const menu = this.menu;
101+
if (menu.isRightSide) {
100102
return {
101-
min: -this.menu.width(),
103+
min: -menu.width(),
102104
max: 0
103105
};
104106
}
105107
// left menu
106108
return {
107109
min: 0,
108-
max: this.menu.width()
110+
max: menu.width()
109111
};
110112
}
111113
}

src/components/menu/menu-types.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Platform } from '../../platform/platform';
1212
* and registers itself with Menu.
1313
*/
1414
export class MenuType implements IMenuType {
15+
1516
ani: Animation;
1617
isOpening: boolean;
1718

@@ -67,7 +68,7 @@ export class MenuType implements IMenuType {
6768
}
6869

6970
destroy() {
70-
this.ani && this.ani.destroy();
71+
this.ani.destroy();
7172
this.ani = null;
7273
}
7374

@@ -84,8 +85,8 @@ class MenuRevealType extends MenuType {
8485
constructor(menu: Menu, plt: Platform) {
8586
super(plt);
8687

87-
let openedX = (menu.width() * (menu.side === 'right' ? -1 : 1)) + 'px';
88-
let contentOpen = new Animation(plt, menu.getContentElement());
88+
const openedX = (menu.width() * (menu.isRightSide ? -1 : 1)) + 'px';
89+
const contentOpen = new Animation(plt, menu.getContentElement());
8990
contentOpen.fromTo('translateX', '0px', openedX);
9091
this.ani.add(contentOpen);
9192
}
@@ -104,24 +105,24 @@ class MenuPushType extends MenuType {
104105
super(plt);
105106

106107
let contentOpenedX: string, menuClosedX: string, menuOpenedX: string;
107-
108-
if (menu.side === 'right') {
108+
const width = menu.width();
109+
if (menu.isRightSide) {
109110
// right side
110-
contentOpenedX = -menu.width() + 'px';
111-
menuClosedX = menu.width() + 'px';
111+
contentOpenedX = -width + 'px';
112+
menuClosedX = width + 'px';
112113
menuOpenedX = '0px';
113114

114115
} else {
115-
contentOpenedX = menu.width() + 'px';
116+
contentOpenedX = width + 'px';
116117
menuOpenedX = '0px';
117-
menuClosedX = -menu.width() + 'px';
118+
menuClosedX = -width + 'px';
118119
}
119120

120-
let menuAni = new Animation(plt, menu.getMenuElement());
121+
const menuAni = new Animation(plt, menu.getMenuElement());
121122
menuAni.fromTo('translateX', menuClosedX, menuOpenedX);
122123
this.ani.add(menuAni);
123124

124-
let contentApi = new Animation(plt, menu.getContentElement());
125+
const contentApi = new Animation(plt, menu.getContentElement());
125126
contentApi.fromTo('translateX', '0px', contentOpenedX);
126127
this.ani.add(contentApi);
127128
}
@@ -140,22 +141,23 @@ class MenuOverlayType extends MenuType {
140141
super(plt);
141142

142143
let closedX: string, openedX: string;
143-
if (menu.side === 'right') {
144+
const width = menu.width();
145+
if (menu.isRightSide) {
144146
// right side
145-
closedX = 8 + menu.width() + 'px';
147+
closedX = 8 + width + 'px';
146148
openedX = '0px';
147149

148150
} else {
149151
// left side
150-
closedX = -(8 + menu.width()) + 'px';
152+
closedX = -(8 + width) + 'px';
151153
openedX = '0px';
152154
}
153155

154-
let menuAni = new Animation(plt, menu.getMenuElement());
156+
const menuAni = new Animation(plt, menu.getMenuElement());
155157
menuAni.fromTo('translateX', closedX, openedX);
156158
this.ani.add(menuAni);
157159

158-
let backdropApi = new Animation(plt, menu.getBackdropElement());
160+
const backdropApi = new Animation(plt, menu.getBackdropElement());
159161
backdropApi.fromTo('opacity', 0.01, 0.35);
160162
this.ani.add(backdropApi);
161163
}

0 commit comments

Comments
 (0)