PageSourceSearch

https://scorm.com/wp-content/themes/rustici/_/js/tabs.js?3902d

js scorm.com collected 2026-10-01 08:50:08 UTC 4,192 bytes, 202 lines download raw bytes

1// Accessible tabs
2// https://a11yproject.com/patterns
3// https://codepen.io/svinkle/pen/edmDF
4
5(function(document, window, $, undefined) {
6  "use strict";
7
8  var $tabWidget = $(".js-tab-widget");
9
10  var setupTabs = function($tab, $allTabs, $tabPanels, $tabListItems, i) {
11    $tab.attr({
12      id: "tab-link-" + i,
13      tabindex: "-1",
14      role: "tab",
15      "aria-selected": "false",
16      "aria-controls": "tab-panel-" + i
17    });
18
19    if (i === 0) {
20      $tab
21        .attr({
22          tabindex: "0",
23          "aria-selected": "true",
24          "aria-describedby": "tab-widget-description"
25        })
26        .addClass("tab-widget__link--active");
27    }
28
29    $tab.on("click", function(e) {
30      e.preventDefault();
31      tabClick($(this), $allTabs, $tabPanels, i);
32    });
33
34    $tab.on("focus", function(e) {
35      tabClick($(this), $allTabs, $tabPanels, i);
36    });
37
38    $tab.on("keydown", function(e) {
39      tabKeydown($(this), $allTabs, $tabPanels, $tabListItems, i, e);
40    });
41  };
42
43  var setupTabPanels = function(tabPanel, i) {
44    tabPanel.attr({
45      id: "tab-panel-" + i,
46      role: "tabpanel",
47      "aria-hidden": "true",
48      "aria-labelledby": "tab-link-" + i
49    });
50
51    if (i === 0) {
52      tabPanel
53        .attr("aria-hidden", "false")
54        .addClass("tab-widget__tab-content--active");
55    }
56  };
57
58  var tabClick = function($thisTab, $allTabs, $tabPanels, i) {
59    $allTabs
60      .attr({
61        tabindex: -1,
62        "aria-selected": "false"
63      })
64      .removeAttr("aria-describedby")
65      .removeClass("tab-widget__link--active");
66
67    $thisTab
68      .attr({
69        tabindex: 0,
70        "aria-selected": "true",
71        "aria-describedby": "tab-widget-description"
72      })
73      .addClass("tab-widget__link--active");
74
75    $tabPanels
76      .attr("aria-hidden", "true")
77      .removeClass("tab-widget__tab-content--active");
78
79    $tabPanels
80      .eq(i)
81      .attr("aria-hidden", "false")
82      .addClass("tab-widget__tab-content--active");
83  };
84
85  var tabKeydown = function(
86    $thisTab,
87    $allTabs,
88    $tabPanels,
89    $tabListItems,
90    i,
91    e
92  ) {
93    var keyCode = e.which,
94      $nextTab = $thisTab
95        .parent()
96        .next()
97        .is("li")
98        ? $thisTab
99            .parent()
100            .next()
101            .find("a")
102        : false,
103      $previousTab = $thisTab
104        .parent()
105        .prev()
106        .is("li")
107        ? $thisTab
108            .parent()
109            .prev()
110            .find("a")
111        : false,
112      $firstTab = $thisTab
113        .parent()
114        .parent()
115        .find("li:first")
116        .find("a"),
117      $lastTab = $thisTab
118        .parent()
119        .parent()
120        .find("li:last")
121        .find("a");
122
123    switch (keyCode) {
124      // Left/Up
125      case 37:
126      case 38:
127        e.preventDefault();
128        e.stopPropagation();
129
130        if (!$previousTab) {
131          $lastTab.focus();
132        } else {
133          $previousTab.focus();
134        }
135
136        break;
137
138      // Right/Down
139      case 39:
140      case 40:
141        e.preventDefault();
142        e.stopPropagation();
143
144        if (!$nextTab) {
145          $firstTab.focus();
146        } else {
147          $nextTab.focus();
148        }
149
150        break;
151
152      // Home
153      case 36:
154        e.preventDefault();
155        e.stopPropagation();
156
157        $firstTab.focus();
158
159        break;
160
161      // End
162      case 35:
163        e.preventDefault();
164        e.stopPropagation();
165
166        $lastTab.focus();
167
168        break;
169
170      // Enter/Space
171      case 13:
172      case 32:
173        e.preventDefault();
174        e.stopPropagation();
175
176        break;
177    }
178  };
179
180  $tabWidget.each(function() {
181    var $this = $(this),
182      $tabList = $this.find("> ul"),
183      $tabListItems = $tabList.find("li"),
184      $allTabs = $tabListItems.find("a"),
185      $tabPanels = $this.find("> div > div");
186
187    $tabList.attr("role", "tablist");
188    $tabListItems.attr("role", "presentation");
189
190    $allTabs.each(function(i) {
191      setupTabs($(this), $allTabs, $tabPanels, $tabListItems, i);
192    });
193
194    $tabPanels.each(function(i) {
195      setupTabPanels($(this), i);
196    });
197  });
198
199  $("html")
200    .addClass("js")
201    .removeClass("no-js");
202})(document, window, jQuery);

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.