OverlayHost
Keeps a feature's floating UI – its balloons, dialogs, panels and the tooltips inside them – in the right DOM tree, and keeps it there as the feature moves.
For a feature that renders its UI outside an editor, in a container the integrator may put anywhere, including inside a shadow root. An editor's own floating UI needs none of this: it is mounted in the root the editor lives in and stays there.
Why it is needed
Floating UI is mounted through a BodyCollection, and it has to go into the same tree as the feature it belongs to. Anywhere else it loses the styles scoped to that tree, and its tooltips come out clipped or mis-styled across the shadow boundary.
Doing that by hand means re-mounting the collection whenever the container moves, unmounting it while the container is detached, registering and unregistering it with the shared TooltipManager, tracking the shadow roots of the inline UI so that tooltips and click-outside detection reach across boundaries, and tearing it all down in the right order. This class does all of it, behind resolvers that say where the feature's UI currently is.
How to use it
const host = new OverlayHost( locale, {
resolveMountTarget: () => getOverlayMountRoot( featureContainer ),
resolveInlineContainer: () => featureContainer
} );
host.sync();
host.bodyCollection.add( balloonPanelView );Copy codeAdd the feature's floating views to bodyCollection. Call sync whenever the container may have moved – right before showing a panel, for instance – and destroy once the feature goes away. It re-syncs on its own too: whenever a view is added to the collection, and on every update event of an updateEmitter, if one is given.
An editor's EditorUI uses this class as well, lending it the body collection and shadow root registry it already has.
Properties
bodyCollection: BodyCollectionreadonlymodule:ui/overlayhost~OverlayHost#bodyCollectionThe body collection holding the floating views. Add the feature's balloons and panels here.
shadowRootRegistry: ShadowRootRegistryreadonlymodule:ui/overlayhost~OverlayHost#shadowRootRegistryTracks the shadow roots hosting the tooltip-bearing UI that lives outside the
bodyCollection: the inline UI container and any nodes registered directly by the owner (an editor registers its editables, toolbars and menu bar)._destroyed: booleanprivatemodule:ui/overlayhost~OverlayHost#_destroyedWhether
destroyhas run, so a repeated call does not release the shared tooltip manager on behalf of another holder._ownsBodyCollection: booleanprivatereadonlymodule:ui/overlayhost~OverlayHost#_ownsBodyCollectionWhether the
bodyCollectionwas created by this host (and is destroyed with it), as opposed to a borrowed one whose owner manages its life cycle._ownsShadowRootRegistry: booleanprivatereadonlymodule:ui/overlayhost~OverlayHost#_ownsShadowRootRegistryWhether the
shadowRootRegistrywas created by this host (and is destroyed with it), as opposed to a borrowed one whose owner manages its life cycle._ownsTooltipManagerReference: booleanprivatereadonlymodule:ui/overlayhost~OverlayHost#_ownsTooltipManagerReferenceWhether this host acquired its own reference to the shared tooltip manager (and releases it on
destroy), as opposed to using a borrowed reference whose holder releases it – an editor counts as a single holder no matter how it splits the work internally._registeredInlineContainer: ShadowRoot | HTMLElement | nullprivatemodule:ui/overlayhost~OverlayHost#_registeredInlineContainerThe inline UI container currently registered with
shadowRootRegistry, so it can be replaced when the feature moves to a different container._resolveInlineContainer?: () => ( ShadowRoot | HTMLElement | null | undefined )privatereadonlymodule:ui/overlayhost~OverlayHost#_resolveInlineContainer_resolveMountTarget: () => ( ShadowRoot | HTMLElement | null )privatereadonlymodule:ui/overlayhost~OverlayHost#_resolveMountTarget_tooltipManager: TooltipManagerprivatereadonlymodule:ui/overlayhost~OverlayHost#_tooltipManagerThe shared tooltip manager the
bodyCollectionis registered with.
Methods
constructor( locale, options )module:ui/overlayhost~OverlayHost#constructorCreates the host: the
bodyCollection(unless a borrowed one is given) and its registration in the sharedTooltipManager. The collection is not mounted in the DOM yet – callsyncfor that.Parameters
locale: LocaleThe locale of the feature (used by the body collection and the tooltip views).
options: OverlayHostOptionsThe resolvers describing where the feature UI lives.
delegate( events ) → EmitterMixinDelegateChaininheritedmodule:ui/overlayhost~OverlayHost#delegateDelegates selected events to another
Emitter. For instance:
Copy codeemitterA.delegate( 'eventX' ).to( emitterB ); emitterA.delegate( 'eventX', 'eventY' ).to( emitterC );then
eventXis delegated (fired by)emitterBandemitterCalong withdata:
Copy codeemitterA.fire( 'eventX', data );and
eventYis delegated (fired by)emitterCalong withdata:
Copy codeemitterA.fire( 'eventY', data );Parameters
events: Array<string>Event names that will be delegated to another emitter.
Returns
destroy() → voidmodule:ui/overlayhost~OverlayHost#destroyDestroys the host: stops hosting tooltips in the
bodyCollection, releases the sharedTooltipManager(so it is destroyed with its last holder) and destroys the collection together with its views and theshadowRootRegistry– except the borrowed ones, which their owners destroy. Safe to call more than once.Returns
void
fire( eventOrInfo, args ) → GetEventInfo<TEvent>[ 'return' ]inheritedmodule:ui/overlayhost~OverlayHost#fireFires an event, executing all callbacks registered for it.
The first parameter passed to callbacks is an
EventInfoobject, followed by the optionalargsprovided in thefire()method call.Type parameters
Parameters
eventOrInfo: GetNameOrEventInfo<TEvent>The name of the event or
EventInfoobject if event is delegated.args: TEvent[ 'args' ]Additional arguments to be passed to the callbacks.
Returns
GetEventInfo<TEvent>[ 'return' ]By default the method returns
undefined. However, the return value can be changed by listeners through modification of theevt.return's property (the event info is the first param of every callback).
listenTo( emitter, event, callback, options? ) → voidinheritedmodule:ui/overlayhost~OverlayHost#listenTo:BASE_EMITTERRegisters a callback function to be executed when an event is fired in a specific (emitter) object.
Events can be grouped in namespaces using
:. When namespaced event is fired, it additionally fires all callbacks for that namespace.
Copy code// myEmitter.on( ... ) is a shorthand for myEmitter.listenTo( myEmitter, ... ). myEmitter.on( 'myGroup', genericCallback ); myEmitter.on( 'myGroup:myEvent', specificCallback ); // genericCallback is fired. myEmitter.fire( 'myGroup' ); // both genericCallback and specificCallback are fired. myEmitter.fire( 'myGroup:myEvent' ); // genericCallback is fired even though there are no callbacks for "foo". myEmitter.fire( 'myGroup:foo' );An event callback can stop the event and set the return value of the
firemethod.Type parameters
Parameters
emitter: EmitterThe object that fires the event.
event: TEvent[ 'name' ]The name of the event.
callback: GetCallback<TEvent>The function to be called on event.
options?: GetCallbackOptions<TEvent>Additional options.
Returns
void
off( event, callback ) → voidinheritedmodule:ui/overlayhost~OverlayHost#offStops executing the callback on the given event. Shorthand for
this.stopListening( this, event, callback ).Parameters
event: stringThe name of the event.
callback: FunctionThe function to stop being called.
Returns
void
on( event, callback, options? ) → voidinheritedmodule:ui/overlayhost~OverlayHost#onRegisters a callback function to be executed when an event is fired.
Shorthand for
this.listenTo( this, event, callback, options )(it makes the emitter listen on itself).Type parameters
Parameters
event: TEvent[ 'name' ]The name of the event.
callback: GetCallback<TEvent>The function to be called on event.
options?: GetCallbackOptions<TEvent>Additional options.
Returns
void
once( event, callback, options? ) → voidinheritedmodule:ui/overlayhost~OverlayHost#onceRegisters a callback function to be executed on the next time the event is fired only. This is similar to calling
onfollowed byoffin the callback.Type parameters
Parameters
event: TEvent[ 'name' ]The name of the event.
callback: GetCallback<TEvent>The function to be called on event.
options?: GetCallbackOptions<TEvent>Additional options.
Returns
void
stopDelegating( event?, emitter? ) → voidinheritedmodule:ui/overlayhost~OverlayHost#stopDelegatingStops delegating events. It can be used at different levels:
- To stop delegating all events.
- To stop delegating a specific event to all emitters.
- To stop delegating a specific event to a specific emitter.
Parameters
event?: stringThe name of the event to stop delegating. If omitted, stops it all delegations.
emitter?: Emitter(requires
event) The object to stop delegating a particular event to. If omitted, stops delegation ofeventto all emitters.
Returns
void
stopListening( emitter?, event?, callback? ) → voidinheritedmodule:ui/overlayhost~OverlayHost#stopListening:BASE_STOPStops listening for events. It can be used at different levels:
- To stop listening to a specific callback.
- To stop listening to a specific event.
- To stop listening to all events fired by a specific object.
- To stop listening to all events fired by all objects.
Parameters
emitter?: EmitterThe object to stop listening to. If omitted, stops it for all objects.
event?: string(Requires the
emitter) The name of the event to stop listening to. If omitted, stops it for all events fromemitter.callback?: Function(Requires the
event) The function to be removed from the call list for the givenevent.
Returns
void
sync() → voidmodule:ui/overlayhost~OverlayHost#syncBrings the host up to date with the resolved targets:
- keeps the
bodyCollectionmounted in the target resolved byresolveMountTarget(re-mounting only when the target changes, unmounting onnull); - keeps the inline UI container tracked for tooltips, re-resolving its shadow root in case a detached container has become connected.
Idempotent – call it whenever the targets may have changed: after attaching the feature to a container, right before showing a floating panel (an editor's UI may be mounted lazily), or on any relevant layout change.
Returns
void
- keeps the