[MediaWiki-commits] [Gerrit] oojs/ui[master]: SelectWidget/MenuSelectWidget: Maintain `aria-activedescenda...
VolkerE has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/349135 ) Change subject: SelectWidget/MenuSelectWidget: Maintain `aria-activedescendant` attribute on focus owner .. SelectWidget/MenuSelectWidget: Maintain `aria-activedescendant` attribute on focus owner Our SelectWidget does not allow individual OptionWidgets to have focus. Instead, it keeps track internally of which of the options really is active (e.g. which option arrow navigation is relative to, or which option will be selected if the user presses the enter key). This makes some implementation details a bit easier. However, it means we have to somehow inform assistive technology about the currently active option, since they can't guess it from the focus. This is done by setting `aria-activedescendant` on the DOM element which actually has focus (the focus owner). This is made a little more complicated because the SelectWidget can stand on its own (e.g. RadioSelectWidget), in which case it is the focus owner itself, or it can be a part of a larger widget (e.g. MenuSelectWidget/DropdownInputWidget), in which case the focus owner is usually somewhere else. As a bonus, SelectWidget will now move focus to the focus owner when one of its options is focussed. The only situation where this makes a difference is when a MenuOptionWidget is focussed through its accesskey. Bug: T149654 Change-Id: Ie993345e44ddb43dfbe2bebe0e12fd2bd9f5812e --- M src/widgets/MenuSelectWidget.js M src/widgets/SelectWidget.js M tests/QUnit.assert.equalDomElement.js 3 files changed, 44 insertions(+), 10 deletions(-) Approvals: jenkins-bot: Verified VolkerE: Looks good to me, approved diff --git a/src/widgets/MenuSelectWidget.js b/src/widgets/MenuSelectWidget.js index de8d457..8533f96 100644 --- a/src/widgets/MenuSelectWidget.js +++ b/src/widgets/MenuSelectWidget.js @@ -65,6 +65,9 @@ // Initialization this.$element.addClass( 'oo-ui-menuSelectWidget' ); + if ( config.widget ) { + this.setFocusOwner( config.widget.$tabIndexed ); + } // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods // that reference properties not initialized at that time of parent class construction @@ -320,6 +323,7 @@ this.toggleClipping( true ); if ( this.getSelectedItem() ) { + this.$focusOwner.attr( 'aria-activedescendant', this.getSelectedItem().getElementId() ); this.getSelectedItem().scrollElementIntoView( { duration: 0 } ); } @@ -328,6 +332,7 @@ this.getElementDocument().addEventListener( 'mousedown', this.onDocumentMouseDownHandler, true ); } } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); this.unbindKeyDownListener(); this.unbindKeyPressListener(); this.getElementDocument().removeEventListener( 'mousedown', this.onDocumentMouseDownHandler, true ); diff --git a/src/widgets/SelectWidget.js b/src/widgets/SelectWidget.js index 444a63e..46bc3ac 100644 --- a/src/widgets/SelectWidget.js +++ b/src/widgets/SelectWidget.js @@ -77,6 +77,7 @@ this.$element .addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' ) .attr( 'role', 'listbox' ); + this.setFocusOwner( this.$element ); if ( Array.isArray( config.items ) ) { this.addItems( config.items ); } @@ -169,7 +170,7 @@ } if ( event.target !== this.$element[ 0 ] ) { - this.$element.focus(); + this.$focusOwner.focus(); } }; @@ -583,6 +584,11 @@ } } if ( changed ) { + if ( item ) { + this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() ); + } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); + } this.emit( 'highlight', item ); } @@ -681,6 +687,13 @@ } } if ( changed ) { + if ( item && !item.constructor.static.highlightable ) { + if ( item ) { + this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() ); + } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); + } + } this.emit( 'select', item ); } @@ -856,3 +869,15 @@ return this; }; + +/** + * Set the DOM element which has focus while the user is interacting with this SelectWidget. + * + * Currently this is just used to s
[MediaWiki-commits] [Gerrit] oojs/ui[master]: SelectWidget/MenuSelectWidget: Maintain 'aria-activedescenda...
Bartosz DziewoĆski has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/349135 ) Change subject: SelectWidget/MenuSelectWidget: Maintain 'aria-activedescendant' attribute on focus owner .. SelectWidget/MenuSelectWidget: Maintain 'aria-activedescendant' attribute on focus owner Our SelectWidget does not allow individual OptionWidgets to have focus. Instead, it keeps track internally of which of the options really is active (e.g. which option arrow navigation is relative to, or which option will be selected if the user presses the enter key). This makes some implementation details a bit easier. However, it means we have to somehow inform accessibility tools about the currently active option, since they can't guess it from the focus. This is done by setting 'aria-activedescendant' on the DOM element which actually has focus (the focus owner). This is made a little more complicated because the SelectWidget can stand on its own (e.g. RadioSelectWidget), in which case it is the focus owner itself, or it can be a part of a larger widget (e.g. MenuSelectWidget/DropdownInputWidget), in which case the focus owner is usually somewhere else. Bug: T149654 Change-Id: Ie993345e44ddb43dfbe2bebe0e12fd2bd9f5812e --- M src/widgets/MenuSelectWidget.js M src/widgets/SelectWidget.js 2 files changed, 30 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/35/349135/1 diff --git a/src/widgets/MenuSelectWidget.js b/src/widgets/MenuSelectWidget.js index de8d457..8533f96 100644 --- a/src/widgets/MenuSelectWidget.js +++ b/src/widgets/MenuSelectWidget.js @@ -65,6 +65,9 @@ // Initialization this.$element.addClass( 'oo-ui-menuSelectWidget' ); + if ( config.widget ) { + this.setFocusOwner( config.widget.$tabIndexed ); + } // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods // that reference properties not initialized at that time of parent class construction @@ -320,6 +323,7 @@ this.toggleClipping( true ); if ( this.getSelectedItem() ) { + this.$focusOwner.attr( 'aria-activedescendant', this.getSelectedItem().getElementId() ); this.getSelectedItem().scrollElementIntoView( { duration: 0 } ); } @@ -328,6 +332,7 @@ this.getElementDocument().addEventListener( 'mousedown', this.onDocumentMouseDownHandler, true ); } } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); this.unbindKeyDownListener(); this.unbindKeyPressListener(); this.getElementDocument().removeEventListener( 'mousedown', this.onDocumentMouseDownHandler, true ); diff --git a/src/widgets/SelectWidget.js b/src/widgets/SelectWidget.js index 444a63e..0fd638c 100644 --- a/src/widgets/SelectWidget.js +++ b/src/widgets/SelectWidget.js @@ -77,6 +77,7 @@ this.$element .addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' ) .attr( 'role', 'listbox' ); + this.setFocusOwner( this.$element ); if ( Array.isArray( config.items ) ) { this.addItems( config.items ); } @@ -583,6 +584,11 @@ } } if ( changed ) { + if ( item ) { + this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() ); + } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); + } this.emit( 'highlight', item ); } @@ -681,6 +687,13 @@ } } if ( changed ) { + if ( item && !item.constructor.static.highlightable ) { + if ( item ) { + this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() ); + } else { + this.$focusOwner.removeAttr( 'aria-activedescendant' ); + } + } this.emit( 'select', item ); } @@ -856,3 +869,15 @@ return this; }; + +/** + * Set the DOM element which has focus while the user is interacting with this SelectWidget. + * + * Currently this is just used to set `aria-activedescendant` on it. + * + * @protected + * @param {jQuery} $focusOwner + */ +OO.ui.SelectWidget.prototype.setFocusOwner = function ( $focusOwner ) { + this.$focusOwner = $focusOwner; +}; -- To view, visit https://gerrit.wikimedia.org/r/349135 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie993345e44ddb43dfbe2bebe0e12fd2bd9f5812e Gerrit-PatchS