react-stickynode
Advanced tools
Comparing version
@@ -86,4 +86,4 @@ /** | ||
this.state = { | ||
top: 0, // A top offset px from screen top for Sticky when scrolling down | ||
bottom: 0, // A bottom offset px from screen top for Sticky when scrolling up *1* | ||
top: 0, // A top offset from viewport top where Sticky sticks to when scrolling up | ||
bottom: 0, // A bottom offset from viewport top where Sticky sticks to when scrolling down | ||
width: 0, // Sticky width | ||
@@ -225,15 +225,2 @@ height: 0, // Sticky height | ||
* Update Sticky position. | ||
* In this function, all coordinates of Sticky and scren are projected to document, so the local variables | ||
* "top"/"bottom" mean the expected top/bottom of Sticky on document. They will move when scrolling. | ||
* | ||
* There are 2 principles to make sure Sticky won't get wrong so much: | ||
* 1. Reset Sticky to the original postion when "top" <= topBoundary | ||
* 2. Release Sticky to the bottom boundary when "bottom" >= bottomBoundary | ||
* | ||
* If "top" and "bottom" are between the boundaries, Sticky will always fix to the top of screen | ||
* when it is shorter then screen. If Sticky is taller then screen, then it will | ||
* 1. Fix to the bottom of screen when scrolling down and "bottom" > Sticky current bottom | ||
* 2. Fix to the top of screen when scrolling up and "top" < Sticky current top | ||
* (The above 2 points act kind of "bottom" dragging Sticky down or "top" dragging it up.) | ||
* 3. Release Sticky when "top" and "bottom" are between Sticky current top and bottom. | ||
*/ | ||
@@ -254,8 +241,15 @@ }, { | ||
var delta = scrollDelta; | ||
// "top" and "bottom" are the positions that self.state.top and self.state.bottom project | ||
// on document from viewport. | ||
var top = scrollTop + self.state.top; | ||
var bottom = scrollTop + self.state.bottom; | ||
// There are 2 principles to make sure Sticky won't get wrong so much: | ||
// 1. Reset Sticky to the original postion when "top" <= topBoundary | ||
// 2. Release Sticky to the bottom boundary when "bottom" >= bottomBoundary | ||
if (top <= self.state.topBoundary) { | ||
// #1 | ||
self.reset(); | ||
} else if (bottom >= self.state.bottomBoundary) { | ||
// #2 | ||
self.stickyBottom = self.state.bottomBoundary; | ||
@@ -266,3 +260,3 @@ self.stickyTop = self.stickyBottom - self.state.height; | ||
if (self.state.height > winHeight - self.state.top) { | ||
// In this case, Sticky is larger then screen minus sticky top | ||
// In this case, Sticky is higher then viewport minus top offset | ||
switch (self.state.status) { | ||
@@ -275,7 +269,8 @@ case STATUS_ORIGINAL: | ||
case STATUS_RELEASED: | ||
// If "top" and "bottom" are inbetween stickyTop and stickyBottom, then Sticky is in | ||
// RELEASE status. Otherwise, it changes to FIXED status, and its bottom sticks to | ||
// viewport bottom when scrolling down, or its top sticks to viewport top when scrolling up. | ||
if (delta > 0 && bottom > self.stickyBottom) { | ||
// scroll down | ||
self.fix(self.state.bottom - self.state.height); | ||
} else if (delta < 0 && top < self.stickyTop) { | ||
// scroll up | ||
this.fix(self.state.top); | ||
@@ -285,16 +280,30 @@ } | ||
case STATUS_FIXED: | ||
var isChanged = true; | ||
if (delta > 0 && self.state.pos === self.state.top) { | ||
// scroll down | ||
var toRelease = true; | ||
var pos = self.state.pos; | ||
var height = self.state.height; | ||
// In regular cases, when Sticky is in FIXED status, | ||
// 1. it's top will stick to the screen top, | ||
// 2. it's bottom will stick to the screen bottom, | ||
// 3. if not the cases above, then it's height gets changed | ||
if (delta > 0 && pos === self.state.top) { | ||
// case 1, and scrolling down | ||
self.stickyTop = top - delta; | ||
self.stickyBottom = self.stickyTop + self.state.height; | ||
} else if (delta < 0 && self.state.pos === self.state.bottom - self.state.height) { | ||
// up | ||
self.stickyBottom = self.stickyTop + height; | ||
} else if (delta < 0 && pos === self.state.bottom - height) { | ||
// case 2, and scrolling up | ||
self.stickyBottom = bottom - delta; | ||
self.stickyTop = self.stickyBottom - self.state.height; | ||
self.stickyTop = self.stickyBottom - height; | ||
} else if (pos !== self.state.bottom - height && pos !== self.state.top) { | ||
// case 3 | ||
// This case only happens when Sticky's bottom sticks to the screen bottom and | ||
// its height gets changed. Sticky should be in RELEASE status and update its | ||
// sticky bottom by calculating how much height it changed. | ||
var deltaHeight = pos + height - self.state.bottom; | ||
self.stickyBottom = bottom - delta + deltaHeight; | ||
self.stickyTop = self.stickyBottom - height; | ||
} else { | ||
isChanged = false; | ||
toRelease = false; | ||
} | ||
if (isChanged) { | ||
if (toRelease) { | ||
self.release(self.stickyTop); | ||
@@ -305,2 +314,4 @@ } | ||
} else { | ||
// In this case, Sticky is shorter then viewport minus top offset | ||
// and will always fix to the top offset of viewport | ||
self.fix(self.state.top); | ||
@@ -328,5 +339,9 @@ } | ||
var self = this; | ||
// when mount, the scrollTop is not necessary on the top | ||
scrollTop = docBody.scrollTop + docEl.scrollTop; | ||
if (self.props.enabled) { | ||
self.setState({ activated: true }); | ||
self.updateInitialDimension(); | ||
this.update(); | ||
self.subscribers = [(0, _subscribeUiEvent.subscribe)('scrollStart', self.handleScrollStart.bind(self), { useRAF: true }), (0, _subscribeUiEvent.subscribe)('scroll', self.handleScroll.bind(self), { useRAF: true, enableScrollInfo: true }), (0, _subscribeUiEvent.subscribe)('resize', self.handleResize.bind(self), { enableResizeInfo: true })]; | ||
@@ -333,0 +348,0 @@ } |
{ | ||
"name": "react-stickynode", | ||
"version": "1.0.14", | ||
"version": "1.0.15", | ||
"description": "A performant and comprehensive React sticky", | ||
@@ -40,12 +40,12 @@ "main": "index.js", | ||
"es5-shim": "^4.0.0", | ||
"eslint-plugin-react": "^3.4.2", | ||
"eslint": "^1.5.1", | ||
"eslint-plugin-react": "^4.2.3", | ||
"eslint": "^2.4.0", | ||
"expect.js": "^0.3.1", | ||
"grunt-atomizer": "^3.0.0", | ||
"grunt-babel": "^5.0.0", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-clean": "^0.7.0", | ||
"grunt-contrib-connect": "^0.11.2", | ||
"grunt-contrib-jshint": "^0.11.2", | ||
"grunt-contrib-watch": "^0.6.1", | ||
"grunt-cli": "^1.1.0", | ||
"grunt-contrib-clean": "^1.0.0", | ||
"grunt-contrib-connect": "^1.0.0", | ||
"grunt-contrib-jshint": "^1.0.0", | ||
"grunt-contrib-watch": "^1.0.0", | ||
"grunt-saucelabs": "^8.3.2", | ||
@@ -56,3 +56,3 @@ "grunt-shell": "^1.1.2", | ||
"istanbul": "^0.4.0", | ||
"jsdom": "^7.0.2", | ||
"jsdom": "^8.0.0", | ||
"jsx-loader": "^0.13.2", | ||
@@ -59,0 +59,0 @@ "jsx-test": "^0.8.0", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
38633
3.82%683
2.09%