Skip to content

Commit 7c8d39e

Browse files
committed
fix: IntersectionObserverShared only fire intersected event when actually intersecting
1 parent 6959d2a commit 7c8d39e

File tree

1 file changed

+51
-50
lines changed

1 file changed

+51
-50
lines changed

src/lib/functions/IntersectionObserverShared.svelte

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,115 @@
11
<script lang="ts" context="module">
2-
let observer: IntersectionObserver;
2+
let observer: IntersectionObserver
33
44
// As each element registers with the observer, map Elements to Callbacks so when an element's intersection changes its callback is invoked
5-
const mapping = new Map();
5+
const mapping = new Map()
66
77
function add(element: HTMLElement, callback: (isIntersecting: boolean) => void) {
8-
mapping.set(element, callback);
9-
observer.observe(element);
8+
mapping.set(element, callback)
9+
observer.observe(element)
1010
}
1111
1212
function remove(element: HTMLElement) {
13-
const deleted = mapping.delete(element);
14-
deleted && observer.unobserve(element);
13+
const deleted = mapping.delete(element)
14+
deleted && observer.unobserve(element)
1515
}
1616
</script>
1717

1818
<script lang="ts">
19-
import { onMount, onDestroy, createEventDispatcher } from "svelte";
19+
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
2020
2121
/**
2222
* Set to `true` to unobserve the element after it intersects the viewport.
2323
*/
24-
export let once = false;
25-
export let intervalMs: number = undefined;
26-
export let top = 0;
27-
export let bottom = 0;
28-
export let left = 0;
29-
export let right = 0;
24+
export let once = false
25+
export let intervalMs: number = undefined
26+
export let top = 0
27+
export let bottom = 0
28+
export let left = 0
29+
export let right = 0
3030
/**
3131
* Percentage of element visibility to trigger an event.
3232
* Value must be between 0 and 1.
3333
*/
34-
export let threshold = 0;
34+
export let threshold = 0
3535
36-
let intersecting = false;
37-
let container: HTMLDivElement;
38-
let childElement: HTMLElement;
39-
let interval;
36+
let intersecting = false
37+
let container: HTMLDivElement
38+
let childElement: HTMLElement
39+
let interval
40+
41+
const dispatch = createEventDispatcher<{ intersected: null, hidden: null }>()
4042
4143
onMount(() => {
42-
childElement = container.firstElementChild as HTMLElement;
44+
childElement = container.firstElementChild as HTMLElement
4345
if (!childElement) {
44-
return console.error("IntersectionObserver: No child element found");
46+
return console.error('IntersectionObserver: No child element found')
4547
}
4648
47-
if (typeof IntersectionObserver !== "undefined") {
49+
if (typeof IntersectionObserver !== 'undefined') {
4850
if (!observer) {
49-
let isIframe = window !== window.parent;
50-
let root = isIframe ? window.document : null; // Use the iframe's document as root if in an iframe
51+
const isIframe = window !== window.parent
52+
const root = isIframe ? window.document : null // Use the iframe's document as root if in an iframe
5153
52-
const rootMargin = `${top}px ${right}px ${bottom}px ${left}px`;
54+
const rootMargin = `${top}px ${right}px ${bottom}px ${left}px`
5355
5456
observer = new IntersectionObserver(
5557
(entries) => {
56-
for (var entry of entries) {
57-
const callback = mapping.get(entry.target);
58-
callback && callback(entry.isIntersecting);
58+
for (const entry of entries) {
59+
const callback = mapping.get(entry.target)
60+
callback && callback(entry.isIntersecting)
5961
}
6062
},
6163
{
6264
root,
6365
rootMargin,
6466
threshold,
6567
},
66-
);
68+
)
6769
}
6870
6971
const fired_when_interesecting_changes = (isIntersecting: boolean) => {
70-
if (once && isIntersecting) remove(childElement);
71-
dispatch('intersected');
72-
intersecting = isIntersecting;
73-
};
74-
add(childElement, fired_when_interesecting_changes);
72+
if (once && isIntersecting) remove(childElement)
73+
if (isIntersecting) dispatch('intersected')
74+
intersecting = isIntersecting
75+
}
76+
add(childElement, fired_when_interesecting_changes)
7577
76-
return () => remove(childElement);
78+
return () => remove(childElement)
7779
}
7880
7981
function handler() {
80-
const bcr = childElement.getBoundingClientRect();
81-
intersecting =
82-
bcr.bottom + bottom > 0 &&
83-
bcr.right + right > 0 &&
84-
bcr.top - top < window.innerHeight &&
85-
bcr.left - left < window.innerWidth;
82+
const bcr = childElement.getBoundingClientRect()
83+
intersecting
84+
= bcr.bottom + bottom > 0
85+
&& bcr.right + right > 0
86+
&& bcr.top - top < window.innerHeight
87+
&& bcr.left - left < window.innerWidth
8688
8789
if (intersecting && once) {
88-
window.removeEventListener("scroll", handler);
90+
window.removeEventListener('scroll', handler)
8991
}
9092
}
9193
92-
window.addEventListener("scroll", handler);
93-
return () => window.removeEventListener("scroll", handler);
94-
});
94+
window.addEventListener('scroll', handler)
95+
return () => window.removeEventListener('scroll', handler)
96+
})
9597
96-
const dispatch = createEventDispatcher<{ intersected: null; hidden: null }>();
9798
$: if (intersecting === true) {
9899
if (intervalMs) {
99100
interval = setInterval(() => {
100101
if (intersecting === true) {
101-
dispatch("intersected");
102+
dispatch('intersected')
102103
}
103-
}, intervalMs);
104+
}, intervalMs)
104105
}
105106
} else {
106-
dispatch("hidden");
107+
dispatch('hidden')
107108
}
108109
109110
onDestroy(() => {
110-
clearInterval(interval);
111-
});
111+
clearInterval(interval)
112+
})
112113
</script>
113114

114115
<div style="display: contents" bind:this={container}>

0 commit comments

Comments
 (0)