Autoscroll

This commit is contained in:
chfhtw
2025-07-21 11:34:58 +02:00
parent 8191c5e19f
commit 90c30f21c1
3 changed files with 66 additions and 3 deletions
+54 -1
View File
@@ -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 */`
<div
class="fhc-calendar-base-grid"
@@ -302,6 +353,8 @@ export default {
</div>
</div>
<div
ref="scroller"
@scrollend="userScroll ? disableAutoScroll() : userScroll = true"
style="display:grid;overflow:auto"
:style="'grid-' + axisCol + ':1/-1;grid-template-' + axisCol + 's:subgrid'"
>
@@ -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: `
<div
@@ -83,6 +88,7 @@ export default {
>
<base-slider ref="slider" v-slot="slot">
<day-view
ref="view"
v-bind="viewAttrs(slot.offset)"
@request-modal-open="$emit('requestModalOpen', $event)"
@request-modal-close="$emit('requestModalClose', $event)"
+6 -2
View File
@@ -44,12 +44,12 @@ export default {
watch: {
currentDate() {
if (this.currentDate.locale != this.focusDate.locale) {
console.log(this.focusDate.toISODate(), this.currentDate.toISODate());
this.focusDate = this.currentDate;
this.$emit('update:range', this.range);
} else {
this.rangeOffset = this.currentDate.startOf('week', { useLocaleWeeks: true }).diff(this.focusDate.startOf('week', { useLocaleWeeks: true }), 'weeks').weeks;
if (this.rangeOffset) {
this.$refs.view.$refs.grid.disableAutoScroll();
this.$emit('update:range', this.range);
this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage);
}
@@ -59,11 +59,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);
},
@@ -73,6 +75,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(weeks) {
const day = this.focusDate.plus({ weeks });
@@ -93,6 +96,7 @@ export default {
},
mounted() {
this.$emit('update:range', this.range);
this.$refs.view.$refs.grid.enableAutoScroll();
},
template: `
<div
@@ -100,7 +104,7 @@ export default {
@cal-click-default.capture="handleClickDefaults"
>
<base-slider ref="slider" v-slot="slot">
<week-view v-bind="viewAttrs(slot.offset)">
<week-view ref="view" v-bind="viewAttrs(slot.offset)">
<template v-slot="slot"><slot v-bind="slot" mode="week" /></template>
</week-view>
</base-slider>