2121//
2222// (Note that calls to `connected` and `disconnected` are delayed by `MutationObserver` which is what we use to track changes to the document)
2323//
24- // In this version of the library, behaviours are enabled on a per-document basis.
24+ // In this version of the library, behaviours are enabled on a per-target basis.
2525// Call `enableBehaviours(document)` to enable behaviour handling for that document.
2626// It is not necessary to call `enableBehaviours(document)` for the main document since it will be enabled automatically.
27- // You can still call it if you want to control when the document behaviours are updated, or you can call `disableBehaviours(document)` if you
27+ // You can still call it if you want to control when the behaviours are updated, or you can call `disableBehaviours(document)` if you
2828// prefer behaviours not to be enabled for the main document.
2929//
30+ // You can also pass an element to `enableBehaviours` to limit the scope to that element.
31+ //
3032// You can get a behaviour from an element if you know the type (or base type) of the behavior:
3133//
3234// const behaviour = getBehaviour(element, MyBehaviour);
@@ -194,11 +196,14 @@ function* chain(current) {
194196}
195197
196198/**
197- * Tests whether the base object is in the prototype chain of the derived object
199+ * Tests whether the ` base` object is in the prototype chain of the ` derived` object
198200 * @param { object } derived
199201 * @param { object } base
200202 */
201- function isBase ( derived , base ) {
203+ function isBase ( { derived, base } ) {
204+ if ( derived === undefined || base === undefined ) {
205+ throw "Invalid argument to isBase" ;
206+ }
202207 for ( const link of chain ( derived ) ) {
203208 if ( link === base ) {
204209 return true ;
@@ -281,7 +286,7 @@ export function getBehaviour(element, behaviourType) {
281286 // If we are given MyBaseBehaviour and we have stored MyDerivedBehaviour,
282287 // we still need to find the behaviour and return it
283288 for ( const [ behaviourType_ , behavior_ ] of instances . entries ( ) ) {
284- if ( isBase ( behaviourType_ , behaviourType ) ) {
289+ if ( isBase ( { derived : behaviourType_ , base : behaviourType } ) ) {
285290 return behavior_ ;
286291 }
287292 }
@@ -291,7 +296,12 @@ export function getBehaviour(element, behaviourType) {
291296
292297/** @typedef { { key: BehaviourKey, elementType: typeof HTMLElement, behaviourType: typeof Behaviour, existingBehaviourType: typeof Behaviour } } Warning */
293298
294- class BehaviourRegistry {
299+ /**
300+ * A `Target` is a document or element in which behaviours have been enabled
301+ * @typedef { Node } Target
302+ * */
303+
304+ export class BehaviourRegistry {
295305
296306 /**
297307 * This contains the behaviours directly applied to a particular element type.
@@ -302,62 +312,70 @@ class BehaviourRegistry {
302312 elementTypeToBehaviourRecord = new Map ( ) ;
303313
304314 /**
305- * Stores documents that we're watching for changes
306- * @type Map<Document , { registry: BehaviourRegistry, controller: AbortController } >
315+ * Stores targets that we're watching for changes
316+ * @type Map<Target , { registry: BehaviourRegistry, controller: AbortController } >
307317 * */
308- documentToRegistry = new Map ( ) ;
318+ targetToRegistry = new Map ( ) ;
309319
310320 /**
311- * Documents that need to be re-examined for behaviours
312- * @type Document []
321+ * Targets that need to be re-examined for behaviours
322+ * @type Target []
313323 */
314- documentQueue = [ ] ;
324+ queue = [ ] ;
315325
316326 /**
317327 * We only ensure the main document is enabled once on the first call to `register`
318328 * so that callers can successfully disable this document without us re-enabling it
319329 */
320- isMainDocumentHandled = false ;
330+ shouldHandleMainDocument = false ;
331+
332+ constructor ( shouldHandleMainDocument = false ) {
333+ this . shouldHandleMainDocument = shouldHandleMainDocument ;
334+ }
321335
322336 /**
323- * Add a document to the queue - the entire document will be examined for elements/attributes that need to be connected to behaviours.
324- * The processing of the document happens in a microtask.
325- * @param { Document } document
337+ * Add a target to the queue - the target node will be examined for elements/attributes that need to be connected to behaviours.
338+ * The processing of the target happens in a microtask.
339+ * @param { Target } target
326340 * */
327- addToQueue ( document ) {
328- if ( ! this . documentQueue . includes ( document ) ) {
329- this . documentQueue . push ( document ) ;
341+ addToQueue ( target ) {
342+ if ( ! this . queue . includes ( target ) ) {
343+ this . queue . push ( target ) ;
330344 this . needsUpdate = true ;
331345 }
332346 }
333347
334- updateDocument ( document ) {
335- const existing = this . documentToRegistry . get ( document ) ;
348+ /**
349+ *
350+ * @param { Target } target
351+ */
352+ updateTarget ( target ) {
353+ const existing = this . targetToRegistry . get ( target ) ;
336354
337355 if ( existing === undefined ) {
338- const controller = listenToElement ( document . body , ( mutations , observer ) => {
356+ const controller = listenToElement ( target , ( mutations , observer ) => {
339357 for ( const mutation of mutations ) {
340358 this . handleMutation ( mutation ) ;
341359 }
342360 } ) ;
343361
344- this . documentToRegistry . set ( document , { registry : this , controller } ) ;
362+ this . targetToRegistry . set ( target , { registry : this , controller } ) ;
345363 }
346364
347- this . connect ( document . body . querySelectorAll ( "*" ) ) ;
365+ this . connect ( target . querySelectorAll ( "*" ) ) ;
348366 }
349367
350368 /**
351- * Processes all the documents in the queue.
369+ * Processes all the targets in the queue.
352370 * Adds mutation observation if necessary and
353- * examines all existing document content to attach behaviours if necessary.
371+ * examines all existing target content to attach behaviours if necessary.
354372 */
355373 update ( ) {
356- const documents = this . documentQueue ;
357- this . documentQueue = [ ] ;
374+ const targets = this . queue ;
375+ this . queue = [ ] ;
358376
359- for ( const document of documents ) {
360- this . updateDocument ( document ) ;
377+ for ( const target of targets ) {
378+ this . updateTarget ( target ) ;
361379 }
362380 }
363381
@@ -421,15 +439,15 @@ class BehaviourRegistry {
421439
422440 // For the first registration, we add the main document to the queue so that users cannot forget to call enable on it
423441 // We only do this once so that users can choose to disable the main document
424- if ( ! this . isMainDocumentHandled ) {
425- this . isMainDocumentHandled = true ;
426- this . addToQueue ( document ) ;
442+ if ( this . shouldHandleMainDocument ) {
443+ this . shouldHandleMainDocument = false ;
444+ this . addToQueue ( globalThis . document ) ;
427445 }
428446
429- // If behaviours get registered after a document is enabled,
430- // we need to update existing documents
431- for ( const document of this . documentToRegistry . keys ( ) ) {
432- this . addToQueue ( document ) ;
447+ // If behaviours get registered after a target is enabled,
448+ // we need to update existing targets
449+ for ( const target of this . targetToRegistry . keys ( ) ) {
450+ this . addToQueue ( target ) ;
433451 }
434452
435453 return { warnings } ;
@@ -487,61 +505,63 @@ class BehaviourRegistry {
487505 }
488506
489507 /**
490- * Starts watching the document and connecting behaviours to relevant elements
491- * @param { Document } document
508+ * Starts watching the target and connecting behaviours to relevant elements
509+ * @param { Target } target
492510 */
493- enable ( document ) {
494- // Here we add the specified document to the queue then immediately process the queue
511+ enable ( target ) {
512+ // Here we add the specified target to the queue then immediately process the queue
495513 // to ensure that all routes are going through the same code paths.
496- this . addToQueue ( document ) ;
514+ this . addToQueue ( target ) ;
497515 this . update ( ) ;
498516 }
499517
500518 /**
501- * Stops watching the document . Does not disconnect already connected behaviours.
502- * @param { Document } document
519+ * Stops watching the target . Does not disconnect already connected behaviours.
520+ * @param { Target } target
503521 */
504- disable ( document ) {
505- if ( document === globalThis . document ) {
522+ disable ( target ) {
523+ if ( target === globalThis . document ) {
506524 // Disable main document handling by saying it's already done
507525 // This code means that users can disable the main document before any registrations.
508526 // Without this code, users would have to ensure that disable is called after the first registration.
509- this . isMainDocumentHandled = true ;
527+ this . shouldHandleMainDocument = false ;
510528 }
511529
512- // Remove this document from the queue if it's there
513- const index = this . documentQueue . indexOf ( document ) ;
530+ // Remove this target from the queue if it's there
531+ const index = this . queue . indexOf ( target ) ;
514532 if ( index >= 0 ) {
515- this . documentQueue . splice ( index , 1 ) ;
533+ this . queue . splice ( index , 1 ) ;
516534 }
517535
518- // Stop listening to this document if we've started listening
519- const existing = this . documentToRegistry . get ( document ) ;
536+ // Stop listening to this target if we've started listening
537+ const existing = this . targetToRegistry . get ( target ) ;
520538 if ( existing !== undefined ) {
521539 existing . controller . abort ( ) ;
522- this . documentToRegistry . delete ( document ) ;
540+ this . targetToRegistry . delete ( target ) ;
523541 }
524542 }
525543}
526544
527545addMicrotaskProperty ( BehaviourRegistry , "update" ) ;
528546
529- const customBehaviours = new BehaviourRegistry ( ) ;
547+ // The global behaviour registry has main document handling turned on
548+ // Other behaviour registries default to main document handling being off
549+ export const customBehaviours = new BehaviourRegistry ( true ) ;
530550
531551/**
532- * Starts watching the document and connecting behaviours to relevant elements
533- * @param { Document } document
552+ * Starts watching the target and connecting behaviours to relevant elements
553+ * @param { Target } target
534554 */
535- export function enableBehaviours ( document ) {
536- customBehaviours . enable ( document ) ;
555+ export function enableBehaviours ( target ) {
556+ customBehaviours . enable ( target ) ;
537557}
538558
539559/**
540- * Stops watching the document . Does not disconnect already connected behaviours.
541- * @param { Document } document
560+ * Stops watching the target . Does not disconnect already connected behaviours.
561+ * @param { Target } target
542562 */
543- export function disableBehaviours ( document ) {
544- customBehaviours . disable ( document ) ;
563+ export function disableBehaviours ( target ) {
564+ customBehaviours . disable ( target ) ;
545565}
546566
547567/**
0 commit comments