mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
fix(menu): rtl support
Squashed commit of the following: commit 57b59eb373e76401caf1c42fa696a67e1e6a69b7 Merge: dcf80e416 f26c4b4fe Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Fri Apr 21 14:38:03 2017 +0300 merge 'master' commit dcf80e4161f33ca3ff4cea5ce0c6358107bbcdff Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Fri Apr 21 01:24:40 2017 +0300 tests(menu): add menu rtl tests commit d65575b9ca63402fdc49991349320ad1dd76f114 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Fri Apr 21 01:24:00 2017 +0300 tests(mock): add platform to mockMenu commit faad17ca3231d999296907a9892b3afdb48e124f Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Fri Apr 21 01:23:01 2017 +0300 fix(menu): update gesture only if it exists commit e50eb184ec5af3cfdb3634b1d7cfe1899da36054 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Fri Apr 21 00:55:50 2017 +0300 refactor(menu): use magic get/set for side update commit 89a1715661fa889157f39401c419fc55d4809f9e Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Thu Apr 20 19:31:49 2017 +0300 revert(menu): revert removed dependency this PR is for a specific feature commit 7c1263624c68fc2729b24f10956841b6ff0c22f6 Merge: 4465f82f6 860567288 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Thu Apr 20 19:26:10 2017 +0300 Merge remote-tracking branch 'upstream/master' into menu commit 4465f82f644a96830379fe3bef8e0fbe53e6f998 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Thu Apr 20 16:11:13 2017 +0300 style(backdrop): fix code style commit da4983a16133ee7d85f3393161d16fe1a33d2fa4 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Thu Apr 20 16:09:18 2017 +0300 revert(renderer): back to renderer1 commit 80ab0941d6351e3787dba11c4a6398da7044fb24 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Sun Apr 16 11:34:34 2017 +0300 fix(swipe-back): change side according to dir commit f99cb9844f325f43d9fb7ca22394e7ccff89f3b3 Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Sun Apr 16 11:26:49 2017 +0300 feat(platform): add dir change event emitter commit 90de5d1105f6554ad759f280d2ed96ff6b3ef28a Author: Amit Moryossef <amitmoryossef@gmail.com> Date: Sat Apr 15 20:13:09 2017 +0300 fix(menu): add gesture side real-time update migrated to Renderer2
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
import { Animation } from '../../animations/animation';
|
||||
|
||||
export type Side = 'left' | 'right' | 'start' | 'end';
|
||||
|
||||
export interface Menu {
|
||||
setOpen(shouldOpen: boolean, animated: boolean): Promise<boolean>;
|
||||
open(): Promise<boolean>;
|
||||
@ -9,7 +11,7 @@ export interface Menu {
|
||||
swipeEnable(shouldEnable: boolean): Menu;
|
||||
isOpen: boolean;
|
||||
enabled: boolean;
|
||||
side: string;
|
||||
side: Side;
|
||||
id: string;
|
||||
isAnimating(): boolean;
|
||||
width(): number;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, forwardRef, Input, NgZone, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { OnInit, OnDestroy, ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, forwardRef, Input, NgZone, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { App } from '../app/app';
|
||||
import { Backdrop } from '../backdrop/backdrop';
|
||||
@ -9,7 +9,7 @@ import { GestureController, GESTURE_GO_BACK_SWIPE, BlockerDelegate } from '../..
|
||||
import { isTrueProperty, assert } from '../../util/util';
|
||||
import { Keyboard } from '../../platform/keyboard';
|
||||
import { MenuContentGesture } from './menu-gestures';
|
||||
import { Menu as MenuInterface } from '../app/menu-interface';
|
||||
import {Menu as MenuInterface, Side} from '../app/menu-interface';
|
||||
import { MenuController } from '../app/menu-controller';
|
||||
import { MenuType } from './menu-types';
|
||||
import { Nav } from '../nav/nav';
|
||||
@ -193,7 +193,7 @@ import { RootNode } from '../split-pane/split-pane';
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
providers: [{provide: RootNode, useExisting: forwardRef(() => Menu) }]
|
||||
})
|
||||
export class Menu implements RootNode, MenuInterface {
|
||||
export class Menu implements RootNode, MenuInterface, OnInit, OnDestroy {
|
||||
|
||||
private _cntEle: HTMLElement;
|
||||
private _gesture: MenuContentGesture;
|
||||
@ -206,6 +206,7 @@ export class Menu implements RootNode, MenuInterface {
|
||||
private _events: UIEventManager;
|
||||
private _gestureBlocker: BlockerDelegate;
|
||||
private _isPane: boolean = false;
|
||||
private _side: Side = 'start';
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
@ -237,11 +238,6 @@ export class Menu implements RootNode, MenuInterface {
|
||||
*/
|
||||
@Input() id: string;
|
||||
|
||||
/**
|
||||
* @input {string} Which side of the view the menu should be placed. Default `"left"`.
|
||||
*/
|
||||
@Input() side: string;
|
||||
|
||||
/**
|
||||
* @input {string} The display type of the menu. Default varies based on the mode,
|
||||
* see the `menuType` in the [config](../../config/Config). Available options:
|
||||
@ -262,6 +258,24 @@ export class Menu implements RootNode, MenuInterface {
|
||||
this.enable(isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @input {string} Which side of the view the menu should be placed. Default `"left"`.
|
||||
*/
|
||||
@Input()
|
||||
get side() {
|
||||
if (this._side === 'right' || (this._side === 'start' && this._plt.isRTL()) || (this._side === 'end' && !this._plt.isRTL())) {
|
||||
return 'right';
|
||||
}
|
||||
return 'left';
|
||||
}
|
||||
|
||||
set side(val: Side) {
|
||||
this._side = val;
|
||||
// Update gesture edge
|
||||
if (this._gesture)
|
||||
this._gesture.setEdges(this.side);
|
||||
}
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, swiping the menu is enabled. Default `true`.
|
||||
*/
|
||||
@ -339,11 +353,7 @@ export class Menu implements RootNode, MenuInterface {
|
||||
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>');
|
||||
}
|
||||
|
||||
// normalize the "side"
|
||||
if (this.side !== 'left' && this.side !== 'right') {
|
||||
this.side = 'left';
|
||||
}
|
||||
this.setElementAttribute('side', this.side);
|
||||
this.setElementAttribute('side', this._side);
|
||||
|
||||
// normalize the "type"
|
||||
if (!this.type) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { MenuController } from '../../app/menu-controller';
|
||||
import { mockMenu } from '../../../util/mock-providers';
|
||||
|
||||
import {mockMenu, mockPlatform} from '../../../util/mock-providers';
|
||||
import {Side} from '../../app/menu-interface';
|
||||
|
||||
describe('MenuController', () => {
|
||||
|
||||
@ -116,6 +116,30 @@ describe('MenuController', () => {
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the only left menu on start ltr', () => {
|
||||
let someMenu = mockMenu();
|
||||
someMenu.side = 'start';
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
let menu = menuCtrl.get('left');
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the only left menu on end rtl', () => {
|
||||
let platform = mockPlatform();
|
||||
platform.setDir('rtl', true);
|
||||
expect(platform.dir()).toEqual('rtl');
|
||||
|
||||
let someMenu = mockMenu(platform);
|
||||
someMenu.side = 'end';
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
expect(someMenu.side).toEqual('left');
|
||||
|
||||
let menu = menuCtrl.get('left');
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the enabled left menu', () => {
|
||||
let someMenu1 = mockMenu();
|
||||
someMenu1.side = 'left';
|
||||
@ -155,6 +179,30 @@ describe('MenuController', () => {
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the only right menu on end ltr', () => {
|
||||
let someMenu = mockMenu();
|
||||
someMenu.side = 'end';
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
let menu = menuCtrl.get('right');
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the only right menu on start rtl', () => {
|
||||
let platform = mockPlatform();
|
||||
platform.setDir('rtl', true);
|
||||
expect(platform.dir()).toEqual('rtl');
|
||||
|
||||
let someMenu = mockMenu(platform);
|
||||
someMenu.side = 'start';
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
expect(someMenu.side).toEqual('right');
|
||||
|
||||
let menu = menuCtrl.get('right');
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should get the menu by left with id', () => {
|
||||
let someMenu = mockMenu();
|
||||
someMenu.id = 'myMenu';
|
||||
@ -165,6 +213,40 @@ describe('MenuController', () => {
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
|
||||
it('should switch menu side in runtime', () => {
|
||||
let someMenu = mockMenu();
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
['left', 'right'].forEach((side: Side) => {
|
||||
someMenu.side = side;
|
||||
expect(someMenu.side).toEqual(side);
|
||||
|
||||
let menu = menuCtrl.get(side);
|
||||
expect(menu).toEqual(someMenu);
|
||||
});
|
||||
});
|
||||
|
||||
it('should switch menu side in runtime by direction', () => {
|
||||
let platform = mockPlatform();
|
||||
platform.setDir('ltr', true);
|
||||
expect(platform.dir()).toEqual('ltr');
|
||||
|
||||
let someMenu = mockMenu(platform);
|
||||
menuCtrl._register(someMenu);
|
||||
|
||||
expect(someMenu.side).toEqual('left');
|
||||
|
||||
let menu = menuCtrl.get('left');
|
||||
expect(menu).toEqual(someMenu);
|
||||
|
||||
platform.setDir('rtl', true);
|
||||
|
||||
expect(someMenu.side).toEqual('right');
|
||||
|
||||
let menu2 = menuCtrl.get('right');
|
||||
expect(menu2).toEqual(someMenu);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('enable()', () => {
|
||||
|
@ -18,10 +18,14 @@ export class SlideEdgeGesture extends SlideGesture {
|
||||
});
|
||||
super(plt, element, opts);
|
||||
// Can check corners through use of eg 'left top'
|
||||
this.edges = opts.edge.split(' ');
|
||||
this.setEdges(opts.edge);
|
||||
this.maxEdgeStart = opts.maxEdgeStart;
|
||||
}
|
||||
|
||||
setEdges(edges: string) {
|
||||
this.edges = edges.split(' ');
|
||||
}
|
||||
|
||||
canStart(ev: any): boolean {
|
||||
let coord = pointerCoord(ev);
|
||||
this._d = this.getContainerDimensions();
|
||||
|
@ -30,6 +30,14 @@ export class SwipeBackGesture extends SlideEdgeGesture {
|
||||
disableScroll: true
|
||||
})
|
||||
});
|
||||
|
||||
this.setSide(plt.dir());
|
||||
|
||||
Platform.dirChanged.subscribe(this.setSide.bind(this));
|
||||
}
|
||||
|
||||
private setSide(dir: string) {
|
||||
this.setEdges(dir === 'ltr' ? 'left' : 'right');
|
||||
}
|
||||
|
||||
canStart(ev: any): boolean {
|
||||
|
@ -50,6 +50,8 @@ export class Platform {
|
||||
private _isPortrait: boolean = null;
|
||||
private _uiEvtOpts = false;
|
||||
|
||||
static dirChanged: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
/** @hidden */
|
||||
zone: NgZone;
|
||||
|
||||
@ -313,9 +315,12 @@ export class Platform {
|
||||
* direction needs to be dynamically changed per user/session.
|
||||
* [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir)
|
||||
* @param {string} dir Examples: `rtl`, `ltr`
|
||||
* @param {boolean} updateDocument
|
||||
*/
|
||||
setDir(dir: string, updateDocument: boolean) {
|
||||
this._dir = (dir || '').toLowerCase();
|
||||
Platform.dirChanged.emit(this._dir);
|
||||
|
||||
if (updateDocument !== false) {
|
||||
this._doc['documentElement'].setAttribute('dir', dir);
|
||||
}
|
||||
|
@ -543,13 +543,14 @@ export function mockTabs(app?: App): Tabs {
|
||||
return new Tabs(null, null, app, config, elementRef, platform, renderer, linker);
|
||||
}
|
||||
|
||||
export function mockMenu(): Menu {
|
||||
export function mockMenu(platform: MockPlatform = null): Menu {
|
||||
let app = mockApp();
|
||||
let gestureCtrl = new GestureController(app);
|
||||
let dom = mockDomController();
|
||||
let elementRef = mockElementRef();
|
||||
let renderer = mockRenderer();
|
||||
return new Menu(null, elementRef, null, null, renderer, null, null, gestureCtrl, dom, app);
|
||||
let plt = platform === null ? mockPlatform() : platform;
|
||||
return new Menu(null, elementRef, null, plt, renderer, null, null, gestureCtrl, dom, app);
|
||||
}
|
||||
|
||||
export function mockDeepLinkConfig(links?: any[]): DeepLinkConfig {
|
||||
|
Reference in New Issue
Block a user