diff options
author | Samy Pesse <samypesse@gmail.com> | 2016-12-04 20:27:44 +0100 |
---|---|---|
committer | Samy Pesse <samypesse@gmail.com> | 2016-12-04 20:27:44 +0100 |
commit | f3af207e6ed786dd817c4a1c4d73efd083afd298 (patch) | |
tree | fcede9ff6de1cef78fc428b2c3e2eea275f67af6 | |
parent | 7d05f8cb89790dc5d30442ce8d6dbd6c7d2edeba (diff) | |
download | gitbook-f3af207e6ed786dd817c4a1c4d73efd083afd298.zip gitbook-f3af207e6ed786dd817c4a1c4d73efd083afd298.tar.gz gitbook-f3af207e6ed786dd817c4a1c4d73efd083afd298.tar.bz2 |
Update url when scrolling in default theme
-rw-r--r-- | packages/gitbook-plugin-theme-default/src/components/Body.js | 91 | ||||
-rw-r--r-- | packages/gitbook-plugin-theme-default/src/components/Theme.js | 6 |
2 files changed, 92 insertions, 5 deletions
diff --git a/packages/gitbook-plugin-theme-default/src/components/Body.js b/packages/gitbook-plugin-theme-default/src/components/Body.js index 993b20d..6332218 100644 --- a/packages/gitbook-plugin-theme-default/src/components/Body.js +++ b/packages/gitbook-plugin-theme-default/src/components/Body.js @@ -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)) + }; + } +); diff --git a/packages/gitbook-plugin-theme-default/src/components/Theme.js b/packages/gitbook-plugin-theme-default/src/components/Theme.js index b8cf89e..b323fc4 100644 --- a/packages/gitbook-plugin-theme-default/src/components/Theme.js +++ b/packages/gitbook-plugin-theme-default/src/components/Theme.js @@ -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> |