mediawiki-extensions-Visual.../modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineButtonWidget.js
WMDE-Fisch ef57268b2e Set selected status to sidebar elements
ARIA-selected only works on specific elements/roles. I tried several
combinations here, the most fitting seemed to be the option role, but
that role did not work very well in FF with NVDA. It also should only
be used as direct child to a listbox e.g. with several children.

The next role that's working with ARIA-selected that seemed fitting
is the gridcell. It's still a bit hacky but works well in IE and FF
with NVDA. I suspect that that's pretty good coverage already then.

Bug: T291284
Change-Id: I85c865b0ab12d3923e472e5f36b5c07b7c722180
2021-10-28 12:40:50 +02:00

106 lines
3.2 KiB
JavaScript

/**
* Generic button-like widget for items in the template dialog sidebar. See
* {@see OO.ui.ButtonWidget} for inspiration.
*
* @class
* @extends OO.ui.OptionWidget
*
* @constructor
* @param {Object} config
* @cfg {string} [icon=''] Symbolic name of an icon, e.g. "puzzle" or "wikiText"
* @cfg {string} label
*/
ve.ui.MWTransclusionOutlineButtonWidget = function VeUiMWTransclusionOutlineButtonWidget( config ) {
// Parent constructor
ve.ui.MWTransclusionOutlineButtonWidget.super.call( this, ve.extendObject( config, {
classes: [ 've-ui-mwTransclusionOutlineButtonWidget' ]
} ) );
// Mixin constructors
OO.ui.mixin.ButtonElement.call( this, {
// FIXME semantically this could be a <legend> and the surrounding OutlinePartWidget a <fieldset>
$button: $( '<span>' ),
framed: false
} );
OO.ui.mixin.IconElement.call( this, config );
OO.ui.mixin.TabIndexedElement.call( this, ve.extendObject( {
$tabIndexed: this.$button
}, config ) );
// FIXME hack for screen readers to understand the selection state
this.$button.attr( {
role: 'gridcell',
'aria-selected': 'false'
} );
this.$element
.append( this.$button.append( this.$icon, this.$label ) );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWTransclusionOutlineButtonWidget, OO.ui.OptionWidget );
OO.mixinClass( ve.ui.MWTransclusionOutlineButtonWidget, OO.ui.mixin.ButtonElement );
OO.mixinClass( ve.ui.MWTransclusionOutlineButtonWidget, OO.ui.mixin.IconElement );
OO.mixinClass( ve.ui.MWTransclusionOutlineButtonWidget, OO.ui.mixin.TabIndexedElement );
ve.ui.MWTransclusionOutlineButtonWidget.static.highlightable = false;
ve.ui.MWTransclusionOutlineButtonWidget.static.pressable = false;
/* Events */
/**
* @event keyPressed
* @param {number} key Typically one of the {@see OO.ui.Keys} constants
*/
/**
* @inheritDoc OO.ui.mixin.ButtonElement
* @param {jQuery.Event} e
* @fires keyPressed
*/
ve.ui.MWTransclusionOutlineButtonWidget.prototype.onKeyDown = function ( e ) {
var withMetaKey = e.ctrlKey || e.metaKey;
if ( e.which === OO.ui.Keys.SPACE &&
!withMetaKey && !e.shiftKey && !e.altKey
) {
// We know we can only select another part, so don't even try to unselect this one
if ( !this.isSelected() ) {
this.emit( 'keyPressed', e.which );
}
// The default behavior of pressing space is to scroll down
e.preventDefault();
return;
} else if ( ( e.which === OO.ui.Keys.UP || e.which === OO.ui.Keys.DOWN ) &&
withMetaKey && e.shiftKey &&
!e.altKey
) {
this.emit( 'keyPressed', e.which );
// TODO: Do we need e.preventDefault() and/or e.stopPropagation() here?
return;
} else if ( e.which === OO.ui.Keys.DELETE &&
withMetaKey &&
!e.shiftKey && !e.altKey
) {
this.emit( 'keyPressed', e.which );
// To not trigger the "clear cache" feature in Chrome we must do both
e.preventDefault();
e.stopPropagation();
return;
}
return OO.ui.mixin.ButtonElement.prototype.onKeyDown.call( this, e );
};
/**
* @inheritDoc
*/
ve.ui.MWTransclusionOutlineButtonWidget.prototype.setSelected = function ( state ) {
if ( this.$button ) {
this.$button.attr( 'aria-selected', state.toString() );
}
return ve.ui.MWTransclusionOutlineButtonWidget.super.prototype.setSelected.call( this, state );
};