Commit 3c188898 authored by Jono Mingard's avatar Jono Mingard
Browse files

Made block configuration dialog keyboard-accessible (Bug #1270987)



Add descriptive alt text to 'Configure' and 'Delete' buttons in page editor,
add descriptive alt text to configuration dialog close button, set focus
to close button when the dialog is opened and add aria-hidden to the
main content of the page so that screen reader users cannot tab out of the
dialog.

Change-Id: I526ddbe08fc8f50171fd1b4b68ee5c7cbcd3e228
Signed-off-by: default avatarJono Mingard <jonom@catalyst.net.nz>
parent b721e8cf
......@@ -633,7 +633,7 @@
sendjsonrequest(config['wwwroot'] + 'view/blocks.json.php', pd, 'POST', function(data) {
var blockinstanceId = button.attr('name').substr(button.attr('name').lastIndexOf('_') + 1);
$('#blockinstance_' + blockinstanceId).remove();
if ($('#blockinstance_' + blockinstanceId + '_configure').length) {
if (!$('#configureblock').hasClass('hidden')) {
removeConfigureBlocks();
showMediaPlayers();
}
......@@ -646,6 +646,7 @@
// refresh the 'add block here' buttons
ViewManager.displayPage(config['wwwroot'] + 'view/blocks.php?id=' + $('#viewid').val());
}
button.removeAttr('disabled');
}, function() {
button.removeAttr('disabled');
});
......@@ -667,7 +668,7 @@
pd[button.attr('name')] = 1;
sendjsonrequest(config['wwwroot'] + 'view/blocks.json.php', pd, 'POST', function(data) {
$('#blockinstance_' + blockinstanceId).remove();
if ($('#blockinstance_' + blockinstanceId + '_configure').length) {
if (!$('#configureblock').hasClass('hidden')) {
removeConfigureBlocks();
showMediaPlayers();
}
......@@ -993,6 +994,7 @@
event.preventDefault();
removeConfigureBlocks();
showMediaPlayers();
button.focus();
});
});
}
......@@ -1016,11 +1018,6 @@
$(temp).removeClass('hidden');
}
});
$('body').prepend('<div/>', {
id: 'overlay'
});
}
function showMediaPlayers() {
......@@ -1038,6 +1035,7 @@
$(this).remove();
});
$('#overlay').remove();
$('#container').removeAttr('aria-hidden');
}
/**
......@@ -1058,10 +1056,17 @@
function addConfigureBlock(oldblock, configblock, removeoncancel) {
hideMediaPlayers();
var temp = $('<div>').html(configblock.html);
var newblock = temp.find('div.blockinstance');
newblock.hide();
var newblock = $('#configureblock').addClass('hidden');
var title = temp.find('.blockinstance .blockinstance-header').html();
var content = temp.find('.blockinstance .blockinstance-content').html();
newblock.find('.blockinstance-header').html(title);
newblock.find('.blockinstance-content').html(content);
$('body').append(newblock);
var blockinstanceId = temp.find('.blockinstance').attr('id');
blockinstanceId = blockinstanceId.substr(0, blockinstanceId.length - '_configure'.length);
blockinstanceId = blockinstanceId.substr(blockinstanceId.lastIndexOf('_') + 1);
var style = {
'position': 'absolute',
'z-index': 1
......@@ -1098,12 +1103,11 @@
}
var deletebutton = newblock.find('input.deletebutton');
deletebutton.unbind().attr('name', 'action_removeblockinstance_id_' + blockinstanceId);
if (removeoncancel) {
rewriteDeleteButton(deletebutton);
var oldblockid = newblock.attr('id').substr(0, newblock.attr('id').length - '_configure'.length);
var blockinstanceId = oldblockid.substr(oldblockid.lastIndexOf('_') + 1);
var cancelbutton = $('#cancel_instconf_action_configureblockinstance_id_' + blockinstanceId);
if (cancelbutton) {
cancelbutton.attr('name', deletebutton.attr('name'));
......@@ -1112,25 +1116,47 @@
}
}
else {
deletebutton.unbind();
deletebutton.click(function(event) {
event.stopPropagation();
event.preventDefault();
removeConfigureBlocks();
showMediaPlayers();
oldblock.find('input.configurebutton').focus();
});
}
newblock.show();
newblock.removeClass('hidden');
appendChildNodes(document.body, DIV({id: 'overlay'}));
eval(configblock.javascript);
(function($) {
// configblock.javascript might use MochiKit so $ must have its default value
eval(configblock.javascript);
})(getElement);
deletebutton.focus();
// Lock focus to the newly opened dialog
$('#container').attr('aria-hidden', 'true');
if (document.addEventListener) {
newblock.data('focuslocker', function(e) {
if (!newblock[0].contains(e.target) && newblock[0].ownerDocument == e.target.ownerDocument) {
console.log(e.target);
e.stopPropagation();
newblock.find('.deletebutton').focus();
}
});
document.addEventListener('focus', newblock.data('focuslocker'), true);
}
} // end of addConfigureBlock()
function removeConfigureBlocks() {
// FF3 hangs unless you delay removal of the iframe inside the old configure block
setTimeout(function() {
$('div.configure').each( function() {
$(this).remove();
$(this).addClass('hidden');
if (newblock.data('focuslocker')) {
document.removeEventListener(newblock.data('focuslocker'));
newblock.removeData('focuslocker');
}
});
}, 1);
}
......
......@@ -4,7 +4,6 @@
<!--[if (gt IE 9)|!(IE)]><!--><html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if} lang="{$LANGUAGE}"><!--<![endif]-->
{include file="header/head.tpl"}
<body class="no-js">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
{if $ADDITIONALHTMLTOPOFBODY}{$ADDITIONALHTMLTOPOFBODY|safe}{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
......@@ -13,6 +12,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper">
<div id="header"><h1 id="site-logo"><a href="{$WWWROOT}"><img src="{$sitelogo}" alt="{$sitename}"></a></h1>
......
......@@ -4,7 +4,6 @@
<!--[if (gt IE 9)|!(IE)]><!--> <html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if} lang="{$LANGUAGE}"><!--<![endif]-->
{include file="header/head.tpl"}
<body id="micro" class="no-js">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
{if !$PRODUCTIONMODE}<div class="sitemessage center">{str tag=notproductionsite section=error}</div>{/if}
......@@ -12,6 +11,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper"><div id="header">
<h1 class="hidden"><a href="{$WWWROOT}">{$hiddenheading|default:"Mahara"|escape}</a></h1>
......
......@@ -5,7 +5,6 @@
<html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if}>
{include file="header/head.tpl"}
<body id="micro" class="no-js">
<div class="center"><a class="skiplink" href="#viewheader">{str tag=skipmenu}</a></div>
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
{if !$PRODUCTIONMODE}<div class="sitemessage center">{str tag=notproductionsite section=error}</div>{/if}
......@@ -13,6 +12,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#viewheader">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper"><div id="header">
<div class="viewheadertop">
......
......@@ -33,7 +33,6 @@ button {
font-family: Arial, "Nimbus Sans L", Helvetica, sans-serif;
}
#container,
.skiplink,
.sitemessage,
#switchwrap { /* Use a 12px base font size with a 16px line height */
font-size: 0.75em; /* 16px x .75 = 12px */
......
......@@ -4,7 +4,6 @@
<!--[if (gt IE 9)|!(IE)]><!--><html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if} lang="{$LANGUAGE}"><!--<![endif]-->
{include file="header/head.tpl"}
<body class="no-js">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
{if $ADDITIONALHTMLTOPOFBODY}{$ADDITIONALHTMLTOPOFBODY|safe}{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
......@@ -13,6 +12,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper">
<div id="header"><h1 id="site-logo"><a href="{$WWWROOT}"><img src="{$sitelogo}" alt="{$sitename}"></a></h1>
......
......@@ -4,7 +4,6 @@
<!--[if (gt IE 9)|!(IE)]><!--><html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if} lang="{$LANGUAGE}"><!--<![endif]-->
{include file="header/head.tpl"}
<body id="micro" class="no-js">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
{if !$PRODUCTIONMODE}<div class="sitemessage center">{str tag=notproductionsite section=error}</div>{/if}
......@@ -12,6 +11,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#mainmiddle">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper">
<div id="header">
......
......@@ -74,4 +74,13 @@
{if $block.javascript}<script type="text/javascript">{$block.javascript|safe}</script>{/if}
{/if}
</div>
<div id="configureblock" class="blockinstance cb configure hidden" role="dialog">
<div class="blockinstance-controls">
<input type="image" src="{theme_url filename=images/btn_close.png}" class="deletebutton" name="close_configuration" alt="{str tag=Close}">
</div>
<div class="blockinstance-header">
</div>
<div class="blockinstance-content">
</div>
</div>
{if $microheaders}{include file="microfooter.tpl"}{else}{include file="footer.tpl"}{/if}
......@@ -6,8 +6,8 @@
{if $retractable && !$configure}
<img src="{theme_url filename=images/retractable.png}" alt="{str tag='retractable' section='view'}" title="{str tag='retractable' section='view'}" class="retractablebtn">
{/if}
{if $configurable && !$configure} <input type="image" src="{theme_url filename=images/btn_configure.png}" class="configurebutton" name="action_configureblockinstance_id_{$id}" alt="&bull;" title="{$strconfigtitletext}">{/if}
{if $configure}<input type="image" src="{theme_url filename=images/btn_close.png}" class="deletebutton" name="action_removeblockinstance_id_{$id}" alt="X" title="{$strremovetitletext}">{else}<input type="image" src="{theme_url filename=images/btn_deleteremove.png}" class="deletebutton" name="action_removeblockinstance_id_{$id}" alt="X" title="{$strremovetitletext}">{/if}
{if $configurable && !$configure} <input type="image" src="{theme_url filename=images/btn_configure.png}" class="configurebutton" name="action_configureblockinstance_id_{$id}" alt="{str tag=Configure section=view}" title="{$strconfigtitletext}">{/if}
{if $configure}<input type="image" src="{theme_url filename=images/btn_close.png}" class="deletebutton" name="action_removeblockinstance_id_{$id}" alt="{str tag=Close}" title="{$strremovetitletext}">{else}<input type="image" src="{theme_url filename=images/btn_deleteremove.png}" class="deletebutton" name="action_removeblockinstance_id_{$id}" alt="{str tag=delete}" title="{$strremovetitletext}">{/if}
</div>
<div class="blockinstance-header">
<h2 class="title">{if $configure}{$configtitle}: {str tag=Configure section=view}{else}{$title|default:"[$strnotitle]"}{/if}</h2>
......
......@@ -5,7 +5,6 @@
<html{if $LANGDIRECTION == 'rtl'} dir="rtl"{/if}>
{include file="header/head.tpl"}
<body id="micro">
<div class="center"><a class="skiplink" href="#viewheader">{str tag=skipmenu}</a></div>
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}<div class="sitemessages">{/if}
{if $USERMASQUERADING}<div class="sitemessage"><img src="{theme_url filename='images/failure.png'}" alt="">{$masqueradedetails} {$becomeyouagain|safe}</div>{/if}
{if !$PRODUCTIONMODE}<div class="sitemessage center">{str tag=notproductionsite section=error}</div>{/if}
......@@ -13,6 +12,7 @@
{if $SITETOP}<div id="switchwrap">{$SITETOP|safe}</div>{/if}
{if $USERMASQUERADING || !$PRODUCTIONMODE || $SITECLOSED || $SITETOP}</div>{/if}
<div id="container">
<div class="center"><a class="skiplink" href="#viewheader">{str tag=skipmenu}</a></div>
<div id="loading-box"></div>
<div id="top-wrapper">
<div id="header">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment