Skip to content

Commit 9cf82cc

Browse files
authored
Added tab focus to top banner and navigation to About/Support Modal (#1733)
1 parent 78d40ea commit 9cf82cc

4 files changed

Lines changed: 111 additions & 6 deletions

File tree

src/web/html/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
<button type="button" aria-label="Edit Favourites" class="btn btn-warning bmd-btn-icon" id="edit-favourites" data-toggle="tooltip" title="Edit favourites">
146146
<i class="material-icons" aria-hidden="true">star</i>
147147
</button>
148-
<div id="content-wrapper">
148+
<div tabindex="0" id="content-wrapper">
149149
<div id="banner" class="row">
150150
<div class="col" style="text-align: left; padding-left: 10px;">
151151
<a href="#" data-toggle="modal" data-target="#download-modal" data-help-title="Downloading CyberChef" data-help="<p>CyberChef can be downloaded to run locally or hosted within your own network. It has no server-side component so all that is required is that the ZIP file is uncompressed and the files are accessible.</p><p>As a user, it is worth noting that unofficial versions of CyberChef could have been modified to introduce Input and/or Recipe exfiltration. We recommend always using the official, open source, up-to-date version of CyberChef hosted at <a href='https://gchq.github.io/CyberChef'>https://gchq.github.io/CyberChef</a> if accessible.</p><p>The Network tab in your browser's Developer console (F12) can be used to inspect the network requests made by a website. This can confirm that no data is uploaded when a CyberChef recipe is baked.</p>">Download CyberChef <i class="material-icons">file_download</i></a>
@@ -173,7 +173,7 @@
173173
Operations
174174
<span class="op-count"></span>
175175
</div>
176-
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off" tabindex="2" data-help-title="Searching for operations" data-help="<p>Use the search box to find useful operations.</p><p>Both operation names and descriptions are queried using a fuzzy matching algorithm.</p>">
176+
<input id="search" type="search" class="form-control" placeholder="Search..." autocomplete="off" tabindex="0" data-help-title="Searching for operations" data-help="<p>Use the search box to find useful operations.</p><p>Both operation names and descriptions are queried using a fuzzy matching algorithm.</p>">
177177
<ul id="search-results" class="op-list"></ul>
178178
<div id="categories" class="panel-group no-select"></div>
179179
</div>
@@ -584,22 +584,22 @@ <h5 class="modal-title">CyberChef - The Cyber Swiss Army Knife</h5>
584584

585585
<ul class="nav nav-tabs" role="tablist">
586586
<li class="nav-item" role="presentation">
587-
<a class="nav-link active" href="#faqs" aria-controls="profile" role="tab" data-toggle="tab">
587+
<a id="tab-1" class="nav-link active" href="#faqs" aria-controls="profile" role="tab" data-toggle="tab">
588588
FAQs
589589
</a>
590590
</li>
591591
<li class="nav-item" role="presentation">
592-
<a class="nav-link" href="#report-bug" aria-controls="messages" role="tab" data-toggle="tab">
592+
<a id="tab-2" class="nav-link" href="#report-bug" aria-controls="messages" role="tab" data-toggle="tab">
593593
Report a bug
594594
</a>
595595
</li>
596596
<li class="nav-item" role="presentation">
597-
<a class="nav-link" href="#about" aria-controls="messages" role="tab" data-toggle="tab">
597+
<a id="tab-3" class="nav-link" href="#about" aria-controls="messages" role="tab" data-toggle="tab">
598598
About
599599
</a>
600600
</li>
601601
<li class="nav-item" role="presentation">
602-
<a class="nav-link" href="#keybindings" aria-controls="messages" role="tab" data-toggle="tab">
602+
<a id="tab-4" class="nav-link" href="#keybindings" aria-controls="messages" role="tab" data-toggle="tab">
603603
Keybindings
604604
</a>
605605
</li>

src/web/stylesheets/layout/_banner.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,36 @@
2626
color: var(--banner-url-colour);
2727
}
2828

29+
#options:focus {
30+
background-color: #eef3ec;
31+
border: solid black 2px;
32+
border-radius: 4px;
33+
}
34+
35+
#support:focus {
36+
background-color: #eef3ec;
37+
border: solid black 2px;
38+
border-radius: 4px;
39+
}
40+
41+
#notice:focus {
42+
background-color: #eef3ec;
43+
border: solid black 2px;
44+
border-radius: 4px;
45+
}
46+
47+
#banner .col a:focus {
48+
background-color: #eef3ec;
49+
border: solid black 2px;
50+
border-radius: 4px;
51+
}
52+
53+
#notice-wrapper #notice:focus {
54+
background-color: #eef3ec;
55+
border: solid black 2px;
56+
border-radius: 4px;
57+
}
58+
2959
#notice-wrapper {
3060
text-align: center;
3161
overflow: hidden;

src/web/stylesheets/layout/_modals.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@
7878
border-left: 2px solid var(--primary-border-colour);
7979
}
8080

81+
p a:focus {
82+
color: #0a6ebd;
83+
text-decoration: underline;
84+
}
85+
8186
.checkbox label input[type=checkbox]+.checkbox-decorator .check,
8287
.checkbox label input[type=checkbox]+.checkbox-decorator .check::before {
8388
border-color: var(--input-border-colour);

src/web/waiters/ControlsWaiter.mjs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,18 @@ class ControlsWaiter {
399399
*/
400400
supportButtonClick(e) {
401401
e.preventDefault();
402+
const faqs = document.getElementById("faqs");
403+
const faqsAElement = faqs.getElementsByTagName("a");
404+
for (let i = 0; i < faqsAElement.length; i++) {
405+
faqsAElement[i].setAttribute("tabindex", "0");
406+
faqsAElement[i].addEventListener("keydown", this.navigateFAQList, false);
407+
}
408+
409+
const tabs = document.querySelectorAll('[role="tab"]');
410+
411+
for (let i = 0; i < tabs.length; i++) {
412+
tabs[i].addEventListener("keydown", this.changeTabs, false);
413+
}
402414

403415
const reportBugInfo = document.getElementById("report-bug-info");
404416
const saveLink = this.generateStateUrl(true, true, null, null, "https://gchq.github.io/CyberChef/");
@@ -415,6 +427,64 @@ ${navigator.userAgent}
415427
}
416428

417429

430+
/**
431+
* @param {Event} ev
432+
*/
433+
changeTabs(ev) {
434+
const tab = ev.target;
435+
ev.preventDefault();
436+
ev.stopPropagation();
437+
438+
if (ev.key === "ArrowRight") {
439+
const nextTab = tab.parentElement;
440+
if (nextTab.nextElementSibling === null) {
441+
tab.parentElement.parentElement.firstElementChild.firstElementChild.focus();
442+
} else {
443+
nextTab.nextElementSibling.firstElementChild.focus();
444+
}
445+
446+
} else if (ev.key === "ArrowLeft") {
447+
const prevTab = tab.parentElement;
448+
449+
if (prevTab.previousElementSibling === null) {
450+
tab.parentElement.parentElement.lastElementChild.firstElementChild.focus();
451+
} else {
452+
prevTab.previousElementSibling.firstElementChild.focus();
453+
}
454+
} else if (ev.key === "Tab" && !ev.shiftKey && ev.target === document.getElementById("tab-1")) {
455+
document.getElementById("faqs").querySelector("[class='btn btn-primary']").focus();
456+
} else if (ev.key === "Tab" && !ev.shiftKey && ev.target === document.getElementById("tab-2")) {
457+
document.getElementById("report-bug").querySelector("[class='btn btn-primary']").focus();
458+
} else if (ev.key === "Tab" && !ev.shiftKey && ev.target === document.getElementById("tab-3")) {
459+
document.getElementById("about").querySelector("[href]").focus();
460+
} else if (ev.key === "Tab" && !ev.shiftKey && ev.target === document.getElementById("tab-4")) {
461+
const button = document.getElementById("support-modal").getElementsByClassName("modal-footer");
462+
const close = button[0].firstElementChild;
463+
close.focus();
464+
} else if (ev.key === "Enter" || ev.key === "Space" || ev.key === " ") {
465+
tab.click();
466+
}
467+
}
468+
469+
/**
470+
* @param {Event} ev
471+
*/
472+
navigateFAQList(ev) {
473+
474+
const el = ev.target.nextElementSibling;
475+
if (ev.key === "Enter" || ev.key === "Space" || ev.key === " ") {
476+
ev.preventDefault();
477+
const question = el.classList;
478+
if (question !== undefined && question.value) {
479+
if (!question.value.includes("show")) {
480+
question.add("show");
481+
} else if (question.contains("show")) {
482+
question.remove("show");
483+
}
484+
}
485+
}
486+
}
487+
418488
/**
419489
* Shows the stale indicator to show that the input or recipe has changed
420490
* since the last bake.

0 commit comments

Comments
 (0)