|
|
|
'use strict';
|
|
|
|
|
|
|
|
var invariant = require('react/lib/invariant');
|
|
|
|
var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM;
|
|
|
|
var getWindowScrollPosition = require('./getWindowScrollPosition');
|
|
|
|
|
|
|
|
function shouldUpdateScroll(state, prevState) {
|
|
|
|
if (!prevState) {
|
|
|
|
return true;
|
|
|
|
} // Don't update scroll position when only the query has changed.
|
|
|
|
if (state.pathname === prevState.pathname) {
|
|
|
|
return false;
|
|
|
|
}var routes = state.routes;
|
|
|
|
var prevRoutes = prevState.routes;
|
|
|
|
|
|
|
|
var sharedAncestorRoutes = routes.filter(function (route) {
|
|
|
|
return prevRoutes.indexOf(route) !== -1;
|
|
|
|
});
|
|
|
|
|
|
|
|
return !sharedAncestorRoutes.some(function (route) {
|
|
|
|
return route.ignoreScrollBehavior;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides the router with the ability to manage window scroll position
|
|
|
|
* according to its scroll behavior.
|
|
|
|
*/
|
|
|
|
var ScrollHistory = {
|
|
|
|
|
|
|
|
statics: {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Records curent scroll position as the last known position for the given URL path.
|
|
|
|
*/
|
|
|
|
recordScrollPosition: function recordScrollPosition(path) {
|
|
|
|
if (!this.scrollHistory) this.scrollHistory = {};
|
|
|
|
|
|
|
|
this.scrollHistory[path] = getWindowScrollPosition();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the last known scroll position for the given URL path.
|
|
|
|
*/
|
|
|
|
getScrollPosition: function getScrollPosition(path) {
|
|
|
|
if (!this.scrollHistory) this.scrollHistory = {};
|
|
|
|
|
|
|
|
return this.scrollHistory[path] || null;
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
componentWillMount: function componentWillMount() {
|
|
|
|
invariant(this.constructor.getScrollBehavior() == null || canUseDOM, 'Cannot use scroll behavior without a DOM');
|
|
|
|
},
|
|
|
|
|
|
|
|
componentDidMount: function componentDidMount() {
|
|
|
|
this._updateScroll();
|
|
|
|
},
|
|
|
|
|
|
|
|
componentDidUpdate: function componentDidUpdate(prevProps, prevState) {
|
|
|
|
this._updateScroll(prevState);
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateScroll: function _updateScroll(prevState) {
|
|
|
|
if (!shouldUpdateScroll(this.state, prevState)) {
|
|
|
|
return;
|
|
|
|
}var scrollBehavior = this.constructor.getScrollBehavior();
|
|
|
|
|
|
|
|
if (scrollBehavior) scrollBehavior.updateScrollPosition(this.constructor.getScrollPosition(this.state.path), this.state.action);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = ScrollHistory;
|