PageSourceSearch

https://scsu.edu/_resources/js/accessible-responsive-tabs.js

js scsu.edu collected 2026-10-01 11:27:40 UTC 5,286 bytes, 192 lines download raw bytes

1/*
2 * jQuery plugin.
3 * Accessible tabs with WAI ARIA.
4 * In mobile tabs become accordion.
5 * */
6
7$.fn.accessibleResponsiveTabs = function () {
8
9  $(this).each(function () {
10    var obj = $(this),
11        tabs = $('.standardTabs', obj),
12        tabContainer = $('.tabContainer', obj);
13
14    tabs.attr('role', 'tablist');
15
16    // tabs init
17    function initTabs() {
18      $('li', tabs).each(function () {
19        var rel = $(this).attr('rel');
20        $('a', $(this)).attr({
21          'role':          'tab',
22          'aria-controls': rel,
23          'tabindex':      -1,
24          'aria-selected': false,
25          'id':            'link' + rel
26        });
27      });
28    }
29
30    function activeTab(active) {
31      // Default tab active
32      var activeLink = $('li.active a', tabs),
33          activeTab = activeLink.parent();
34      // current active tab
35      if (active) {
36        // if click on accordion mode
37        if (active.hasClass("accordionHeading")) {
38          relAccordionHeading = active.attr('rel');
39          activeLink = $('li[rel^=' + relAccordionHeading + '] a', tabs);
40          activeTab = activeLink.parent();
41        } else {
42          activeLink = active;
43          activeTab = active.parent();
44        }
45      }
46      // reset tabs
47      initTabs();
48      $('li', tabs).removeClass('active');
49      // active tab
50      activeLink.attr({
51        'tabindex':      0,
52        'aria-selected': true
53      });
54      activeTab.addClass('active');
55    }
56
57    initTabs();
58    activeTab();
59
60    // Accordion init
61    function initAccordions() {
62      $('.accordionHeading', tabContainer).each(function () {
63        var rel = $(this).attr('rel');
64        $(this).attr({
65          'role':          'tab',
66          'aria-controls': rel,
67          'tabindex':      -1,
68          'aria-selected': false
69        });
70      });
71    }
72
73    function activeAccordion() {
74      var activeTabRel = $('li.active', tabs).attr('rel'),
75          activeAccordionHeading = $('.accordionHeading[rel^=' + activeTabRel + ']');
76
77      // Reset all accordions
78      initAccordions();
79      // Active current accordion heading
80      activeAccordionHeading.attr({
81        'tabindex':      0,
82        'aria-selected': true
83      });
84    }
85
86    initAccordions();
87    activeAccordion();
88
89    // Content init
90    function initContents() {
91      $('.tabContent', tabContainer).each(function () {
92        var labelledby = 'link' + $(this).attr('id');
93        $(this).attr({
94          'role':            'tabpanel',
95          'aria-labelledby': labelledby,
96          'aria-hidden':     true
97        });
98      });
99    }
100
101    function activeContent() {
102      var activeTabRel = $('li.active', tabs).attr('rel'),
103          activeContent = $('#' + activeTabRel);
104
105      // Reset all contents
106      initContents();
107      $(".tabContent", obj).removeClass('active');
108      // Active current content
109      activeContent.addClass('active').attr({
110        'aria-hidden': false
111      });
112    }
113
114    initContents();
115    activeContent();
116
117
118    // If in tab mode
119    $('li > a', tabs).click(function (e) {
120      // active current tab
121      activeTab($(this));
122
123      // active current content
124      activeContent();
125
126      // active current accordion
127      activeAccordion();
128
129      e.preventDefault();
130    });
131
132    // Keyboard if in tab mode
133    $('li > a', tabs).on('keydown', function (e) {
134      var activeTab = $('li.active', tabs),
135          firstTab = $('li:first-child', tabs),
136          lastTab = $('li:last-child', tabs);
137
138      // prev
139      if (e.keyCode == 37 || e.keyCode == 38) {
140        if (activeTab.is($('li:first-child', tabs))) {
141          lastTab.children('a').click().focus();
142        } else {
143          activeTab.prev().children('a').click().focus();
144        }
145      }
146      // next
147      else if (e.keyCode == 40 || e.keyCode == 39) {
148        if (activeTab.is($('li:last-child', tabs))) {
149          firstTab.children('a').click().focus();
150        } else {
151          activeTab.next().children('a').click().focus();
152        }
153      }
154    });
155
156    // If in accordion mode
157    $('.accordionHeading', obj).click(function () {
158      // active current tab
159      activeTab($(this));
160
161      // active current content
162      activeContent();
163
164      // active current accordion
165      activeAccordion();
166    });
167
168    // Keyboard if in accordion mode
169    $('.accordionHeading', tabContainer).on('keydown', function (e) {
170      var activeAccordionHeading = $(".accordionHeading[aria-selected='true']", tabContainer),
171          firstAccordionHeading = $('.accordionHeading:first-of-type', tabContainer),
172          lastAccordionHeading = $('.accordionHeading:last-of-type', tabContainer);
173
174      // prev
175      if (e.keyCode == 37 || e.keyCode == 38) {
176        if (activeAccordionHeading.is($('.accordionHeading:first-of-type', tabContainer))) {
177          lastAccordionHeading.click().focus();
178        } else {
179          activeAccordionHeading.prev().prev().click().focus();
180        }
181      }
182      // next
183      if (e.keyCode == 40 || e.keyCode == 39) {
184        if (activeAccordionHeading.is($('.accordionHeading:last-of-type', tabContainer))) {
185          firstAccordionHeading.click().focus();
186        } else {
187          activeAccordionHeading.next().next().click().focus();
188        }
189      }
190    });
191  });
192};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.