[LON-CAPA-cvs] cvs: loncom /interface loncommon.pm
raeburn
raeburn at source.lon-capa.org
Sun Jun 28 08:07:51 EDT 2026
raeburn Sun Jun 28 12:07:51 2026 EDT
Modified files:
/loncom/interface loncommon.pm
Log:
- WCAG 2 compliance: keyboard-only access to modal windows.
Focus is trapped within open modal window; use Esc key to exit.
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1531 loncom/interface/loncommon.pm:1.1532
--- loncom/interface/loncommon.pm:1.1531 Sun Jun 21 19:46:38 2026
+++ loncom/interface/loncommon.pm Sun Jun 28 12:07:51 2026
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1531 2026/06/21 19:46:38 raeburn Exp $
+# $Id: loncommon.pm,v 1.1532 2026/06/28 12:07:51 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -10959,6 +10959,21 @@
<script type="text/javascript">
// <![CDATA[
// <!-- BEGIN LON-CAPA Internal
+
+function isSafari() {
+ var ua = navigator.userAgent.toLowerCase();
+ return ((ua.indexOf('safari') != -1) && (ua.indexOf('chrome') === -1));
+}
+
+function setIframeFocus(iframe) {
+ iframe.focus();
+ if(isSafari()) {
+ window.setTimeout(function() {
+ iframe.contentWindow.focus();
+ }, 100)
+ }
+}
+
var modalWindow = {
parent:"body",
windowId:null,
@@ -10993,6 +11008,54 @@
modalWindow.height = height;
modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='"+transparency+"' src='" + source + "' style='"+style+"'></iframe>";
modalWindow.open();
+ const iframe = document.querySelector('#myModal iframe');
+ if (iframe) {
+ iframe.addEventListener('load', () => {
+ const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
+ const myFocusTrapper = (e) => {
+ if (e.key === 'Escape') {
+ modalWindow.close();
+ return;
+ }
+ if (e.key === 'Tab') {
+ const focusableSelector = [
+ 'iframe',
+ '[href]:not([href="#"])',
+ 'input:not([disabled])',
+ 'select:not([disabled])',
+ 'textarea:not([disabled])',
+ 'button:not([disabled])',
+ 'object',
+ 'embed',
+ '[contenteditable]',
+ '[tabindex]:not([tabindex="-1"])'
+ ].join(',');
+ const rawElements = iframeDoc.querySelectorAll(focusableSelector);
+ const iframeElements = Array.from(rawElements).filter(el => {
+ const style = iframe.contentWindow.getComputedStyle(el);
+ return style.display !== 'none' && style.visibility !== 'hidden';
+ });
+ if (iframeElements.length > 0) {
+ const lastidx = iframeElements.length - 1;
+ if (e.shiftKey) {
+ if (iframe.contentWindow.document.activeElement === iframeElements[0]) {
+ iframeElements[lastidx].focus();
+ e.preventDefault();
+ }
+ } else {
+ if (iframe.contentWindow.document.activeElement === iframeElements[lastidx]) {
+ iframeElements[0].focus();
+ e.preventDefault();
+ }
+ }
+ }
+ }
+ };
+ iframeDoc.body.addEventListener('keydown', myFocusTrapper);
+ setIframeFocus(iframe);
+ });
+ }
+
};
// END LON-CAPA Internal -->
// ]]>
More information about the LON-CAPA-cvs
mailing list