From 033c213cf223f9e83985cf67223872e97ceff9b5 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 21 May 2019 10:22:53 +0200 Subject: [PATCH] fix scrolling for markdown content, which is loaded asynchronous The code to find and scroll to the anchor is now moved from the ScrollToTop component to the MarkdownView. The anchor with the id from location hash, is searched after the MarkdownView and all its children finished rendering. --- .../ui-components/src/MarkdownView.js | 42 +++++++++++++++---- scm-ui/src/containers/ScrollToTop.js | 10 +---- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/scm-ui-components/packages/ui-components/src/MarkdownView.js b/scm-ui-components/packages/ui-components/src/MarkdownView.js index 164c06b84a..4620004f59 100644 --- a/scm-ui-components/packages/ui-components/src/MarkdownView.js +++ b/scm-ui-components/packages/ui-components/src/MarkdownView.js @@ -4,12 +4,17 @@ import SyntaxHighlighter from "./SyntaxHighlighter"; import Markdown from "react-markdown/with-html"; import {binder} from "@scm-manager/ui-extensions"; import MarkdownHeadingRenderer from "./MarkdownHeadingRenderer"; +import { withRouter } from "react-router-dom"; + type Props = { content: string, renderContext?: Object, renderers?: Object, - enableAnchorHeadings: boolean + enableAnchorHeadings: boolean, + + // context props + location: any }; class MarkdownView extends React.Component { @@ -18,10 +23,27 @@ class MarkdownView extends React.Component { enableAnchorHeadings: false }; + contentRef: ?HTMLDivElement; + constructor(props: Props) { super(props); } + componentDidUpdate() { + // we have to use componentDidUpdate, because we have to wait until all + // children are rendered and componentDidMount is called before the + // markdown content was rendered. + const hash = this.props.location.hash; + if (this.contentRef && hash) { + // we query only child elements, to avoid strange scrolling with multiple + // markdown elements on one page. + const element = this.contentRef.querySelector(hash); + if (element && element.scrollIntoView) { + element.scrollIntoView(); + } + } + } + render() { const {content, renderers, renderContext, enableAnchorHeadings} = this.props; @@ -45,15 +67,17 @@ class MarkdownView extends React.Component { } return ( - +
(this.contentRef = el)}> + +
); } } -export default MarkdownView; +export default withRouter(MarkdownView); diff --git a/scm-ui/src/containers/ScrollToTop.js b/scm-ui/src/containers/ScrollToTop.js index 77054b8463..d48ea6531a 100644 --- a/scm-ui/src/containers/ScrollToTop.js +++ b/scm-ui/src/containers/ScrollToTop.js @@ -11,15 +11,7 @@ type Props = { class ScrollToTop extends React.Component { componentDidUpdate(prevProps) { if (this.props.location.pathname !== prevProps.location.pathname) { - const hash = this.props.location.hash; - if (hash) { - const element = document.getElementById(hash.substring(1)); - if (element && element.scrollIntoView) { - element.scrollIntoView(); - } - } else { - window.scrollTo(0, 0); - } + window.scrollTo(0, 0); } }