FocusCycler (ui)
@ckeditor/ckeditor5-ui/src/focuscycler
A utility class that helps cycling over focusable views in a
ViewCollection
when the focus is tracked by the
FocusTracker
instance. It helps implementing keyboard
navigation in HTML forms, toolbars, lists and the like.
To work properly it requires:
- a collection of focusable (HTML
tabindex
attribute) views that implement thefocus()
method, - an associated focus tracker to determine which view is focused.
A simple cycler setup can look like this:
const focusables = new ViewCollection<FocusableView>();
const focusTracker = new FocusTracker();
// Add focusable views to the focus tracker.
focusTracker.add( ... );
Then, the cycler can be used manually:
const cycler = new FocusCycler( { focusables, focusTracker } );
// Will focus the first focusable view in #focusables.
cycler.focusFirst();
// Will log the next focusable item in #focusables.
console.log( cycler.next );
Alternatively, it can work side by side with the KeystrokeHandler
:
const keystrokeHandler = new KeystrokeHandler();
// Activate the keystroke handler.
keystrokeHandler.listenTo( sourceOfEvents );
const cycler = new FocusCycler( {
focusables, focusTracker, keystrokeHandler,
actions: {
// When arrowup of arrowleft is detected by the #keystrokeHandler,
// focusPrevious() will be called on the cycler.
focusPrevious: [ 'arrowup', 'arrowleft' ],
}
} );
Check out the "Deep dive into focus tracking" guide to learn more.
Filtering
Properties
-
Actions that the cycler can take when a keystroke is pressed. Requires
options.keystrokeHandler
to be passed and working. When an action is performed,preventDefault
andstopPropagation
will be called on the event the keystroke fired in the DOM.actions: { // Will call #focusPrevious() when arrowleft or arrowup is pressed. focusPrevious: [ 'arrowleft', 'arrowup' ], // Will call #focusNext() when arrowdown is pressed. focusNext: 'arrowdown' }
-
An index of the view in the
focusables
which is focused according tofocusTracker
. Returnsnull
when there is no such view. -
Returns the first focusable view in
focusables
. Returnsnull
if there is none.Note: Hidden views (e.g. with
display: none
) are ignored. -
A focus tracker instance that the cycler uses to determine the current focus state in
focusables
. -
A focusable views collection that the cycler operates on.
-
readonly
keystrokeHandler : KeystrokeHandler | undefined
module:ui/focuscycler~FocusCycler#keystrokeHandler
An instance of the
KeystrokeHandler
which can respond to certain keystrokes and cycle the focus. -
Returns the last focusable view in
focusables
. Returnsnull
if there is none.Note: Hidden views (e.g. with
display: none
) are ignored. -
Returns the next focusable view in
focusables
based oncurrent
. Returnsnull
if there is none.Note: Hidden views (e.g. with
display: none
) are ignored. -
Returns the previous focusable view in
focusables
based oncurrent
. Returnsnull
if there is none.Note: Hidden views (e.g. with
display: none
) are ignored.
Methods
-
constructor( options = { [options.actions], options.focusTracker, options.focusables, [options.keystrokeHandler], [options.keystrokeHandlerOptions] } )
module:ui/focuscycler~FocusCycler#constructor
Creates an instance of the focus cycler utility.
Parameters
options : object
Configuration options.
Properties[ options.actions ] : FocusCyclerActions
options.focusTracker : FocusTracker
options.focusables : ViewCollection<FocusableView>
[ options.keystrokeHandler ] : KeystrokeHandler
[ options.keystrokeHandlerOptions ] : KeystrokeHandlerOptions
-
chain( chainedFocusCycler ) → void
module:ui/focuscycler~FocusCycler#chain
Allows for creating continuous focus cycling across multiple focus cyclers and their collections of
focusables
.It starts listening to the
FocusCyclerForwardCycleEvent
andFocusCyclerBackwardCycleEvent
events of the chained focus cycler and engages, whenever the user reaches the last (forwards navigation) or first (backwards navigation) focusable view and would normally start over. Instead, the navigation continues on the higher level (flattens).For instance, for the following nested focus navigation structure, the focus would get stuck the moment the AB gets focused and its focus cycler starts managing it:
┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ │ AA │ │ AB │ │ AC │ │ │ │ │ │ │ │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├───┐ │ │ │ │ ├───► │ └─────┘ └─────┘ └─────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────┘ │ │ │ │ │ │ │ │ │ └────────────┘ └──────────────────────────────────┘ └────────────┘
Chaining a focus tracker that manages AA, AB, and AC with the focus tracker that manages ABA, ABB, and ABC creates a seamless navigation experience instead:
┌────────────┐ ┌──────────────────────────────────┐ ┌────────────┐ │ AA │ │ AB │ │ AC │ │ │ │ │ │ │ │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ │ │ │ ┌──► ABA ├──► ABB ├──► ABC ├──┐ │ │ │ ┌──► ├───┼─┘ └─────┘ └─────┘ └─────┘ └──┼───► ├──┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────────┘ └──────────────────────────────────┘ └────────────┘ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────┘
See
unchain
to reverse the chaining.Parameters
chainedFocusCycler : FocusCycler
Returns
void
-
Delegates selected events to another
Emitter
. For instance:emitterA.delegate( 'eventX' ).to( emitterB ); emitterA.delegate( 'eventX', 'eventY' ).to( emitterC );
then
eventX
is delegated (fired by)emitterB
andemitterC
along withdata
:emitterA.fire( 'eventX', data );
and
eventY
is delegated (fired by)emitterC
along withdata
:emitterA.fire( 'eventY', data );
Parameters
events : Array<string>
Event names that will be delegated to another emitter.
Returns
-
inherited
fire( eventOrInfo, args ) → GetEventInfo<TEvent>[ 'return' ]
module:ui/focuscycler~FocusCycler#fire
Fires an event, executing all callbacks registered for it.
The first parameter passed to callbacks is an
EventInfo
object, followed by the optionalargs
provided in thefire()
method call.Type parameters
Parameters
eventOrInfo : GetNameOrEventInfo<TEvent>
The name of the event or
EventInfo
object 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).
-
focusFirst() → void
module:ui/focuscycler~FocusCycler#focusFirst
Focuses the
first
item infocusables
.Note: Hidden views (e.g. with
display: none
) are ignored.Returns
void
-
focusLast() → void
module:ui/focuscycler~FocusCycler#focusLast
Focuses the
last
item infocusables
.Note: Hidden views (e.g. with
display: none
) are ignored.Returns
void
-
focusNext() → void
module:ui/focuscycler~FocusCycler#focusNext
Focuses the
next
item infocusables
.Note: Hidden views (e.g. with
display: none
) are ignored.Returns
void
-
focusPrevious() → void
module:ui/focuscycler~FocusCycler#focusPrevious
Focuses the
previous
item infocusables
.Note: Hidden views (e.g. with
display: none
) are ignored.Returns
void
-
inherited
listenTo( emitter, event, callback, [ options ] ) → void
module:ui/focuscycler~FocusCycler#listenTo:BASE_EMITTER
Registers 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.// 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
fire
method.Type parameters
Parameters
emitter : Emitter
The 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
-
Stops executing the callback on the given event. Shorthand for
this.stopListening( this, event, callback )
.Parameters
event : string
The name of the event.
callback : Function
The function to stop being called.
Returns
void
-
Registers 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
-
Registers a callback function to be executed on the next time the event is fired only. This is similar to calling
on
followed byoff
in 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
-
inherited
stopDelegating( [ event ], [ emitter ] ) → void
module:ui/focuscycler~FocusCycler#stopDelegating
Stops 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 ] : string
The 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 ofevent
to all emitters.
Returns
void
-
inherited
stopListening( [ emitter ], [ event ], [ callback ] ) → void
module:ui/focuscycler~FocusCycler#stopListening:BASE_STOP
Stops 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 ] : Emitter
The 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
-
unchain( otherFocusCycler ) → void
module:ui/focuscycler~FocusCycler#unchain
-
Focuses the given view if it exists.
Parameters
view : null | FocusableView
The view to be focused
direction : 1 | 1
The direction of the focus if the view has focusable children.
Returns
void
-
private
_getDomFocusableItem( step ) → null | FocusableView
module:ui/focuscycler~FocusCycler#_getDomFocusableItem
Returns the next or previous focusable view in
focusables
with respect tocurrent
.Parameters
step : 1 | 1
Either
1
for checking forward fromcurrent
or-1
for checking backwards.
Returns
null | FocusableView
Events
-
backwardCycle( eventInfo )
module:ui/focuscycler~FocusCycler#event:backwardCycle
Fired when the focus cycler is about to move the focus from the first focusable item to the last one.
Parameters
eventInfo : EventInfo
An object containing information about the fired event.
-
forwardCycle( eventInfo )
module:ui/focuscycler~FocusCycler#event:forwardCycle
Fired when the focus cycler is about to move the focus from the last focusable item to the first one.
Parameters
eventInfo : EventInfo
An object containing information about the fired event.
Every day, we work hard to keep our documentation complete. Have you spotted outdated information? Is something missing? Please report it via our issue tracker.
With the release of version 42.0.0, we have rewritten much of our documentation to reflect the new import paths and features. We appreciate your feedback to help us ensure its accuracy and completeness.