Fix tabs, improve setup documentation to be explicit about vscode
[rnaseq-cwl-training.git] / assets / js / tabs.js
1 window.addEventListener('load', function() {
2   // Get relevant elements and collections
3     const allTabbed = document.querySelectorAll('.tabbed');
4
5     allTabbed.forEach((tabbed) => {
6
7   const tablist = tabbed.querySelector('ul');
8   const tabs = tablist.querySelectorAll('a');
9   const panels = tabbed.querySelectorAll('[id^="section"]');
10
11   // The tab switching function
12   const switchTab = (oldTab, newTab) => {
13     newTab.focus();
14     // Make the active tab focusable by the user (Tab key)
15     newTab.removeAttribute('tabindex');
16     // Set the selected state
17     newTab.setAttribute('aria-selected', 'true');
18     newTab.classList.add('active');
19     oldTab.removeAttribute('aria-selected');
20     oldTab.setAttribute('tabindex', '-1');
21     oldTab.classList.remove('active');
22     // Get the indices of the new and old tabs to find the correct
23     // tab panels to show and hide
24     let index = Array.prototype.indexOf.call(tabs, newTab);
25     let oldIndex = Array.prototype.indexOf.call(tabs, oldTab);
26     panels[oldIndex].hidden = true;
27     panels[index].hidden = false;
28   }
29
30   // Add the tablist role to the first <ul> in the .tabbed container
31   tablist.setAttribute('role', 'tablist');
32
33   // Add semantics are remove user focusability for each tab
34   Array.prototype.forEach.call(tabs, (tab, i) => {
35     tab.setAttribute('role', 'tab');
36     tab.setAttribute('id', 'tab' + (i + 1));
37     tab.setAttribute('tabindex', '-1');
38 //     tab.setAttribute('class', 'active');
39     tab.parentNode.setAttribute('role', 'presentation');
40
41     // Handle clicking of tabs for mouse users
42     tab.addEventListener('click', e => {
43       e.preventDefault();
44       let currentTab = tablist.querySelector('[aria-selected]');
45       if (e.currentTarget !== currentTab) {
46         switchTab(currentTab, e.currentTarget);
47       }
48     });
49
50     // Handle keydown events for keyboard users
51     tab.addEventListener('keydown', e => {
52       // Get the index of the current tab in the tabs node list
53       let index = Array.prototype.indexOf.call(tabs, e.currentTarget);
54       // Work out which key the user is pressing and
55       // Calculate the new tab's index where appropriate
56       let dir = e.which === 37 ? index - 1 : e.which === 39 ? index + 1 : e.which === 40 ? 'down' : null;
57       if (dir !== null) {
58         e.preventDefault();
59         // If the down key is pressed, move focus to the open panel,
60         // otherwise switch to the adjacent tab
61         dir === 'down' ? panels[i].focus() : tabs[dir] ? switchTab(e.currentTarget, tabs[dir]) : void 0;
62       }
63     });
64   });
65
66   // Add tab panel semantics and hide them all
67   Array.prototype.forEach.call(panels, (panel, i) => {
68     panel.setAttribute('role', 'tabpanel');
69     panel.setAttribute('tabindex', '-1');
70     let id = panel.getAttribute('id');
71     panel.setAttribute('aria-labelledby', tabs[i].id);
72     panel.hidden = true;
73   });
74
75   // Initially activate the first tab and reveal the first tab panel
76   tabs[0].removeAttribute('tabindex');
77   tabs[0].setAttribute('aria-selected', 'true');
78   tabs[0].setAttribute('class', 'active');
79   panels[0].hidden = false;
80     });
81 }
82 );