Skip to content
Snippets Groups Projects
Commit 46ccf78e authored by permcu's avatar permcu
Browse files

Use v-intersect to keep track of currently visible days

Seems way more reliable than keeping scroll position (as was done
previously; inspired by the vue static site generator vuepress)
parent eeabf590
No related branches found
No related tags found
No related merge requests found
......@@ -58,10 +58,14 @@
</template>
<template #default="{ items }">
<v-list-item
v-for="day in groupDocsByDay(items)"
v-for="{ date, docs, first, last } in groupDocsByDay(items)"
v-intersect="onIntersect"
:data-date="date.toISODate()"
:data-first="first"
:data-last="last"
two-line
:key="'day-' + day[0]"
:id="'documentation_' + day[0].toISODate()"
:key="'day-' + date"
:id="'documentation_' + date.toISODate()"
>
<v-list-item-content>
<v-subheader class="text-h6">{{
......@@ -69,7 +73,7 @@
}}</v-subheader>
<v-list max-width="100%" class="pt-0 mt-n1">
<v-list-item
v-for="doc in day.slice(1)"
v-for="doc in docs"
:key="'documentation-' + (doc.oldId || doc.id)"
>
<documentation-modal
......@@ -144,8 +148,9 @@ export default {
data() {
return {
gqlQuery: documentationsForCoursebook,
currentDate: "",
visible: [],
knownDates: {},
docsByDay: {},
lastQuery: null,
dateStart: "",
dateEnd: "",
......@@ -208,7 +213,8 @@ export default {
}
// Resetting known dates to dateRange around current date
this.knownDates = {};
const dateRange = this.dateRange(DateTime.fromISO(this.$route.hash.substring(1)))
this.currentDate = this.$route.hash.substring(1);
const dateRange = this.dateRange(DateTime.fromISO(this.$route.hash.substring(1)));
dateRange.forEach((ts) => this.knownDates[ts] = true);
const lastIdx = dateRange.length - 1;
// Returning a dateRange each around first & last date for the initial query
......@@ -234,47 +240,23 @@ export default {
const docsByDay = docs.reduce((byDay, doc) => {
// This works with dummy. Does actual doc have dateStart instead?
const day = DateTime.fromISO(doc.datetimeStart).startOf("day");
byDay[day] ??= [day];
byDay[day].push(doc);
byDay[day] ??= {date: day, docs: [], first: false, last: false};
byDay[day]['docs'].push(doc);
return byDay;
}, {});
// => [[dt doc ...] ...]
return Object.keys(docsByDay)
.sort()
.map((key) => docsByDay[key]);
// sorting is necessary since backend can send docs unordered
},
debounce(fn, delay) {
let timer;
return () => {
console.log('debounce');
clearTimeout(timer);
timer = setTimeout(fn, delay);
}
},
// Adapted from
// https://github.com/vuejs/vuepress/blob/38e98634af117f83b6a32c8ff42488d91b66f663/packages/%40vuepress/plugin-active-header-links/clientRootMixin.js
setCurrentDay() {
const days = Array.from(document.querySelectorAll("[id^='documentation_']"));
const scrollTop = Math.max(
window.pageYOffset,
document.documentElement.scrollTop,
document.body.scrollTop
);
for (let i = 0; i < days.length; i++) {
const day = days[i];
const nextDay =days[i + 1];
if ((scrollTop >= day.offsetTop + 10 || i == 0) && (!nextDay || scrollTop < nextDay.offsetTop - 10)) {
const date = day.id.split("_")[1];
if (date !== this.$route.hash.substring(1)) {
this.gotoDate(date);
.map((key, i, {length}) => {
const day = docsByDay[key];
if (i === 0) {
day['first'] = true;
} else if (i === length - 1) {
day['last'] = true;
}
return
}
}
return day;
});
// sorting is necessary since backend can send docs unordered
},
/**
* @param {"prev"|"next"} direction
......@@ -382,10 +364,40 @@ export default {
this.assureDate(DateTime.fromISO(date));
// scroll
},
onIntersect(entries, observer) {
const entry = entries[0];
if (entry.isIntersecting) {
// coming
console.log('intersect', this.visible);
// track visible
if (this.visible[0] > entry.target.dataset.date || this.visible.length === 0) {
// coming is new first (top) date
this.visible.unshift(entry.target.dataset.date);
console.log('current', this.visible[0]);
} else if (this.visible[this.visible.length -1] < entry.target.dataset.date) {
// coming is new last (bottom) date
this.visible.push(entry.target.dataset.date);
}
// load more
if (entry.target.dataset.first) {
console.log('load up');
} else if (entry.target.dataset.last) {
console.log('load down');
}
} else if (this.visible[0] === entry.target.dataset.date) {
// first (top) visible date is going
this.visible.shift()
console.log('current', this.visible[0]);
} else if (this.visible[this.visible.length - 1] === entry.target.dataset.date) {
// last (bottom) visible date is going
this.visible.pop()
}
},
},
created() {
this.resetDate();
window.addEventListener('scroll', this.debounce(this.setCurrentDay, 300));
},
};
</script>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment