mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 14:01:20 +08:00
fix(gestures): gesture controller handled by components
* fix(gestures): gesture controller is handled by components fixes #9046 * fix(gestures): adds hybrid disable scroll assistance fixes #9130 fixes #9052 fixes #7444
This commit is contained in:

committed by
Adam Bradley

parent
339857af1e
commit
32ab817181
@ -5,7 +5,8 @@ import { Form } from '../../util/form';
|
||||
import { Key } from '../../util/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { assert } from '../../util/util';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -53,15 +54,18 @@ export class ActionSheetCmp {
|
||||
hdrId: string;
|
||||
id: number;
|
||||
mode: string;
|
||||
gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(
|
||||
private _viewCtrl: ViewController,
|
||||
private _config: Config,
|
||||
private _elementRef: ElementRef,
|
||||
private _form: Form,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
renderer: Renderer
|
||||
) {
|
||||
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = params.data;
|
||||
this.mode = _config.get('mode');
|
||||
renderer.setElementClass(_elementRef.nativeElement, `action-sheet-${this.mode}`, true);
|
||||
@ -110,6 +114,14 @@ export class ActionSheetCmp {
|
||||
this.d.buttons = buttons;
|
||||
}
|
||||
|
||||
ionViewWillEnter() {
|
||||
this.gestureBlocker.block();
|
||||
}
|
||||
|
||||
ionViewDidLeave() {
|
||||
this.gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
this._form.focusOut();
|
||||
|
||||
@ -166,6 +178,11 @@ export class ActionSheetCmp {
|
||||
dismiss(role: any): Promise<any> {
|
||||
return this._viewCtrl.dismiss(null, role);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this.gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this.gestureBlocker.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
let actionSheetIds = -1;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { isPresent } from '../../util/util';
|
||||
import { isPresent, assert } from '../../util/util';
|
||||
import { Key } from '../../util/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -86,14 +86,18 @@ export class AlertCmp {
|
||||
msgId: string;
|
||||
subHdrId: string;
|
||||
mode: string;
|
||||
gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(
|
||||
public _viewCtrl: ViewController,
|
||||
public _elementRef: ElementRef,
|
||||
public _config: Config,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
renderer: Renderer
|
||||
) {
|
||||
// gesture blocker is used to disable gestures dynamically
|
||||
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = params.data;
|
||||
this.mode = _config.get('mode');
|
||||
renderer.setElementClass(_elementRef.nativeElement, `alert-${this.mode}`, true);
|
||||
@ -172,6 +176,27 @@ export class AlertCmp {
|
||||
}
|
||||
}
|
||||
|
||||
ionViewWillEnter() {
|
||||
this.gestureBlocker.block();
|
||||
}
|
||||
|
||||
ionViewDidLeave() {
|
||||
this.gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
let activeElement: any = document.activeElement;
|
||||
if (document.activeElement) {
|
||||
activeElement.blur();
|
||||
}
|
||||
|
||||
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
|
||||
if (focusableEle) {
|
||||
focusableEle.focus();
|
||||
}
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@HostListener('body:keyup', ['$event'])
|
||||
keyUp(ev: KeyboardEvent) {
|
||||
if (this.enabled && this._viewCtrl.isLast()) {
|
||||
@ -193,19 +218,6 @@ export class AlertCmp {
|
||||
}
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
let activeElement: any = document.activeElement;
|
||||
if (document.activeElement) {
|
||||
activeElement.blur();
|
||||
}
|
||||
|
||||
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
|
||||
if (focusableEle) {
|
||||
focusableEle.focus();
|
||||
}
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
btnClick(button: any, dismissDelay?: number) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
@ -293,6 +305,11 @@ export class AlertCmp {
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this.gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this.gestureBlocker.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
let alertIds = -1;
|
||||
|
@ -5,6 +5,7 @@ import { Config } from '../../config/config';
|
||||
import { Ion } from '../ion';
|
||||
import { OverlayPortal } from '../nav/overlay-portal';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { nativeTimeout } from '../../util/dom';
|
||||
|
||||
export const AppRootToken = new OpaqueToken('USERROOT');
|
||||
|
||||
@ -23,6 +24,8 @@ export const AppRootToken = new OpaqueToken('USERROOT');
|
||||
})
|
||||
export class IonicApp extends Ion implements OnInit {
|
||||
|
||||
private _stopScrollPlugin: any;
|
||||
private _rafId: number;
|
||||
@ViewChild('viewport', {read: ViewContainerRef}) _viewport: ViewContainerRef;
|
||||
|
||||
@ViewChild('modalPortal', { read: OverlayPortal }) _modalPortal: OverlayPortal;
|
||||
@ -45,6 +48,7 @@ export class IonicApp extends Ion implements OnInit {
|
||||
super(config, elementRef, renderer);
|
||||
// register with App that this is Ionic's appRoot component. tada!
|
||||
app._appRoot = this;
|
||||
this._stopScrollPlugin = window['IonicStopScroll'];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -109,7 +113,26 @@ export class IonicApp extends Ion implements OnInit {
|
||||
* @private
|
||||
*/
|
||||
_disableScroll(shouldDisableScroll: boolean) {
|
||||
this.setElementClass('disable-scroll', shouldDisableScroll);
|
||||
console.log('App Root: Scroll Disable Assist', shouldDisableScroll);
|
||||
|
||||
if (shouldDisableScroll) {
|
||||
this.stopScroll().then(() => {
|
||||
this._rafId = nativeTimeout(() => this.setElementClass('disable-scroll', true), 16 * 2);
|
||||
});
|
||||
} else {
|
||||
cancelAnimationFrame(this._rafId);
|
||||
this.setElementClass('disable-scroll', false);
|
||||
}
|
||||
}
|
||||
|
||||
stopScroll(): Promise<boolean> {
|
||||
if (this._stopScrollPlugin) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._stopScrollPlugin.stop(() => resolve(true));
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export class App {
|
||||
private _title: string = '';
|
||||
private _titleSrv: Title = new Title();
|
||||
private _rootNav: NavController = null;
|
||||
private _canDisableScroll: boolean;
|
||||
private _disableScrollAssist: boolean;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -71,7 +71,7 @@ export class App {
|
||||
// listen for hardware back button events
|
||||
// register this back button action with a default priority
|
||||
_platform.registerBackButtonAction(this.navPop.bind(this));
|
||||
this._canDisableScroll = _config.get('canDisableScroll', false);
|
||||
this._disableScrollAssist = _config.getBoolean('disableScrollAssist', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,7 +124,7 @@ export class App {
|
||||
* scrolling is enabled. When set to `true`, scrolling is disabled.
|
||||
*/
|
||||
setScrollDisabled(disableScroll: boolean) {
|
||||
if (this._canDisableScroll) {
|
||||
if (this._disableScrollAssist) {
|
||||
this._appRoot._disableScroll(disableScroll);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,3 @@ ion-backdrop {
|
||||
opacity: .01;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
ion-backdrop.hide-backdrop {
|
||||
display: none;
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
import { Directive, ElementRef, Input, Renderer } from '@angular/core';
|
||||
|
||||
import { GestureController } from '../../gestures/gesture-controller';
|
||||
import { isTrueProperty } from '../../util/util';
|
||||
|
||||
import { Directive, ElementRef, Renderer } from '@angular/core';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -16,26 +12,11 @@ import { isTrueProperty } from '../../util/util';
|
||||
},
|
||||
})
|
||||
export class Backdrop {
|
||||
private _gestureID: number = null;
|
||||
@Input() disableScroll = true;
|
||||
|
||||
constructor(
|
||||
private _gestureCtrl: GestureController,
|
||||
private _elementRef: ElementRef,
|
||||
private _renderer: Renderer) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (isTrueProperty(this.disableScroll)) {
|
||||
this._gestureID = this._gestureCtrl.newID();
|
||||
this._gestureCtrl.disableScroll(this._gestureID);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this._gestureID) {
|
||||
this._gestureCtrl.enableScroll(this._gestureID);
|
||||
}
|
||||
}
|
||||
private _renderer: Renderer
|
||||
) { }
|
||||
|
||||
getNativeElement(): HTMLElement {
|
||||
return this._elementRef.nativeElement;
|
||||
|
@ -51,7 +51,7 @@ ion-content.js-scroll > .scroll-content {
|
||||
will-change: initial;
|
||||
}
|
||||
|
||||
.disable-scroll .ion-page .scroll-content {
|
||||
.disable-scroll .ion-page {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { ItemSliding } from './item-sliding';
|
||||
import { List } from '../list/list';
|
||||
|
||||
import { GesturePriority } from '../../gestures/gesture-controller';
|
||||
import { GestureController, GesturePriority, GESTURE_ITEM_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { PanGesture } from '../../gestures/drag-gesture';
|
||||
import { pointerCoord } from '../../util/dom';
|
||||
import { NativeRafDebouncer } from '../../util/debouncer';
|
||||
|
||||
const DRAG_THRESHOLD = 10;
|
||||
const MAX_ATTACK_ANGLE = 20;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export class ItemSlidingGesture extends PanGesture {
|
||||
|
||||
private preSelectedContainer: ItemSliding = null;
|
||||
@ -17,14 +17,16 @@ export class ItemSlidingGesture extends PanGesture {
|
||||
private firstCoordX: number;
|
||||
private firstTimestamp: number;
|
||||
|
||||
constructor(public list: List) {
|
||||
constructor(public list: List, gestureCtrl: GestureController) {
|
||||
super(list.getNativeElement(), {
|
||||
maxAngle: MAX_ATTACK_ANGLE,
|
||||
threshold: DRAG_THRESHOLD,
|
||||
maxAngle: 20,
|
||||
threshold: 10,
|
||||
zone: false,
|
||||
debouncer: new NativeRafDebouncer(),
|
||||
gesture: list._gestureCtrl.create('item-sliding', {
|
||||
gesture: gestureCtrl.createGesture({
|
||||
name: GESTURE_ITEM_SWIPE,
|
||||
priority: GesturePriority.SlidingItem,
|
||||
disableScroll: false // TODO: set true
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ export class List extends Ion {
|
||||
|
||||
} else if (!this._slidingGesture) {
|
||||
console.debug('enableSlidingItems');
|
||||
this._slidingGesture = new ItemSlidingGesture(this);
|
||||
this._slidingGesture = new ItemSlidingGesture(this, this._gestureCtrl);
|
||||
this._slidingGesture.listen();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Component, ElementRef, Renderer, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { Config } from '../../config/config';
|
||||
import { isDefined, isUndefined } from '../../util/util';
|
||||
import { isDefined, isUndefined, assert } from '../../util/util';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
import { LoadingOptions } from './loading-options';
|
||||
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -12,7 +13,7 @@ import { LoadingOptions } from './loading-options';
|
||||
@Component({
|
||||
selector: 'ion-loading',
|
||||
template:
|
||||
'<ion-backdrop [class.hide-backdrop]="!d.showBackdrop"></ion-backdrop>' +
|
||||
'<ion-backdrop [hidden]="!d.showBackdrop"></ion-backdrop>' +
|
||||
'<div class="loading-wrapper">' +
|
||||
'<div *ngIf="showSpinner" class="loading-spinner">' +
|
||||
'<ion-spinner [name]="d.spinner"></ion-spinner>' +
|
||||
@ -29,14 +30,17 @@ export class LoadingCmp {
|
||||
id: number;
|
||||
showSpinner: boolean;
|
||||
durationTimeout: number;
|
||||
gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(
|
||||
private _viewCtrl: ViewController,
|
||||
private _config: Config,
|
||||
private _elementRef: ElementRef,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
renderer: Renderer
|
||||
) {
|
||||
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = params.data;
|
||||
|
||||
renderer.setElementClass(_elementRef.nativeElement, `loading-${_config.get('mode')}`, true);
|
||||
@ -62,17 +66,21 @@ export class LoadingCmp {
|
||||
this.showSpinner = isDefined(this.d.spinner) && this.d.spinner !== 'hide';
|
||||
}
|
||||
|
||||
ionViewWillEnter() {
|
||||
this.gestureBlocker.block();
|
||||
}
|
||||
|
||||
ionViewDidLeave() {
|
||||
this.gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
ionViewDidEnter() {
|
||||
let activeElement: any = document.activeElement;
|
||||
if (document.activeElement) {
|
||||
activeElement.blur();
|
||||
}
|
||||
activeElement && activeElement.blur();
|
||||
|
||||
// If there is a duration, dismiss after that amount of time
|
||||
if ( this.d && this.d.duration ) {
|
||||
this.durationTimeout = (<any> setTimeout( () => {
|
||||
this.dismiss('backdrop');
|
||||
}, this.d.duration));
|
||||
this.durationTimeout = setTimeout(() => this.dismiss('backdrop'), this.d.duration);
|
||||
}
|
||||
|
||||
}
|
||||
@ -83,6 +91,11 @@ export class LoadingCmp {
|
||||
}
|
||||
return this._viewCtrl.dismiss(null, role);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this.gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this.gestureBlocker.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
let loadingIds = -1;
|
||||
|
@ -2,7 +2,7 @@ import { Menu } from './menu';
|
||||
import { SlideEdgeGesture } from '../../gestures/slide-edge-gesture';
|
||||
import { SlideData } from '../../gestures/slide-gesture';
|
||||
import { assign } from '../../util/util';
|
||||
import { GestureController, GesturePriority } from '../../gestures/gesture-controller';
|
||||
import { GestureController, GesturePriority, GESTURE_MENU_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { NativeRafDebouncer } from '../../util/debouncer';
|
||||
|
||||
/**
|
||||
@ -14,17 +14,19 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
public menu: Menu,
|
||||
contentEle: HTMLElement,
|
||||
gestureCtrl: GestureController,
|
||||
options: any = {}) {
|
||||
options: any = {}
|
||||
) {
|
||||
super(contentEle, assign({
|
||||
direction: 'x',
|
||||
edge: menu.side,
|
||||
threshold: 0,
|
||||
maxEdgeStart: menu.maxEdgeStart || 50,
|
||||
maxAngle: 40,
|
||||
zone: false,
|
||||
debouncer: new NativeRafDebouncer(),
|
||||
gesture: gestureCtrl.create('menu-swipe', {
|
||||
gesture: gestureCtrl.createGesture({
|
||||
name: GESTURE_MENU_SWIPE,
|
||||
priority: GesturePriority.MenuSwipe,
|
||||
disableScroll: true
|
||||
})
|
||||
}, options));
|
||||
}
|
||||
@ -52,13 +54,6 @@ export class MenuContentGesture extends SlideEdgeGesture {
|
||||
let z = (this.menu.side === 'right' ? slide.min : slide.max);
|
||||
let stepValue = (slide.distance / z);
|
||||
|
||||
console.debug('menu gesture, onSlide', this.menu.side,
|
||||
'distance', slide.distance,
|
||||
'min', slide.min,
|
||||
'max', slide.max,
|
||||
'z', z,
|
||||
'stepValue', stepValue);
|
||||
|
||||
this.menu.swipeProgress(stepValue);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { MenuContentGesture } from './menu-gestures';
|
||||
import { MenuController } from './menu-controller';
|
||||
import { MenuType } from './menu-types';
|
||||
import { Platform } from '../../platform/platform';
|
||||
import { GestureController } from '../../gestures/gesture-controller';
|
||||
import { BlockerDelegate, GestureController, GESTURE_GO_BACK_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { UIEventManager } from '../../util/ui-event-manager';
|
||||
import { Content } from '../content/content';
|
||||
|
||||
@ -181,7 +181,7 @@ import { Content } from '../content/content';
|
||||
selector: 'ion-menu',
|
||||
template:
|
||||
'<div class="menu-inner"><ng-content></ng-content></div>' +
|
||||
'<ion-backdrop disableScroll="false"></ion-backdrop>',
|
||||
'<ion-backdrop></ion-backdrop>',
|
||||
host: {
|
||||
'role': 'navigation'
|
||||
},
|
||||
@ -198,7 +198,7 @@ export class Menu {
|
||||
private _isPers: boolean = false;
|
||||
private _init: boolean = false;
|
||||
private _events: UIEventManager = new UIEventManager();
|
||||
private _gestureID: number = 0;
|
||||
private _gestureBlocker: BlockerDelegate;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -305,9 +305,9 @@ export class Menu {
|
||||
private _zone: NgZone,
|
||||
private _gestureCtrl: GestureController
|
||||
) {
|
||||
if (_gestureCtrl) {
|
||||
this._gestureID = _gestureCtrl.newID();
|
||||
}
|
||||
this._gestureBlocker = _gestureCtrl.createBlocker({
|
||||
disable: [GESTURE_GO_BACK_SWIPE]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -503,7 +503,7 @@ export class Menu {
|
||||
this._events.unlistenAll();
|
||||
if (isOpen) {
|
||||
// Disable swipe to go back gesture
|
||||
this._gestureCtrl.disableGesture('goback-swipe', this._gestureID);
|
||||
this._gestureBlocker.block();
|
||||
|
||||
this._cntEle.classList.add('menu-content-open');
|
||||
let callback = this.onBackdropClick.bind(this);
|
||||
@ -519,7 +519,7 @@ export class Menu {
|
||||
|
||||
} else {
|
||||
// Enable swipe to go back gesture
|
||||
this._gestureCtrl.enableGesture('goback-swipe', this._gestureID);
|
||||
this._gestureBlocker.unblock();
|
||||
|
||||
this._cntEle.classList.remove('menu-content-open');
|
||||
this.setElementClass('show-menu', false);
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { Component, ViewChild, NgModule } from '@angular/core';
|
||||
import { IonicApp, IonicModule, MenuController, NavController, AlertController, Nav } from '../../../..';
|
||||
import { AlertController, IonicApp, IonicModule, MenuController, ModalController, NavController, Nav, ViewController } from '../../../..';
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: 'page1.html'
|
||||
})
|
||||
export class Page1 {
|
||||
constructor(public navCtrl: NavController, public alertCtrl: AlertController) {}
|
||||
constructor(
|
||||
public navCtrl: NavController,
|
||||
public alertCtrl: AlertController,
|
||||
public modalCtrl: ModalController
|
||||
) { }
|
||||
|
||||
presentAlert() {
|
||||
let alert = this.alertCtrl.create({
|
||||
@ -18,11 +22,24 @@ export class Page1 {
|
||||
alert.present();
|
||||
}
|
||||
|
||||
presentModal() {
|
||||
let modal = this.modalCtrl.create(Modal);
|
||||
modal.present();
|
||||
}
|
||||
|
||||
goToPage2() {
|
||||
this.navCtrl.push(Page2);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({templateUrl: 'modal.html'})
|
||||
export class Modal {
|
||||
constructor(public viewController: ViewController) {}
|
||||
close() {
|
||||
this.viewController.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({templateUrl: 'page3.html'})
|
||||
export class Page3 {}
|
||||
@ -106,7 +123,8 @@ export class E2EApp {
|
||||
E2EPage,
|
||||
Page1,
|
||||
Page2,
|
||||
Page3
|
||||
Page3,
|
||||
Modal
|
||||
],
|
||||
imports: [
|
||||
IonicModule.forRoot(E2EApp)
|
||||
@ -117,7 +135,8 @@ export class E2EApp {
|
||||
E2EPage,
|
||||
Page1,
|
||||
Page2,
|
||||
Page3
|
||||
Page3,
|
||||
Modal
|
||||
]
|
||||
})
|
||||
export class AppModule {}
|
||||
|
20
src/components/menu/test/basic/modal.html
Normal file
20
src/components/menu/test/basic/modal.html
Normal file
@ -0,0 +1,20 @@
|
||||
<ion-header>
|
||||
|
||||
<ion-navbar>
|
||||
<ion-title>
|
||||
MODAL
|
||||
</ion-title>
|
||||
</ion-navbar>
|
||||
|
||||
</ion-header>
|
||||
|
||||
|
||||
<ion-content padding>
|
||||
|
||||
<p>
|
||||
<button ion-button (click)="close()">Close</button>
|
||||
</p>
|
||||
|
||||
<div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div>
|
||||
|
||||
</ion-content>
|
@ -64,6 +64,10 @@
|
||||
<button ion-button (click)="presentAlert()">Open alert</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button ion-button (click)="presentModal()">Open modal</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button ion-button (click)="goToPage2()">Go to Page 2</button>
|
||||
</p>
|
||||
|
@ -3,7 +3,8 @@ import { Component, ComponentFactoryResolver, HostListener, Renderer, ViewChild,
|
||||
import { Key } from '../../util/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
import { GestureController, BlockerDelegate, GESTURE_MENU_SWIPE, GESTURE_GO_BACK_SWIPE } from '../../gestures/gesture-controller';
|
||||
import { assert } from '../../util/util';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -11,7 +12,7 @@ import { ViewController } from '../../navigation/view-controller';
|
||||
@Component({
|
||||
selector: 'ion-modal',
|
||||
template:
|
||||
'<ion-backdrop disableScroll="false" (click)="_bdClick()"></ion-backdrop>' +
|
||||
'<ion-backdrop (click)="_bdClick()"></ion-backdrop>' +
|
||||
'<div class="modal-wrapper">' +
|
||||
'<div #viewport nav-viewport></div>' +
|
||||
'</div>'
|
||||
@ -20,13 +21,20 @@ export class ModalCmp {
|
||||
|
||||
@ViewChild('viewport', { read: ViewContainerRef }) _viewport: ViewContainerRef;
|
||||
|
||||
/** @private */
|
||||
_bdDismiss: boolean;
|
||||
|
||||
/** @private */
|
||||
_enabled: boolean;
|
||||
_gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(public _cfr: ComponentFactoryResolver, public _renderer: Renderer, public _navParams: NavParams, public _viewCtrl: ViewController) {
|
||||
constructor(
|
||||
public _cfr: ComponentFactoryResolver,
|
||||
public _renderer: Renderer,
|
||||
public _navParams: NavParams,
|
||||
public _viewCtrl: ViewController,
|
||||
gestureCtrl: GestureController
|
||||
) {
|
||||
this._gestureBlocker = gestureCtrl.createBlocker({
|
||||
disable: [GESTURE_MENU_SWIPE, GESTURE_GO_BACK_SWIPE]
|
||||
});
|
||||
this._bdDismiss = _navParams.data.opts.enableBackdropDismiss;
|
||||
}
|
||||
|
||||
@ -46,9 +54,20 @@ export class ModalCmp {
|
||||
this._setCssClass(componentRef, 'ion-page');
|
||||
this._setCssClass(componentRef, 'show-page');
|
||||
this._enabled = true;
|
||||
|
||||
this._viewCtrl.willEnter.subscribe(this._viewWillEnter.bind(this));
|
||||
this._viewCtrl.didLeave.subscribe(this._viewDidLeave.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
_viewWillEnter() {
|
||||
this._gestureBlocker.block();
|
||||
}
|
||||
|
||||
_viewDidLeave() {
|
||||
this._gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
/** @private */
|
||||
_setCssClass(componentRef: any, className: string) {
|
||||
this._renderer.setElementClass(componentRef.location.nativeElement, className, true);
|
||||
@ -66,4 +85,9 @@ export class ModalCmp {
|
||||
this._bdClick();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this._gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this._gestureBlocker.destroy();
|
||||
}
|
||||
}
|
||||
|
@ -834,7 +834,9 @@ export const deepLinkConfig: DeepLinkConfig = {
|
||||
TabItemPage
|
||||
],
|
||||
imports: [
|
||||
IonicModule.forRoot(E2EApp, null, deepLinkConfig)
|
||||
IonicModule.forRoot(E2EApp, {
|
||||
swipeBackEnabled: true
|
||||
}, deepLinkConfig)
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
entryComponents: [
|
||||
|
@ -2,7 +2,7 @@ import { Component, ElementRef, EventEmitter, Input, HostListener, NgZone, Outpu
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
|
||||
import { CSS, cancelRaf, pointerCoord, nativeRaf } from '../../util/dom';
|
||||
import { clamp, isNumber, isPresent, isString } from '../../util/util';
|
||||
import { clamp, isNumber, isPresent, isString, assert } from '../../util/util';
|
||||
import { Config } from '../../config/config';
|
||||
import { Key } from '../../util/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
@ -12,6 +12,7 @@ import { Haptic } from '../../util/haptic';
|
||||
import { UIEventManager } from '../../util/ui-event-manager';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
import { Debouncer, NativeRafDebouncer } from '../../util/debouncer';
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -454,14 +455,17 @@ export class PickerCmp {
|
||||
lastClick: number;
|
||||
id: number;
|
||||
mode: string;
|
||||
_gestureBlocker: BlockerDelegate;
|
||||
|
||||
constructor(
|
||||
private _viewCtrl: ViewController,
|
||||
private _elementRef: ElementRef,
|
||||
private _config: Config,
|
||||
gestureCtrl: GestureController,
|
||||
params: NavParams,
|
||||
renderer: Renderer
|
||||
) {
|
||||
this._gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = params.data;
|
||||
this.mode = _config.get('mode');
|
||||
renderer.setElementClass(_elementRef.nativeElement, `picker-${this.mode}`, true);
|
||||
@ -523,6 +527,14 @@ export class PickerCmp {
|
||||
});
|
||||
}
|
||||
|
||||
ionViewWillEnter() {
|
||||
this._gestureBlocker.block();
|
||||
}
|
||||
|
||||
ionViewDidLeave() {
|
||||
this._gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this._cols.forEach(column => {
|
||||
column.refresh();
|
||||
@ -617,6 +629,12 @@ export class PickerCmp {
|
||||
});
|
||||
return selected;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this._gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this._gestureBlocker.destroy();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let pickerIds = -1;
|
||||
|
@ -4,7 +4,8 @@ import { Config } from '../../config/config';
|
||||
import { Key } from '../../util/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { assert } from '../../util/util';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -12,7 +13,7 @@ import { ViewController } from '../../navigation/view-controller';
|
||||
@Component({
|
||||
selector: 'ion-popover',
|
||||
template:
|
||||
'<ion-backdrop (click)="_bdClick()" [class.hide-backdrop]="!d.showBackdrop"></ion-backdrop>' +
|
||||
'<ion-backdrop (click)="_bdClick()" [hidden]="!d.showBackdrop"></ion-backdrop>' +
|
||||
'<div class="popover-wrapper">' +
|
||||
'<div class="popover-arrow"></div>' +
|
||||
'<div class="popover-content">' +
|
||||
@ -32,10 +33,9 @@ export class PopoverCmp {
|
||||
enableBackdropDismiss?: boolean;
|
||||
};
|
||||
|
||||
/** @private */
|
||||
_enabled: boolean;
|
||||
_gestureBlocker: BlockerDelegate;
|
||||
|
||||
/** @private */
|
||||
id: number;
|
||||
|
||||
constructor(
|
||||
@ -44,8 +44,10 @@ export class PopoverCmp {
|
||||
public _renderer: Renderer,
|
||||
public _config: Config,
|
||||
public _navParams: NavParams,
|
||||
public _viewCtrl: ViewController
|
||||
public _viewCtrl: ViewController,
|
||||
gestureCtrl: GestureController,
|
||||
) {
|
||||
this._gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
|
||||
this.d = _navParams.data.opts;
|
||||
|
||||
_renderer.setElementClass(_elementRef.nativeElement, `popover-${_config.get('mode')}`, true);
|
||||
@ -62,13 +64,11 @@ export class PopoverCmp {
|
||||
|
||||
ionViewPreLoad() {
|
||||
let activeElement: any = document.activeElement;
|
||||
if (document.activeElement) {
|
||||
activeElement.blur();
|
||||
}
|
||||
activeElement && activeElement.blur();
|
||||
|
||||
this._load(this._navParams.data.component);
|
||||
}
|
||||
|
||||
/** @private */
|
||||
_load(component: any) {
|
||||
if (component) {
|
||||
const componentFactory = this._cfr.resolveComponentFactory(component);
|
||||
@ -76,12 +76,23 @@ export class PopoverCmp {
|
||||
// ******** DOM WRITE ****************
|
||||
const componentRef = this._viewport.createComponent(componentFactory, this._viewport.length, this._viewport.parentInjector, []);
|
||||
this._viewCtrl._setInstance(componentRef.instance);
|
||||
|
||||
this._enabled = true;
|
||||
|
||||
// Subscribe to events in order to block gestures
|
||||
// TODO, should we unsubscribe? memory leak?
|
||||
this._viewCtrl.willEnter.subscribe(this._viewWillEnter.bind(this));
|
||||
this._viewCtrl.didLeave.subscribe(this._viewDidLeave.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
/** @private */
|
||||
_viewWillEnter() {
|
||||
this._gestureBlocker.block();
|
||||
}
|
||||
|
||||
_viewDidLeave() {
|
||||
this._gestureBlocker.unblock();
|
||||
}
|
||||
|
||||
_setCssClass(componentRef: any, className: string) {
|
||||
this._renderer.setElementClass(componentRef.location.nativeElement, className, true);
|
||||
}
|
||||
@ -98,6 +109,11 @@ export class PopoverCmp {
|
||||
this._bdClick();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
assert(this._gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
|
||||
this._gestureBlocker.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
let popoverIds = -1;
|
||||
|
@ -2,7 +2,7 @@ import { Directive, EventEmitter, Host, Input, Output, NgZone } from '@angular/c
|
||||
|
||||
import { Content } from '../content/content';
|
||||
import { CSS, pointerCoord } from '../../util/dom';
|
||||
import { GestureController, GestureDelegate, GesturePriority } from '../../gestures/gesture-controller';
|
||||
import { GestureController, GestureDelegate, GesturePriority, GESTURE_REFRESHER } from '../../gestures/gesture-controller';
|
||||
import { isTrueProperty } from '../../util/util';
|
||||
import { PointerEvents, UIEventManager } from '../../util/ui-event-manager';
|
||||
|
||||
@ -200,7 +200,8 @@ export class Refresher {
|
||||
|
||||
constructor(@Host() private _content: Content, private _zone: NgZone, gestureCtrl: GestureController) {
|
||||
_content.setElementClass('has-refresher', true);
|
||||
this._gesture = gestureCtrl.create('refresher', {
|
||||
this._gesture = gestureCtrl.createGesture({
|
||||
name: GESTURE_REFRESHER,
|
||||
priority: GesturePriority.Refresher,
|
||||
});
|
||||
}
|
||||
|
@ -53,10 +53,10 @@
|
||||
|
||||
.back-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.show-back-button {
|
||||
display: inline-block;
|
||||
}
|
||||
.back-button.show-back-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.back-button-text {
|
||||
|
Reference in New Issue
Block a user