Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ahomu
Created July 17, 2016 16:26
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahomu/3ead2f992541f42d731113d8d3c54ef5 to your computer and use it in GitHub Desktop.
Save ahomu/3ead2f992541f42d731113d8d3c54ef5 to your computer and use it in GitHub Desktop.
'use strict';
import * as React from 'react';
import * as assign from 'object-assign';
import * as debounce from 'lodash.debounce';
import { appLogger as log } from '../../../utils/Log';
import BaseComponent from '../../base';
const EVENT_SCROLL = 'scroll';
const EVENT_POP_STATE = 'popstate';
const TYPE_CLICK = 'click';
const TYPE_REPLACE_STATE = 'replacestate';
const TYPE_POP_STATE = 'popstate';
const TYPE_DEFAULT = 'default';
export default class ScrollHandler extends BaseComponent {
static propTypes = {
className : React.PropTypes.string,
navigate : React.PropTypes.object
};
static defaultProps = {};
debouncedSaveScrollPosition = null;
_saveScrollPosition() {
const historyState = window.history.state || {};
historyState.scroll = {
x : (window.scrollX !== undefined) ? window.scrollX : document.documentElement.scrollLeft, // for IE10
y : (window.scrollY !== undefined) ? window.scrollY : document.documentElement.scrollTop // for IE10
};
const title = document.title;
const url = location.href;
const newState = assign({ origUrl : url }, historyState);
log.debug(`Save current scroll position: ${historyState.scroll.x}, ${historyState.scroll.y}`);
history.replaceState(newState, title, url);
}
componentDidMount() {
this.debouncedSaveScrollPosition = debounce(this._saveScrollPosition, 300);
window.addEventListener(EVENT_SCROLL, this.debouncedSaveScrollPosition);
window.addEventListener(EVENT_POP_STATE, this._saveScrollPosition);
}
componentWillReceiveProps(nextProps) {
const navigate = nextProps.navigate;
const navParams = navigate.params || {};
const historyState = window.history.state || {};
switch (navigate.type) {
case TYPE_POP_STATE:
const scroll = historyState.scroll || { x : 0, y : 0 };
log.debug(`Restore backward scroll position: ${scroll.x}, ${scroll.y}`);
setTimeout(() => window.scrollTo(scroll.x, scroll.y), 4);
break;
case TYPE_CLICK:
case TYPE_DEFAULT:
case TYPE_REPLACE_STATE:
default:
if (navigate.preserveScrollPosition) {
historyState.scroll = {
x : (window.scrollX !== undefined) ? window.scrollX : document.documentElement.scrollLeft, // for IE10
y : (window.scrollY !== undefined) ? window.scrollY : document.documentElement.scrollTop // for IE10
};
} else {
historyState.scroll = {
x : 0,
y : 0
};
log.debug(`Adjust forward scroll top: 0, 0`);
window.scrollTo(0, 0);
}
history.replaceState(historyState, navParams.pageTitle, navigate.url);
break;
}
}
shouldComponentUpdate() {
return false;
}
componentWillUnmount() {
this.debouncedSaveScrollPosition.cancel();
window.removeEventListener(EVENT_SCROLL, this.debouncedSaveScrollPosition);
window.removeEventListener(EVENT_POP_STATE, this._saveScrollPosition);
}
render() {
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment