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
;