mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 05:58:26 +08:00
fix(gesture/tapclick): ios support
This commit is contained in:
31
packages/core/src/components.d.ts
vendored
31
packages/core/src/components.d.ts
vendored
@ -1000,6 +1000,36 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
GestureController as IonGestureController
|
||||||
|
} from './components/gesture-controller/gesture-controller';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLIonGestureControllerElement extends IonGestureController, HTMLStencilElement {
|
||||||
|
}
|
||||||
|
var HTMLIonGestureControllerElement: {
|
||||||
|
prototype: HTMLIonGestureControllerElement;
|
||||||
|
new (): HTMLIonGestureControllerElement;
|
||||||
|
};
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ion-gesture-controller": HTMLIonGestureControllerElement;
|
||||||
|
}
|
||||||
|
interface ElementTagNameMap {
|
||||||
|
"ion-gesture-controller": HTMLIonGestureControllerElement;
|
||||||
|
}
|
||||||
|
namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
"ion-gesture-controller": JSXElements.IonGestureControllerAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace JSXElements {
|
||||||
|
export interface IonGestureControllerAttributes extends HTMLAttributes {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Gesture as IonGesture
|
Gesture as IonGesture
|
||||||
} from './components/gesture/gesture';
|
} from './components/gesture/gesture';
|
||||||
@ -2660,7 +2690,6 @@ declare global {
|
|||||||
onionScroll?: ScrollCallback;
|
onionScroll?: ScrollCallback;
|
||||||
onionScrollEnd?: ScrollCallback;
|
onionScrollEnd?: ScrollCallback;
|
||||||
onionScrollStart?: ScrollCallback;
|
onionScrollStart?: ScrollCallback;
|
||||||
scrollEvents?: boolean;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
import { Component, Method, EventEmitter, Event } from "@stencil/core";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
tag: 'ion-gesture-controller'
|
||||||
|
})
|
||||||
export class GestureController {
|
export class GestureController {
|
||||||
|
|
||||||
private gestureId = 0;
|
private gestureId = 0;
|
||||||
@ -6,21 +12,21 @@ export class GestureController {
|
|||||||
private disabledScroll = new Set<number>();
|
private disabledScroll = new Set<number>();
|
||||||
private capturedId: number|null = null;
|
private capturedId: number|null = null;
|
||||||
|
|
||||||
createGesture(gestureName: string, gesturePriority: number, disableScroll: boolean): GestureDelegate {
|
@Event() ionGestureCaptured: EventEmitter<string>;
|
||||||
return new GestureDelegate(this, this.newID(), gestureName, gesturePriority, disableScroll);
|
|
||||||
|
@Method()
|
||||||
|
create(config: GestureConfig): Promise<GestureDelegate> {
|
||||||
|
return Promise.resolve(new GestureDelegate(this, this.newID(), config.name, config.priority, config.disableScroll));
|
||||||
}
|
}
|
||||||
|
|
||||||
createBlocker(opts: BlockerOptions = {}): BlockerDelegate {
|
@Method()
|
||||||
|
createBlocker(opts: BlockerConfig = {}): BlockerDelegate {
|
||||||
return new BlockerDelegate(this.newID(), this,
|
return new BlockerDelegate(this.newID(), this,
|
||||||
opts.disable,
|
opts.disable,
|
||||||
!!opts.disableScroll
|
!!opts.disableScroll
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
newID(): number {
|
|
||||||
return this.gestureId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
start(gestureName: string, id: number, priority: number): boolean {
|
start(gestureName: string, id: number, priority: number): boolean {
|
||||||
if (!this.canStart(gestureName)) {
|
if (!this.canStart(gestureName)) {
|
||||||
this.requestedStart.delete(id);
|
this.requestedStart.delete(id);
|
||||||
@ -43,6 +49,7 @@ export class GestureController {
|
|||||||
if (maxPriority === priority) {
|
if (maxPriority === priority) {
|
||||||
this.capturedId = id;
|
this.capturedId = id;
|
||||||
this.requestedStart.clear();
|
this.requestedStart.clear();
|
||||||
|
this.ionGestureCaptured.emit(gestureName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
requestedStart.delete(id);
|
requestedStart.delete(id);
|
||||||
@ -121,6 +128,9 @@ export class GestureController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private newID(): number {
|
||||||
|
return this.gestureId++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -180,14 +190,11 @@ export class GestureDelegate {
|
|||||||
this.release();
|
this.release();
|
||||||
this.ctrl = null;
|
this.ctrl = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class BlockerDelegate {
|
export class BlockerDelegate {
|
||||||
|
|
||||||
blocked = false;
|
|
||||||
|
|
||||||
private ctrl: GestureController|null;
|
private ctrl: GestureController|null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -212,7 +219,6 @@ export class BlockerDelegate {
|
|||||||
if (this.disableScroll) {
|
if (this.disableScroll) {
|
||||||
this.ctrl.disableScroll(this.blockerDelegateId);
|
this.ctrl.disableScroll(this.blockerDelegateId);
|
||||||
}
|
}
|
||||||
this.blocked = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unblock() {
|
unblock() {
|
||||||
@ -227,7 +233,6 @@ export class BlockerDelegate {
|
|||||||
if (this.disableScroll) {
|
if (this.disableScroll) {
|
||||||
this.ctrl.enableScroll(this.blockerDelegateId);
|
this.ctrl.enableScroll(this.blockerDelegateId);
|
||||||
}
|
}
|
||||||
this.blocked = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
@ -237,13 +242,20 @@ export class BlockerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface BlockerOptions {
|
export interface GestureConfig {
|
||||||
disableScroll?: boolean;
|
name: string;
|
||||||
disable?: string[];
|
priority: number;
|
||||||
|
disableScroll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const BLOCK_ALL: BlockerOptions = {
|
export interface BlockerConfig {
|
||||||
|
disable?: string[];
|
||||||
|
disableScroll?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const BLOCK_ALL: BlockerConfig = {
|
||||||
disable: ['menu-swipe', 'goback-swipe'],
|
disable: ['menu-swipe', 'goback-swipe'],
|
||||||
disableScroll: true
|
disableScroll: true
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,20 @@
|
|||||||
<!-- Auto Generated Below -->
|
<!-- Auto Generated Below -->
|
||||||
|
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
#### ionGestureCaptured
|
||||||
|
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
#### create()
|
||||||
|
|
||||||
|
|
||||||
|
#### createBlocker()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
*Built by [StencilJS](https://stenciljs.com/)*
|
*Built with [StencilJS](https://stenciljs.com/)*
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { Component, Element, Event, EventEmitter, EventListenerEnable, Listen, Prop, Watch } from '@stencil/core';
|
import { Component, Event, EventEmitter, EventListenerEnable, Listen, Prop, Watch } from '@stencil/core';
|
||||||
import { ElementRef, applyStyles, assert, getElementReference, now, updateDetail } from '../../utils/helpers';
|
import { ElementRef, assert, now, updateDetail } from '../../utils/helpers';
|
||||||
import { BLOCK_ALL, BlockerDelegate, GestureController, GestureDelegate } from '../gesture-controller/gesture-controller';
|
import { BlockerDelegate, GestureDelegate, BlockerConfig, BLOCK_ALL } from '../gesture-controller/gesture-controller';
|
||||||
import { DomController } from '../../index';
|
import { DomController } from '../../index';
|
||||||
import { PanRecognizer } from './recognizers';
|
import { PanRecognizer } from './recognizers';
|
||||||
|
|
||||||
declare const Ionic: { gesture: GestureController };
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
tag: 'ion-gesture'
|
tag: 'ion-gesture'
|
||||||
@ -14,7 +12,6 @@ export class Gesture {
|
|||||||
|
|
||||||
private detail: GestureDetail = {};
|
private detail: GestureDetail = {};
|
||||||
private positions: number[] = [];
|
private positions: number[] = [];
|
||||||
private ctrl: GestureController;
|
|
||||||
private gesture: GestureDelegate;
|
private gesture: GestureDelegate;
|
||||||
private lastTouch = 0;
|
private lastTouch = 0;
|
||||||
private pan: PanRecognizer;
|
private pan: PanRecognizer;
|
||||||
@ -25,8 +22,7 @@ export class Gesture {
|
|||||||
private isMoveQueued = false;
|
private isMoveQueued = false;
|
||||||
private blocker: BlockerDelegate;
|
private blocker: BlockerDelegate;
|
||||||
|
|
||||||
@Element() private el: HTMLElement;
|
@Prop({ connect: 'ion-gesture-controller' }) gestureCtrl: HTMLIonGestureControllerElement;
|
||||||
|
|
||||||
@Prop({ context: 'dom' }) dom: DomController;
|
@Prop({ context: 'dom' }) dom: DomController;
|
||||||
@Prop({ context: 'enableListener' }) enableListener: EventListenerEnable;
|
@Prop({ context: 'enableListener' }) enableListener: EventListenerEnable;
|
||||||
|
|
||||||
@ -76,13 +72,18 @@ export class Gesture {
|
|||||||
*/
|
*/
|
||||||
@Event() ionPress: EventEmitter;
|
@Event() ionPress: EventEmitter;
|
||||||
|
|
||||||
|
componentWillLoad() {
|
||||||
|
return this.gestureCtrl.create({
|
||||||
|
name: this.gestureName,
|
||||||
|
priority: this.gesturePriority,
|
||||||
|
disableScroll: this.disableScroll
|
||||||
|
}).then((gesture) => this.gesture = gesture);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
// in this case, we already know the GestureController and Gesture are already
|
// in this case, we already know the GestureController and Gesture are already
|
||||||
// apart of the same bundle, so it's safe to load it this way
|
// apart of the same bundle, so it's safe to load it this way
|
||||||
// only create one instance of GestureController, and reuse the same one later
|
// only create one instance of GestureController, and reuse the same one later
|
||||||
this.ctrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
|
||||||
this.gesture = this.ctrl.createGesture(this.gestureName, this.gesturePriority, this.disableScroll);
|
|
||||||
|
|
||||||
const types = this.type.replace(/\s/g, '').toLowerCase().split(',');
|
const types = this.type.replace(/\s/g, '').toLowerCase().split(',');
|
||||||
if (types.indexOf('pan') > -1) {
|
if (types.indexOf('pan') > -1) {
|
||||||
@ -91,15 +92,9 @@ export class Gesture {
|
|||||||
this.hasPress = (types.indexOf('press') > -1);
|
this.hasPress = (types.indexOf('press') > -1);
|
||||||
|
|
||||||
this.disabledChanged(this.disabled);
|
this.disabledChanged(this.disabled);
|
||||||
if (this.pan || this.hasPress) {
|
|
||||||
this.dom.write(() => {
|
|
||||||
applyStyles(getElementReference(this.el, this.attachTo), GESTURE_INLINE_STYLES);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.autoBlockAll) {
|
if (this.autoBlockAll) {
|
||||||
this.blocker = this.ctrl.createBlocker(BLOCK_ALL);
|
this.setBlocker(BLOCK_ALL).then(b => b.block());
|
||||||
this.blocker.block();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,12 +111,19 @@ export class Gesture {
|
|||||||
|
|
||||||
@Watch('block')
|
@Watch('block')
|
||||||
protected blockChanged(block: string) {
|
protected blockChanged(block: string) {
|
||||||
|
this.setBlocker({ disable: block.split(',')});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setBlocker(config: BlockerConfig) {
|
||||||
if (this.blocker) {
|
if (this.blocker) {
|
||||||
this.blocker.destroy();
|
this.blocker.destroy();
|
||||||
}
|
}
|
||||||
if (block) {
|
if (config) {
|
||||||
this.blocker = this.ctrl.createBlocker({ disable: block.split(',')});
|
return this.gestureCtrl.componentOnReady()
|
||||||
|
.then(ctrl => ctrl.createBlocker(config))
|
||||||
|
.then(blocker => this.blocker = blocker);
|
||||||
}
|
}
|
||||||
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DOWN *************************
|
// DOWN *************************
|
||||||
@ -459,19 +461,12 @@ export class Gesture {
|
|||||||
this.blocker = null;
|
this.blocker = null;
|
||||||
}
|
}
|
||||||
this.gesture && this.gesture.destroy();
|
this.gesture && this.gesture.destroy();
|
||||||
this.ctrl = this.gesture = this.pan = this.detail = this.detail.event = null;
|
this.gesture = this.pan = this.detail = this.detail.event = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const GESTURE_INLINE_STYLES = {
|
|
||||||
'touch-action': 'none',
|
|
||||||
'user-select': 'none',
|
|
||||||
'-webkit-user-drag': 'none',
|
|
||||||
'-webkit-tap-highlight-color': 'rgba(0,0,0,0)'
|
|
||||||
};
|
|
||||||
|
|
||||||
const MOUSE_WAIT = 2500;
|
const MOUSE_WAIT = 2500;
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,9 +221,6 @@ export class InfiniteScroll {
|
|||||||
|
|
||||||
private enableScrollEvents(shouldListen: boolean) {
|
private enableScrollEvents(shouldListen: boolean) {
|
||||||
if (this.scrollEl) {
|
if (this.scrollEl) {
|
||||||
if (shouldListen) {
|
|
||||||
this.scrollEl.scrollEvents = true;
|
|
||||||
}
|
|
||||||
this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl);
|
this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### scrollEvents
|
|
||||||
|
|
||||||
boolean
|
|
||||||
|
|
||||||
|
|
||||||
## Attributes
|
## Attributes
|
||||||
|
|
||||||
#### onion-scroll
|
#### onion-scroll
|
||||||
@ -44,11 +39,6 @@ boolean
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### scroll-events
|
|
||||||
|
|
||||||
boolean
|
|
||||||
|
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
#### ionScroll
|
#### ionScroll
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { Component, Element, Event, EventEmitter, EventListenerEnable, Listen, Method, Prop, Watch } from '@stencil/core';
|
import { Component, Element, Event, EventEmitter, EventListenerEnable, Listen, Method, Prop } from '@stencil/core';
|
||||||
import { Config, DomController, GestureDetail } from '../../index';
|
import { Config, DomController, GestureDetail } from '../../index';
|
||||||
import { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller';
|
import { GestureDelegate } from '../gesture-controller/gesture-controller';
|
||||||
|
|
||||||
declare const Ionic: { gesture: GestureController };
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -20,6 +18,7 @@ export class Scroll {
|
|||||||
|
|
||||||
@Element() private el: HTMLElement;
|
@Element() private el: HTMLElement;
|
||||||
|
|
||||||
|
@Prop({ connect: 'ion-gesture-controller'}) gestureCtrl: HTMLIonGestureControllerElement;
|
||||||
@Prop({ context: 'config'}) config: Config;
|
@Prop({ context: 'config'}) config: Config;
|
||||||
@Prop({ context: 'enableListener'}) enableListener: EventListenerEnable;
|
@Prop({ context: 'enableListener'}) enableListener: EventListenerEnable;
|
||||||
@Prop({ context: 'dom' }) dom: DomController;
|
@Prop({ context: 'dom' }) dom: DomController;
|
||||||
@ -44,22 +43,19 @@ export class Scroll {
|
|||||||
*/
|
*/
|
||||||
@Event() ionScrollEnd: EventEmitter;
|
@Event() ionScrollEnd: EventEmitter;
|
||||||
|
|
||||||
|
componentWillLoad() {
|
||||||
@Prop() scrollEvents = false;
|
return this.gestureCtrl.create({
|
||||||
@Watch('scrollEvents')
|
name: 'scroll',
|
||||||
scrollChanged(enabled: boolean) {
|
priority: 100,
|
||||||
this.enableListener(this, 'scroll', enabled);
|
disableScroll: false,
|
||||||
|
}).then(gesture => this.gesture = gesture);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
if (this.isServer) {
|
if (this.isServer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
|
||||||
this.gesture = gestureCtrl.createGesture('scroll', 100, false);
|
|
||||||
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
||||||
this.scrollChanged(this.scrollEvents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUnload() {
|
componentDidUnload() {
|
||||||
@ -69,7 +65,7 @@ export class Scroll {
|
|||||||
|
|
||||||
// Native Scroll *************************
|
// Native Scroll *************************
|
||||||
|
|
||||||
@Listen('scroll', { passive: true, enabled: false })
|
@Listen('scroll', { passive: true })
|
||||||
onNativeScroll() {
|
onNativeScroll() {
|
||||||
if (!this.queued) {
|
if (!this.queued) {
|
||||||
this.queued = true;
|
this.queued = true;
|
||||||
@ -219,6 +215,7 @@ export class Scroll {
|
|||||||
if (this.onionScrollStart) {
|
if (this.onionScrollStart) {
|
||||||
this.onionScrollStart(detail);
|
this.onionScrollStart(detail);
|
||||||
}
|
}
|
||||||
|
this.gesture.capture();
|
||||||
this.ionScrollStart.emit(detail);
|
this.ionScrollStart.emit(detail);
|
||||||
}
|
}
|
||||||
detail.deltaY = (detail.scrollTop - detail.startY);
|
detail.deltaY = (detail.scrollTop - detail.startY);
|
||||||
@ -277,6 +274,8 @@ export class Scroll {
|
|||||||
detail.timeStamp = timeStamp;
|
detail.timeStamp = timeStamp;
|
||||||
|
|
||||||
// emit that the scroll has ended
|
// emit that the scroll has ended
|
||||||
|
this.gesture.release();
|
||||||
|
|
||||||
if (this.onionScrollEnd) {
|
if (this.onionScrollEnd) {
|
||||||
this.onionScrollEnd(detail);
|
this.onionScrollEnd(detail);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import { Component, Element, EventListenerEnable, Listen, Prop } from '@stencil/core';
|
import { Component, Element, EventListenerEnable, Listen, Prop } from '@stencil/core';
|
||||||
import { now, pointerCoordX, pointerCoordY } from '../../utils/helpers';
|
import { now, pointerCoordX, pointerCoordY } from '../../utils/helpers';
|
||||||
import { GestureController } from '../gesture-controller/gesture-controller';
|
|
||||||
|
|
||||||
declare const Ionic: { gesture: GestureController };
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -13,8 +10,7 @@ export class TapClick {
|
|||||||
private app: HTMLIonAppElement;
|
private app: HTMLIonAppElement;
|
||||||
private lastTouch = -MOUSE_WAIT*10;
|
private lastTouch = -MOUSE_WAIT*10;
|
||||||
private lastActivated = 0;
|
private lastActivated = 0;
|
||||||
|
private cancelled = false;
|
||||||
private gestureCtrl: GestureController;
|
|
||||||
|
|
||||||
private activatableEle: HTMLElement | null;
|
private activatableEle: HTMLElement | null;
|
||||||
private activeDefer: any;
|
private activeDefer: any;
|
||||||
@ -30,40 +26,37 @@ export class TapClick {
|
|||||||
if (this.isServer) {
|
if (this.isServer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
|
|
||||||
|
|
||||||
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('document:click', {passive: false, capture: true})
|
@Listen('body:click', {passive: false, capture: true})
|
||||||
onBodyClick(ev: Event) {
|
onBodyClick(ev: Event) {
|
||||||
if (this.shouldCancel()) {
|
if (this.cancelled || this.shouldCancel()) {
|
||||||
debugger;
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touch Events
|
// Touch Events
|
||||||
@Listen('document:touchstart', { passive: true })
|
@Listen('document:touchstart', { passive: true, capture: true })
|
||||||
onTouchStart(ev: TouchEvent) {
|
onTouchStart(ev: TouchEvent) {
|
||||||
this.lastTouch = now(ev);
|
this.lastTouch = now(ev);
|
||||||
this.pointerDown(ev);
|
this.pointerDown(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('document:touchcancel', { passive: true })
|
@Listen('document:touchcancel', { passive: true, capture: true })
|
||||||
onTouchCancel(ev: TouchEvent) {
|
onTouchCancel(ev: TouchEvent) {
|
||||||
this.lastTouch = now(ev);
|
this.lastTouch = now(ev);
|
||||||
this.pointerUp(ev);
|
this.pointerUp(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('document:touchend', { passive: true })
|
@Listen('document:touchend', { passive: false, capture: true })
|
||||||
onTouchEnd(ev: TouchEvent) {
|
onTouchEnd(ev: TouchEvent) {
|
||||||
this.lastTouch = now(ev);
|
this.lastTouch = now(ev);
|
||||||
this.pointerUp(ev);
|
this.pointerUp(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('document:mousedown', { passive: true })
|
@Listen('document:mousedown', { passive: true, capture: true })
|
||||||
onMouseDown(ev: MouseEvent) {
|
onMouseDown(ev: MouseEvent) {
|
||||||
const t = now(ev) - MOUSE_WAIT;
|
const t = now(ev) - MOUSE_WAIT;
|
||||||
if (this.lastTouch < t) {
|
if (this.lastTouch < t) {
|
||||||
@ -71,7 +64,7 @@ export class TapClick {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('document:mouseup', { passive: true })
|
@Listen('document:mouseup', { passive: false, capture: true })
|
||||||
onMouseUp(ev: TouchEvent) {
|
onMouseUp(ev: TouchEvent) {
|
||||||
const t = now(ev) - MOUSE_WAIT;
|
const t = now(ev) - MOUSE_WAIT;
|
||||||
if (this.lastTouch < t) {
|
if (this.lastTouch < t) {
|
||||||
@ -80,25 +73,32 @@ export class TapClick {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Listen('body:ionScrollStart')
|
@Listen('body:ionScrollStart')
|
||||||
scrollStarted() {
|
@Listen('body:ionGestureCaptured')
|
||||||
|
cancelActive() {
|
||||||
clearTimeout(this.activeDefer);
|
clearTimeout(this.activeDefer);
|
||||||
if (this.activatableEle) {
|
if (this.activatableEle) {
|
||||||
this.removeActivated(false);
|
this.removeActivated(false);
|
||||||
this.activatableEle = null;
|
this.activatableEle = null;
|
||||||
}
|
}
|
||||||
|
this.cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private pointerDown(ev: any) {
|
private pointerDown(ev: any) {
|
||||||
if (this.activatableEle) {
|
if (this.activatableEle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.shouldCancel()) {
|
this.cancelled = this.shouldCancel();
|
||||||
|
|
||||||
|
if (!this.cancelled) {
|
||||||
this.setActivatedElement(getActivatableTarget(ev.target), ev);
|
this.setActivatedElement(getActivatableTarget(ev.target), ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private pointerUp(ev: UIEvent) {
|
private pointerUp(ev: UIEvent) {
|
||||||
this.setActivatedElement(null, ev);
|
this.setActivatedElement(null, ev);
|
||||||
|
if (this.cancelled) {
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setActivatedElement(el: HTMLElement | null, ev: UIEvent) {
|
private setActivatedElement(el: HTMLElement | null, ev: UIEvent) {
|
||||||
@ -175,10 +175,6 @@ export class TapClick {
|
|||||||
console.debug('click prevent: appDisabled');
|
console.debug('click prevent: appDisabled');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.gestureCtrl.isCaptured()) {
|
|
||||||
console.debug('click prevent: tap-click (gesture is captured)');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ ion-toggle {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
contain: content;
|
contain: content;
|
||||||
|
|
||||||
|
touch-action: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-toggle ion-gesture {
|
ion-toggle ion-gesture {
|
||||||
@ -52,8 +55,10 @@ ion-toggle input {
|
|||||||
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: 0;
|
||||||
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
// touch-action: pan-x;
|
||||||
|
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -16,13 +16,13 @@ import { debounce } from '../../utils/helpers';
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class Toggle implements CheckboxInput {
|
export class Toggle implements CheckboxInput {
|
||||||
|
|
||||||
private didLoad: boolean;
|
private didLoad: boolean;
|
||||||
private gestureConfig: any;
|
private gestureConfig: any;
|
||||||
private inputId: string;
|
private inputId: string;
|
||||||
private nativeInput: HTMLInputElement;
|
private nativeInput: HTMLInputElement;
|
||||||
private pivotX: number;
|
private pivotX: number;
|
||||||
|
|
||||||
|
|
||||||
@State() activated = false;
|
@State() activated = false;
|
||||||
|
|
||||||
@State() keyFocus: boolean;
|
@State() keyFocus: boolean;
|
||||||
@ -88,6 +88,7 @@ export class Toggle implements CheckboxInput {
|
|||||||
'onMove': this.onDragMove.bind(this),
|
'onMove': this.onDragMove.bind(this),
|
||||||
'onEnd': this.onDragEnd.bind(this),
|
'onEnd': this.onDragEnd.bind(this),
|
||||||
'gestureName': 'toggle',
|
'gestureName': 'toggle',
|
||||||
|
'passive': false,
|
||||||
'gesturePriority': 30,
|
'gesturePriority': 30,
|
||||||
'type': 'pan',
|
'type': 'pan',
|
||||||
'direction': 'x',
|
'direction': 'x',
|
||||||
@ -141,6 +142,10 @@ export class Toggle implements CheckboxInput {
|
|||||||
private onDragStart(detail: GestureDetail) {
|
private onDragStart(detail: GestureDetail) {
|
||||||
this.pivotX = detail.currentX;
|
this.pivotX = detail.currentX;
|
||||||
this.activated = true;
|
this.activated = true;
|
||||||
|
|
||||||
|
// touch-action does not work in iOS
|
||||||
|
detail.event.preventDefault();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDragMove(detail: GestureDetail) {
|
private onDragMove(detail: GestureDetail) {
|
||||||
|
6
packages/core/src/index.d.ts
vendored
6
packages/core/src/index.d.ts
vendored
@ -36,9 +36,9 @@ export { PanRecognizer } from './components/gesture/recognizers';
|
|||||||
export {
|
export {
|
||||||
BLOCK_ALL,
|
BLOCK_ALL,
|
||||||
BlockerDelegate,
|
BlockerDelegate,
|
||||||
BlockerOptions,
|
GestureDelegate,
|
||||||
GestureController,
|
BlockerConfig,
|
||||||
GestureDelegate
|
GestureConfig,
|
||||||
} from './components/gesture-controller/gesture-controller';
|
} from './components/gesture-controller/gesture-controller';
|
||||||
export { Grid } from './components/grid/grid';
|
export { Grid } from './components/grid/grid';
|
||||||
export { Header } from './components/header/header';
|
export { Header } from './components/header/header';
|
||||||
|
@ -20,7 +20,7 @@ exports.config = {
|
|||||||
{ components: ['ion-datetime', 'ion-picker', 'ion-picker-column', 'ion-picker-controller'] },
|
{ components: ['ion-datetime', 'ion-picker', 'ion-picker-column', 'ion-picker-controller'] },
|
||||||
{ components: ['ion-events'] },
|
{ components: ['ion-events'] },
|
||||||
{ components: ['ion-fab', 'ion-fab-button', 'ion-fab-list'] },
|
{ components: ['ion-fab', 'ion-fab-button', 'ion-fab-list'] },
|
||||||
{ components: ['ion-gesture'] },
|
{ components: ['ion-gesture', 'ion-gesture-controller'] },
|
||||||
{ components: ['ion-grid', 'ion-row', 'ion-col'] },
|
{ components: ['ion-grid', 'ion-row', 'ion-col'] },
|
||||||
{ components: ['ion-item', 'ion-item-divider', 'ion-item-group', 'ion-label', 'ion-list', 'ion-list-header', 'ion-skeleton-text'] },
|
{ components: ['ion-item', 'ion-item-divider', 'ion-item-group', 'ion-label', 'ion-list', 'ion-list-header', 'ion-skeleton-text'] },
|
||||||
{ components: ['ion-item-sliding', 'ion-item-options', 'ion-item-option'] },
|
{ components: ['ion-item-sliding', 'ion-item-options', 'ion-item-option'] },
|
||||||
|
Reference in New Issue
Block a user