diff --git a/webapp/app/router.scrollBehavior.js b/webapp/app/router.scrollBehavior.js new file mode 100644 index 000000000..041310f9c --- /dev/null +++ b/webapp/app/router.scrollBehavior.js @@ -0,0 +1,7 @@ +export default function(to, from, savedPosition) { + let position = { x: 0, y: 0 } + if (savedPosition) { + position = savedPosition + } + return position +} diff --git a/webapp/components/Comment.vue b/webapp/components/Comment.vue index 2cebde0b6..b1a75f896 100644 --- a/webapp/components/Comment.vue +++ b/webapp/components/Comment.vue @@ -79,8 +79,10 @@ import ContentMenu from '~/components/ContentMenu' import ContentViewer from '~/components/Editor/ContentViewer' import HcCommentForm from '~/components/CommentForm/CommentForm' import CommentMutations from '~/graphql/CommentMutations' +import scrollToAnchor from '~/mixins/scrollToAnchor.js' export default { + mixins: [scrollToAnchor], data: function() { return { isCollapsed: true, diff --git a/webapp/components/CommentList/CommentList.spec.js b/webapp/components/CommentList/CommentList.spec.js index 3e77d84fb..460f1a4ea 100644 --- a/webapp/components/CommentList/CommentList.spec.js +++ b/webapp/components/CommentList/CommentList.spec.js @@ -50,9 +50,6 @@ describe('CommentList.vue', () => { }, }, }, - $route: { - hash: '', - }, } stubs = { EditorContent: "
", diff --git a/webapp/components/CommentList/CommentList.vue b/webapp/components/CommentList/CommentList.vue index b5eb070c8..2013140c1 100644 --- a/webapp/components/CommentList/CommentList.vue +++ b/webapp/components/CommentList/CommentList.vue @@ -32,8 +32,10 @@ diff --git a/webapp/mixins/scrollToAnchor.js b/webapp/mixins/scrollToAnchor.js new file mode 100644 index 000000000..e68658f07 --- /dev/null +++ b/webapp/mixins/scrollToAnchor.js @@ -0,0 +1,32 @@ +export function scrollToAnchor(anchor) { + if (!anchor) return + if (!window || !document) { + return + } + const container = document.querySelector(anchor) + if (container) { + const { top } = container.getBoundingClientRect() + setTimeout(() => { + // we have to set a small timeout to ensure this part comes after nuxt + // scrollBehaviour: https://nuxtjs.org/api/configuration-router/#scrollbehavior + window.scroll({ + top, + left: 0, + behavior: 'smooth', + }) + }, 250) + } +} + +export default { + watch: { + $route(to, from) { + const anchor = to && to.hash + scrollToAnchor(anchor) + }, + }, + mounted() { + const anchor = this.$route && this.$route.hash + scrollToAnchor(anchor) + }, +} diff --git a/webapp/nuxt.config.js b/webapp/nuxt.config.js index 5e7726d43..f1747b479 100644 --- a/webapp/nuxt.config.js +++ b/webapp/nuxt.config.js @@ -124,80 +124,6 @@ export default { middleware: ['authenticated', 'termsAndConditions'], linkActiveClass: 'router-link-active', linkExactActiveClass: 'router-link-exact-active', - scrollBehavior: (to, _from, savedPosition) => { - let position = false - // if no children detected and scrollToTop is not explicitly disabled - if ( - to.matched.length < 2 && - to.matched.every(r => r.components.default.options.scrollToTop !== false) - ) { - // scroll to the top of the page - position = { - x: 0, - y: 0, - } - } else if (to.matched.some(r => r.components.default.options.scrollToTop)) { - // if one of the children has scrollToTop option set to true - position = { - x: 0, - y: 0, - } - } - - // savedPosition is only available for popstate navigations (back button) - if (savedPosition) { - position = savedPosition - } - - return new Promise(resolve => { - // wait for the out transition to complete (if necessary) - window.$nuxt.$once('triggerScroll', () => { - let processInterval = null - let processTime = 0 - const callInterval = 100 - const callIntervalLimit = 2000 - - // coords will be used if no selector is provided, - // or if the selector didn't match any element. - if (to.hash) { - let hash = to.hash - // CSS.escape() is not supported with IE and Edge. - if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') { - hash = '#' + window.CSS.escape(hash.substr(1)) - } - try { - processInterval = setInterval(() => { - const hashIsFound = document.querySelector(hash) - - if (hashIsFound) { - position = { - selector: hash, - offset: { x: 0, y: -500 }, - } - } - processTime += callInterval - if (hashIsFound || processTime >= callIntervalLimit) { - clearInterval(processInterval) - processInterval = null - } - }, callInterval) - } catch (e) { - /* eslint-disable-next-line no-console */ - console.warn( - 'Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).', - ) - } - } - - let resolveInterval = setInterval(() => { - if (!processInterval) { - clearInterval(resolveInterval) - resolve(position) - } - }, callInterval) - }) - }) - }, }, /*