From 90c30f21c1eb50a610eae9ea2ed2731969660237 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Mon, 21 Jul 2025 11:34:58 +0200 Subject: [PATCH] Autoscroll --- public/js/components/Calendar/Base/Grid.js | 55 +++++++++++++++++++++- public/js/components/Calendar/Mode/Day.js | 6 +++ public/js/components/Calendar/Mode/Week.js | 8 +++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js index c6b7dd2a3..f9f55bd63 100644 --- a/public/js/components/Calendar/Base/Grid.js +++ b/public/js/components/Calendar/Base/Grid.js @@ -57,7 +57,10 @@ export default { }, data() { return { - dragging: false + dragging: false, + resizeObserver: null, + mutationObserver: null, + userScroll: true }; }, computed: { @@ -255,8 +258,56 @@ export default { } return dayTimestamp + this.start + Math.floor((this.end - this.start) * mouseFrac); + }, + + /* SCROLLING */ + enableAutoScroll() { + if (!this.resizeObserver) + this.resizeObserver = new ResizeObserver(this.scrollToEarliestEvent); + this.resizeObserver.observe(this.$refs.body); + + if (!this.mutationObserver) + this.mutationObserver = new MutationObserver(mutations => { + if (mutations.some(m => [].some.call(m.addedNodes, el => el.matches('.fhc-calendar-base-grid-line-event')))) + this.scrollToEarliestEvent(); + }); + this.mutationObserver.observe(this.$refs.body, { + subtree: true, + childList: true + }); + + this.scrollToEarliestEvent(); + }, + disableAutoScroll() { + if (this.resizeObserver) + this.resizeObserver.disconnect(); + this.resizeObserver = null; + + if (this.mutationObserver) + this.mutationObserver.disconnect(); + this.mutationObserver = null; + }, + scrollToEarliestEvent() { + const eventElements = this.$refs.scroller.querySelectorAll('.fhc-calendar-base-grid-line-event'); + const earliestEventOffset = eventElements.values() + .reduce((res, el) => { + const top = el.offsetTop; + if (!res[1] || top < res[0]) + return [top, el]; + return res; + }, [0, null]); + + this.userScroll = false; + if (earliestEventOffset[1]) { + earliestEventOffset[1].scrollIntoView({ behavior: "smooth" }); + } else { + this.$refs.scroller.scrollTo(0, 0); + } } }, + beforeUnmount() { + this.disableAutoScroll(); + }, template: /* html */`
diff --git a/public/js/components/Calendar/Mode/Day.js b/public/js/components/Calendar/Mode/Day.js index bc0896888..68ca1fa89 100644 --- a/public/js/components/Calendar/Mode/Day.js +++ b/public/js/components/Calendar/Mode/Day.js @@ -46,6 +46,7 @@ export default { currentDate() { this.rangeOffset = this.currentDate.startOf('day').diff(this.focusDate.startOf('day'), 'days').days; if (this.rangeOffset) { + this.$refs.view.$refs.grid.disableAutoScroll(); this.$emit('update:range', this.range); this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage); } @@ -54,11 +55,13 @@ export default { methods: { prevPage() { this.rangeOffset = this.$refs.slider.target - 1; + this.$refs.view.$refs.grid.disableAutoScroll(); this.$emit('update:range', this.range); this.$refs.slider.prevPage().then(this.updatePage); }, nextPage() { this.rangeOffset = this.$refs.slider.target + 1; + this.$refs.view.$refs.grid.disableAutoScroll(); this.$emit('update:range', this.range); this.$refs.slider.nextPage().then(this.updatePage); }, @@ -68,6 +71,7 @@ export default { this.rangeOffset = 0; this.$emit('update:currentDate', this.focusDate); this.$emit('update:range', this.range); + this.$refs.view.$refs.grid.enableAutoScroll(); }, viewAttrs(days) { const day = this.focusDate.plus({ days }); @@ -76,6 +80,7 @@ export default { }, mounted() { this.$emit('update:range', this.range); + this.$refs.view.$refs.grid.enableAutoScroll(); }, template: `
- +