| 
1 | 1 | /*  | 
2 |  | - * @author Mikel Tuesta <[email protected]>  | 
 | 2 | + * This file is part of the FoesScrollProxy library.  | 
 | 3 | + *  | 
 | 4 | + * (c) Mikel Tuesta <[email protected]>  | 
 | 5 | + *  | 
 | 6 | + * For the full copyright and license information, please view the LICENSE  | 
 | 7 | + * file that was distributed with this source code.  | 
3 | 8 |  */  | 
4 |  | -'use strict';  | 
5 | 9 | 
 
  | 
6 |  | -(function (window, GeometricHelpers, DomHelpers, ScrollProxyListener, _) {  | 
 | 10 | +import DOMHelpers from '../Helpers/DOMHelpers';  | 
 | 11 | +import ScrollProxyObserver from './ScrollProxyObserver';  | 
 | 12 | +import debounce from 'lodash.debounce';  | 
7 | 13 | 
 
  | 
8 |  | -  /**  | 
9 |  | -   * ParallaxController - Singleton  | 
10 |  | -   *  | 
11 |  | -   * @constructor  | 
12 |  | -   */  | 
13 |  | -  var ScrollProxy = (function () {  | 
14 |  | -    var instance;  | 
 | 14 | +class ScrollProxy {  | 
15 | 15 | 
 
  | 
16 |  | -    function ScrollProxy() {  | 
17 |  | -      var latestKnownScrollPosition = DomHelpers.getScrollPosition(),  | 
18 |  | -        viewportSize = DomHelpers.getViewportSize(),  | 
19 |  | -        listeners = [],  | 
20 |  | -        rendering = false;  | 
 | 16 | +  constructor() {  | 
 | 17 | +    this.observers = new Map();  | 
 | 18 | +    this.isUpdatingDOM = false;  | 
21 | 19 | 
 
  | 
22 |  | -      var notifyListeners = function () {  | 
23 |  | -        var args = Array.prototype.slice.call(arguments),  | 
24 |  | -          methodName = args.splice(0, 1);  | 
25 |  | -        for (var i = 0; i < listeners.length; i++) {  | 
26 |  | -          listeners[i][methodName].apply(listeners[i], args);  | 
27 |  | -        }  | 
28 |  | -      };  | 
29 |  | -      var requestFrame = function () {  | 
30 |  | -        if (!rendering) {  | 
31 |  | -          window.requestAnimationFrame(render);  | 
32 |  | -        }  | 
33 |  | -        rendering = true;  | 
34 |  | -      };  | 
35 |  | -      var render = function () {  | 
36 |  | -        notifyListeners('render');  | 
37 |  | -        rendering = false;  | 
38 |  | -      };  | 
39 |  | -      var onScroll = function () {  | 
40 |  | -        latestKnownScrollPosition = DomHelpers.getScrollPosition();  | 
41 |  | -        notifyListeners('onScroll', latestKnownScrollPosition);  | 
42 |  | -        requestFrame();  | 
43 |  | -      };  | 
44 |  | -      var onResize = function () {  | 
45 |  | -        viewportSize = DomHelpers.getViewportSize();  | 
46 |  | -        notifyListeners('onResize', viewportSize);  | 
47 |  | -      };  | 
48 |  | -      var bindListeners = function () {  | 
49 |  | -        window.addEventListener('scroll', onScroll);  | 
50 |  | -        window.addEventListener('resize', _.debounce(onResize, 200));  | 
51 |  | -      };  | 
52 |  | -      var addListener = function (listener) {  | 
53 |  | -        if (!(listener instanceof ScrollProxyListener)) {  | 
54 |  | -          throw 'Provided listener must be an instance of ScrollProxyListener.';  | 
55 |  | -        }  | 
56 |  | -        listeners.push(listener);  | 
57 |  | -      };  | 
58 |  | -      var removeListener = function (listener) {  | 
59 |  | -        var listenerIndex = listeners.indexOf(listener);  | 
60 |  | -        if (listenerIndex !== -1) {  | 
61 |  | -          listeners.splice(listenerIndex, 1);  | 
62 |  | -        }  | 
63 |  | -      };  | 
64 |  | -      var init = function () {  | 
65 |  | -        bindListeners();  | 
66 |  | -      };  | 
67 |  | -      init();  | 
 | 20 | +    this.onScroll = () => {  | 
 | 21 | +      const scrollPosition = DOMHelpers.getScrollPosition();  | 
 | 22 | +      this.notifyObservers('onScroll', scrollPosition);  | 
 | 23 | +      this.requestDOMUpdate();  | 
 | 24 | +    };  | 
68 | 25 | 
 
  | 
69 |  | -      return {  | 
70 |  | -        addListener: addListener,  | 
71 |  | -        removeListener: removeListener  | 
72 |  | -      }  | 
73 |  | -    }  | 
 | 26 | +    this.onResize = () => {  | 
 | 27 | +      const viewportSize = DOMHelpers.getViewportSize();  | 
 | 28 | +      this.notifyObservers('onResize', viewportSize);  | 
 | 29 | +    };  | 
74 | 30 | 
 
  | 
75 |  | -    return {  | 
76 |  | -      getInstance: function () {  | 
77 |  | -        if (!instance) {  | 
78 |  | -          instance = new ScrollProxy();  | 
79 |  | -        }  | 
80 |  | -        return instance;  | 
 | 31 | +    this.requestDOMUpdate = () => {  | 
 | 32 | +      if (!this.isUpdatingDOM) {  | 
 | 33 | +        window.requestAnimationFrame(this.updateDOM);  | 
81 | 34 |       }  | 
 | 35 | +      this.isUpdatingDOM = true;  | 
82 | 36 |     };  | 
83 |  | -  })();  | 
84 | 37 | 
 
  | 
85 |  | -  // Expose ScrollProxy  | 
86 |  | -  window.ScrollProxy = ScrollProxy;  | 
 | 38 | +    this.updateDOM = () => {  | 
 | 39 | +      this.notifyObservers('updateDOM');  | 
 | 40 | +      this.isUpdatingDOM = false;  | 
 | 41 | +    };  | 
 | 42 | + | 
 | 43 | +    this.notifyObservers = (methodName, ...methodParams) => {  | 
 | 44 | +      this.observers.forEach((observer, uuid) => {  | 
 | 45 | +        observer[methodName](...methodParams);  | 
 | 46 | +      });  | 
 | 47 | +    };  | 
 | 48 | + | 
 | 49 | +    window.addEventListener('scroll', this.onScroll);  | 
 | 50 | +    window.addEventListener('resize', debounce(this.onResize, 200));  | 
 | 51 | +  }  | 
 | 52 | + | 
 | 53 | +  addObserver(observer) {  | 
 | 54 | +    if (!(observer instanceof ScrollProxyObserver)) {  | 
 | 55 | +      throw new TypeError('Provided object must inherit from ScrollProxyObserver abstract class.');  | 
 | 56 | +    }  | 
 | 57 | + | 
 | 58 | +    const uuid = Symbol();  | 
 | 59 | +    this.observers.set(uuid, observer);  | 
 | 60 | +    return uuid;  | 
 | 61 | +  };  | 
 | 62 | + | 
 | 63 | +  removeObserver(uuid) {  | 
 | 64 | +    return this.observers.delete(uuid);  | 
 | 65 | +  };  | 
 | 66 | +}  | 
 | 67 | + | 
 | 68 | +const instance = new ScrollProxy();  | 
87 | 69 | 
 
  | 
88 |  | -})(window, window.GeometricHelpers, window.DomHelpers, window.ScrollProxyListener, _);  | 
 | 70 | +export default instance;  | 
0 commit comments