Thanks for your attention, I appreciate any feedback.
My current script half works (click "i" in bottom right corner".
It will focus first link AFTER pressing TAB (or keyCode 9) to focus links inside <div id="Foo2">
. But I have to hit TAB first.
<script type="text/javascript">
$(document).keydown(
function(e)
{
if (e.keyCode == 38) {
e.preventDefault(); // this makes it so arrow up doesn't scroll
$("link:focus").prev().focus();
}
if (e.keyCode == 40) {
e.preventDefault();
$("link:focus").next().focus();
}
}
);
</script>
standard bootstrap 3 collapse with input search and hidden well:
<a class="demo" data-toggle="collapse" href="#Foo"><i class="fa fa-info"></i></a>
<div class="collapse" id="Foo">
<form action="" method="post" role="form">
<input autocomplete="off" autofocus="" class="form-control" id="inputSearch" name="search" placeholder="" type="text">
</form>
<!-- this auto populates on search input with database stuff -->
<div class="hidden" id="Foo2"></div>
</div>
here is hidden well / autopopulate stuff after user search query:
<div id="Foo2" class="">
<div tabindex="-1">
<a class="link" href="#">database result #1</a>
<a class="link" href="#">database result #2</a>
<a class="link" href="#">database result #3</a>
<a class="link" href="#">database result #4</a>
</div>
</div>
To detect the arrow key when it is pressed, use onkeydown in JavaScript. The button has key code. As you know the left arrow key has the code 37. The up arrow key has the code 38 and right has the 39 and down has 40.
By adding key handling, a tab index, a role and an aria-label, this div essentially becomes an accessible button and then we can add whatever content we want within the button. This solution works great for simple components that actually look and function like a button.
JavaScript tab key code is 9. Use the keydown event to get the tab key code or char code in JavaScript.
As this is marked accessibility
there are a lot of things to consider that will not only make your life easier but make things more accessible.
This answer got quite long so section 4 covers most of your points, everything else are improvements you can make for accessibility.
As your "i" button does not work without JavaScript you should use a <button>
instead of an anchor (<a>
).
Also you need some 'visually-hidden' text within the <button>
as screen readers will not have any information to present to users (icons are not accessible).
Finally using font-awesome is a bad idea both from performance and from an accessibility perspective. Some users (i.e. those with dyslexia) may use a custom style sheet to swap out the fonts on your site. Some of these style sheets swap all of the fonts out, this includes your icon fonts (so your pretty icons then become the dreaded 'rectangle' for missing fonts).
Improve your site load times with only 500 BYTES per inline SVG vs 185 KILOBYTES for the two font awesome fonts and reduce your request count by 2.
.visually-hidden {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
white-space: nowrap; /* added line */
}
svg{
width: 40px;
height: 40px;
padding: 4px;
}
<!-- Button not an anchor -->
<button class="demo" data-toggle="collapse">
<!--I added an inline SVG instead here-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path style="fill:#030104;" d="M10,16c1.105,0,2,0.895,2,2v8c0,1.105-0.895,2-2,2H8v4h16v-4h-1.992c-1.102,0-2-0.895-2-2L20,12H8 v4H10z"/>
<circle style="fill:#030104;" cx="16" cy="4" r="4"/>
</svg>
<!--This 'Visually Hidden' text is accessible to screen readers but isn't visible, see the CSS for a reusable Class you can use to hide things visually but still have them accessible-->
<span class="visually-hidden">Information / Relevant Text Explaining The Button</span>
</button>
At the moment when a screen reader user lands on your search <input>
they will not know what the field is called.
Use a visually hidden <label>
that is associated with the <input>
using for=""
as the easiest way to fix this. The for=""
should point to the ID of the relevant input.
<label for="inputSearch" class="visually-hidden">Search Criteria</label>
<input autocomplete="off" autofocus="" class="form-control" id="inputSearch" name="search" placeholder="" type="text">`
Your results should be returned within an unordered list <ul>
.
For screen reader users this then let's them know how many results have been returned (as a screen reader will say 'list, 4 items, first item selected' or something similar.)
So wrap your search results in an <ul>
and <li>
. As an added bonus you can then use the <ul>
as the container to remove unnecessary nodes.
<ul id="Foo2" class="" tabindex="-1">
<li><a class="link" href="#">database result #1</a></li>
<li><a class="link" href="#">database result #2</a></li>
<li><a class="link" href="#">database result #3</a></li>
<li><a class="link" href="#">database result #4</a></li>
</ul>
Although not shown in your code on the link to your website the links in your collapsable section are #646970
for the font and #DEDEDE
for the background.
As the font is only 17px this means that you do not pass WCAG AA for colour contrast here.
Either change the font size to at least 18.66px
(19px) or make the background grey lighter (#E8E8E8
would work as a minimum - although i would probably go for #3D3F43
foreground and #D4D4D4
background to get a WCAG AAA rating for contrast of over 7:1).
WAI-ARIA is used to tell screen readers additional information that isn't available using just <html>
elements.
Your 'i' button is a toggle for collapsible information so you need to add aria-expanded="false"
to the button initially and then change this to aria-expanded="true"
when you open the collapsed section.
You can do this within your <button>
click to open and or close the hidden section (toggling the state).
Doing this informs the screen reader that clicking this <button>
will open up some information and will also let them know the state (is it opened aria-expanded="true"
or is it closed aria-expanded="false"
).
aria
This answer is getting quite long and scary so instead I will provide a link that demonstrates an accessible autocomplete that you can explore.
To focus the first link you just need to fix your selector (you didn't show this in your example).
$("#Foo a:first").focus();
is all you need here.
You should treat the section that appears as a modal
and trap the focus inside (so constant tabbing will loop within all the available controls).
With regards to tabbing and alt tabbing please see this answer I gave - This helper lets you find all the focusable items within a container and then ensure that focus stays within that container. It isn't perfect (as it only intercepts Tab and Alt + Tab and screen reader users may use other keys but it is a great start.)
Finally to close the item the Escape Key is accessible with e.keyCode == 27
, I am sure you can work that one out yourself, don't forget to toggle to aria-expanded="false"
after pressing it (also focus the 'i' button when you press Escape as it is expected behaviour to be returned back to where you were on Escape to Close.)!
I am sure I have missed some accessibility issues but that should give you a real good start (and implementing the items listed will give you a good understanding of the basics of accessibility for future development!)
Any questions just ask.
Let's go by parts:
How make script autofocus 1st link WITHOUT having to press TAB?
You can use Bootstrap's collapse event shown.bs.collapse:
$('#Foo').on('shown.bs.collapse', function () {
$('#Foo2').children().children('a:first').focus(); //it will focus the first "a" tag in "div tabindex=-1"
e.preventDefault(); //If you call HTMLElement.focus() from a mousedown event handler, you must call event.preventDefault() to keep the focus from leaving the HTMLElement (seen on https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus)
});
Can script reverse too? Up arrow should "re-autofocus" input field and let user continue typing...
Yup; modifying your code, it would look like this:
if (e.keyCode == 38) {
e.preventDefault();
$("#inputSearch").focus();
}
How do we make ESC close collapse? So user's don't have to reclick button
Yes, using collapse('hide'):
if (e.keyCode == 27) {
e.preventDefault();
$("#Foo").collapse('hide');
}
Notes:
Final JQuery code looks like this:
$(document).keyup(
function(e) {
if (e.keyCode == 38) {
e.preventDefault(); // this makes it so arrow up doesn't scroll
$("#inputSearch").focus();
}
if (e.keyCode == 40) {
e.preventDefault();
$(".link:focus").next().focus();
}
if (e.keyCode == 27) {
e.preventDefault();
$("#Foo").collapse('hide');
}
}
);
$('#Foo').on('shown.bs.collapse', function () {
$('#Foo2').children().children('a:first').focus();
e.preventDefault();
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With