MDL-79061 course: Create a sr-only mutations logger
* Create SRLogger that extends from the default Logger class. This logger outputs the feedback to a sr-only ARIA live region to allow screen readers to announce the feedback from mutations. * Update the course editor to use the SRLogger.
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -15,6 +15,14 @@
|
||||
|
||||
import ajax from 'core/ajax';
|
||||
import {getString} from "core/str";
|
||||
import SRLogger from "core/local/reactive/srlogger";
|
||||
|
||||
/**
|
||||
* Flag to determine whether the screen reader-only logger has already been set, so we only need to set it once.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
let isLoggerSet = false;
|
||||
|
||||
/**
|
||||
* Default mutation manager
|
||||
@@ -128,6 +136,11 @@ export default class {
|
||||
* @return {Object} the log entry
|
||||
*/
|
||||
async _getLoggerEntry(stateManager, action, itemIds, data = {}) {
|
||||
if (!isLoggerSet) {
|
||||
// In case the logger has not been set from init(), ensure we set the logger.
|
||||
stateManager.setLogger(new SRLogger());
|
||||
isLoggerSet = true;
|
||||
}
|
||||
const feedbackParams = {
|
||||
action,
|
||||
itemType: data.itemType ?? action.split('_')[0],
|
||||
@@ -167,10 +180,13 @@ export default class {
|
||||
* @param {StateManager} stateManager the state manager
|
||||
*/
|
||||
init(stateManager) {
|
||||
// Add a method to prepare the fields when some update is comming from the server.
|
||||
// Add a method to prepare the fields when some update is coming from the server.
|
||||
stateManager.addUpdateTypes({
|
||||
prepareFields: this._prepareFields,
|
||||
});
|
||||
// Use the screen reader-only logger (SRLogger) to handle the feedback messages from the mutations.
|
||||
stateManager.setLogger(new SRLogger());
|
||||
isLoggerSet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
define("core/local/reactive/srlogger",["exports","core/local/reactive/logger"],(function(_exports,_logger){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_logger=(obj=_logger)&&obj.__esModule?obj:{default:obj};class SRLogger extends _logger.default{add(entry){if(entry.feedbackMessage){let loggerFeedback=document.getElementById(SRLogger.liveRegionId);loggerFeedback||(loggerFeedback=document.createElement("div"),loggerFeedback.id=SRLogger.liveRegionId,loggerFeedback.classList.add("sr-only"),loggerFeedback.setAttribute("aria-live","polite"),document.body.append(loggerFeedback)),loggerFeedback.innerHTML=entry.feedbackMessage,setTimeout((()=>{loggerFeedback.innerHTML=""}),4e3)}}}return _exports.default=SRLogger,function(obj,key,value){key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}(SRLogger,"liveRegionId","sr-logger-feedback-container"),_exports.default}));
|
||||
|
||||
//# sourceMappingURL=srlogger.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"srlogger.min.js","sources":["../../../src/local/reactive/srlogger.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Screen reader-only (sr-only) reactive mutations logger class.\n *\n * This logger can be used by the StateManager to log mutation feedbacks and actions.\n * The feedback messages logged by this logger will be rendered in a sr-only, ARIA live region.\n *\n * @module core/local/reactive/srlogger\n * @class SRLogger\n * @copyright 2023 Jun Pataleta <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Logger from 'core/local/reactive/logger';\n\n/**\n * Logger entry structure.\n *\n * @typedef {object} LoggerEntry\n * @property {string} feedbackMessage Feedback message.\n */\n\n/**\n * Screen reader-only (sr-only) reactive mutations logger class.\n *\n * @class SRLogger\n */\nexport default class SRLogger extends Logger {\n /**\n * The element ID of the ARIA live region where the logger feedback will be rendered.\n *\n * @type {string}\n */\n static liveRegionId = 'sr-logger-feedback-container';\n\n /**\n * Add a log entry.\n * @param {LoggerEntry} entry Log entry.\n */\n add(entry) {\n if (entry.feedbackMessage) {\n // Fetch or create an ARIA live region that will serve as the container for the logger feedback.\n let loggerFeedback = document.getElementById(SRLogger.liveRegionId);\n if (!loggerFeedback) {\n loggerFeedback = document.createElement('div');\n loggerFeedback.id = SRLogger.liveRegionId;\n loggerFeedback.classList.add('sr-only');\n loggerFeedback.setAttribute('aria-live', 'polite');\n document.body.append(loggerFeedback);\n }\n // Set the ARIA live region's contents with the feedback.\n loggerFeedback.innerHTML = entry.feedbackMessage;\n\n // Clear the feedback message after 4 seconds to avoid the contents from being read out in case the user navigates\n // to this region. This is similar to the default timeout of toast messages before disappearing from view.\n setTimeout(() => {\n loggerFeedback.innerHTML = '';\n }, 4000);\n }\n }\n}\n"],"names":["SRLogger","Logger","add","entry","feedbackMessage","loggerFeedback","document","getElementById","liveRegionId","createElement","id","classList","setAttribute","body","append","innerHTML","setTimeout"],"mappings":"iQAyCqBA,iBAAiBC,gBAYlCC,IAAIC,UACIA,MAAMC,gBAAiB,KAEnBC,eAAiBC,SAASC,eAAeP,SAASQ,cACjDH,iBACDA,eAAiBC,SAASG,cAAc,OACxCJ,eAAeK,GAAKV,SAASQ,aAC7BH,eAAeM,UAAUT,IAAI,WAC7BG,eAAeO,aAAa,YAAa,UACzCN,SAASO,KAAKC,OAAOT,iBAGzBA,eAAeU,UAAYZ,MAAMC,gBAIjCY,YAAW,KACPX,eAAeU,UAAY,KAC5B,kLA9BMf,wBAMK"}
|
||||
@@ -0,0 +1,75 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Screen reader-only (sr-only) reactive mutations logger class.
|
||||
*
|
||||
* This logger can be used by the StateManager to log mutation feedbacks and actions.
|
||||
* The feedback messages logged by this logger will be rendered in a sr-only, ARIA live region.
|
||||
*
|
||||
* @module core/local/reactive/srlogger
|
||||
* @class SRLogger
|
||||
* @copyright 2023 Jun Pataleta <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import Logger from 'core/local/reactive/logger';
|
||||
|
||||
/**
|
||||
* Logger entry structure.
|
||||
*
|
||||
* @typedef {object} LoggerEntry
|
||||
* @property {string} feedbackMessage Feedback message.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Screen reader-only (sr-only) reactive mutations logger class.
|
||||
*
|
||||
* @class SRLogger
|
||||
*/
|
||||
export default class SRLogger extends Logger {
|
||||
/**
|
||||
* The element ID of the ARIA live region where the logger feedback will be rendered.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
static liveRegionId = 'sr-logger-feedback-container';
|
||||
|
||||
/**
|
||||
* Add a log entry.
|
||||
* @param {LoggerEntry} entry Log entry.
|
||||
*/
|
||||
add(entry) {
|
||||
if (entry.feedbackMessage) {
|
||||
// Fetch or create an ARIA live region that will serve as the container for the logger feedback.
|
||||
let loggerFeedback = document.getElementById(SRLogger.liveRegionId);
|
||||
if (!loggerFeedback) {
|
||||
loggerFeedback = document.createElement('div');
|
||||
loggerFeedback.id = SRLogger.liveRegionId;
|
||||
loggerFeedback.classList.add('sr-only');
|
||||
loggerFeedback.setAttribute('aria-live', 'polite');
|
||||
document.body.append(loggerFeedback);
|
||||
}
|
||||
// Set the ARIA live region's contents with the feedback.
|
||||
loggerFeedback.innerHTML = entry.feedbackMessage;
|
||||
|
||||
// Clear the feedback message after 4 seconds to avoid the contents from being read out in case the user navigates
|
||||
// to this region. This is similar to the default timeout of toast messages before disappearing from view.
|
||||
setTimeout(() => {
|
||||
loggerFeedback.innerHTML = '';
|
||||
}, 4000);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user