-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy patharticle-scroller.vue
More file actions
96 lines (92 loc) · 3.24 KB
/
article-scroller.vue
File metadata and controls
96 lines (92 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<template>
<div>
<loading-spinner v-if="loadingTop" :id="'scrollerTop'"/>
<!-- Todo: Transition group -->
<slot/>
<loading-spinner v-if="loadingBottom"/>
</div>
</template>
<script>
import LoadingSpinner from 'components/loading-spinner';
export default {
components: {
LoadingSpinner,
},
props: {'articles': {}, 'loadTopHandler': {}, 'loadBottomHandler': {}, 'getElementName': {}, 'noLazyLoad': Boolean},
data() {
return {
loadingTop: false,
loadingBottom: false,
lastScrollTop: 0,
}
},
computed: {
loading() {
return this.loadingTop || this.loadingBottom;
},
currentChapterId(){
return this.$route.params.chapterId;
}
},
mounted() {
this.addScrollHandler();
},
beforeDestroy() {
this.removeScrollHandler();
},
methods: {
addScrollHandler() {
this.$nextTick(() => {
window.addEventListener('scroll', this.scrollHandler);
});
},
removeScrollHandler() {
window.removeEventListener('scroll', this.scrollHandler);
},
scrollHandler(event) {
if (this.loading) {
return;
}
// https://stackoverflow.com/questions/28633221/document-body-scrolltop-firefox-returns-0-only-js
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
let halfScreen = window.innerHeight / 2;
let hitBottomOfWindow = scrollTop + window.innerHeight >= document.documentElement.offsetHeight-2;
let hitTop = scrollTop == 0;
this.lastScrollTop = scrollTop;
for (let i = 0; i < this.articles.length; i++) {
let article = this.articles[i];
let element = document.querySelector('#'+this.getElementName(article));
let elementRect = element.getBoundingClientRect();
// If article is in the top half of screen and has changed
if (elementRect.top < halfScreen && elementRect.bottom > halfScreen && article.chapterId != this.currentChapterId) {
this.$emit('change', article);
break; // This break is important in case two articles are in the top half of screen
}
}
if (!this.noLazyLoad) {
if (hitTop && this.loadTopHandler != null) {
this.loadingTop = true;
this.loadTopHandler().then(() => {
this.loadingTop = false;
}).catch(() => {
this.loadingTop = false;
});
}
if (hitBottomOfWindow && this.loadBottomHandler != null) {
this.loadingBottom = true;
this.loadBottomHandler().then(() => {
this.loadingBottom = false;
}).catch(() => {
this.loadingBottom = false;
});
}
}
},
}
};
</script>
<style>
#scrollerTop #loader {
margin: 0 auto;
}
</style>