javascript - Hidden Div Tab-through (accessibility) -
i have section have hidden divs being displayed on click. trying achieve accessibility compliance if tab through , open 1 of sections tab through inner content of section , return left off initially.
eg. if tab through , open section 1 able tab through inner contents of section 1 , after go button opens section 2, , forth...
i have created fiddle html / script https://jsfiddle.net/rjvw915r/10/
html example:
<div id="dropdown-menus"> <div id="section1-drop" class="drop-section hidden-panel"> <a href="#">link 1</a> <a href="#">link 2</a> </div> <div id="section2-drop" class="drop-section hidden-panel"> <a href="#">link 1</a> <a href="#">link 2</a> </div> </div> <ul id="dropdown-links" class="menu main-tabs"> <li> <a class="panel-btn" href="javascript:dropmenu('section1');" id="drop-link-section1">section 1</a> </li> <li> <a class="panel-btn" href="javascript:dropmenu('section2');" id="drop-link-section2">section 2</a> </li> </ul> javascript:
function dropmenu(menusection) { if ( !($('#dropdown-menus #' + menusection + '-drop').is(':hidden')) ) { // select panel open. closes panel. $('#dropdown-menus #' + menusection + '-drop').slideup(500); $('#dropdown-menus #' + menusection + '-drop').removeclass('active'); $('a#drop-link-' + menusection).removeclass('active'); // scroll top of buttons. var aid = $("#dropdown-links"); $('html,body').animate({scrolltop: aid.offset().top-480},400,function(){}); } else if ( $('#dropdown-menus .drop-section').hasclass('active') && $('#dropdown-menus #' + menusection + '-drop').is(':hidden') ) { // panel open. // closes open panel , opens selected panel. $('.menu a.active').removeclass('active'); $('#dropdown-menus .active').slideup(500,function(){ $('#dropdown-menus #' + menusection + '-drop').slidedown(500); $('#dropdown-menus #' + menusection + '-drop').addclass('active'); $('a#drop-link-' + menusection).addclass('active'); }).removeclass('active'); // scroll top of panel. var aid = $("#dropdown-menus"); $('html,body').animate({scrolltop: aid.offset().top-155},400,function(){}); } else { // no panel open. opens selected panel. $('#dropdown-menus #' + menusection + '-drop').slidedown(500); $('#dropdown-menus #' + menusection + '-drop').addclass('active'); $('a#drop-link-' + menusection).addclass('active'); // scroll top of panel. var aid = $("#dropdown-menus"); $('html,body').animate({scrolltop: aid.offset().top-155},400,function(){}); } } thank you!
you can use click event perform javascript actions when link clicked or enter pressed.
<div id="dropdown-menus"> <div id="section1-drop" class="drop-section hidden-panel"> <a href="#">link 1</a> <a href="#">link 2</a> </div> <div id="section2-drop" class="drop-section hidden-panel"> <a href="#">link 3</a> <a href="#">link 4</a> </div> </div> <ul id="dropdown-links" class="menu main-tabs"> <li> <a class="panel-btn" data-section="section1-drop" id="drop-link-section1">section 1</a> </li> <li> <a class="panel-btn" data-section="section2-drop" id="drop-link-section2">section 2</a> </li> </ul> above, have removed href attribute , added data-section element specifies section link activates. more semantic , readable, , can set our handlers within jquery.
define focus handler:
// setup focus handler root links $('.panel-btn').on('click', function(e) { var link = $(this); var section = link.attr('data-section'); // pass in current link , section name dropmenu dropmenu($(this), section); }); i've cleaned drop menu function bit clarify what's happening
function dropmenu(link, menusection) { // section specified menusection id var section = $('#' + menusection); // open section checking active class var opensection = $('#dropdown-menus').find('.drop-section.active'); // anonymous function activating section , focussing // first link within section var showsection = function() { // slide section view section.slidedown(500).addclass('active'); // focus first link in section. section.find('a').first().focus(); } // if there section open, want slide first, // call showsection when has completed. if(opensection.length > 0) { // if open section 1 clicked, want // close section rather open if(opensecion[0] === section[0]) { opensection.slideup(500).removeclass('active'); } else { opensection.slideup(500, showsection).removeclass('active'); } } // otherwise, can show section straight away. else { showsection(); } } this pretty standard, need handle moving between sections expect happen natively using tab key. problem since 'drop sections' above root links, tabbing last link in drop section take section 1 since next tabbable element in document. prevent this, need work around of default functionality , implement our own.
first, you'll need configure keydown handler catch tabbing before happens
// setup keydown handler handle tabbing on section links $('.drop-section').on('keydown', 'a', function(e) { if(e.keycode === tab_key) { var link = $(this); // flag determins whether prevent default tab behaviour var preventdef = false; // travel previous link on shift + tab if(e.shiftkey) { preventdef = travelprevious(link); } // travel next link on tab else { preventdef = travelnext(link); } // prevent default focus behaviour if(preventdef) { e.preventdefault(); } } }); then need functions handle next tab, , previous tab
// handles travelling next link function travelnext(link) { var next = link.next(); if(next.length > 0) { // continue default behaviour of moving next link return false; } // drop section parent id var parentid = link.parents('.drop-section').attr('id'); // root link data-section attribute matches parent id var rootlink = $('.panel-btn[data-section=' + parentid + ']').parent(); // next root link move to. var nextlink = rootlink.next().find('a'); // focus on next root link, fire dropmenu // next section. nextlink.focus(); // prevent default behaviour return true; } function travelprevious(link) { var prev = link.prev(); if(prev.length > 0) { // continue default behaviour of moving previous link return false; } // drop section parent id var parentid = link.parents('.drop-section').attr('id'); // li container root link data-section attribute matches parent id var rootlink = $('.panel-btn[data-section=' + parentid + ']').parent(); // previous root link move to. var prevlink = rootlink.prev().find('a'); // focus on previous root link, fire dropmenu // previous section. prevlink.focus(); // prevent default behaviour return true; } this still not complete solution because not handle reaching end or beginning of sections. should start , believe answers first question. if other questions this, should ask them seperately.
here fiddle example https://jsfiddle.net/rjvw915r/17/
update
if links contained in non-standard way within drop-section, method above won't quite work, uses next , prev functions direct siblings. if each a tag contained in div or li wrapper, have no direct siblings.
we can work around looking known parent element, , finding siblings via selector. in keydown function, add additional code retrieve these elements, , pass them travel functions.
$('.drop-section').on('keydown', 'a', function(e) { if(e.keycode === tab_key) { var link = $(this); // retrieve available links within parent. var linkcollection = link.parents('.drop-section').find('a'); ... in each of travel functions pass these links in
preventdef = travelprevious(link, linkcollection); ... preventdef = travelnext(link, linkcollection); by finding index of current link, can ascertain whether has siblings before or after it.
in travelnext function check see if there links after it
// find current link sits within collection var linkindex = linkcollection.index(link); var nextindex = linkindex + 1; if(nextindex < linkcollection.length) { // continue default behaviour of moving next link. return false; } in travelprevious function check see if there links before it
// find current link sits within collection var linkindex = linkcollection.index(link); var nextindex = linkindex - 1; if(nextindex >= 0) { // continue default behaviour of moving previous link return false; } see updated fiddle https://jsfiddle.net/rjvw915r/18/
Comments
Post a Comment