11const privateData = new WeakMap ( )
22
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-
263// Functional stand in for the W3 spec "queue a task" paradigm
274function task ( ) : Promise < void > {
285 return new Promise ( resolve => setTimeout ( resolve , 0 ) )
@@ -32,27 +9,6 @@ function isWildcard(accept: string | null) {
329 return accept && ! ! accept . split ( ',' ) . find ( x => x . match ( / ^ \s * \* \/ \* / ) )
3310}
3411
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-
5612function getData ( el : IncludeFragmentElement ) {
5713 const src = el . src
5814 let data = privateData . get ( el )
@@ -157,12 +113,12 @@ export default class IncludeFragmentElement extends HTMLElement {
157113 if ( attribute === 'src' ) {
158114 // Source changed after attached so replace element.
159115 if ( this . isConnected && this . loading === 'eager' ) {
160- handleData ( this )
116+ this . # handleData( )
161117 }
162118 } else if ( attribute === 'loading' ) {
163119 // Loading mode changed to Eager after attached so replace element.
164120 if ( this . isConnected && oldVal !== 'eager' && this . loading === 'eager' ) {
165- handleData ( this )
121+ this . # handleData( )
166122 }
167123 }
168124 }
@@ -181,10 +137,10 @@ export default class IncludeFragmentElement extends HTMLElement {
181137
182138 connectedCallback ( ) : void {
183139 if ( this . src && this . loading === 'eager' ) {
184- handleData ( this )
140+ this . # handleData( )
185141 }
186142 if ( this . loading === 'lazy' ) {
187- observer . observe ( this )
143+ this . # observer. observe ( this )
188144 }
189145 }
190146
@@ -210,6 +166,51 @@ export default class IncludeFragmentElement extends HTMLElement {
210166 fetch ( request : RequestInfo ) : Promise < Response > {
211167 return fetch ( request )
212168 }
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+ }
213214}
214215
215216declare global {
0 commit comments