2 var Marionette = require('backbone.marionette');
3 var behaviourLookup = require('./lookup');
4 var _ = require('lodash');
5 var rafUtils = require('../../utils/raf-utils');
6 var passiveEventListener = require('../../utils/passive-event-listener');
8 var Behavior = Marionette.Behavior.extend({
10 scrollElementSelector: null,
14 initialize: function() {
15 var selector = this.options.scrollElementSelector;
16 var wrapperSelector = this.options.contentWrapper;
19 this.scrollElement = selector ? document.querySelector(selector) : this.view.el;
20 this.wrapper = wrapperSelector ? this.scrollElement.querySelector(wrapperSelector) : null;
22 // Make sure every time the collectionView renders it decorates its childs and updates the banners
23 this.listenTo(this.view, 'render', this.decorateIfVisible);
25 // Debounced actions for improved performance
26 this.lazyDecorator = _.debounce(this.decorateIfVisible.bind(this), 500);
27 this.lazyDecoratorQueue = rafUtils.debounce(this.decorateQueue, this);
29 this.lazyTracker = _.debounce(this.trackViewport.bind(this), 500);
30 this.lazyPointerEvents = _.debounce(this.enablePointerEvents.bind(this), 250);
32 this.scrollHandler = this.smoothScroll.bind(this);
33 passiveEventListener.addEventListener(this.scrollElement, 'scroll', this.scrollHandler);
36 // Trigger an event on the child of it's currently on screen
37 decorateIfVisible: function() {
38 this.view.children.each(
40 if (this.isElementVisible(child.el)) child.trigger('messageInViewport');
45 onAddChild: function(child) {
46 this.queue.push(child);
47 this.lazyDecoratorQueue();
50 decorateQueue: function() {
51 var queue = this.queue;
54 queue.forEach(function(child) {
55 if (this.isElementVisible(child.el)) child.trigger('messageInViewport');
59 // Give an element tells you if it's on screen or above/below the fold
60 isElementVisible: function(el) {
61 var rect = el.getBoundingClientRect();
63 rect.bottom >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight)
67 // Trigger an event on the view after scrolling to keep track of the most centered element on screen
68 trackViewport: function() {
69 this.view.triggerMethod('trackViewportCenter');
72 // Disable hover and other pointer events while scrolling
73 disablePointerEvents: function() {
74 if (this.wrapper && !this.wrapper.classList.contains('disable-hover'))
75 this.wrapper.classList.add('disable-hover');
78 enablePointerEvents: function() {
79 if (this.wrapper) this.wrapper.classList.remove('disable-hover');
82 smoothScroll: function() {
83 this.disablePointerEvents();
86 this.lazyPointerEvents();
89 onDestroy: function() {
90 passiveEventListener.removeEventListener(this.scrollElement, 'scroll', this.scrollHandler);
94 behaviourLookup.register('SmoothScroll', Behavior);
95 module.exports = Behavior;