Bartosz Dziewoński has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/189609

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, 64 insertions(+), 12 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/09/189609/1

diff --git a/src/widgets/ComboBoxWidget.js b/src/widgets/ComboBoxWidget.js
index 6531dc9..88735be 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,21 @@
        // 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(
-               { $: this.$, indicator: 'down', disabled: this.isDisabled() },
+               {
+                       $: this.$,
+                       indicator: 'down',
+                       $indicator: this.$indicator,
+                       disabled: this.isDisabled()
+               },
                config.input
        ) );
        this.menu = new OO.ui.TextInputMenuSelectWidget( this.input, $.extend(
@@ -34,9 +46,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, {
@@ -54,6 +69,7 @@
 /* Setup */
 
 OO.inheritClass( OO.ui.ComboBoxWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ComboBoxWidget, OO.ui.TabIndexedElement );
 
 /* Methods */
 
@@ -81,12 +97,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 81678b4..560c39e 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( { $: this.$, widget: 
this }, config.menu ) );
-       this.$handle = this.$( '<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: newchange
Gerrit-Change-Id: I14b06ccf19a91d88b406d7e4e5bb92ef233ed421
Gerrit-PatchSet: 1
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>

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

Reply via email to