-
Notifications
You must be signed in to change notification settings - Fork 19
0.3.1 to 1.0.0 Migration Guide
The 1.0.0 release of CAM finished adding support for all ARIA roles. It also brought in some bug fixes and improvements, some of which are breaking changes that lead to multiple 1.0 pre-release versions of CAM before the 1.0.0 version was released. The purpose of this page is to document the breaking changes and how to address them in consuming projects. This page organizes the breaking changes by category, but all need to be addressed as part of the upgrade to the 1.0.0 version of CAM.
-
ROLES.OPTION
has been split intoROLES.SINGLESELECTOPTION
andROLES.MULTISELECTOPTION
. This was needed in order to support gettingROLES.SINGLESELECTLISTBOX
working visually consistent across browsers combined with CAM's one-to-one role to HTML tag mapping.- If an option is being added to a
ROLES.SINGLESELECTLISTBOX
, then replaceROLES.OPTION
withROLES.SINGLESELECTOPTION
. - For options added to
ROLES.MULTISELECTLISTBOX
, then replaceROLES.OPTION
withROLES.MULTISELECTOPTION
.
- If an option is being added to a
- If event listeners are bound after the
register
function is called, such as byaddEventListener
oron
, then no changes are needed. - In the 0.x versions of CAM, the object passed to
register
could containonFocus
andonKeyboardClick
callbacks for handling those particular events. In order to handle any event, those fields have been replaced by anevents
array of objects that allows for binding an event handler for any event. The objects that make up this array have a field ofeventName
for the string name of the particular event to bind for, and alistener
field for specifying the event handler function. A sample of this way of binding event listeners can be seen in the test app at https://github.com/CurriculumAssociates/createjs-accessibility-tester/blob/290d6ab51c49381345b3b831c37c4f5c7ef48c89/src/widgets/ScrollBar.js#L29-L38.- For prior
onFocus
andonKeyboardClick
fields, for example:onFocus: _focusHandler, onKeyboardClick: _keyboardClickHandler,
- Becomes:
events: [ { eventName: 'focus', listener: _focusHandler }, { eventName: 'keyboardClick', listener: _keyboardClickHandler } ],
- For prior
-
ROLES.ROW
used to emit akeyboardClick
event when used inside aROLES.TREEGRID
to indicate that a row should expand or collapse. That has been replaced byROLES.TREEGRID
emittingcollapseRow
orexpandRow
events. To handle this, thekeyboardClick
event listener on the row DisplayObject should be removed, and event listeners added to the tree grid DisplayObject for the collapse and expand row events.
Due to trying using semantic markup as much as possible, most keyboard behavior is actually the browser's default behavior for that element. But there are cases where CAM needs to add a keydown listener in order to follow WAI-ARIA Practices (https://www.w3.org/TR/wai-aria-practices-1.1/). Since CAM can emit keydown events once .accessible.enableKeyEvents
on a registered DisplayObject is set to true, the intent is to allow for calling preventDefault on the event object passed to those listeners to prevent both default browser behavior and CAM's internal keydown listeners from providing their default behavior, in order to allow consuming projects to customize the behavior completely as needed. In 0.x not all keyboard listeners followed this pattern (some would, others would turn off the CAM keydown listener just by setting .accessible.enableKeyEvents
to true). So, consuming projects should ensure that they are calling preventDefault in their keydown listeners when they want to disable default keyboard behavior as provided either by the browser or CAM.
CAM tries to help ensure its translation of DisplayObjects to HTML produces valid a HTML structure by performing checks when adding a DisplayObject to the accessibility tree. It does this in the addChild
and addChildAt
functions of the AccessibilityObject
and its subclasses by checking if the role and any other relevant properties of the DisplayObject trying to be added are valid given the this
instance's role. However, in 0.x not all roles performed this check leading to it being overly lenient and allowing for invalid DOM structures. An audit and update of all roles was done for 1.0 and the added missing restrictions are:
-
ROLES.BUTTON
only allows for interactive elements (either semantically or with a tabIndex set) to be added as children. This still allows for non-interactive children, such as a button wrapping an image. -
ROLES.CHECKBOX
,ROLES.IMG
,ROLES.RADIO
,ROLES.SINGLELINETEXTBOX
,ROLES.SEPARATOR
,ROLES.SLIDER
, andROLES.SPINBUTTON
cannot have children. -
ROLES.ORDEREDLIST
andROLES.UNORDEREDLIST
can only haveROLES.LISTITEM
as children. -
ROLES.ROW
can only haveROLES.CELL
,ROLES.GRIDCELL
,ROLES.COLUMNHEADER
, andROLES.ROWHEADER
as children. -
ROLES.TABLEBODY
,ROLES.TABLEFOOT
, andROLES.TABLEHEAD
can only haveROLES.ROW
as children. -
ROLES.TREE
can only haveROLES.TREEITEM
as children.
- The
hasPopUp
getter/setter of AccessibilityObject (the base class used to populate a registered DisplayObject's.accessible
field) has been updated from a boolean to a string in order to allow for all the valid values that https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup specifies- For existing
true
orfalse
parameter values, add quotes around the value or use another mechanism to convert it to a string - For existing undefined parameter values, no change needs to be made
- For existing
This module uses camelCase for the various getters/setters available off of a registered DisplayObject's .accessible
field. However, in 0.x, not all getters/setters followed this convention which has been corrected as part of the 1.0 release. The table below shows the change in name between 0.x and 1.0, where consuming projects should be updated to the 1.0 names. Since these getters/setters are defined by AccessibilityObject
or its subclasses, some roles may already be using the camelCase in 0.x, but for simplicity the table below doesn't break out the 0.x to 1.0 changes by role; the 1.0 name should now work with all roles that support that getter/setter.
0.x Name | 1.0 Name |
---|---|
autocomplete | autoComplete |
autofocus | autoFocus |
colcount | colCount |
colindex | colIndex |
colspan | colSpan |
crossorigin | crossOrigin |
hreflang | hrefLang |
ismap | isMap |
longdesc | longDesc |
rowcount | rowCount |
rowindex | rowIndex |
rowspan | rowSpan |
srcset | srcSet |
usemap | useMap |
valuetext | valueText |
On AccessibilityObject
there used to be a getter named reactProps
. While the comment did list its access level as package, due to the lack of a _
some consuming projects thought it was a public property and would directly modify its contents. Since that object and its fields are an internal implementation detail of this module, it should not be accessed or modified by consuming projects. To help make this clear when not looking at the documentation comment, the getter has been removed. Consuming projects should use the public getters/setters of a registered DisplayObject's .accessible
field. If there is not one available for the corresponding HTML attribute, then a PR or issue should be opened so adding support for that can be discussed and potentially added.
Due to the display of the select tag being controlled by the browser and not stylable through CSS, in some browsers an open listbox would appear over the canvas even if the DOM translation produced by CAM is otherwise hidden. To address this, CAM 1.0 changed from using the semantic select tag to the non-semantic ul tag. This is what caused the earlier discussed ROLES.OPTION
splitting into single and multiselect variants, so that the single select option would use the li tag in order to ensure a valid DOM. A consequence of this is now single select listboxes require an option to be designated as the default selection. The test-app already does this (starting at https://github.com/CurriculumAssociates/createjs-accessibility-tester/blob/main/src/widgets/ListBox.js#L25-L26 which gets to https://github.com/CurriculumAssociates/createjs-accessibility-tester/blob/main/src/widgets/ListBox.js#L110). A sample of how to do this is:
listboxDisplayObject.accessible.selected = optionDisplayObjects[0];