mediawiki-extensions-Revisi.../modules/ext.RevisionSlider.SliderArrowView.js
WMDE-Fisch 5f8bf83849 Improve support for screenreaders
This patch improves screenreader support by applying some basic
rules and improving the OOjs UI usage. Things done here:

- make use of 'aria-label' attribute to label interactive buttons
- use connect method on help button to allow keyboard interaction
- give hint on help button that it opens a dialog
- communicate state of autoexpand button
- add attributes to make screenreaders understand the accordion
mechanism if the slider widget

See:
https://www.w3.org/TR/wai-aria-practices/#button
https://www.w3.org/TR/wai-aria-practices/#accordion

Bug: T165489
Change-Id: I7a174e5971a751ec54d4d5115d5441f0a577c103
2017-06-12 09:14:22 +00:00

152 lines
4.5 KiB
JavaScript

( function ( mw, $ ) {
/**
* Module containing presentation logic for the arrow buttons
*
* @param {SliderView} sliderView
* @constructor
*/
var SliderArrowView = function ( sliderView ) {
this.sliderView = sliderView;
};
$.extend( SliderArrowView.prototype, {
/**
* @type {SliderView}
*/
sliderView: null,
/**
* Renders the backwards arrow button, returns it
* and renders and adds the popup for it.
*
* @return {OO.ui.ButtonWidget}
*/
renderBackwardArrow: function () {
var backwardArrowButton,
backwardArrowPopup;
backwardArrowButton = new OO.ui.ButtonWidget( {
icon: 'previous',
width: 20,
height: 140,
framed: true,
classes: [ 'mw-revslider-arrow', 'mw-revslider-arrow-backwards' ]
} );
backwardArrowPopup = new OO.ui.PopupWidget( {
$content: $( '<p>' ).text( mw.msg( 'revisionslider-arrow-tooltip-older' ) ),
$floatableContainer: backwardArrowButton.$element,
padded: true,
width: 200,
classes: [ 'mw-revslider-tooltip', 'mw-revslider-arrow-tooltip' ]
} );
backwardArrowButton.connect( this, {
click: [ 'arrowClickHandler', backwardArrowButton ]
} );
backwardArrowButton.$element
.attr( 'data-dir', -1 )
.children().attr( 'aria-label', mw.msg( 'revisionslider-arrow-tooltip-older' ) )
.mouseover( { button: backwardArrowButton, popup: backwardArrowPopup }, this.showPopup )
.mouseout( { popup: backwardArrowPopup }, this.hidePopup )
.focusin( { button: backwardArrowButton }, this.arrowFocusHandler );
$( 'body' ).append( backwardArrowPopup.$element );
return backwardArrowButton;
},
/**
* Renders the forwards arrow button, returns it
* and renders and adds the popup for it.
*
* @return {OO.ui.ButtonWidget}
*/
renderForwardArrow: function () {
var forwardArrowButton,
forwardArrowPopup;
forwardArrowButton = new OO.ui.ButtonWidget( {
icon: 'next',
width: 20,
height: 140,
framed: true,
classes: [ 'mw-revslider-arrow', 'mw-revslider-arrow-forwards' ]
} );
forwardArrowPopup = new OO.ui.PopupWidget( {
$content: $( '<p>' ).text( mw.msg( 'revisionslider-arrow-tooltip-newer' ) ),
$floatableContainer: forwardArrowButton.$element,
padded: true,
width: 200,
classes: [ 'mw-revslider-tooltip', 'mw-revslider-arrow-tooltip' ]
} );
forwardArrowButton.connect( this, {
click: [ 'arrowClickHandler', forwardArrowButton ]
} );
forwardArrowButton.$element
.attr( 'data-dir', 1 )
.children().attr( 'aria-label', mw.msg( 'revisionslider-arrow-tooltip-newer' ) )
.mouseover( { button: forwardArrowButton, popup: forwardArrowPopup }, this.showPopup )
.mouseout( { popup: forwardArrowPopup }, this.hidePopup )
.focusin( { button: forwardArrowButton }, this.arrowFocusHandler );
$( 'body' ).append( forwardArrowPopup.$element );
return forwardArrowButton;
},
showPopup: function ( e ) {
var button = e.data.button,
popup = e.data.popup;
if ( typeof button !== 'undefined' && button.isDisabled() ) {
return;
}
popup.$element.css( {
left: $( this ).offset().left + $( this ).outerWidth() / 2 + 'px',
top: $( this ).offset().top + $( this ).outerHeight() + 'px'
} );
popup.toggle( true );
},
hidePopup: function ( e ) {
var popup = e.data.popup;
popup.toggle( false );
},
/**
* @param {OO.ui.ButtonWidget} button
*/
arrowClickHandler: function ( button ) {
if ( button.isDisabled() ) {
return;
}
mw.track( 'counter.MediaWiki.RevisionSlider.event.arrowClick' );
this.sliderView.slide( button.$element.data( 'dir' ) );
},
/**
* Disabled oo.ui.ButtonWidgets get focused when clicked. In particular cases
* (arrow gets clicked when disabled, none other elements gets focus meanwhile, the other arrow is clicked)
* previously disabled arrow button still has focus and has OOjs-ui focused button styles
* applied (blue border) which is not what is wanted. And generally setting a focus on disabled
* buttons does not seem right in case of RevisionSlider's arrow buttons.
* This method removes focus from the disabled button if such case happens.
*
* @param {jQuery.Event} e
*/
arrowFocusHandler: function ( e ) {
var button = e.data.button;
if ( button.isDisabled() ) {
button.$element.find( 'a.oo-ui-buttonElement-button' ).blur();
}
}
} );
mw.libs.revisionSlider = mw.libs.revisionSlider || {};
mw.libs.revisionSlider.SliderArrowView = SliderArrowView;
}( mediaWiki, jQuery ) );