1
1
const privateData = new WeakMap ( )
2
2
3
- const observer = new IntersectionObserver (
4
- entries => {
5
- for ( const entry of entries ) {
6
- if ( entry . isIntersecting ) {
7
- const { target} = entry
8
- observer . unobserve ( target )
9
- if ( ! ( target instanceof IncludeFragmentElement ) ) return
10
- if ( target . loading === 'lazy' ) {
11
- handleData ( target )
12
- }
13
- }
14
- }
15
- } ,
16
- {
17
- // Currently the threshold is set to 256px from the bottom of the viewport
18
- // with a threshold of 0.1. This means the element will not load until about
19
- // 2 keyboard-down-arrow presses away from being visible in the viewport,
20
- // giving us some time to fetch it before the contents are made visible
21
- rootMargin : '0px 0px 256px 0px' ,
22
- threshold : 0.01
23
- }
24
- )
25
-
26
3
// Functional stand in for the W3 spec "queue a task" paradigm
27
4
function task ( ) : Promise < void > {
28
5
return new Promise ( resolve => setTimeout ( resolve , 0 ) )
@@ -32,27 +9,6 @@ function isWildcard(accept: string | null) {
32
9
return accept && ! ! accept . split ( ',' ) . find ( x => x . match ( / ^ \s * \* \/ \* / ) )
33
10
}
34
11
35
- async function handleData ( el : IncludeFragmentElement ) {
36
- observer . unobserve ( el )
37
- return getData ( el ) . then (
38
- function ( html : string ) {
39
- const template = document . createElement ( 'template' )
40
- // eslint-disable-next-line github/no-inner-html
41
- template . innerHTML = html
42
- const fragment = document . importNode ( template . content , true )
43
- const canceled = ! el . dispatchEvent (
44
- new CustomEvent ( 'include-fragment-replace' , { cancelable : true , detail : { fragment} } )
45
- )
46
- if ( canceled ) return
47
- el . replaceWith ( fragment )
48
- el . dispatchEvent ( new CustomEvent ( 'include-fragment-replaced' ) )
49
- } ,
50
- function ( ) {
51
- el . classList . add ( 'is-error' )
52
- }
53
- )
54
- }
55
-
56
12
function getData ( el : IncludeFragmentElement ) {
57
13
const src = el . src
58
14
let data = privateData . get ( el )
@@ -157,12 +113,12 @@ export default class IncludeFragmentElement extends HTMLElement {
157
113
if ( attribute === 'src' ) {
158
114
// Source changed after attached so replace element.
159
115
if ( this . isConnected && this . loading === 'eager' ) {
160
- handleData ( this )
116
+ this . # handleData( )
161
117
}
162
118
} else if ( attribute === 'loading' ) {
163
119
// Loading mode changed to Eager after attached so replace element.
164
120
if ( this . isConnected && oldVal !== 'eager' && this . loading === 'eager' ) {
165
- handleData ( this )
121
+ this . # handleData( )
166
122
}
167
123
}
168
124
}
@@ -181,10 +137,10 @@ export default class IncludeFragmentElement extends HTMLElement {
181
137
182
138
connectedCallback ( ) : void {
183
139
if ( this . src && this . loading === 'eager' ) {
184
- handleData ( this )
140
+ this . # handleData( )
185
141
}
186
142
if ( this . loading === 'lazy' ) {
187
- observer . observe ( this )
143
+ this . # observer. observe ( this )
188
144
}
189
145
}
190
146
@@ -210,6 +166,51 @@ export default class IncludeFragmentElement extends HTMLElement {
210
166
fetch ( request : RequestInfo ) : Promise < Response > {
211
167
return fetch ( request )
212
168
}
169
+
170
+ #observer = new IntersectionObserver (
171
+ entries => {
172
+ for ( const entry of entries ) {
173
+ if ( entry . isIntersecting ) {
174
+ const { target} = entry
175
+ this . #observer. unobserve ( target )
176
+ if ( ! ( target instanceof IncludeFragmentElement ) ) return
177
+ if ( target . loading === 'lazy' ) {
178
+ this . #handleData( )
179
+ }
180
+ }
181
+ }
182
+ } ,
183
+ {
184
+ // Currently the threshold is set to 256px from the bottom of the viewport
185
+ // with a threshold of 0.1. This means the element will not load until about
186
+ // 2 keyboard-down-arrow presses away from being visible in the viewport,
187
+ // giving us some time to fetch it before the contents are made visible
188
+ rootMargin : '0px 0px 256px 0px' ,
189
+ threshold : 0.01
190
+ }
191
+ )
192
+
193
+ #handleData( ) : Promise < void > {
194
+ this . #observer. unobserve ( this )
195
+
196
+ return getData ( this ) . then (
197
+ ( html : string ) => {
198
+ const template = document . createElement ( 'template' )
199
+ // eslint-disable-next-line github/no-inner-html
200
+ template . innerHTML = html
201
+ const fragment = document . importNode ( template . content , true )
202
+ const canceled = ! this . dispatchEvent (
203
+ new CustomEvent ( 'include-fragment-replace' , { cancelable : true , detail : { fragment} } )
204
+ )
205
+ if ( canceled ) return
206
+ this . replaceWith ( fragment )
207
+ this . dispatchEvent ( new CustomEvent ( 'include-fragment-replaced' ) )
208
+ } ,
209
+ ( ) => {
210
+ this . classList . add ( 'is-error' )
211
+ }
212
+ )
213
+ }
213
214
}
214
215
215
216
declare global {
0 commit comments