Hello Telerik Team,
Our customers identified a few accessibility concerns related to the RadEditor Image Manager and Document Manager popup windows:
- Keyboard Focus on Popup Activation
When a user tabs to the Image Manager plugin and presses Enter, the popup window opens. However, keyboard focus does not automatically move into the popup. Instead, the user must press the Tab key again to shift focus manually.
➤ To meet accessibility standards, focus should move directly into the modal or popup when it appears. This ensures that keyboard and screen reader users can interact with the dialog immediately without navigating through background content. - Missing Dialog Roles and Labels
The dialog containers ( see below ) currently lack appropriate accessibility roles.
➤ Each dialog container should includerole="dialog".
➤ If the dialog has a visible title, it should also includearia-labelledbyreferencing the ID of that title element. This allows assistive technologies to announce the dialog context clearly.
Is there any way to fix these two issues?
Thanks,
Lan
4 Answers, 1 is accepted
Hi Lan,
Thank you for outlining the accessibility concerns with the RadEditor Image Manager and Document Manager popup windows. Here's how you can address both issues:
1. Keyboard Focus on Popup Activation
To ensure that keyboard focus moves directly into the popup when it opens, you can use the RadEditor's client-side OnClientCommandExecuted event. This allows you to set focus to the first interactive element (the toolbar of RadFileExplorer) within the dialog:
<telerik:RadEditor runat="server" ID="RadEditor2" Height="600px" EnableAriaSupport="true" OnClientCommandExecuted="OnClientCommandExecuted">
<Content></Content>
<Modules>
<telerik:EditorModule Name="RadEditorStatistics" Visible="true" />
<telerik:EditorModule Name="RadEditorDomInspector" Visible="true" />
<telerik:EditorModule Name="RadEditorNodeInspector" Visible="false" />
<telerik:EditorModule Name="RadEditorHtmlInspector" Visible="true" />
</Modules>
<ImageManager ViewPaths="~/Images" />
<DocumentManager ViewPaths="~/Images" />
</telerik:RadEditor>
<script type="text/javascript">
function OnClientCommandExecuted(sender, args) {
var dialogWindow,
isIframe,
commandName = args.get_commandName();
switch (commandName) {
case "ImageManager":
case "DocumentManager":
default:
}
dialogWindow = sender.get_dialogOpener()._dialogContainers[commandName];
if (dialogWindow) {
isIframe = dialogWindow.get_contentFrame();
if (isIframe) {
dialogWindow.add_pageLoad(function (e) {
var contentDocument = e.get_contentFrame().contentDocument;
var toolbar = contentDocument.getElementById('RadFileExplorer1_toolbar');
setTimeout(function () {
toolbar.focus();
}, 0);
});
}
}
}
</script>This approach ensures that users relying on the keyboard are placed directly inside the dialog when it appears.
2. Adding Dialog Roles and Labels
You need to set the EnableAriaSupport="true" property in the RadEditor declaration and the RadWindow-based dialog will be rendered with a role="dialog" and aria-labelledby attributes:
Regards,
Rumen
Progress Telerik
Start the 2025 Survey
Hello Rumen,
Thank you for your feedback.
The current solution addresses the following two issues:
- Ensuring keyboard focus upon popup activation
- Adding appropriate dialog roles and labels for accessibility
We’d also like to explore whether the following enhancements can be implemented for the image/file manager popups:
- Allow closing the modal via the ESC key
- Restore focus to the triggering element once the modal is closed
Would these be feasible to support in the current framework?
Thank you again for your help!
Lan
You are welcome, Lan.
You can achieve both new requirements (Esc to close the dialog and restore the selection) using the code below:
<telerik:RadEditor runat="server" ID="RadEditor2" Height="600px" EnableAriaSupport="true" OnClientCommandExecuted="OnClientCommandExecuted">
<Content>line1 <br> line 2</Content>
<Modules>
<telerik:EditorModule Name="RadEditorStatistics" Visible="true" />
<telerik:EditorModule Name="RadEditorDomInspector" Visible="true" />
<telerik:EditorModule Name="RadEditorNodeInspector" Visible="false" />
<telerik:EditorModule Name="RadEditorHtmlInspector" Visible="true" />
</Modules>
<ImageManager ViewPaths="~/Images" />
<DocumentManager ViewPaths="~/Images" />
</telerik:RadEditor>
<script type="text/javascript">
var lastFocusedElement, range = null;
function OnClientCommandExecuted(sender, args) {
var dialogWindow,
isIframe,
commandName = args.get_commandName();
var editor = sender;
// Store the currently focused element before opening dialog
lastFocusedElement = sender.get_document().activeElement; // or
range = sender.getSelection().getRange(true);
switch (commandName) {
case "ImageManager":
case "DocumentManager":
default:
}
dialogWindow = sender.get_dialogOpener()._dialogContainers[commandName];
if (dialogWindow) {
isIframe = dialogWindow.get_contentFrame();
if (isIframe) {
dialogWindow.add_pageLoad(function (e) {
var contentDocument = e.get_contentFrame().contentDocument;
var toolbar = contentDocument.getElementById('RadFileExplorer1_toolbar');
setTimeout(function () {
toolbar.focus();
}, 0);
// Add ESC key handler to close the dialog
attachEscKeyHandler(contentDocument, dialogWindow);
});
}
// Also attach ESC handler to the dialog window itself
attachEscKeyHandler(document, dialogWindow);
// Attach close event handler to restore focus
dialogWindow.add_close(function (sender, args) {
restoreFocus(editor);
});
}
}
function restoreFocus(editor) {
// Restore focus to the element that triggered the dialog
if (range) {
setTimeout(function () {
try {
// lastFocusedElement.focus();
editor.getSelection().selectRange(range)
} catch (e) {
// Element might not be focusable anymore
console.log('Could not restore focus:', e);
}
}, 100);
}
}
function attachEscKeyHandler(doc, radWindow) {
if (!doc || !radWindow) return;
// Remove any existing handler to avoid duplicates
if (doc._escKeyHandler) {
doc.removeEventListener('keydown', doc._escKeyHandler);
}
// Create and attach new handler
doc._escKeyHandler = function (e) {
if (e.keyCode === 27 || e.key === 'Escape') {
// Use RadWindow's client-side close() method
if (radWindow && radWindow.close) {
radWindow.close();
}
}
};
doc.addEventListener('keydown', doc._escKeyHandler);
}
</script>
Regards,
Rumen
Progress Telerik
Start the 2025 Survey
Hello Rumen,
Thanks so much for the quick reply! The ESC key behavior works great, but I’m still having trouble restoring focus to the previous clicked element. I tried run below scripts on both OnClientCommandExecuting and OnClientCommandExecuted, but they only return the focused element inside the content area. So when the popup closes, focus jumps back to the editor. Any ideas on how to fix this?
Thanks a lot!
Lan
lastFocusedElement = sender.get_document().activeElement; // or range = sender.getSelection().getRange(true);Hi Lan,
To restore focus to the exact element that triggered the dialog (such as a toolbar button or an external control), you should capture the focused element from the entire page, not just from the editor's content area. The approach using sender.get_document().activeElement only tracks elements inside the editor's editable iframe-based content area, which is why focus returns to the editor itself.
Here’s how you can address this:
Capture the focused element before opening the dialog:
Usedocument.activeElementinside theOnClientCommandExecutingevent. This will store a reference to the actual page element that was focused, including toolbar buttons or external controls.Restore focus after the dialog closes:
Use the.focus()method on the stored element inside your dialog's close handler.
Example:
var lastFocusedElement = null;
function OnClientCommandExecuting(sender, args) {
// Capture the focused element on the page (works for toolbar buttons, etc.)
lastFocusedElement = document.activeElement;
}
function restoreFocus() {
// Restore focus to the previously focused element
if (lastFocusedElement && typeof lastFocusedElement.focus === "function") {
setTimeout(function () {
lastFocusedElement.focus();
}, 100);
}
}
// Attach restoreFocus to your dialog's close event
Attach the event to RadEditor:
<telerik:RadEditor runat="server" ID="RadEditor1"
OnClientCommandExecuting="OnClientCommandExecuting"
...>
...
</telerik:RadEditor>Make sure your triggering elements (toolbar buttons, etc.) are focusable (<button>, <a>, or have tabindex="0").
Regards,
Rumen
Progress Telerik
Start the 2025 Survey
