jenkins-bot has submitted this change and it was merged.

Change subject: DropdownWidget, ComboBoxWidget: Make keyboard-accessible
......................................................................


DropdownWidget, ComboBoxWidget: Make keyboard-accessible

Make the dropdown box, or the little combo box arrow, focusable by
adding TabIndexedElement mixin. Handle both clicks and keypresses on
them.

The combo box arrow now does double duty, as an indicator for the text
input and as a tabindexed element for the combo box itself. This
appears to work without a hitch! We've built a really clever library.

Not included: focus state styles. Browser defaults will be used
(usually a blue outline).

Bug: T87705
Change-Id: I14b06ccf19a91d88b406d7e4e5bb92ef233ed421
---
M src/widgets/ComboBoxWidget.js
M src/widgets/DropdownWidget.js
2 files changed, 63 insertions(+), 12 deletions(-)

Approvals:
  Trevor Parscal: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/widgets/ComboBoxWidget.js b/src/widgets/ComboBoxWidget.js
index 00b4e10..b765805 100644
--- a/src/widgets/ComboBoxWidget.js
+++ b/src/widgets/ComboBoxWidget.js
@@ -3,6 +3,7 @@
  *
  * @class
  * @extends OO.ui.Widget
+ * @mixins OO.ui.TabIndexedElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -17,10 +18,20 @@
        // Parent constructor
        OO.ui.ComboBoxWidget.super.call( this, config );
 
+       // Properties (must be set before TabIndexedElement constructor call)
+       this.$indicator = this.$( '<span>' );
+
+       // Mixin constructors
+       OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { 
$tabIndexed: this.$indicator } ) );
+
        // Properties
        this.$overlay = config.$overlay || this.$element;
        this.input = new OO.ui.TextInputWidget( $.extend(
-               { indicator: 'down', disabled: this.isDisabled() },
+               {
+                       indicator: 'down',
+                       $indicator: this.$indicator,
+                       disabled: this.isDisabled()
+               },
                config.input
        ) );
        this.menu = new OO.ui.TextInputMenuSelectWidget( this.input, $.extend(
@@ -33,9 +44,12 @@
        ) );
 
        // Events
+       this.$indicator.on( {
+               click: this.onClick.bind( this ),
+               keypress: this.onKeyPress.bind( this )
+       } );
        this.input.connect( this, {
                change: 'onInputChange',
-               indicator: 'onInputIndicator',
                enter: 'onInputEnter'
        } );
        this.menu.connect( this, {
@@ -53,6 +67,7 @@
 /* Setup */
 
 OO.inheritClass( OO.ui.ComboBoxWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ComboBoxWidget, OO.ui.TabIndexedElement );
 
 /* Methods */
 
@@ -80,12 +95,29 @@
 };
 
 /**
- * Handle input indicator events.
+ * Handle mouse click events.
+ *
+ * @param {jQuery.Event} e Mouse click event
  */
-OO.ui.ComboBoxWidget.prototype.onInputIndicator = function () {
-       if ( !this.isDisabled() ) {
+OO.ui.ComboBoxWidget.prototype.onClick = function ( e ) {
+       if ( !this.isDisabled() && e.which === 1 ) {
                this.menu.toggle();
+               this.input.$input[ 0 ].focus();
        }
+       return false;
+};
+
+/**
+ * Handle key press events.
+ *
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.ComboBoxWidget.prototype.onKeyPress = function ( e ) {
+       if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which 
=== OO.ui.Keys.ENTER ) ) {
+               this.menu.toggle();
+               this.input.$input[ 0 ].focus();
+       }
+       return false;
 };
 
 /**
diff --git a/src/widgets/DropdownWidget.js b/src/widgets/DropdownWidget.js
index 7a379e0..c26f3cc 100644
--- a/src/widgets/DropdownWidget.js
+++ b/src/widgets/DropdownWidget.js
@@ -12,6 +12,7 @@
  * @mixins OO.ui.IndicatorElement
  * @mixins OO.ui.LabelElement
  * @mixins OO.ui.TitledElement
+ * @mixins OO.ui.TabIndexedElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
@@ -24,18 +25,24 @@
        // Parent constructor
        OO.ui.DropdownWidget.super.call( this, config );
 
+       // Properties (must be set before TabIndexedElement constructor call)
+       this.$handle = this.$( '<span>' );
+
        // Mixin constructors
        OO.ui.IconElement.call( this, config );
        OO.ui.IndicatorElement.call( this, config );
        OO.ui.LabelElement.call( this, config );
        OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: 
this.$label } ) );
+       OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { 
$tabIndexed: this.$handle } ) );
 
        // Properties
        this.menu = new OO.ui.MenuSelectWidget( $.extend( { widget: this }, 
config.menu ) );
-       this.$handle = $( '<span>' );
 
        // Events
-       this.$element.on( { click: this.onClick.bind( this ) } );
+       this.$handle.on( {
+               click: this.onClick.bind( this ),
+               keypress: this.onKeyPress.bind( this )
+       } );
        this.menu.connect( this, { select: 'onMenuSelect' } );
 
        // Initialization
@@ -54,6 +61,7 @@
 OO.mixinClass( OO.ui.DropdownWidget, OO.ui.IndicatorElement );
 OO.mixinClass( OO.ui.DropdownWidget, OO.ui.LabelElement );
 OO.mixinClass( OO.ui.DropdownWidget, OO.ui.TitledElement );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.TabIndexedElement );
 
 /* Methods */
 
@@ -89,17 +97,28 @@
 };
 
 /**
- * Handles mouse click events.
+ * Handle mouse click events.
  *
  * @param {jQuery.Event} e Mouse click event
  */
 OO.ui.DropdownWidget.prototype.onClick = function ( e ) {
-       // Skip clicks within the menu
-       if ( $.contains( this.menu.$element[ 0 ], e.target ) ) {
-               return;
+       if ( !this.isDisabled() && e.which === 1 ) {
+               if ( this.menu.isVisible() ) {
+                       this.menu.toggle( false );
+               } else {
+                       this.menu.toggle( true );
+               }
        }
+       return false;
+};
 
-       if ( !this.isDisabled() ) {
+/**
+ * Handle key press events.
+ *
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.DropdownWidget.prototype.onKeyPress = function ( e ) {
+       if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which 
=== OO.ui.Keys.ENTER ) ) {
                if ( this.menu.isVisible() ) {
                        this.menu.toggle( false );
                } else {

-- 
To view, visit https://gerrit.wikimedia.org/r/189609
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I14b06ccf19a91d88b406d7e4e5bb92ef233ed421
Gerrit-PatchSet: 5
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz DziewoƄski <[email protected]>
Gerrit-Reviewer: TheDJ <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to