Skip to content

Commit d164d40

Browse files
author
Mikel Tuesta
committed
Refactored ScrollStickyWithContentsListener. Updated ScrollProxyListener base object to track the object's state.
1 parent 94252a3 commit d164d40

3 files changed

Lines changed: 81 additions & 30 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "foes-scrollproxy",
3-
"version": "0.4.0",
3+
"version": "0.4.1",
44
"license": "MIT",
55
"description": "",
66
"keywords": [

src/Core/ScrollProxyListener.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
(function(window, DomHelpers, undefined) {
2020

2121
function ScrollProxyListener() {
22+
this.state = undefined;
2223
this.viewportSize = DomHelpers.getViewportSize();
2324
this.latestKnownScrollPosition = undefined;
2425

@@ -37,8 +38,27 @@
3738
this.onResize = function (viewportSize) {
3839
this.viewportSize = viewportSize;
3940
};
41+
/**
42+
* @param state
43+
*/
44+
this.setState = function(state) {
45+
this.state = state;
46+
this.onStateChanged(this.state);
47+
};
48+
49+
/**
50+
* @param state
51+
*/
52+
this.onStateChanged = function(state) {
53+
54+
};
4055
}
4156

57+
ScrollProxyListener.STATE = {
58+
IDLE: 'IDLE',
59+
RUNNING: 'RUNNING'
60+
};
61+
4262
// Expose ScrollProxyListener
4363
window.ScrollProxyListener = ScrollProxyListener;
4464

src/Plugins/ScrollStickyWithContentsListener.js

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
DOWN: 'DOWN'
2222
};
2323

24-
function ScrollStickyWithContentsListener($sticky, $container, stickyTopOffset, stickyBottomOffset, triggerOffset) {
24+
function ScrollStickyWithContentsListener($sticky, $container, stickyOffsetTop, stickyOffsetBottom, triggerOffset) {
2525
ScrollProxyListener.call(this);
2626

2727
this.latestKnownScrollY = 0;
@@ -31,68 +31,98 @@
3131
this.$sticky = $sticky;
3232
this.$container = $container;
3333

34+
this.triggerOffset = triggerOffset !== undefined ? triggerOffset : 0;
35+
this.stickyOffsetTop = stickyOffsetTop !== undefined ? stickyOffsetTop : 0;
36+
this.stickyOffsetBottom = stickyOffsetBottom !== undefined ? stickyOffsetBottom : 0;
37+
this.stickyOffsetLeft = -1;
38+
this.containerOffsetTop = -1;
39+
3440
this.maxStickyTranslate = -1;
41+
this.maxStickyInnerTranslateY = 0;
3542
this.containerHeight = -1;
3643
this.stickyHeight = -1;
37-
38-
this.stickyTopOffset = typeof stickyTopOffset !== 'undefined' ? stickyTopOffset : 0;
39-
this.stickyBottomOffset = typeof stickyBottomOffset !== 'undefined' ? stickyBottomOffset : 0;
40-
this.containerOffsetTop = -1;
41-
this.stickyOffsetLeft = -1;
42-
this.triggerOffset = typeof triggerOffset !== 'undefined' ? triggerOffset : 0;
44+
this.stickyExceedsViewport = false;
4345

4446
this.stickyRect = {};
4547

46-
this.init = function() {
48+
this.init = function () {
49+
this.setState(ScrollProxyListener.STATE.RUNNING);
4750
this.reset();
4851

4952
this.latestKnownScrollY = window.pageYOffset;
5053

51-
this.containerHeight = this.$container.height();
52-
this.stickyHeight = this.$sticky.height();
53-
this.stickyWidth = this.$sticky.parent().outerWidth();
54-
55-
this.maxStickyTranslate = Math.max(this.containerHeight - this.stickyHeight - this.stickyTopOffset - this.stickyBottomOffset, 0);
54+
this.containerHeight = this.$container.outerHeight(true);
55+
this.stickyHeight = this.$sticky.outerHeight(true);
56+
this.stickyWidth = this.$sticky.outerWidth(true);
5657
this.stickyOffsetLeft = Math.floor(DomHelpers.getViewportData(this.$sticky.get(0), this.viewportSize).rect.left);
5758

59+
this.stickyFullHeight = this.stickyHeight + this.stickyOffsetTop + this.stickyOffsetBottom;
60+
61+
this.stickyExceedsViewport = this.stickyFullHeight > this.viewportSize.height;
62+
this.maxStickyTranslate = Math.max(this.containerHeight - this.stickyHeight - this.stickyOffsetTop);
63+
this.maxStickyInnerTranslateY = (this.stickyHeight + this.stickyOffsetBottom) - this.viewportSize.height;
64+
5865
this.onScroll();
5966
this.render();
6067
};
6168

69+
this.onStateChanged = function(state) {
70+
switch (state) {
71+
case ScrollProxyListener.STATE.IDLE:
72+
this.setScrollObserve(false);
73+
this.setRenderNeeded(false);
74+
break;
75+
case ScrollProxyListener.STATE.RUNNING:
76+
this.setScrollObserve(true);
77+
this.setRenderNeeded(true);
78+
}
79+
};
80+
81+
this.setScrollObserve = function(observeScroll) {
82+
this.observeScroll = observeScroll;
83+
};
84+
85+
this.setRenderNeeded = function(needsRender) {
86+
this.needsRender = needsRender;
87+
};
88+
6289
this.render = function () {
63-
var stickyTranslate = 0,
64-
stickyExceedsViewport = this.stickyHeight > this.viewportSize.height;
90+
if (!this.needsRender) return;
6591

6692
if (this.containerOffsetTop - this.triggerOffset < 0) {
93+
var maxST = this.stickyExceedsViewport ? this.maxStickyTranslate + this.maxStickyInnerTranslateY + this.stickyOffsetTop : this.maxStickyTranslate;
94+
6795
var absContainerOffsetTop = Math.abs(this.containerOffsetTop),
68-
maxStickyInnerTranslateY = this.stickyHeight - this.viewportSize.height + this.stickyTopOffset + this.stickyBottomOffset,
69-
currentStickyTop = this.stickyRect.top;
70-
stickyTranslate = absContainerOffsetTop >= this.maxStickyTranslate ? this.maxStickyTranslate : absContainerOffsetTop;
96+
stickyTranslate = absContainerOffsetTop >= maxST ? maxST : absContainerOffsetTop;
7197

72-
if (stickyTranslate === this.maxStickyTranslate) {
73-
TweenLite.set(this.$sticky, { position: 'absolute', top: this.maxStickyTranslate, left: '' });
98+
if (stickyTranslate === maxST) {
99+
TweenLite.set(this.$sticky, { position: 'absolute', top: this.maxStickyTranslate + this.stickyOffsetTop, y: '', left: '' });
74100
} else {
75101
var top = 0;
76-
if (stickyExceedsViewport) {
102+
if (this.stickyExceedsViewport) {
77103
if (isNaN(this.latestKnownScrollYDelta)) {
78104
if (this.scrollDirection === SCROLL_DIRECTION.UP) {
79105
this.latestKnownScrollYDelta = 0;
80106
} else {
81-
this.latestKnownScrollYDelta = - maxStickyInnerTranslateY;
107+
this.latestKnownScrollYDelta = -this.maxStickyInnerTranslateY;
82108
}
83109
}
84-
top = Math.floor(Math.min(Math.max(currentStickyTop + this.latestKnownScrollYDelta, - maxStickyInnerTranslateY), this.stickyTopOffset));
110+
111+
top = Math.floor(Math.min(Math.max(this.stickyRect.top + this.latestKnownScrollYDelta, - this.maxStickyInnerTranslateY), this.stickyOffsetTop));
85112
} else {
86-
top = this.stickyTopOffset;
113+
top = this.stickyOffsetTop;
87114
}
88115
TweenLite.set(this.$sticky, { position: 'fixed', top: 0, y: top, left: this.stickyOffsetLeft, width: this.stickyWidth });
89116
}
90117
} else {
91-
TweenLite.set(this.$sticky, { clearProps: 'all' });
118+
TweenLite.set(this.$sticky, {clearProps: 'all'});
92119
}
93120
};
94121

95122
this.onScroll = function (latestKnownScrollPosition) {
123+
if (!this.observeScroll) return;
124+
125+
96126
if (latestKnownScrollPosition === undefined) {
97127
latestKnownScrollPosition = DomHelpers.getScrollPosition();
98128
}
@@ -102,16 +132,17 @@
102132
this.latestKnownScrollY = latestKnownScrollPosition.y;
103133

104134
this.stickyRect = DomHelpers.getViewportData(this.$sticky.get(0), this.viewportSize).rect;
105-
this.containerOffsetTop = Math.floor(DomHelpers.getViewportData(this.$container.get(0), this.viewportSize).rect.top);
135+
this.containerOffsetTop = DomHelpers.getViewportData(this.$container.get(0), this.viewportSize).rect.top;
106136
};
107137

108-
this.onResize = function(viewportSize) {
138+
this.onResize = function (viewportSize) {
109139
this.viewportSize = viewportSize;
110140
this.init();
111141
};
112142

113-
this.reset = function() {
114-
TweenLite.set(this.$sticky, { clearProps: 'all' });
143+
this.reset = function () {
144+
TweenLite.set(this.$container, {position: 'relative'});
145+
TweenLite.set(this.$sticky, {clearProps: 'all'});
115146
};
116147
}
117148

0 commit comments

Comments
 (0)