Update url when scrolling in default theme

This commit is contained in:
Samy Pesse
2016-12-04 20:27:44 +01:00
parent 7d05f8cb89
commit f3af207e6e
2 changed files with 92 additions and 5 deletions
@@ -4,10 +4,81 @@ const { React } = GitBook;
const Page = require('./Page');
const Toolbar = require('./Toolbar');
const HEADINGS_SELECTOR = 'h1[id],h2[id],h3[id],h4[id]';
/**
* Get offset of an element relative to a parent container.
* @param {DOMElement} container
* @param {DOMElement} element
* @return {Number} offset
*/
function getOffset(container, element, type = 'Top') {
const parent = element.parentElement;
let base = 0;
if (parent != container) {
base = getOffset(container, parent, type);
}
return base + element[`offset${type}`];
}
/**
* Find the current heading anchor for a scroll position.
* @param {DOMElement} container
* @param {Number} top
* @return {String}
*/
function getHeadingID(container, top) {
let id;
const headings = container.querySelectorAll(HEADINGS_SELECTOR);
headings.forEach(heading => {
if (id) {
return;
}
const offset = getOffset(container, heading);
if (offset > top) {
id = heading.getAttribute('id');
}
});
return id;
}
const Body = React.createClass({
propTypes: {
page: GitBook.PropTypes.Page,
readme: GitBook.PropTypes.Readme
page: GitBook.PropTypes.Page,
readme: GitBook.PropTypes.Readme,
history: GitBook.PropTypes.History,
updateURI: React.PropTypes.func
},
/**
* User is scrolling the page, update the location with current section's ID.
*/
onScroll(event) {
const { history, updateURI } = this.props;
const { location } = history;
const container = event.target;
// Find the id matching the current scroll position
const hash = getHeadingID(container, container.scrollTop);
// Update url if changed
if (hash !== location.hash) {
updateURI(location.merge({ hash }));
}
},
/**
* Component has been updated with a new location,
* scroll to the right anchor.
*/
componentDidUpdate() {
},
render() {
@@ -15,7 +86,10 @@ const Body = React.createClass({
return (
<GitBook.InjectedComponent matching={{ role: 'body:wrapper' }}>
<div className="Body page-wrapper">
<div
className="Body page-wrapper"
onScroll={this.onScroll}
>
<GitBook.InjectedComponent matching={{ role: 'toolbar:wrapper' }}>
<Toolbar title={page.title} readme={readme} />
</GitBook.InjectedComponent>
@@ -28,4 +102,13 @@ const Body = React.createClass({
}
});
module.exports = Body;
module.exports = GitBook.connect(Body,
() => {
return {};
},
({ History }, dispatch) => {
return {
updateURI: (location) => dispatch(History.replace(location))
};
}
);
@@ -38,7 +38,11 @@ const Theme = React.createClass({
<Sidebar key={0} summary={summary} />
) : null}
<div key={1} className="Body-Flex">
<Body page={page} readme={readme} />
<Body
page={page}
readme={readme}
history={history}
/>
</div>
</ReactCSSTransitionGroup>
</GitBook.FlexBox>