Interface TabOrderOverview
Tab Order Overview
Smart GWT has logic to automatically assign and manage tab indices for focusable components and elements within those components (for example Buttons, FormItems, Form Item icons, etc). This system has been designed to provide an intuitive user interaction experience by default, and to support being customized for alternative tabbing behaviors by application code (see "Custom Tab Orders", below). The TabIndexManager
class
is a singleton class responsible for maintaining the tab order for a chain of elements, and
parcelling out tab index values. This class is not directly responsible for updating any
elements in the DOM - instead it associates a unique ID with a position in a hierarchical data structure
, and provides APIs to
restructure and reorder entries in the tree, request a numeric tab index value for each entry,
and fire a notification method when an entry's tab index changes due to the tree being
restructured.
The actual tab indices are lazily generated when requested, and will be slotted within the "auto-generated tab index" range (see Canvas.TAB_INDEX_FLOOR and TAB_INDEX_CEILING). A gap will be left between the assigned tab indices to minimize needing to reshuffle due to slotting elements before already assigned tab-indices, and logic is in place to handle reassigning tab indices to accommodate this if it does become necessary.
A notification method will be fired if any calculated tab index becomes obsolete due to the tree structure changing (either a parent is moved or we run out of space between elements and have to reassign indices to later elements).
Each Smart GWT Canvas uses its own ID to register
with the TabIndexManager at creation time and has built in logic to update its position in the
as the page structure changes, and, for focusable widgets, ensure the returned tabIndex value
is assigned to the widget handle. FormItem
s and
FormItemIcon
s are similarly registered with
TabIndexManager and apply the returned tab index to the appropriate element on the page.
By default canvas tab positions are updated as follows:
- On draw, top level elements are always moved to the end of the tab-order
- When children are added to a parent, they
will be moved to be a sub-element of the parent entry, in the position returned by
Canvas.getChildTabPosition()
. Note that this method is overridden for Layouts to have tabbing occur in specified member order.
DynamicForm.sortItemsIntoTabOrder()
and FormItem.getIconTabPosition()
for details on how the TabIndexManager is integrated with
FormItems and FormItemIcons. Note that for canFocus false widgets, or widgets with tab index explicitly specified as either -1 or some value below TAB_INDEX_FLOOR will still be present in the TabIndexManager's data tree (we'll just never request a tab-index for them). This allows us to manage the tab index of their children in a logically consistent manner
Custom Tab order Tabbing behavior for canvases may be customized in a number of ways:
- An explicit
Canvas.tabIndex
may be specified for any canvas. This is appropriate for very simple customizations only. It will not impact the tab-index of any child, so to build an intuitive user experience using explicit tabIndex values typically requires an explicit tabIndex be specified for every focusable element on the page. - The
Canvas.setRelativeTabPosition()
method may be used to assign a custom relative, or "local" tab position for a canvas. This is the position within the canvas's parent widget, or within top level widgets if the canvas has no parent orCanvas.updateTabPositionOnReparent
is false. - To actually provide an explicit
tab-position for some Canvas, a developer may use the
TabIndexManager.moveTarget()
method and pass in the canvas' ID as the first parameter. - Canvases may also choose not to
have their tab position updated on draw (see
Canvas.updateTabPositionOnDraw
or reparent (seeCanvas.updateTabPositionOnReparent
).
This is useful for providing tab index management logic that doesn't match up with top level draw order, or the canvas parent-child hierarchy.
CustomTabElements
for
details on how to achieve this.