|
| 1 | +<% if (router.scrollBehavior) { %> |
| 2 | +<%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> |
| 3 | +export default <%= serializeFunction(router.scrollBehavior) %> |
| 4 | + <%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %> |
| 5 | + <% } else { %>import { getMatchedComponents } from './utils' |
| 6 | + |
| 7 | + if (process.client) { |
| 8 | + if ('scrollRestoration' in window.history) { |
| 9 | + window.history.scrollRestoration = 'manual' |
| 10 | + |
| 11 | + // reset scrollRestoration to auto when leaving page, allowing page reload |
| 12 | + // and back-navigation from other pages to use the browser to restore the |
| 13 | + // scrolling position. |
| 14 | + window.addEventListener('beforeunload', () => { |
| 15 | + window.history.scrollRestoration = 'auto' |
| 16 | + }) |
| 17 | + |
| 18 | + // Setting scrollRestoration to manual again when returning to this page. |
| 19 | + window.addEventListener('load', () => { |
| 20 | + window.history.scrollRestoration = 'manual' |
| 21 | + }) |
| 22 | + } |
| 23 | + } |
| 24 | + |
| 25 | +export default function (to, from, savedPosition) { |
| 26 | + // if the returned position is falsy or an empty object, |
| 27 | + // will retain current scroll position. |
| 28 | + let position = false |
| 29 | + |
| 30 | + // if no children detected and scrollToTop is not explicitly disabled |
| 31 | + const Pages = getMatchedComponents(to) |
| 32 | + if ( |
| 33 | + Pages.length < 2 && |
| 34 | + Pages.every(Page => Page.options.scrollToTop !== false) |
| 35 | + ) { |
| 36 | + // scroll to the top of the page |
| 37 | + position = { x: 0, y: 0 } |
| 38 | + } else if (Pages.some(Page => Page.options.scrollToTop)) { |
| 39 | + // if one of the children has scrollToTop option set to true |
| 40 | + position = { x: 0, y: 0 } |
| 41 | + } |
| 42 | + |
| 43 | + // savedPosition is only available for popstate navigations (back button) |
| 44 | + if (savedPosition) { |
| 45 | + position = savedPosition |
| 46 | + } |
| 47 | + |
| 48 | + const nuxt = window.<%= globals.nuxt %> |
| 49 | + |
| 50 | + // triggerScroll is only fired when a new component is loaded |
| 51 | + if (to.path === from.path && to.hash !== from.hash) { |
| 52 | + nuxt.$nextTick(() => nuxt.$emit('triggerScroll')) |
| 53 | + } |
| 54 | + |
| 55 | + return new Promise((resolve) => { |
| 56 | + // wait for the out transition to complete (if necessary) |
| 57 | + nuxt.$once('triggerScroll', () => { |
| 58 | + // coords will be used if no selector is provided, |
| 59 | + // or if the selector didn't match any element. |
| 60 | + if (to.hash) { |
| 61 | + let hash = to.hash |
| 62 | + // CSS.escape() is not supported with IE and Edge. |
| 63 | + if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') { |
| 64 | + hash = '#' + window.CSS.escape(hash.substr(1)) |
| 65 | + } |
| 66 | + try { |
| 67 | + if (document.querySelector(hash)) { |
| 68 | + // scroll to anchor by returning the selector |
| 69 | + position = { selector: hash, offset: {x:0, y: 100} } |
| 70 | + } |
| 71 | + } catch (e) { |
| 72 | + <%= isTest ? '// eslint-disable-next-line no-console' : '' %> |
| 73 | + console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).') |
| 74 | + } |
| 75 | + } |
| 76 | + resolve(position) |
| 77 | + }) |
| 78 | + }) |
| 79 | + } |
| 80 | +<% } %> |
0 commit comments