|
21 | 21 | DOWN: 'DOWN' |
22 | 22 | }; |
23 | 23 |
|
24 | | - function ScrollStickyWithContentsListener($sticky, $container, stickyTopOffset, stickyBottomOffset, triggerOffset) { |
| 24 | + function ScrollStickyWithContentsListener($sticky, $container, stickyOffsetTop, stickyOffsetBottom, triggerOffset) { |
25 | 25 | ScrollProxyListener.call(this); |
26 | 26 |
|
27 | 27 | this.latestKnownScrollY = 0; |
|
31 | 31 | this.$sticky = $sticky; |
32 | 32 | this.$container = $container; |
33 | 33 |
|
| 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 | + |
34 | 40 | this.maxStickyTranslate = -1; |
| 41 | + this.maxStickyInnerTranslateY = 0; |
35 | 42 | this.containerHeight = -1; |
36 | 43 | 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; |
43 | 45 |
|
44 | 46 | this.stickyRect = {}; |
45 | 47 |
|
46 | | - this.init = function() { |
| 48 | + this.init = function () { |
| 49 | + this.setState(ScrollProxyListener.STATE.RUNNING); |
47 | 50 | this.reset(); |
48 | 51 |
|
49 | 52 | this.latestKnownScrollY = window.pageYOffset; |
50 | 53 |
|
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); |
56 | 57 | this.stickyOffsetLeft = Math.floor(DomHelpers.getViewportData(this.$sticky.get(0), this.viewportSize).rect.left); |
57 | 58 |
|
| 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 | + |
58 | 65 | this.onScroll(); |
59 | 66 | this.render(); |
60 | 67 | }; |
61 | 68 |
|
| 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 | + |
62 | 89 | this.render = function () { |
63 | | - var stickyTranslate = 0, |
64 | | - stickyExceedsViewport = this.stickyHeight > this.viewportSize.height; |
| 90 | + if (!this.needsRender) return; |
65 | 91 |
|
66 | 92 | if (this.containerOffsetTop - this.triggerOffset < 0) { |
| 93 | + var maxST = this.stickyExceedsViewport ? this.maxStickyTranslate + this.maxStickyInnerTranslateY + this.stickyOffsetTop : this.maxStickyTranslate; |
| 94 | + |
67 | 95 | 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; |
71 | 97 |
|
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: '' }); |
74 | 100 | } else { |
75 | 101 | var top = 0; |
76 | | - if (stickyExceedsViewport) { |
| 102 | + if (this.stickyExceedsViewport) { |
77 | 103 | if (isNaN(this.latestKnownScrollYDelta)) { |
78 | 104 | if (this.scrollDirection === SCROLL_DIRECTION.UP) { |
79 | 105 | this.latestKnownScrollYDelta = 0; |
80 | 106 | } else { |
81 | | - this.latestKnownScrollYDelta = - maxStickyInnerTranslateY; |
| 107 | + this.latestKnownScrollYDelta = -this.maxStickyInnerTranslateY; |
82 | 108 | } |
83 | 109 | } |
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)); |
85 | 112 | } else { |
86 | | - top = this.stickyTopOffset; |
| 113 | + top = this.stickyOffsetTop; |
87 | 114 | } |
88 | 115 | TweenLite.set(this.$sticky, { position: 'fixed', top: 0, y: top, left: this.stickyOffsetLeft, width: this.stickyWidth }); |
89 | 116 | } |
90 | 117 | } else { |
91 | | - TweenLite.set(this.$sticky, { clearProps: 'all' }); |
| 118 | + TweenLite.set(this.$sticky, {clearProps: 'all'}); |
92 | 119 | } |
93 | 120 | }; |
94 | 121 |
|
95 | 122 | this.onScroll = function (latestKnownScrollPosition) { |
| 123 | + if (!this.observeScroll) return; |
| 124 | + |
| 125 | + |
96 | 126 | if (latestKnownScrollPosition === undefined) { |
97 | 127 | latestKnownScrollPosition = DomHelpers.getScrollPosition(); |
98 | 128 | } |
|
102 | 132 | this.latestKnownScrollY = latestKnownScrollPosition.y; |
103 | 133 |
|
104 | 134 | 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; |
106 | 136 | }; |
107 | 137 |
|
108 | | - this.onResize = function(viewportSize) { |
| 138 | + this.onResize = function (viewportSize) { |
109 | 139 | this.viewportSize = viewportSize; |
110 | 140 | this.init(); |
111 | 141 | }; |
112 | 142 |
|
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'}); |
115 | 146 | }; |
116 | 147 | } |
117 | 148 |
|
|
0 commit comments