Skip to content

Commit

Permalink
fix(content): scroll listener is auto enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Mar 29, 2017
1 parent 54acc74 commit b37f500
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 45 deletions.
59 changes: 48 additions & 11 deletions src/components/content/content.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnDestroy, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnDestroy, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';

import { App } from '../app/app';
import { Config } from '../../config/config';
Expand All @@ -17,6 +17,14 @@ import { ViewController } from '../../navigation/view-controller';
export { ScrollEvent } from '../../util/scroll-view';


export class EventEmitterProxy<T> extends EventEmitter<T> {
onSubscribe: Function;
subscribe(generatorOrNext?: any, error?: any, complete?: any): any {
this.onSubscribe();
return super.subscribe(generatorOrNext, error, complete);
}
}

/**
* @name Content
* @description
Expand Down Expand Up @@ -125,7 +133,7 @@ export { ScrollEvent } from '../../util/scroll-view';
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class Content extends Ion implements OnDestroy {
export class Content extends Ion implements OnDestroy, AfterViewInit {
/** @internal */
_cTop: number;
/** @internal */
Expand Down Expand Up @@ -311,18 +319,39 @@ export class Content extends Ion implements OnDestroy {

/**
* @output {ScrollEvent} Emitted when the scrolling first starts.
* If it is used programatically, scroll events must be enabled explicitally with `enableScrollListener()`:
*
* ```ts
* content.ionScrollStart((ev) => onEvent(ev));
* content.enableScrollListener();
* ```
*
*/
@Output() ionScrollStart: EventEmitter<ScrollEvent> = new EventEmitter<ScrollEvent>();
@Output() ionScrollStart: EventEmitterProxy<ScrollEvent> = new EventEmitterProxy<ScrollEvent>();

/**
* @output {ScrollEvent} Emitted on every scroll event.
* If it is used programatically, scroll events must be enabled explicitally with `enableScrollListener()`:
*
* ```ts
* content.ionScroll((ev) => onEvent(ev));
* content.enableScrollListener();
* ```
*
*/
@Output() ionScroll: EventEmitter<ScrollEvent> = new EventEmitter<ScrollEvent>();
@Output() ionScroll: EventEmitterProxy<ScrollEvent> = new EventEmitterProxy<ScrollEvent>();

/**
* @output {ScrollEvent} Emitted when scrolling ends.
* If it is used programatically, scroll events must be enabled explicitally with `enableScrollListener()`:
*
* ```ts
* content.ionScrollEnd((ev) => onEvent(ev));
* content.enableScrollListener();
* ```
*
*/
@Output() ionScrollEnd: EventEmitter<ScrollEvent> = new EventEmitter<ScrollEvent>();
@Output() ionScrollEnd: EventEmitterProxy<ScrollEvent> = new EventEmitterProxy<ScrollEvent>();


constructor(
Expand All @@ -339,6 +368,11 @@ export class Content extends Ion implements OnDestroy {
) {
super(config, elementRef, renderer, 'content');

let enableScrollListener = this.enableScrollListener.bind(this);
this.ionScroll.onSubscribe = enableScrollListener;
this.ionScrollStart.onSubscribe = enableScrollListener;
this.ionScrollEnd.onSubscribe = enableScrollListener;

this.statusbarPadding = config.getBoolean('statusbarPadding', false);
this._imgReqBfr = config.getNumber('imgRequestBuffer', 1400);
this._imgRndBfr = config.getNumber('imgRenderBuffer', 400);
Expand All @@ -348,7 +382,8 @@ export class Content extends Ion implements OnDestroy {
// goal is to completely remove this when iOS
// fully supports scroll events
// listen to JS scroll events
this._scroll = new ScrollView(_plt, _dom, config.getBoolean('virtualScrollEventAssist'));
const jsScroll = config.getBoolean('virtualScrollEventAssist');
this._scroll = new ScrollView(_app, _plt, _dom, jsScroll);

while (navCtrl) {
if (isTabs(<any>navCtrl)) {
Expand Down Expand Up @@ -383,7 +418,7 @@ export class Content extends Ion implements OnDestroy {
/**
* @hidden
*/
enableScrollListener() {
ngAfterViewInit() {
assert(this.getFixedElement(), 'fixed element was not found');
assert(this.getScrollElement(), 'scroll element was not found');

Expand All @@ -398,9 +433,6 @@ export class Content extends Ion implements OnDestroy {

// subscribe to every scroll move
scroll.onScroll = (ev) => {
// remind the app that it's currently scrolling
this._app.setScrolling();

// emit to all of our other friends things be scrolling
this.ionScroll.emit(ev);

Expand All @@ -413,8 +445,13 @@ export class Content extends Ion implements OnDestroy {

this.imgsUpdate();
};
}

scroll.setEnabled();
/**
* @hidden
*/
enableScrollListener() {
this._scroll.eventsEnabled = true;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/util/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ export function setupEvents(plt: Platform, dom: DomController): Events {
let contentEle = <any>el.closest('.scroll-content');
if (contentEle) {
var style = contentEle.style;
var scroll = new ScrollView(plt, dom, false);
scroll.init(contentEle, 0, 0);
var scroll = new ScrollView(null, plt, dom, false);
scroll._el = contentEle;
// We need to stop scrolling if it's happening and scroll up

style['WebkitBackfaceVisibility'] = 'hidden';
Expand Down
56 changes: 24 additions & 32 deletions src/util/scroll-view.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import { assert } from './util';
import { App } from '../components/app/app';
import { DomController, DomCallback } from '../platform/dom-controller';
import { Platform, EventListenerOptions } from '../platform/platform';
import { pointerCoord } from './dom';
Expand All @@ -12,11 +13,11 @@ export class ScrollView {
onScroll: (ev: ScrollEvent) => void;
onScrollEnd: (ev: ScrollEvent) => void;
initialized: boolean = false;
enabled: boolean = false;
eventsEnabled: boolean = false;
contentTop: number;
contentBottom: number;

private _el: HTMLElement;
_el: HTMLElement;
private _js: boolean;
private _t: number = 0;
private _l: number = 0;
Expand All @@ -25,6 +26,7 @@ export class ScrollView {


constructor(
private _app: App,
private _plt: Platform,
private _dom: DomController,
virtualScrollEventAssist: boolean
Expand Down Expand Up @@ -60,35 +62,19 @@ export class ScrollView {

if (!this.initialized) {
this.initialized = true;

if (this.enabled) {
this.enable();
}
}
}

setEnabled() {
if (!this.enabled) {
this.enabled = true;
if (this.initialized) {
this.enable();
if (this._js) {
this.enableJsScroll();
} else {
this.enableNativeScrolling();
}
}
}

enable() {
assert(this.initialized, 'scroll must be initialized');
assert(this.enabled, 'scroll-view must be enabled');
assert(this._el, 'scroll-view, element can not be null');

if (this._js) {
this.enableJsScroll();
} else {
this.enableNativeScrolling();
}
}

private enableNativeScrolling() {
assert(this.onScrollStart, 'onScrollStart is not defined');
assert(this.onScroll, 'onScroll is not defined');
assert(this.onScrollEnd, 'onScrollEnd is not defined');

this._js = false;
if (!this._el) {
return;
Expand All @@ -101,6 +87,14 @@ export class ScrollView {
const positions: number[] = [];

function scrollCallback(scrollEvent: UIEvent) {
// remind the app that it's currently scrolling
self._app.setScrolling();

// if events are disabled, we do nothing
if (!self.eventsEnabled) {
return;
}

ev.timeStamp = scrollEvent.timeStamp;
// Event.timeStamp is 0 in firefox
if (!ev.timeStamp) {
Expand Down Expand Up @@ -151,13 +145,12 @@ export class ScrollView {

if (startPos !== endPos) {
// compute relative movement between these two points
var timeOffset = (positions[endPos] - positions[startPos]);
var movedTop = (positions[startPos - 2] - positions[endPos - 2]);
var movedLeft = (positions[startPos - 1] - positions[endPos - 1]);

var factor = FRAME_MS / (positions[endPos] - positions[startPos]);
// based on XXms compute the movement to apply for each render step
ev.velocityY = ((movedTop / timeOffset) * FRAME_MS);
ev.velocityX = ((movedLeft / timeOffset) * FRAME_MS);
ev.velocityY = movedTop * factor;
ev.velocityX = movedLeft * factor;

// figure out which direction we're scrolling
ev.directionY = (movedTop > 0 ? 'up' : 'down');
Expand Down Expand Up @@ -546,11 +539,10 @@ export class ScrollView {
this._endTmr && this._dom.cancel(this._endTmr);
this._lsn && this._lsn();

this.onScrollStart = this.onScroll = this.onScrollEnd = null;

let ev = this.ev;
ev.domWrite = ev.contentElement = ev.fixedElement = ev.scrollElement = ev.headerElement = null;
this._lsn = this._el = this._dom = this.ev = ev = null;
this.onScrollStart = this.onScroll = this.onScrollEnd = null;
}

}
Expand Down

0 comments on commit b37f500

Please sign in to comment.