From 9bdf26b5e733e678bb4d79d6bf82ae3ed46c8b64 Mon Sep 17 00:00:00 2001 From: Nathan Rankin <18nrankin@gmail.com> Date: Sun, 24 Sep 2023 14:44:02 -0400 Subject: [PATCH 1/3] Fix scrolling --- src/core/event/index.js | 64 +++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/src/core/event/index.js b/src/core/event/index.js index 516f1fb27..ca3eec6c6 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -1,4 +1,3 @@ -import Tweezer from 'tweezer.js'; import { isMobile } from '../util/env.js'; import { body, on } from '../util/dom.js'; import * as dom from '../util/dom.js'; @@ -49,40 +48,43 @@ export function Events(Base) { #nav = {}; #hoverOver = false; - #scroller = null; #enableScrollEvent = true; #coverHeight = 0; - #scrollTo(el, offset = 0) { - if (this.#scroller) { - this.#scroller.stop(); - } - + #scrollTo(el) { this.#enableScrollEvent = false; - this.#scroller = new Tweezer({ - start: window.pageYOffset, - end: - Math.round(el.getBoundingClientRect().top) + - window.pageYOffset - - offset, - duration: 500, - }) - .on('tick', v => window.scrollTo(0, v)) - .on('done', () => { + el.scrollIntoView({ behavior: 'smooth' }); + + // Determine when scrolling has stopped + let prevTop; + const intervalId = setInterval(() => { + const top = el.getBoundingClientRect().top; + if (top === prevTop) { + clearInterval(intervalId); this.#enableScrollEvent = true; - this.#scroller = null; - }) - .begin(); + } + prevTop = top; + }, 500); } - #highlight(path) { + #interval; + async #highlight(path) { + let delayed = false; if (!this.#enableScrollEvent) { - return; + delayed = true; + clearInterval(this.#interval); + await new Promise(resolve => { + this.#interval = setInterval(() => { + if (this.#enableScrollEvent) { + clearInterval(this.#interval); + resolve(); + } + }, 100); + }); } const sidebar = dom.getNode('.sidebar'); const anchors = dom.findAll('.anchor'); - const wrap = dom.find(sidebar, '.sidebar-nav'); let active = dom.find(sidebar, 'li.active'); const doc = document.documentElement; const top = @@ -107,7 +109,7 @@ export function Events(Base) { const li = this.#nav[this.#getNavKey(path, last.getAttribute('data-id'))]; - if (!li || li === active) { + if (!li || (li === active && !delayed)) { return; } @@ -116,20 +118,8 @@ export function Events(Base) { active = li; // Scroll into view - // https://github.com/vuejs/vuejs.org/blob/master/themes/vue/source/js/common.js#L282-L297 if (!this.#hoverOver && dom.body.classList.contains('sticky')) { - const height = sidebar.clientHeight; - const curOffset = 0; - const cur = active.offsetTop + active.clientHeight + 40; - const isInView = - active.offsetTop >= wrap.scrollTop && cur <= wrap.scrollTop + height; - const notThan = cur - curOffset < height; - - sidebar.scrollTop = isInView - ? wrap.scrollTop - : notThan - ? curOffset - : cur - height; + active.scrollIntoView(); } } From 5cb872b3b84f49b962ecfbddba9675c4ee5453ff Mon Sep 17 00:00:00 2001 From: Nathan Rankin <18nrankin@gmail.com> Date: Sun, 24 Sep 2023 15:22:29 -0400 Subject: [PATCH 2/3] Fix scroll to top --- src/core/event/index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/event/index.js b/src/core/event/index.js index ca3eec6c6..c79181e72 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -1,8 +1,8 @@ -import { isMobile } from '../util/env.js'; -import { body, on } from '../util/dom.js'; -import * as dom from '../util/dom.js'; -import { removeParams } from '../router/util.js'; import config from '../config.js'; +import { removeParams } from '../router/util.js'; +import * as dom from '../util/dom.js'; +import { body, on } from '../util/dom.js'; +import { isMobile } from '../util/env.js'; /** @typedef {import('../Docsify.js').Constructor} Constructor */ @@ -17,14 +17,14 @@ export function Events(Base) { // If 'history', rely on the browser's scroll auto-restoration when going back or forward if (source !== 'history') { - // Scroll to ID if specified - if (this.route.query.id) { - this.#scrollIntoView(this.route.path, this.route.query.id); - } // Scroll to top if a link was clicked and auto2top is enabled if (source === 'navigate') { auto2top && this.#scroll2Top(auto2top); } + // Scroll to ID if specified + if (this.route.query.id) { + this.#scrollIntoView(this.route.path, this.route.query.id); + } } if (this.config.loadNavbar) { From 87c7e077d70dfacb990e57b542a0e14a1b0ab69f Mon Sep 17 00:00:00 2001 From: Nathan Rankin <18nrankin@gmail.com> Date: Sun, 24 Sep 2023 15:40:07 -0400 Subject: [PATCH 3/3] Wait for document load --- src/core/event/index.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/core/event/index.js b/src/core/event/index.js index c79181e72..c6cf10a6a 100644 --- a/src/core/event/index.js +++ b/src/core/event/index.js @@ -50,33 +50,47 @@ export function Events(Base) { #hoverOver = false; #enableScrollEvent = true; #coverHeight = 0; - - #scrollTo(el) { + #delayScrollInterval; + async #scrollTo(el) { this.#enableScrollEvent = false; + + if (document.readyState !== 'complete') { + clearInterval(this.#delayScrollInterval); + await new Promise(resolve => { + this.#delayScrollInterval = setInterval(() => { + if (document.readyState === 'complete') { + clearInterval(this.#delayScrollInterval); + resolve(); + } + }, 100); + }); + } + el.scrollIntoView({ behavior: 'smooth' }); // Determine when scrolling has stopped let prevTop; - const intervalId = setInterval(() => { + const completeIntervalId = setInterval(() => { const top = el.getBoundingClientRect().top; if (top === prevTop) { - clearInterval(intervalId); + console.log('clearing'); + clearInterval(completeIntervalId); this.#enableScrollEvent = true; } prevTop = top; }, 500); } - #interval; + #delayHighlightInterval; async #highlight(path) { let delayed = false; if (!this.#enableScrollEvent) { delayed = true; - clearInterval(this.#interval); + clearInterval(this.#delayHighlightInterval); await new Promise(resolve => { - this.#interval = setInterval(() => { + this.#delayHighlightInterval = setInterval(() => { if (this.#enableScrollEvent) { - clearInterval(this.#interval); + clearInterval(this.#delayHighlightInterval); resolve(); } }, 100);