|
1 | 1 | <script lang="ts" context="module">
|
2 |
| - let observer: IntersectionObserver; |
| 2 | + let observer: IntersectionObserver |
3 | 3 |
|
4 | 4 | // 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() |
6 | 6 |
|
7 | 7 | 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) |
10 | 10 | }
|
11 | 11 |
|
12 | 12 | 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) |
15 | 15 | }
|
16 | 16 | </script>
|
17 | 17 |
|
18 | 18 | <script lang="ts">
|
19 |
| - import { onMount, onDestroy, createEventDispatcher } from "svelte"; |
| 19 | + import { createEventDispatcher, onDestroy, onMount } from 'svelte' |
20 | 20 |
|
21 | 21 | /**
|
22 | 22 | * Set to `true` to unobserve the element after it intersects the viewport.
|
23 | 23 | */
|
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 |
30 | 30 | /**
|
31 | 31 | * Percentage of element visibility to trigger an event.
|
32 | 32 | * Value must be between 0 and 1.
|
33 | 33 | */
|
34 |
| - export let threshold = 0; |
| 34 | + export let threshold = 0 |
35 | 35 |
|
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 }>() |
40 | 42 |
|
41 | 43 | onMount(() => {
|
42 |
| - childElement = container.firstElementChild as HTMLElement; |
| 44 | + childElement = container.firstElementChild as HTMLElement |
43 | 45 | if (!childElement) {
|
44 |
| - return console.error("IntersectionObserver: No child element found"); |
| 46 | + return console.error('IntersectionObserver: No child element found') |
45 | 47 | }
|
46 | 48 |
|
47 |
| - if (typeof IntersectionObserver !== "undefined") { |
| 49 | + if (typeof IntersectionObserver !== 'undefined') { |
48 | 50 | 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 |
51 | 53 |
|
52 |
| - const rootMargin = `${top}px ${right}px ${bottom}px ${left}px`; |
| 54 | + const rootMargin = `${top}px ${right}px ${bottom}px ${left}px` |
53 | 55 |
|
54 | 56 | observer = new IntersectionObserver(
|
55 | 57 | (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) |
59 | 61 | }
|
60 | 62 | },
|
61 | 63 | {
|
62 | 64 | root,
|
63 | 65 | rootMargin,
|
64 | 66 | threshold,
|
65 | 67 | },
|
66 |
| - ); |
| 68 | + ) |
67 | 69 | }
|
68 | 70 |
|
69 | 71 | 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) |
75 | 77 |
|
76 |
| - return () => remove(childElement); |
| 78 | + return () => remove(childElement) |
77 | 79 | }
|
78 | 80 |
|
79 | 81 | 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 |
86 | 88 |
|
87 | 89 | if (intersecting && once) {
|
88 |
| - window.removeEventListener("scroll", handler); |
| 90 | + window.removeEventListener('scroll', handler) |
89 | 91 | }
|
90 | 92 | }
|
91 | 93 |
|
92 |
| - window.addEventListener("scroll", handler); |
93 |
| - return () => window.removeEventListener("scroll", handler); |
94 |
| - }); |
| 94 | + window.addEventListener('scroll', handler) |
| 95 | + return () => window.removeEventListener('scroll', handler) |
| 96 | + }) |
95 | 97 |
|
96 |
| - const dispatch = createEventDispatcher<{ intersected: null; hidden: null }>(); |
97 | 98 | $: if (intersecting === true) {
|
98 | 99 | if (intervalMs) {
|
99 | 100 | interval = setInterval(() => {
|
100 | 101 | if (intersecting === true) {
|
101 |
| - dispatch("intersected"); |
| 102 | + dispatch('intersected') |
102 | 103 | }
|
103 |
| - }, intervalMs); |
| 104 | + }, intervalMs) |
104 | 105 | }
|
105 | 106 | } else {
|
106 |
| - dispatch("hidden"); |
| 107 | + dispatch('hidden') |
107 | 108 | }
|
108 | 109 |
|
109 | 110 | onDestroy(() => {
|
110 |
| - clearInterval(interval); |
111 |
| - }); |
| 111 | + clearInterval(interval) |
| 112 | + }) |
112 | 113 | </script>
|
113 | 114 |
|
114 | 115 | <div style="display: contents" bind:this={container}>
|
|
0 commit comments