77const ARIA_PREFIX = 'aria-' ;
88const ROLE_ATTRIBUTE = 'role' ;
99
10- // TODO: Finalize this.
10+ /** Represents an ARIA role that an element may have. */
1111export enum Role {
12- GRID = 'grid' ,
13- GRIDCELL = 'gridcell' ,
1412 GROUP = 'group' ,
1513 LISTBOX = 'listbox' ,
16- MENU = 'menu' ,
17- MENUITEM = 'menuitem' ,
18- MENUITEMCHECKBOX = 'menuitemcheckbox' ,
19- OPTION = 'option' ,
2014 PRESENTATION = 'presentation' ,
21- ROW = 'row' ,
2215 TREE = 'tree' ,
2316 TREEITEM = 'treeitem' ,
2417 SEPARATOR = 'separator' ,
25- STATUS = 'status' ,
26- REGION = 'region' ,
2718 IMAGE = 'image' ,
2819 FIGURE = 'figure' ,
2920 BUTTON = 'button' ,
3021 CHECKBOX = 'checkbox' ,
3122 TEXTBOX = 'textbox' ,
32- APPLICATION = 'application' ,
3323}
3424
35- // TODO: Finalize this.
25+ /** Represents ARIA-specific state that can be configured for an element. */
3626export enum State {
37- ACTIVEDESCENDANT = 'activedescendant' ,
38- COLCOUNT = 'colcount' ,
39- DISABLED = 'disabled' ,
40- EXPANDED = 'expanded' ,
41- INVALID = 'invalid' ,
4227 LABEL = 'label' ,
43- LABELLEDBY = 'labelledby' ,
4428 LEVEL = 'level' ,
45- ORIENTATION = 'orientation' ,
4629 POSINSET = 'posinset' ,
47- ROWCOUNT = 'rowcount' ,
4830 SELECTED = 'selected' ,
4931 SETSIZE = 'setsize' ,
50- VALUEMAX = 'valuemax' ,
51- VALUEMIN = 'valuemin' ,
5232 LIVE = 'live' ,
5333 HIDDEN = 'hidden' ,
5434 ROLEDESCRIPTION = 'roledescription' ,
55- ATOMIC = 'atomic' ,
5635 OWNS = 'owns' ,
5736}
5837
5938let isMutatingAriaProperty = false ;
6039
40+ /**
41+ * Updates the specific role for the specified element.
42+ *
43+ * @param element The element whose ARIA role should be changed.
44+ * @param roleName The new role for the specified element, or null if its role
45+ * should be cleared.
46+ */
6147export function setRole ( element : Element , roleName : Role | null ) {
6248 isMutatingAriaProperty = true ;
6349 if ( roleName ) {
@@ -66,6 +52,13 @@ export function setRole(element: Element, roleName: Role | null) {
6652 isMutatingAriaProperty = false ;
6753}
6854
55+ /**
56+ * Returns the ARIA role of the specified element, or null if it either doesn't
57+ * have a designated role or if that role is unknown.
58+ *
59+ * @param element The element from which to retrieve its ARIA role.
60+ * @returns The ARIA role of the element, or null if undefined or unknown.
61+ */
6962export function getRole ( element : Element ) : Role | null {
7063 // This is an unsafe cast which is why it needs to be checked to ensure that
7164 // it references a valid role.
@@ -76,6 +69,18 @@ export function getRole(element: Element): Role | null {
7669 return null ;
7770}
7871
72+ /**
73+ * Sets the specified ARIA state by its name and value for the specified
74+ * element.
75+ *
76+ * Note that the type of value is not validated against the specific type of
77+ * state being changed, so it's up to callers to ensure the correct value is
78+ * used for the given state.
79+ *
80+ * @param element The element whose ARIA state may be changed.
81+ * @param stateName The state to change.
82+ * @param value The new value to specify for the provided state.
83+ */
7984export function setState (
8085 element : Element ,
8186 stateName : State ,
@@ -90,11 +95,39 @@ export function setState(
9095 isMutatingAriaProperty = false ;
9196}
9297
98+ /**
99+ * Returns a string representation of the specified state for the specified
100+ * element, or null if it's not defined or specified.
101+ *
102+ * Note that an explicit set state of 'null' will return the 'null' string, not
103+ * the value null.
104+ *
105+ * @param element The element whose state is being retrieved.
106+ * @param stateName The state to retrieve.
107+ * @returns The string representation of the requested state for the specified
108+ * element, or null if not defined.
109+ */
93110export function getState ( element : Element , stateName : State ) : string | null {
94111 const attrStateName = ARIA_PREFIX + stateName ;
95112 return element . getAttribute ( attrStateName ) ;
96113}
97114
115+ /**
116+ * Softly requests that the specified text be read to the user if a screen
117+ * reader is currently active.
118+ *
119+ * This relies on a centrally managed ARIA live region that should not interrupt
120+ * existing announcements (that is, this is what's considered a polite
121+ * announcement).
122+ *
123+ * Callers should use this judiciously. It's often considered bad practice to
124+ * over announce information that can be inferred from other sources on the
125+ * page, so this ought to only be used when certain context cannot be easily
126+ * determined (such as dynamic states that may not have perfect ARIA
127+ * representations or indications).
128+ *
129+ * @param text The text to politely read to the user.
130+ */
98131export function announceDynamicAriaState ( text : string ) {
99132 const ariaAnnouncementSpan = document . getElementById ( 'blocklyAriaAnnounce' ) ;
100133 if ( ! ariaAnnouncementSpan ) {
@@ -103,6 +136,12 @@ export function announceDynamicAriaState(text: string) {
103136 ariaAnnouncementSpan . innerHTML = text ;
104137}
105138
139+ /**
140+ * Determines whether an ARIA property is in the process of being changed.
141+ *
142+ * @returns Returns whether an ARIA property is changing for any element,
143+ * specifically via setRole() or stateState().
144+ */
106145export function isCurrentlyMutatingAriaProperty ( ) : boolean {
107146 return isMutatingAriaProperty ;
108147}
0 commit comments