@@ -10,7 +10,9 @@ import {ElementRef, Injectable, NgZone, Optional, SkipSelf} from '@angular/core'
1010import { Platform } from '@angular/cdk/platform' ;
1111import { Subject } from 'rxjs/Subject' ;
1212import { Subscription } from 'rxjs/Subscription' ;
13+ import { Observable } from 'rxjs/Observable' ;
1314import { fromEvent } from 'rxjs/observable/fromEvent' ;
15+ import { of as observableOf } from 'rxjs/observable/of' ;
1416import { auditTime } from 'rxjs/operator/auditTime' ;
1517import { Scrollable } from './scrollable' ;
1618
@@ -27,7 +29,7 @@ export class ScrollDispatcher {
2729 constructor ( private _ngZone : NgZone , private _platform : Platform ) { }
2830
2931 /** Subject for notifying that a registered scrollable reference element has been scrolled. */
30- _scrolled : Subject < void > = new Subject < void > ( ) ;
32+ private _scrolled : Subject < void > = new Subject < void > ( ) ;
3133
3234 /** Keeps track of the global `scroll` and `resize` subscriptions. */
3335 _globalSubscription : Subscription | null = null ;
@@ -47,8 +49,7 @@ export class ScrollDispatcher {
4749 * @param scrollable Scrollable instance to be registered.
4850 */
4951 register ( scrollable : Scrollable ) : void {
50- const scrollSubscription = scrollable . elementScrolled ( ) . subscribe ( ( ) => this . _notify ( ) ) ;
51-
52+ const scrollSubscription = scrollable . elementScrolled ( ) . subscribe ( ( ) => this . _scrolled . next ( ) ) ;
5253 this . scrollableReferences . set ( scrollable , scrollSubscription ) ;
5354 }
5455
@@ -66,44 +67,34 @@ export class ScrollDispatcher {
6667 }
6768
6869 /**
69- * Subscribes to an observable that emits an event whenever any of the registered Scrollable
70+ * Returns an observable that emits an event whenever any of the registered Scrollable
7071 * references (or window, document, or body) fire a scrolled event. Can provide a time in ms
7172 * to override the default "throttle" time.
7273 */
73- scrolled ( auditTimeInMs : number = DEFAULT_SCROLL_TIME , callback : ( ) => any ) : Subscription {
74- // Scroll events can only happen on the browser, so do nothing if we're not on the browser.
75- if ( ! this . _platform . isBrowser ) {
76- return Subscription . EMPTY ;
77- }
78-
79- // In the case of a 0ms delay, use an observable without auditTime
80- // since it does add a perceptible delay in processing overhead.
81- let observable = auditTimeInMs > 0 ?
82- auditTime . call ( this . _scrolled . asObservable ( ) , auditTimeInMs ) :
83- this . _scrolled . asObservable ( ) ;
84-
85- this . _scrolledCount ++ ;
86-
87- if ( ! this . _globalSubscription ) {
88- this . _globalSubscription = this . _ngZone . runOutsideAngular ( ( ) => {
89- return fromEvent ( window . document , 'scroll' ) . subscribe ( ( ) => this . _notify ( ) ) ;
90- } ) ;
91- }
74+ scrolled ( auditTimeInMs : number = DEFAULT_SCROLL_TIME ) : Observable < void > {
75+ return this . _platform . isBrowser ? Observable . create ( observer => {
76+ if ( ! this . _globalSubscription ) {
77+ this . _addGlobalListener ( ) ;
78+ }
9279
93- // Note that we need to do the subscribing from here, in order to be able to remove
94- // the global event listeners once there are no more subscriptions.
95- let subscription = observable . subscribe ( callback ) ;
80+ // In the case of a 0ms delay, use an observable without auditTime
81+ // since it does add a perceptible delay in processing overhead.
82+ const subscription = auditTimeInMs > 0 ?
83+ auditTime . call ( this . _scrolled , auditTimeInMs ) . subscribe ( observer ) :
84+ this . _scrolled . subscribe ( observer ) ;
9685
97- subscription . add ( ( ) => {
98- this . _scrolledCount -- ;
86+ this . _scrolledCount ++ ;
9987
100- if ( this . _globalSubscription && ! this . scrollableReferences . size && ! this . _scrolledCount ) {
101- this . _globalSubscription . unsubscribe ( ) ;
102- this . _globalSubscription = null ;
103- }
104- } ) ;
88+ return ( ) => {
89+ subscription . unsubscribe ( ) ;
90+ this . _scrolledCount -- ;
10591
106- return subscription ;
92+ if ( this . _globalSubscription && ! this . scrollableReferences . size && ! this . _scrolledCount ) {
93+ this . _globalSubscription . unsubscribe ( ) ;
94+ this . _globalSubscription = null ;
95+ }
96+ } ;
97+ } ) : observableOf < void > ( ) ;
10798 }
10899
109100 /** Returns all registered Scrollables that contain the provided element. */
@@ -133,9 +124,11 @@ export class ScrollDispatcher {
133124 return false ;
134125 }
135126
136- /** Sends a notification that a scroll event has been fired. */
137- _notify ( ) {
138- this . _scrolled . next ( ) ;
127+ /** Sets up the global scroll and resize listeners. */
128+ private _addGlobalListener ( ) {
129+ this . _globalSubscription = this . _ngZone . runOutsideAngular ( ( ) => {
130+ return fromEvent ( window . document , 'scroll' ) . subscribe ( ( ) => this . _scrolled . next ( ) ) ;
131+ } ) ;
139132 }
140133}
141134
0 commit comments