Created
July 17, 2016 16:26
-
-
Save ahomu/3ead2f992541f42d731113d8d3c54ef5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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