@@ -919,9 +919,9 @@ function web_editor(config) {
919
919
}
920
920
921
921
// Trap focus in modal and pass focus to first actionable element
922
- function focusModal ( ) {
922
+ function focusModal ( modalId ) {
923
923
document . querySelector ( 'body > :not(.vex)' ) . setAttribute ( 'aria-hidden' , true ) ;
924
- var dialog = document . querySelector ( '.modal-div' ) ;
924
+ var dialog = document . querySelector ( modalId ) ;
925
925
var focusableEls = dialog . querySelectorAll ( 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])' ) ;
926
926
$ ( focusableEls ) . each ( function ( ) {
927
927
$ ( this ) . attr ( 'tabindex' , '0' ) ;
@@ -930,10 +930,15 @@ function web_editor(config) {
930
930
dialog . onkeydown = function ( event ) {
931
931
if ( event . which == 9 ) {
932
932
// if tab key is pressed
933
- var focusedEl = document . activeElement ;
934
933
var numberOfFocusableEls = focusableEls . length ;
935
- var focusedElIndex = Array . prototype . indexOf . call ( focusableEls , focusedEl ) ;
934
+ if ( ! numberOfFocusableEls ) {
935
+ dialog . focus ( ) ;
936
+ event . preventDefault ( ) ;
937
+ return ;
938
+ }
936
939
940
+ var focusedEl = document . activeElement ;
941
+ var focusedElIndex = Array . prototype . indexOf . call ( focusableEls , focusedEl ) ;
937
942
if ( event . which == 16 ) {
938
943
// if focused on first item and user shift-tabs back, go to the last focusable item
939
944
if ( focusedElIndex == 0 ) {
@@ -987,7 +992,7 @@ function web_editor(config) {
987
992
vex . open ( {
988
993
content : Mustache . render ( template , loadStrings ) ,
989
994
afterOpen : function ( vexContent ) {
990
- focusModal ( ) ;
995
+ focusModal ( "#files-modal" ) ;
991
996
$ ( "#show-files" ) . attr ( "title" , loadStrings [ "show-files" ] + " (" + micropythonFs . ls ( ) . length + ")" ) ;
992
997
document . getElementById ( "show-files" ) . innerHTML = loadStrings [ "show-files" ] + " (" + micropythonFs . ls ( ) . length + ") <i class='fa fa-caret-down'>" ;
993
998
$ ( '#save-hex' ) . click ( function ( ) {
@@ -1173,7 +1178,7 @@ function web_editor(config) {
1173
1178
vex . open ( {
1174
1179
content : Mustache . render ( template , context ) ,
1175
1180
afterOpen : function ( vexContent ) {
1176
- focusModal ( ) ;
1181
+ focusModal ( "#snippet-modal" ) ;
1177
1182
$ ( vexContent ) . find ( '.snippet-selection' ) . click ( function ( e ) {
1178
1183
var snippet_name = $ ( this ) . find ( '.snippet-name' ) . text ( ) ;
1179
1184
EDITOR . triggerSnippet ( snippet_name ) ;
@@ -1236,15 +1241,16 @@ function web_editor(config) {
1236
1241
loadPy ( file . name , e . target . result ) ;
1237
1242
} ;
1238
1243
reader . readAsText ( file ) ;
1244
+ $ ( '#editor' ) . focus ( ) ;
1239
1245
} else if ( ext == 'hex' ) {
1240
1246
reader . onload = function ( e ) {
1241
1247
loadHex ( file . name , e . target . result ) ;
1242
1248
} ;
1243
1249
reader . readAsText ( file ) ;
1244
- } else {
1250
+ $ ( '#editor' ) . focus ( ) ;
1251
+ } else {
1245
1252
invalidFileWarning ( ext ) ;
1246
1253
}
1247
- $ ( '#editor' ) . focus ( ) ;
1248
1254
}
1249
1255
1250
1256
function showDisconnectError ( event ) {
@@ -1329,7 +1335,7 @@ function web_editor(config) {
1329
1335
$ ( "#flashing-info" ) . addClass ( 'hidden' ) ;
1330
1336
1331
1337
// Log error to console for feedback
1332
- console . log ( "An error occured whilst attempting to use WebUSB." ) ;
1338
+ console . log ( "An error occurred whilst attempting to use WebUSB." ) ;
1333
1339
console . log ( "Details of the error can be found below, and may be useful when trying to replicate and debug the error." ) ;
1334
1340
console . log ( err ) ;
1335
1341
console . trace ( ) ;
@@ -1347,7 +1353,7 @@ function web_editor(config) {
1347
1353
1348
1354
// Disconnect from the microbit
1349
1355
doDisconnect ( ) ;
1350
-
1356
+
1351
1357
var errorType ;
1352
1358
var errorTitle ;
1353
1359
var errorDescription ;
@@ -1450,6 +1456,15 @@ function web_editor(config) {
1450
1456
// Attach download handler
1451
1457
$ ( "#flashing-overlay-download" ) . click ( doDownload ) ;
1452
1458
1459
+ // Make the modal accessible now that all the content is present
1460
+ focusModal ( "#flashing-overlay" ) ;
1461
+ // If escape key is pressed close modal
1462
+ $ ( '#flashing-overlay' ) . keydown ( function ( e ) {
1463
+ if ( e . which == 27 ) {
1464
+ flashErrorClose ( ) ;
1465
+ }
1466
+ } ) ;
1467
+
1453
1468
// Send event
1454
1469
var errorMessage = ( err . message ? ( err . message . replace ( / \W + / g, '-' ) . replace ( / \W $ / , '' ) . toLowerCase ( ) ) : "" ) ;
1455
1470
// Append error message, replace all special chars with '-', if last char is '-' remove it
@@ -1614,11 +1629,9 @@ function web_editor(config) {
1614
1629
document . dispatchEvent ( new CustomEvent ( 'webusb' , { detail : details } ) ) ;
1615
1630
1616
1631
console . log ( "Flash complete" ) ;
1617
-
1632
+
1618
1633
// Close overview
1619
- setTimeout ( function ( ) {
1620
- $ ( "#flashing-overlay-container" ) . hide ( ) ;
1621
- } , 500 ) ;
1634
+ setTimeout ( flashErrorClose , 500 ) ;
1622
1635
} )
1623
1636
. catch ( webusbErrorHandler )
1624
1637
. finally ( function ( ) {
@@ -1720,16 +1733,32 @@ function web_editor(config) {
1720
1733
$ ( "#modal-msg-title" ) . text ( title ) ;
1721
1734
$ ( "#modal-msg-content" ) . html ( content ) ;
1722
1735
var modalLinks = [ ] ;
1736
+ var addCloseClickListener = false ;
1723
1737
if ( links ) {
1724
1738
Object . keys ( links ) . forEach ( function ( key ) {
1725
1739
if ( links [ key ] === "close" ) {
1726
- modalLinks . push ( '<a href="#" onclick = "$(\'' + overlayContainer + '\').hide()">Close</a>' ) ;
1740
+ modalLinks . push ( '<a href="#" id="modal-msg-close-link">' + key + '</a>' ) ;
1741
+ addCloseClickListener = true ;
1727
1742
} else {
1728
1743
modalLinks . push ( '<a href="' + links [ key ] + '" target="_blank">' + key + '</a>' ) ;
1729
1744
}
1730
1745
} ) ;
1731
1746
}
1732
1747
$ ( "#modal-msg-links" ) . html ( ( modalLinks ) . join ( ' | ' ) ) ;
1748
+ focusModal ( "#modal-msg-overlay" ) ;
1749
+ var modalMsgClose = function ( ) {
1750
+ $ ( overlayContainer ) . hide ( )
1751
+ $ ( overlayContainer ) . off ( "keydown" ) ;
1752
+ } ;
1753
+ $ ( "#modal-msg-close-cross" ) . click ( modalMsgClose ) ;
1754
+ if ( addCloseClickListener ) {
1755
+ $ ( "#modal-msg-close-link" ) . click ( modalMsgClose ) ;
1756
+ }
1757
+ $ ( overlayContainer ) . keydown ( function ( e ) {
1758
+ if ( e . which == 27 ) {
1759
+ modalMsgClose ( ) ;
1760
+ }
1761
+ } ) ;
1733
1762
}
1734
1763
1735
1764
function formatMenuContainer ( parentButtonId , containerId ) {
@@ -1941,4 +1970,5 @@ function web_editor(config) {
1941
1970
function flashErrorClose ( ) {
1942
1971
$ ( '#flashing-overlay-error' ) . html ( "" ) ;
1943
1972
$ ( '#flashing-overlay-container' ) . hide ( ) ;
1973
+ $ ( '#flashing-overlay' ) . off ( "keydown" ) ;
1944
1974
}
0 commit comments