refactor(refresh): uses new UIEventManager

This commit is contained in:
Manu Mtz.-Almeida
2016-06-21 11:37:31 +02:00
parent 38ab17b0a8
commit 14b8049771
3 changed files with 57 additions and 82 deletions

View File

@ -171,6 +171,13 @@ export class Content extends Ion {
}; };
} }
/**
* @private
*/
getScrollElement(): HTMLElement {
return this._scrollEle;
}
/** /**
* @private * @private
* Call a method when scrolling has stopped * Call a method when scrolling has stopped

View File

@ -4,6 +4,7 @@ import {Content} from '../content/content';
import {Icon} from '../icon/icon'; import {Icon} from '../icon/icon';
import {isTrueProperty} from '../../util/util'; import {isTrueProperty} from '../../util/util';
import {CSS, pointerCoord, transitionEnd} from '../../util/dom'; import {CSS, pointerCoord, transitionEnd} from '../../util/dom';
import {PointerEvents, UIEventManager} from '../../util/ui-event-manager';
/** /**
@ -95,15 +96,10 @@ import {CSS, pointerCoord, transitionEnd} from '../../util/dom';
export class Refresher { export class Refresher {
private _appliedStyles: boolean = false; private _appliedStyles: boolean = false;
private _didStart: boolean; private _didStart: boolean;
private _lastStart: number = 0;
private _lastCheck: number = 0; private _lastCheck: number = 0;
private _isEnabled: boolean = true; private _isEnabled: boolean = true;
private _mDown: Function; private _events: UIEventManager = new UIEventManager(false);
private _mMove: Function; private _pointerEvents: PointerEvents;
private _mUp: Function;
private _tStart: Function;
private _tMove: Function;
private _tEnd: Function;
/** /**
* The current state which the refresher is in. The refresher's states include: * The current state which the refresher is in. The refresher's states include:
@ -202,8 +198,7 @@ export class Refresher {
constructor( constructor(
@Host() private _content: Content, @Host() private _content: Content,
private _zone: NgZone, private _zone: NgZone,
elementRef: ElementRef elementRef: ElementRef) {
) {
_content.addCssClass('has-refresher'); _content.addCssClass('has-refresher');
// deprecated warning // deprecated warning
@ -222,31 +217,22 @@ export class Refresher {
private _onStart(ev: TouchEvent): any { private _onStart(ev: TouchEvent): any {
// if multitouch then get out immediately // if multitouch then get out immediately
if (ev.touches && ev.touches.length > 1) { if (ev.touches && ev.touches.length > 1) {
return 1; return false;
} }
let coord = pointerCoord(ev); let coord = pointerCoord(ev);
console.debug('Pull-to-refresh, onStart', ev.type, 'y:', coord.y); console.debug('Pull-to-refresh, onStart', ev.type, 'y:', coord.y);
let now = Date.now();
if (this._lastStart + 100 > now) {
return 2;
}
this._lastStart = now;
if ( ev.type === 'mousedown' && !this._mMove) {
this._mMove = this._content.addMouseMoveListener( this._onMove.bind(this) );
}
this.startY = this.currentY = coord.y; this.startY = this.currentY = coord.y;
this.progress = 0; this.progress = 0;
if (!this.pullMax) { if (!this.pullMax) {
this.pullMax = (this.pullMin + 60); this.pullMax = (this.pullMin + 60);
} }
return true;
} }
private _onMove(ev: TouchEvent): any { private _onMove(ev: TouchEvent) {
// this method can get called like a bazillion times per second, // this method can get called like a bazillion times per second,
// so it's built to be as efficient as possible, and does its // so it's built to be as efficient as possible, and does its
// best to do any DOM read/writes only when absolutely necessary // best to do any DOM read/writes only when absolutely necessary
@ -396,12 +382,6 @@ export class Refresher {
// reset on any touchend/mouseup // reset on any touchend/mouseup
this.startY = null; this.startY = null;
if (this._mMove) {
// we don't want to always listen to mousemoves
// remove it if we're still listening
this._mMove();
this._mMove = null;
}
} }
private _beginRefresh() { private _beginRefresh() {
@ -463,10 +443,8 @@ export class Refresher {
this.state = state; this.state = state;
this._setCss(0, '', true, delay); this._setCss(0, '', true, delay);
if (this._mMove) { if (this._pointerEvents) {
// always remove the mousemove event this._pointerEvents.stop();
this._mMove();
this._mMove = null;
} }
} }
@ -481,43 +459,13 @@ export class Refresher {
} }
private _setListeners(shouldListen: boolean) { private _setListeners(shouldListen: boolean) {
const self = this; this._events.unlistenAll();
const content = self._content; this._pointerEvents = null;
if (shouldListen) { if (shouldListen) {
// add listener outside of zone this._pointerEvents = this._events.pointerEvents(this._content.getScrollElement(),
// touch handlers this._onStart.bind(this),
self._zone.runOutsideAngular(function() { this._onMove.bind(this),
if (!self._tStart) { this._onEnd.bind(this));
self._tStart = content.addTouchStartListener( self._onStart.bind(self) );
}
if (!self._tMove) {
self._tMove = content.addTouchMoveListener( self._onMove.bind(self) );
}
if (!self._tEnd) {
self._tEnd = content.addTouchEndListener( self._onEnd.bind(self) );
}
// mouse handlers
// mousemove does not get added until mousedown fires
if (!self._mDown) {
self._mDown = content.addMouseDownListener( self._onStart.bind(self) );
}
if (!self._mUp) {
self._mUp = content.addMouseUpListener( self._onEnd.bind(self) );
}
});
} else {
// unregister event listeners from content element
self._mDown && self._mDown();
self._mMove && self._mMove();
self._mUp && self._mUp();
self._tStart && self._tStart();
self._tMove && self._tMove();
self._tEnd && self._tEnd();
self._mDown = self._mMove = self._mUp = self._tStart = self._tMove = self._tEnd = null;
} }
} }

View File

@ -1,9 +1,12 @@
import {ElementRef} from '@angular/core'; import {ElementRef} from '@angular/core';
const MOUSE_WAIT = 2 * 1000;
class PointerEvents {
/**
* @private
*/
export class PointerEvents {
private rmTouchStart: Function = null; private rmTouchStart: Function = null;
private rmTouchMove: Function = null; private rmTouchMove: Function = null;
private rmTouchEnd: Function = null; private rmTouchEnd: Function = null;
@ -14,6 +17,8 @@ class PointerEvents {
private lastTouchEvent: number = 0; private lastTouchEvent: number = 0;
mouseWait: number = 2 * 1000;
constructor(private ele: any, constructor(private ele: any,
private pointerDown: any, private pointerDown: any,
private pointerMove: any, private pointerMove: any,
@ -26,7 +31,7 @@ class PointerEvents {
} }
private handleTouchStart(ev: any) { private handleTouchStart(ev: any) {
this.lastTouchEvent = Date.now() + MOUSE_WAIT; this.lastTouchEvent = Date.now() + this.mouseWait;
if (!this.pointerDown(ev)) { if (!this.pointerDown(ev)) {
return; return;
} }
@ -72,21 +77,26 @@ class PointerEvents {
this.pointerUp(ev); this.pointerUp(ev);
} }
destroy() { stop() {
this.rmTouchStart && this.rmTouchStart();
this.rmTouchMove && this.rmTouchMove(); this.rmTouchMove && this.rmTouchMove();
this.rmTouchEnd && this.rmTouchEnd(); this.rmTouchEnd && this.rmTouchEnd();
this.rmMouseStart && this.rmMouseStart();
this.rmMouseMove && this.rmMouseMove();
this.rmMouseUp && this.rmMouseUp();
this.rmTouchStart = null;
this.rmTouchMove = null; this.rmTouchMove = null;
this.rmTouchEnd = null; this.rmTouchEnd = null;
this.rmMouseStart = null;
this.rmMouseMove && this.rmMouseMove();
this.rmMouseUp && this.rmMouseUp();
this.rmMouseMove = null; this.rmMouseMove = null;
this.rmMouseUp = null; this.rmMouseUp = null;
}
destroy() {
this.rmTouchStart && this.rmTouchStart();
this.rmTouchStart = null;
this.rmMouseStart && this.rmMouseStart();
this.rmMouseStart = null;
this.stop();
this.pointerDown = null; this.pointerDown = null;
this.pointerMove = null; this.pointerMove = null;
@ -97,6 +107,10 @@ class PointerEvents {
} }
/**
* @private
*/
export class UIEventManager { export class UIEventManager {
private events: Function[] = []; private events: Function[] = [];
@ -110,7 +124,10 @@ export class UIEventManager {
return this.pointerEvents(ref.nativeElement, pointerStart, pointerMove, pointerEnd, option); return this.pointerEvents(ref.nativeElement, pointerStart, pointerMove, pointerEnd, option);
} }
pointerEvents(element: any, pointerDown: any, pointerMove: any, pointerUp: any, option: any = false): Function { pointerEvents(element: any, pointerDown: any, pointerMove: any, pointerUp: any, option: any = false): PointerEvents {
if (!element) {
return;
}
let submanager = new PointerEvents( let submanager = new PointerEvents(
element, element,
pointerDown, pointerDown,
@ -121,10 +138,13 @@ export class UIEventManager {
let removeFunc = () => submanager.destroy(); let removeFunc = () => submanager.destroy();
this.events.push(removeFunc); this.events.push(removeFunc);
return removeFunc; return submanager;
} }
listen(element: any, eventName: string, callback: any, option: any = false): Function { listen(element: any, eventName: string, callback: any, option: any = false): Function {
if (!element) {
return;
}
let removeFunc = listenEvent(element, eventName, this.zoneWrapped, option, callback); let removeFunc = listenEvent(element, eventName, this.zoneWrapped, option, callback);
this.events.push(removeFunc); this.events.push(removeFunc);
return removeFunc; return removeFunc;