Skip to content

Commit 2a2801a

Browse files
committed
Implement statistics for journey entries
1 parent f8d5ccd commit 2a2801a

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

src/main/handlebars/journey.handlebars

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,29 @@ parent: feed
9292
9393
mapping.project(document.querySelector('#map'));
9494
95-
// Update statistics
96-
window.setTimeout(() => {
97-
fetch('/api/statistics/{{journey.slug}}', {method: 'POST', body: '{{sign journey.slug}}'});
98-
}, 10000);
95+
// Update statistics for journey after a little while. To determine which entries the
96+
// user has spent time viewing, use intersection observer
97+
{{&use 'statistics'}}
98+
const statistics = new Statistics();
99+
statistics.add('{{journey.slug}}', '{{sign journey.slug}}', 10000);
100+
statistics.schedule('{{journey.slug}}');
101+
102+
const observer = new IntersectionObserver(
103+
(entries) => {
104+
for (const entry of entries) {
105+
if (entry.isIntersecting) {
106+
statistics.schedule(entry.target.id);
107+
} else {
108+
statistics.withdraw(entry.target.id);
109+
}
110+
}
111+
},
112+
{ threshold: 0.2 }
113+
);
114+
{{#each itinerary}}
115+
observer.observe(document.querySelector('#{{scroll slug}}'));
116+
statistics.add('{{scroll slug}}', '{{sign slug}}', Math.min({{size images}} * 1500, 5000));
117+
{{/each}}
99118
</script>
100119
{{/inline}}
101120
{{/layout}}

src/main/js/statistics.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class Statistics {
2+
#tasks = {};
3+
4+
/** Adds a statistics target with a given delay */
5+
add(target, signature, delay) {
6+
this.#tasks[target] = { signature, delay, timer : null, completed : false };
7+
}
8+
9+
/** Schedules the given statistics target */
10+
schedule(target) {
11+
const task = this.#tasks[target];
12+
if (task === undefined) throw new Error(`Undefined target ${target}`);
13+
14+
task.timer && clearTimeout(task.timer);
15+
task.completed || (task.timer = setTimeout(
16+
() => fetch('/api/statistics/' + target, { method: 'POST', body: task.signature }).then(() => task.completed = true),
17+
task.delay
18+
));
19+
}
20+
21+
/** Withdraws any scheduling for the given statistics target */
22+
withdraw(target) {
23+
const task = this.#tasks[target];
24+
if (task === undefined) return;
25+
26+
clearTimeout(task.timer);
27+
task.timer = null;
28+
}
29+
}

0 commit comments

Comments
 (0)