Accessibility: Improve accessibility for the Plugin details modal.
The plugin details modal can be invoked from several screens. There's now a new `.open-plugin-details-modal` CSS class to be used in combination with the `.thickbox` CSS class that adds everything needed for accessibility. - Adds an ARIA role `dialog` and an `aria-label` attribute to the modal - Adds a `title` attribute to the iframe inside the modal - Constrains tabbing within the modal - Restores focus back in a proper place when closing the modal Also, improves a bit the native Thickbox implementation: it should probably be replaced with some more modern tool but at least keyboard focus should be moved inside the modal. Fixes #33305. Built from https://develop.svn.wordpress.org/trunk@36964 git-svn-id: http://core.svn.wordpress.org/trunk@36932 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
@@ -1,14 +1,23 @@
|
||||
/* global plugininstallL10n, tb_click */
|
||||
/* global plugininstallL10n, tb_click, tb_remove */
|
||||
|
||||
/* Plugin Browser Thickbox related JS*/
|
||||
var tb_position;
|
||||
jQuery( document ).ready( function( $ ) {
|
||||
|
||||
var tbWindow,
|
||||
$focusedBefore,
|
||||
$iframeBody,
|
||||
$tabbables,
|
||||
$firstTabbable,
|
||||
$lastTabbable;
|
||||
|
||||
tb_position = function() {
|
||||
var tbWindow = $( '#TB_window' ),
|
||||
width = $( window ).width(),
|
||||
var width = $( window ).width(),
|
||||
H = $( window ).height() - ( ( 792 < width ) ? 60 : 20 ),
|
||||
W = ( 792 < width ) ? 772 : width - 20;
|
||||
|
||||
tbWindow = $( '#TB_window' );
|
||||
|
||||
if ( tbWindow.length ) {
|
||||
tbWindow.width( W ).height( H );
|
||||
$( '#TB_iframeContent' ).width( W ).height( H );
|
||||
@@ -38,16 +47,111 @@ jQuery( document ).ready( function( $ ) {
|
||||
tb_position();
|
||||
});
|
||||
|
||||
$( '.plugin-card, .plugins .plugin-version-author-uri' ).on( 'click', 'a.thickbox', function( e ) {
|
||||
/*
|
||||
* Custom events: when a Thickbox iframe has loaded and when the Thickbox
|
||||
* modal gets removed from the DOM.
|
||||
*/
|
||||
$( 'body' )
|
||||
.on( 'thickbox:iframe:loaded', tbWindow, function() {
|
||||
iframeLoaded();
|
||||
})
|
||||
.on( 'thickbox:removed', function() {
|
||||
// Set focus back to the element that opened the modal dialog.
|
||||
// Note: IE 8 would need this wrapped in a fake setTimeout `0`.
|
||||
$focusedBefore.focus();
|
||||
});
|
||||
|
||||
function iframeLoaded() {
|
||||
var $iframe = tbWindow.find( '#TB_iframeContent' );
|
||||
|
||||
// Get the iframe body.
|
||||
$iframeBody = $iframe.contents().find( 'body' );
|
||||
|
||||
// Get the tabbable elements and handle the keydown event on first load.
|
||||
handleTabbables();
|
||||
|
||||
// Set initial focus on the "Close" button.
|
||||
$firstTabbable.focus();
|
||||
|
||||
/*
|
||||
* When the "Install" button is disabled (e.g. the Plugin is already installed)
|
||||
* then we can't predict where the last focusable element is. We need to get
|
||||
* the tabbable elements and handle the keydown event again and again,
|
||||
* each time the active tab panel changes.
|
||||
*/
|
||||
$( '#plugin-information-tabs a', $iframeBody ).on( 'click', function() {
|
||||
handleTabbables();
|
||||
});
|
||||
|
||||
// Close the modal when pressing Escape.
|
||||
$iframeBody.on( 'keydown', function( event ) {
|
||||
if ( 27 !== event.which ) {
|
||||
return;
|
||||
}
|
||||
tb_remove();
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the tabbable elements and detach/attach the keydown event.
|
||||
* Called after the iframe has fully loaded so we have all the elements we need.
|
||||
* Called again each time a Tab gets clicked.
|
||||
* @todo Consider to implement a WordPress general utility for this and don't use jQuery UI.
|
||||
*/
|
||||
function handleTabbables() {
|
||||
var $firstAndLast;
|
||||
// Get all the tabbable elements.
|
||||
$tabbables = $( ':tabbable', $iframeBody );
|
||||
// Our first tabbable element is always the "Close" button.
|
||||
$firstTabbable = tbWindow.find( '#TB_closeWindowButton' );
|
||||
// Get the last tabbable element.
|
||||
$lastTabbable = $tabbables.last();
|
||||
// Make a jQuery collection.
|
||||
$firstAndLast = $firstTabbable.add( $lastTabbable );
|
||||
// Detach any previously attached keydown event.
|
||||
$firstAndLast.off( 'keydown.wp-plugin-details' );
|
||||
// Attach again the keydown event on the first and last focusable elements.
|
||||
$firstAndLast.on( 'keydown.wp-plugin-details', function( event ) {
|
||||
constrainTabbing( event );
|
||||
});
|
||||
}
|
||||
|
||||
// Constrain tabbing within the plugin modal dialog.
|
||||
function constrainTabbing( event ) {
|
||||
if ( 9 !== event.which ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $lastTabbable[0] === event.target && ! event.shiftKey ) {
|
||||
event.preventDefault();
|
||||
$firstTabbable.focus();
|
||||
} else if ( $firstTabbable[0] === event.target && event.shiftKey ) {
|
||||
event.preventDefault();
|
||||
$lastTabbable.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Open the Plugin details modal.
|
||||
$( '.thickbox.open-plugin-details-modal' ).on( 'click', function( e ) {
|
||||
// The `data-title` attribute is used only in the Plugin screens.
|
||||
var title = $( this ).data( 'title' ) ? plugininstallL10n.plugin_information + ' ' + $( this ).data( 'title' ) : plugininstallL10n.plugin_modal_label;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Store the element that has focus before opening the modal dialog, i.e. the control which opens it.
|
||||
$focusedBefore = $( this );
|
||||
|
||||
tb_click.call(this);
|
||||
|
||||
$('#TB_title').css({'background-color':'#23282d','color':'#cfcfcf'});
|
||||
$('#TB_ajaxWindowTitle').html( '<strong>' + plugininstallL10n.plugin_information + '</strong> ' + $(this).data( 'title' ) );
|
||||
$('#TB_iframeContent').attr( 'title', plugininstallL10n.plugin_information + ' ' + $(this).data( 'title' ) );
|
||||
$('#TB_closeWindowButton').focus();
|
||||
// Set ARIA role and ARIA label.
|
||||
tbWindow.attr({
|
||||
'role': 'dialog',
|
||||
'aria-label': plugininstallL10n.plugin_modal_label
|
||||
});
|
||||
|
||||
// Set title attribute on the iframe.
|
||||
tbWindow.find( '#TB_iframeContent' ).attr( 'title', title );
|
||||
});
|
||||
|
||||
/* Plugin install related JS */
|
||||
|
||||
Reference in New Issue
Block a user