You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.4 KiB

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