summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pesse <samypesse@gmail.com>2016-12-04 20:27:44 +0100
committerSamy Pesse <samypesse@gmail.com>2016-12-04 20:27:44 +0100
commitf3af207e6ed786dd817c4a1c4d73efd083afd298 (patch)
treefcede9ff6de1cef78fc428b2c3e2eea275f67af6
parent7d05f8cb89790dc5d30442ce8d6dbd6c7d2edeba (diff)
downloadgitbook-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.js91
-rw-r--r--packages/gitbook-plugin-theme-default/src/components/Theme.js6
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>