@@ -663,23 +663,31 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') {
663
663
},
664
664
665
665
createTabs : function () {
666
+ /* the accessibility options of this component have been defined according to: */
667
+ /* www.w3.org/WAI/ARIA/apg/example-index/tabs/tabs-manual.html */
666
668
var tabGroups = document .querySelectorAll (' .sf-tabs:not([data-processed=true])' );
667
669
668
670
/* create the tab navigation for each group of tabs */
669
671
for (var i = 0 ; i < tabGroups .length ; i++ ) {
670
672
var tabs = tabGroups[i].querySelectorAll (' :scope > .tab' );
671
- var tabNavigation = document .createElement (' ul ' );
673
+ var tabNavigation = document .createElement (' div ' );
672
674
tabNavigation .className = ' tab-navigation' ;
675
+ tabNavigation .setAttribute (' role' , ' tablist' );
673
676
674
677
var selectedTabId = ' tab-' + i + ' -0' ; /* select the first tab by default */
675
678
for (var j = 0 ; j < tabs .length ; j++ ) {
676
679
var tabId = ' tab-' + i + ' -' + j;
677
680
var tabTitle = tabs[j].querySelector (' .tab-title' ).innerHTML ;
678
681
679
- var tabNavigationItem = document .createElement (' li' );
682
+ var tabNavigationItem = document .createElement (' button' );
683
+ tabNavigationItem .classList .add (' tab-control' );
680
684
tabNavigationItem .setAttribute (' data-tab-id' , tabId);
685
+ tabNavigationItem .setAttribute (' role' , ' tab' );
686
+ tabNavigationItem .setAttribute (' aria-controls' , tabId);
681
687
if (hasClass (tabs[j], ' active' )) { selectedTabId = tabId; }
682
- if (hasClass (tabs[j], ' disabled' )) { addClass (tabNavigationItem, ' disabled' ); }
688
+ if (hasClass (tabs[j], ' disabled' )) {
689
+ addClass (tabNavigationItem, ' disabled' );
690
+ }
683
691
tabNavigationItem .innerHTML = tabTitle;
684
692
tabNavigation .appendChild (tabNavigationItem);
685
693
@@ -693,24 +701,31 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') {
693
701
694
702
/* display the active tab and add the 'click' event listeners */
695
703
for (i = 0 ; i < tabGroups .length ; i++ ) {
696
- tabNavigation = tabGroups[i].querySelectorAll (' :scope > .tab-navigation li ' );
704
+ tabNavigation = tabGroups[i].querySelectorAll (' :scope > .tab-navigation .tab-control ' );
697
705
698
706
for (j = 0 ; j < tabNavigation .length ; j++ ) {
699
707
tabId = tabNavigation[j].getAttribute (' data-tab-id' );
700
- document .getElementById (tabId).querySelector (' .tab-title' ).className = ' hidden' ;
708
+ const tabPanel = document .getElementById (tabId);
709
+ tabPanel .setAttribute (' role' , ' tabpanel' );
710
+ tabPanel .setAttribute (' aria-labelledby' , tabId);
711
+ tabPanel .querySelector (' .tab-title' ).className = ' hidden' ;
701
712
702
713
if (hasClass (tabNavigation[j], ' active' )) {
703
- document .getElementById (tabId).className = ' block' ;
714
+ tabPanel .className = ' block' ;
715
+ tabNavigation[j].setAttribute (' aria-selected' , ' true' );
716
+ tabNavigation[j].removeAttribute (' tabindex' );
704
717
} else {
705
- document .getElementById (tabId).className = ' hidden' ;
718
+ tabPanel .className = ' hidden' ;
719
+ tabNavigation[j].removeAttribute (' aria-selected' );
720
+ tabNavigation[j].setAttribute (' tabindex' , ' -1' );
706
721
}
707
722
708
723
tabNavigation[j].addEventListener (' click' , function (e ) {
709
724
var activeTab = e .target || e .srcElement ;
710
725
711
726
/* needed because when the tab contains HTML contents, user can click */
712
- /* on any of those elements instead of their parent '<li >' element */
713
- while (activeTab .tagName .toLowerCase () !== ' li ' ) {
727
+ /* on any of those elements instead of their parent '<button >' element */
728
+ while (activeTab .tagName .toLowerCase () !== ' button ' ) {
714
729
activeTab = activeTab .parentNode ;
715
730
}
716
731
@@ -720,9 +735,13 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') {
720
735
var tabId = tabNavigation[k].getAttribute (' data-tab-id' );
721
736
document .getElementById (tabId).className = ' hidden' ;
722
737
removeClass (tabNavigation[k], ' active' );
738
+ tabNavigation[k].removeAttribute (' aria-selected' );
739
+ tabNavigation[k].setAttribute (' tabindex' , ' -1' );
723
740
}
724
741
725
742
addClass (activeTab, ' active' );
743
+ activeTab .setAttribute (' aria-selected' , ' true' );
744
+ activeTab .removeAttribute (' tabindex' );
726
745
var activeTabId = activeTab .getAttribute (' data-tab-id' );
727
746
document .getElementById (activeTabId).className = ' block' ;
728
747
});
@@ -894,7 +913,7 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') {
894
913
document .querySelector (' #log-filter-channel .filter-active-num' ).innerText = (channels .length === selectedChannels .length ) ? ' All' : selectedChannels .length ;
895
914
896
915
/* update the currently selected "log type" tab */
897
- document .querySelectorAll (' #log-filter-type li ' ).forEach ((tab ) => tab .classList .remove (' active' ));
916
+ document .querySelectorAll (' #log-filter-type .tab-control ' ).forEach ((tab ) => tab .classList .remove (' active' ));
898
917
document .querySelector (` #log-filter-type input[value="${ selectedType} "]` ).parentElement .classList .add (' active' );
899
918
},
900
919
};
0 commit comments