@pimaonline/pimaonline-themepack 3.0.0 → 3.10.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. package/LICENSE.md +30 -30
  2. package/README.md +100 -69
  3. package/dist/css/main.css +1 -1
  4. package/dist/css/plugins/alt-icons.css +1 -0
  5. package/dist/css/plugins/font-awesome.css +1 -1
  6. package/dist/css/routes.css +1 -1
  7. package/dist/css/themes/aviation/styles.css +1 -1
  8. package/dist/css/themes/bct/styles.css +1 -0
  9. package/dist/css/themes/bio/styles.css +1 -0
  10. package/dist/css/themes/business/styles.css +1 -1
  11. package/dist/css/themes/fsc/styles.css +1 -1
  12. package/dist/css/themes/hrs/styles.css +1 -1
  13. package/dist/css/themes/lgm/styles.css +1 -1
  14. package/dist/css/themes/psy/styles.css +1 -0
  15. package/dist/img/theme-images/bct/Blueprint-background.png +0 -0
  16. package/dist/img/theme-images/bio/original/dna.svg +1 -0
  17. package/dist/img/theme-images/bio/original/humans.svg +1 -0
  18. package/dist/img/theme-images/bio/original/leaves.svg +33 -0
  19. package/dist/img/theme-images/bio/original/marine-bottom.svg +1 -0
  20. package/dist/img/theme-images/bio/original/marine-top.svg +1 -0
  21. package/dist/img/theme-images/bio/original/microbes.svg +1 -0
  22. package/dist/img/theme-images/ecn/arrow-2.svg +4 -4
  23. package/dist/img/theme-images/ecn/arrow.svg +4 -4
  24. package/dist/img/theme-images/ecn/point.svg +3 -3
  25. package/dist/img/theme-images/eng/button-bkg.svg +178 -178
  26. package/dist/img/theme-images/eng/halftone.svg +177 -177
  27. package/dist/img/theme-images/eng/long-button-bkg.svg +353 -353
  28. package/dist/img/theme-images/fsc/bottomwave-pinkred.svg +16 -16
  29. package/dist/img/theme-images/fsc/bottomwave-redorange.svg +16 -16
  30. package/dist/img/theme-images/fsc/bottomwave-yellow.svg +16 -16
  31. package/dist/img/theme-images/fsc/bottomwave-yelloworange.svg +16 -16
  32. package/dist/img/theme-images/fsc/mainwave-pinkred.svg +16 -16
  33. package/dist/img/theme-images/fsc/mainwave-redorange.svg +16 -16
  34. package/dist/img/theme-images/fsc/mainwave-yellow.svg +16 -16
  35. package/dist/img/theme-images/fsc/mainwave-yelloworange.svg +16 -16
  36. package/dist/img/theme-images/music/half_note.svg +5 -5
  37. package/dist/img/theme-images/psy/counseling-icon.svg +1 -0
  38. package/dist/img/theme-images/psy/psych-icon.svg +17 -0
  39. package/dist/img/theme-images/resort/flourish-left.svg +32 -32
  40. package/dist/img/theme-images/resort/flourish-main.svg +37 -37
  41. package/dist/img/theme-images/resort/flourish-right.svg +31 -31
  42. package/dist/img/theme-images/resort/separator.svg +15 -15
  43. package/dist/img/theme-images/ss/blockquote.svg +2 -2
  44. package/dist/img/theme-images/ss/list-style.svg +3 -3
  45. package/dist/img/theme-images/ss/main-large-blob.svg +3 -3
  46. package/dist/img/theme-images/ss/main-small-blob.svg +3 -3
  47. package/dist/img/theme-images/ss/small-blob.svg +3 -3
  48. package/dist/img/theme-images/ss/tall-blob.svg +3 -3
  49. package/dist/img/theme-images/widgets/separator.svg +17 -17
  50. package/dist/js/jumpTo.js +3 -3
  51. package/dist/js/scripts.js +326 -326
  52. package/dist/js/scripts2.js +1006 -541
  53. package/dist/js/themes/ecn.js +13 -0
  54. package/dist/js/themes/hrs.js +19 -0
  55. package/dist/js/themes/ss.js +197 -0
  56. package/dist/plugins/fancybox/fancybox-example.html +51 -51
  57. package/dist/plugins/fancybox/fancybox.css +72 -72
  58. package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.css +97 -97
  59. package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.js +122 -122
  60. package/dist/plugins/fancybox/helpers/jquery.fancybox-media.js +201 -201
  61. package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.css +54 -54
  62. package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.js +165 -165
  63. package/dist/plugins/fancybox/jquery.fancybox.css +274 -274
  64. package/dist/plugins/fancybox/jquery.fancybox.js +2018 -2018
  65. package/dist/plugins/fancybox/jquery.fancybox.pack.js +46 -46
  66. package/dist/plugins/flashcards/README.md +135 -135
  67. package/dist/plugins/flashcards/config.rb +24 -24
  68. package/dist/plugins/flashcards/css/style.css +215 -215
  69. package/dist/plugins/flashcards/flashcards-example.html +65 -65
  70. package/dist/plugins/flashcards/index.html +90 -90
  71. package/dist/plugins/flashcards/js/flash_cards.min.js +11 -11
  72. package/dist/plugins/flashcards/js/plugins/flash_cards.js +62 -62
  73. package/dist/plugins/flashcards/js/plugins/jquery.cycle.js +1147 -1147
  74. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.js +9404 -9404
  75. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.min.js +3 -3
  76. package/dist/plugins/flashcards/js/vendor/modernizr-2.5.3.min.js +3 -3
  77. package/dist/plugins/flashcards/resources/fonts/flash_cards/flash_cards.svg +20 -20
  78. package/dist/plugins/floating-particles/floating-particles.js +67 -67
  79. package/dist/plugins/font-awesome-icons/webfonts/brands.svg +1460 -0
  80. package/dist/plugins/font-awesome-icons/webfonts/fa-brands-400.ttf +0 -0
  81. package/dist/plugins/font-awesome-icons/webfonts/fa-brands-400.woff2 +0 -0
  82. package/dist/plugins/font-awesome-icons/webfonts/fa-regular-400.ttf +0 -0
  83. package/dist/plugins/font-awesome-icons/webfonts/fa-regular-400.woff2 +0 -0
  84. package/dist/plugins/font-awesome-icons/webfonts/fa-solid-900.ttf +0 -0
  85. package/dist/plugins/font-awesome-icons/webfonts/fa-solid-900.woff2 +0 -0
  86. package/dist/plugins/font-awesome-icons/webfonts/fa-v4compatibility.ttf +0 -0
  87. package/dist/plugins/font-awesome-icons/webfonts/fa-v4compatibility.woff2 +0 -0
  88. package/dist/plugins/font-awesome-icons/webfonts/regular.svg +497 -0
  89. package/dist/plugins/font-awesome-icons/webfonts/solid.svg +4178 -0
  90. package/dist/plugins/global-homepage-overrides/global-homepage-overrides.css +539 -539
  91. package/dist/plugins/global-homepage-overrides/global-homepage-overrides.html +18 -18
  92. package/dist/plugins/global-homepage-overrides/global-homepage-overrides.js +52 -52
  93. package/dist/plugins/preview-banner/preview-banner.css +125 -125
  94. package/dist/plugins/preview-banner/preview-banner.html +17 -17
  95. package/dist/plugins/preview-banner/preview-banner.js +56 -56
  96. package/package.json +42 -39
  97. package/dist/plugins/font-awesome-icons/webfonts/fa-brands-400.eot +0 -0
  98. package/dist/plugins/font-awesome-icons/webfonts/fa-brands-400.svg +0 -3570
  99. package/dist/plugins/font-awesome-icons/webfonts/fa-brands-400.woff +0 -0
  100. package/dist/plugins/font-awesome-icons/webfonts/fa-regular-400.eot +0 -0
  101. package/dist/plugins/font-awesome-icons/webfonts/fa-regular-400.svg +0 -803
  102. package/dist/plugins/font-awesome-icons/webfonts/fa-regular-400.woff +0 -0
  103. package/dist/plugins/font-awesome-icons/webfonts/fa-solid-900.eot +0 -0
  104. package/dist/plugins/font-awesome-icons/webfonts/fa-solid-900.svg +0 -4700
  105. package/dist/plugins/font-awesome-icons/webfonts/fa-solid-900.woff +0 -0
@@ -1,327 +1,327 @@
1
- /// @description Main JS file for PimaOnline Themepack
2
- /// @dependencies jQuery 3.3.1 or later
3
-
4
- window.addEventListener("DOMContentLoaded", () => {
5
-
6
- const courseBody = document.querySelector("body");
7
- const contentWrapper = document.querySelector("#content-wrapper");
8
- const secondColumn = document.querySelector("#second-column");
9
- const thirdColumn = document.querySelector("#third-column");
10
- const columnWidget = document.querySelector("#column-widget");
11
- const videoWrapper = document.querySelector("#video-wrapper");
12
- const rolePres = document.querySelectorAll('[role="presentation"]');
13
- const imageGallery = document.querySelector(".image-gallery");
14
- const vocabListWidget = document.querySelector("dl.vocab-list");
15
- const vocabTerms = document.querySelectorAll("dl.vocab-list dt");
16
- const vocabDefs = document.querySelectorAll("dl.vocab-list dd");
17
- const vocabCloseBtns = document.querySelectorAll("dl.vocab-list button");
18
- const vocabLists = document.querySelectorAll("dl[class^='vocab-list']");
19
- const mediaContainers = document.querySelectorAll(".media-container");
20
- const tabsWidgets = document.querySelectorAll(".tabs");
21
-
22
- // Grid
23
- const addGrid = () => {
24
- if (secondColumn && thirdColumn) {
25
- courseBody.id = "three-column";
26
- } else if (secondColumn && !columnWidget) {
27
- courseBody.id = "two-column";
28
- } else if (columnWidget) {
29
- courseBody.id = "two-col-widget";
30
- } else if (videoWrapper) {
31
- courseBody.id = "video-grid";
32
- } else {
33
- courseBody.id = "one-column";
34
- }
35
- };
36
- addGrid();
37
-
38
- // JS to add role and aria-label to content-wrapper, second-column, and third-column
39
- const addAria = () => {
40
- contentWrapper.setAttribute("role", "main");
41
- if (secondColumn) {
42
- secondColumn.setAttribute("role", "region");
43
- secondColumn.setAttribute("aria-label", "Second column");
44
- }
45
- if (thirdColumn) {
46
- thirdColumn.setAttribute("role", "region");
47
- thirdColumn.setAttribute("aria-label", "Third column");
48
- }
49
- };
50
- addAria();
51
-
52
- // Clean up HTML
53
- const cleanMarkup = () => {
54
- // Remove role="presentation" attr from any element that has it
55
- if (rolePres) {
56
- rolePres.forEach((roleElem) => roleElem.removeAttribute("role"));
57
- }
58
- // Set functino to remove atrributes from elements
59
- const discardAttributes = (element, ...attributes) => {
60
- attributes.forEach((attribute) => element.removeAttribute(attribute));
61
- }
62
- // Remove attributes from tables
63
- const tableElems = document.querySelectorAll("table, thead, tbody, tr, th, td");
64
- tableElems.forEach((elem) => {
65
- discardAttributes(elem, "cellspacing", "cellpadding", "width", "style");
66
- });
67
- };
68
- cleanMarkup();
69
-
70
- // Helper JS for Responsive Tables
71
- const initResponsiveTables = () => {
72
- const tables = document.querySelectorAll(".display, .display-lg")
73
- for (let table = 0; table < tables.length; table++) {
74
- let headertext = [],
75
- headers = tables[table].querySelectorAll(".display table th, table.display th, .display-lg table th, table.display-lg th"),
76
- tablebody = tables[table].querySelector(".display table tbody, table.display tbody, .display-lg table tbody, table.display-lg tbody");
77
- for (let header = 0; header < headers.length; header++) {
78
- let current = headers[header];
79
- headertext.push(current.textContent.replace(/\r?\n|\r/, ""));
80
- }
81
- for (let y = 0, row; row = tablebody.rows[y]; y++) {
82
- for (let j = 0, col; col = row.cells[j]; j++) {
83
- col.setAttribute("data-th", headertext[j]);
84
- }
85
- }
86
- }
87
- }
88
- initResponsiveTables();
89
-
90
- // This is called by anchor links via onlick="" in the HTML
91
- // Added because default anchor links don't work on all browsers using D2L
92
- const addScript = (script) => {
93
- let newScript = document.createElement("script");
94
- newScript.setAttribute("src", script);
95
-
96
- document.body.append(newScript);
97
- }
98
-
99
- if(document.querySelector("[onclick]")) {
100
- addScript("https://cdn.jsdelivr.net/npm/@pimaonline/pimaonline-themepack/dist/js/jumpTo.js");
101
- }
102
-
103
- // Image gallery
104
- const callImageGallery = () => {
105
- // Create link element with font-awesome cdn and append it to the <head>
106
- const docHead = document.querySelector("head");
107
- const fontAwesomeCdn = document.createElement("link");
108
- fontAwesomeCdn.setAttribute("rel", "stylesheet");
109
- fontAwesomeCdn.setAttribute("href", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css");
110
- docHead.appendChild(fontAwesomeCdn);
111
- // Begin image gallery
112
- const imgGalleries = document.querySelectorAll(".image-gallery"),
113
- imgBoxes = document.querySelectorAll(".image-box"),
114
- modalBoxContent = `<div class="modal-box invisible">
115
- <div class="gallery-overlay"></div>
116
- <figure class="modal-box--image"><i class="fa-solid fa-x close-img"></i> <img src="#" alt="image here" /><figcaption class="img-caption"></figcaption></figure>
117
- </div>
118
- <button class="hide-gallery">Hide</button>`;
119
-
120
- // createModalBox.innerHTML = modalBoxContent;
121
- for (let imgGallery = 0; imgGallery < imgGalleries.length; imgGallery++) {
122
- imgGalleries[imgGallery].insertAdjacentHTML("afterbegin", modalBoxContent);
123
- }
124
-
125
- if (document.querySelector(".modal-box")) {
126
- const overlay = document.querySelector(".gallery-overlay"),
127
- modalBox = document.querySelector(".modal-box"),
128
- modalImg = document.querySelector(".modal-box--image img"),
129
- modalCaption = document.querySelector(".img-caption"),
130
- closeImg = document.querySelector(".close-img");
131
-
132
- for (let imgBox = 0; imgBox < imgBoxes.length; imgBox++) {
133
- imgBoxes[imgBox].onclick = function () {
134
- modalBox.classList.remove("invisible");
135
- let imgSrc = this.querySelector("img").src;
136
- modalImg.src = imgSrc;
137
- let imgCaption = this.querySelector("img").alt;
138
- modalCaption.innerHTML = imgCaption;
139
- }
140
- }
141
- overlay.onclick = () => {
142
- modalBox.classList.add("invisible");
143
- }
144
- window.onkeydown = (esc) => {
145
- if (esc.keyCode === 27) {
146
- modalBox.classList.add("invisible");
147
- }
148
- }
149
- closeImg.onclick = () => {
150
- modalBox.classList.add("invisible");
151
- }
152
- const hideGalleries = document.querySelectorAll(".hide-gallery");
153
- for (let hideGallery = 0; hideGallery < hideGalleries.length; hideGallery++) {
154
- hideGalleries[hideGallery].addEventListener("click", () => {
155
- hideGalleries[hideGallery].nextElementSibling.classList.toggle("invisible");
156
- if (hideGalleries[hideGallery].innerHTML === "Hide") {
157
- hideGalleries[hideGallery].innerHTML = "Show";
158
- } else {
159
- hideGalleries[hideGallery].innerHTML = "Hide";
160
- }
161
- });
162
- }
163
- };
164
- }
165
- if (imageGallery) {
166
- callImageGallery();
167
- }
168
-
169
- // Vocab list widget
170
- const callVocabList = () => {
171
- if (vocabCloseBtns) {
172
- for(let btn = 0; btn < vocabCloseBtns.length; btn++) {
173
- vocabCloseBtns[btn].addEventListener("click", () => {
174
- for(let node = 0; node < vocabLists[btn].children.length;node++) {
175
- if(vocabLists[btn].children[node].tagName == "DD") {
176
- vocabLists[btn].children[node].removeAttribute("style");
177
- }
178
- if(vocabLists[btn].children[node].tagName == "DT") {
179
- vocabLists[btn].children[node].removeAttribute("class");
180
- }
181
- }});
182
- }
183
- }
184
- for (let activeTerm = 0; activeTerm < vocabTerms.length; activeTerm++) {
185
- vocabTerms[activeTerm].addEventListener("click", function() {
186
- this.classList.toggle("active");
187
- let termPanel = this.nextElementSibling;
188
- if (termPanel.style.display === "block") { termPanel.removeAttribute("style"); }
189
- else { termPanel.style.display = "block"; }
190
- });
191
-
192
- vocabTerms[activeTerm].addEventListener("keydown", function(e) {
193
- if(e.key === "Enter") {
194
- this.classList.toggle("active");
195
- let termPanel = this.nextElementSibling;
196
- if (termPanel.style.display === "block") { termPanel.removeAttribute("style"); }
197
- else { termPanel.style.display = "block"; }
198
- }
199
- });
200
- }
201
- }
202
- if (vocabListWidget) {callVocabList();}
203
-
204
- //
205
- const addMediaContainersAria = () => {
206
- mediaContainers.forEach((eachContainer, index) => {
207
- // loopID: find the current index value, convert it to its letter equivalent, then convert to lowercase
208
- let loopId = String.fromCharCode(index + 65).toLowerCase();
209
- let mediaObject = eachContainer.querySelector(".media-object");
210
- let iframe = mediaObject.firstElementChild;
211
- let mediaInfo = mediaObject.nextElementSibling;
212
-
213
- // If element DOES NOT have "aria-describedby" && it DOES have a sibling element.
214
- if (!iframe.hasAttribute("aria-describedby") && mediaInfo != null) {
215
- iframe.setAttribute("aria-describedby", `${loopId}`);
216
- mediaInfo.id = `${[loopId]}`;
217
- }
218
- });
219
- }
220
- if (mediaContainers) {addMediaContainersAria();}
221
-
222
- //Tabs Widget
223
- const callTabsWidget = () => {
224
-
225
- let tabsWidgetsNum = 0;
226
-
227
- tabsWidgets.forEach((tab,index) => {
228
- let tabInputs = tab.querySelectorAll("input")
229
- let tabLabels = tab.querySelectorAll("label")
230
- let tabDivs = tab.querySelectorAll("div")
231
-
232
- let groupNum = index + 1;
233
-
234
- //Add region and aria-label to parent div
235
- tab.setAttribute("role", "region");
236
- tab.setAttribute("aria-label", `tab group ${groupNum}`)
237
-
238
- for(tabIndex = 0; tabIndex < tabInputs.length; tabIndex++) {
239
-
240
- let tabNum = tabsWidgetsNum + 1;
241
-
242
- //Add class, id, name, and aria-described by for inputs
243
- tabInputs[tabIndex].classList.add("tab-input");
244
- tabInputs[tabIndex].setAttribute("type", "radio")
245
- tabInputs[tabIndex].setAttribute("id", `tab${tabNum}`);
246
- tabInputs[tabIndex].setAttribute("name", `hint-group-${groupNum}` )
247
- tabInputs[tabIndex].setAttribute("aria-describedby", `tabHeading${tabNum}`)
248
- //Add class and for for labels
249
- tabLabels[tabIndex].classList.add("tab-header");
250
- tabLabels[tabIndex].setAttribute("for", `tab${tabNum}`)
251
- //Add class, tabindex, and id for divs
252
- tabDivs[tabIndex].classList.add("tab-panel")
253
- tabDivs[tabIndex].setAttribute("tabindex", 0)
254
- tabDivs[tabIndex].setAttribute("id", `tabHeading${tabNum}`)
255
- //Add attributes for hide tab
256
- if(tabIndex + 1 == tabInputs.length) {
257
- tabLabels[tabIndex].classList.add("hide-tab")
258
- tabInputs[tabIndex].checked = true;
259
- tabDivs[tabIndex].classList.add("hide-panel")
260
- }
261
- tabsWidgetsNum++;
262
- }
263
- })
264
- }
265
- if (tabsWidgets) {callTabsWidget();}
266
-
267
- // Toggle footnotes
268
- const toggleBtns = document.querySelectorAll(".toggle-btn, .toggle-footnotes");
269
-
270
- if (document.querySelector(".toggle-btn") || document.querySelector(".toggle-footnotes")) {
271
- for (let toggleBtn = 0; toggleBtn < toggleBtns.length; toggleBtn++) {
272
- // Add tabindex
273
- toggleBtns[toggleBtn].setAttribute("tabindex", "0");
274
-
275
- // Show/hide on click
276
- toggleBtns[toggleBtn].addEventListener("click", () => {
277
- toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
278
- })
279
-
280
- // Show/hide on enter for users who use tab
281
- toggleBtns[toggleBtn].addEventListener("keydown", (enter) => {
282
- if (enter.keyCode === 13) {
283
- toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
284
- }
285
- })
286
- }
287
- }
288
-
289
- // Call function with jQuery scripts
290
- const callJquery = () => {
291
- // Toggle Button's Arrow Right Points Down on Click
292
- $('.arrow-right').on('click', function () {
293
- $(this).toggleClass('arrow-down');
294
- });
295
- // TOOLTIP
296
- // Allows Screen readers to toggle a tooltip on click and to say if the tooltip is collapsed or expanded.
297
- $(".tooltip").click(function () {
298
- $(this).children(".tip-hover").toggle();
299
- if ($(this).children(".tip-hover").is(':visible')) {
300
- $(this).attr('aria-expanded', 'true');
301
- $(this).removeClass('hidden');
302
- } else {
303
- $(this).attr('aria-expanded', 'false');
304
- $(this).addClass('hidden');
305
- }
306
- });
307
- let start = 999;
308
- $('.tooltip').each(function (i) {
309
- $(this).css('z-index', start--);
310
- });
311
- $(".tooltip .video-container").parent().css("width", "450px");
312
- }
313
- callJquery();
314
-
315
- // Fancybox
316
- if (document.querySelector(".fancybox")) {
317
- $("[data-fancybox]").fancybox({
318
- idleTime: false,
319
- topRatio: 0.1,
320
- helpers: {
321
- title: {
322
- type: 'inside'
323
- },
324
- }
325
- });
326
- }
1
+ /// @description Main JS file for PimaOnline Themepack
2
+ /// @dependencies jQuery 3.3.1 or later
3
+
4
+ window.addEventListener("DOMContentLoaded", () => {
5
+
6
+ const courseBody = document.querySelector("body");
7
+ const contentWrapper = document.querySelector("#content-wrapper");
8
+ const secondColumn = document.querySelector("#second-column");
9
+ const thirdColumn = document.querySelector("#third-column");
10
+ const columnWidget = document.querySelector("#column-widget");
11
+ const videoWrapper = document.querySelector("#video-wrapper");
12
+ const rolePres = document.querySelectorAll('[role="presentation"]');
13
+ const imageGallery = document.querySelector(".image-gallery");
14
+ const vocabListWidget = document.querySelector("dl.vocab-list");
15
+ const vocabTerms = document.querySelectorAll("dl.vocab-list dt");
16
+ const vocabDefs = document.querySelectorAll("dl.vocab-list dd");
17
+ const vocabCloseBtns = document.querySelectorAll("dl.vocab-list button");
18
+ const vocabLists = document.querySelectorAll("dl[class^='vocab-list']");
19
+ const mediaContainers = document.querySelectorAll(".media-container");
20
+ const tabsWidgets = document.querySelectorAll(".tabs");
21
+
22
+ // Grid
23
+ const addGrid = () => {
24
+ if (secondColumn && thirdColumn) {
25
+ courseBody.id = "three-column";
26
+ } else if (secondColumn && !columnWidget) {
27
+ courseBody.id = "two-column";
28
+ } else if (columnWidget) {
29
+ courseBody.id = "two-col-widget";
30
+ } else if (videoWrapper) {
31
+ courseBody.id = "video-grid";
32
+ } else {
33
+ courseBody.id = "one-column";
34
+ }
35
+ };
36
+ addGrid();
37
+
38
+ // JS to add role and aria-label to content-wrapper, second-column, and third-column
39
+ const addAria = () => {
40
+ contentWrapper.setAttribute("role", "main");
41
+ if (secondColumn) {
42
+ secondColumn.setAttribute("role", "region");
43
+ secondColumn.setAttribute("aria-label", "Second column");
44
+ }
45
+ if (thirdColumn) {
46
+ thirdColumn.setAttribute("role", "region");
47
+ thirdColumn.setAttribute("aria-label", "Third column");
48
+ }
49
+ };
50
+ addAria();
51
+
52
+ // Clean up HTML
53
+ const cleanMarkup = () => {
54
+ // Remove role="presentation" attr from any element that has it
55
+ if (rolePres) {
56
+ rolePres.forEach((roleElem) => roleElem.removeAttribute("role"));
57
+ }
58
+ // Set functino to remove atrributes from elements
59
+ const discardAttributes = (element, ...attributes) => {
60
+ attributes.forEach((attribute) => element.removeAttribute(attribute));
61
+ }
62
+ // Remove attributes from tables
63
+ const tableElems = document.querySelectorAll("table, thead, tbody, tr, th, td");
64
+ tableElems.forEach((elem) => {
65
+ discardAttributes(elem, "cellspacing", "cellpadding", "width", "style");
66
+ });
67
+ };
68
+ cleanMarkup();
69
+
70
+ // Helper JS for Responsive Tables
71
+ const initResponsiveTables = () => {
72
+ const tables = document.querySelectorAll(".display, .display-lg")
73
+ for (let table = 0; table < tables.length; table++) {
74
+ let headertext = [],
75
+ headers = tables[table].querySelectorAll(".display table th, table.display th, .display-lg table th, table.display-lg th"),
76
+ tablebody = tables[table].querySelector(".display table tbody, table.display tbody, .display-lg table tbody, table.display-lg tbody");
77
+ for (let header = 0; header < headers.length; header++) {
78
+ let current = headers[header];
79
+ headertext.push(current.textContent.replace(/\r?\n|\r/, ""));
80
+ }
81
+ for (let y = 0, row; row = tablebody.rows[y]; y++) {
82
+ for (let j = 0, col; col = row.cells[j]; j++) {
83
+ col.setAttribute("data-th", headertext[j]);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ initResponsiveTables();
89
+
90
+ // This is called by anchor links via onlick="" in the HTML
91
+ // Added because default anchor links don't work on all browsers using D2L
92
+ const addScript = (script) => {
93
+ let newScript = document.createElement("script");
94
+ newScript.setAttribute("src", script);
95
+
96
+ document.body.append(newScript);
97
+ }
98
+
99
+ if(document.querySelector("[onclick]")) {
100
+ addScript("https://cdn.jsdelivr.net/npm/@pimaonline/pimaonline-themepack/dist/js/jumpTo.js");
101
+ }
102
+
103
+ // Image gallery
104
+ const callImageGallery = () => {
105
+ // Create link element with font-awesome cdn and append it to the <head>
106
+ const docHead = document.querySelector("head");
107
+ const fontAwesomeCdn = document.createElement("link");
108
+ fontAwesomeCdn.setAttribute("rel", "stylesheet");
109
+ fontAwesomeCdn.setAttribute("href", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css");
110
+ docHead.appendChild(fontAwesomeCdn);
111
+ // Begin image gallery
112
+ const imgGalleries = document.querySelectorAll(".image-gallery"),
113
+ imgBoxes = document.querySelectorAll(".image-box"),
114
+ modalBoxContent = `<div class="modal-box invisible">
115
+ <div class="gallery-overlay"></div>
116
+ <figure class="modal-box--image"><i class="fa-solid fa-x close-img"></i> <img src="#" alt="image here" /><figcaption class="img-caption"></figcaption></figure>
117
+ </div>
118
+ <button class="hide-gallery">Hide</button>`;
119
+
120
+ // createModalBox.innerHTML = modalBoxContent;
121
+ for (let imgGallery = 0; imgGallery < imgGalleries.length; imgGallery++) {
122
+ imgGalleries[imgGallery].insertAdjacentHTML("afterbegin", modalBoxContent);
123
+ }
124
+
125
+ if (document.querySelector(".modal-box")) {
126
+ const overlay = document.querySelector(".gallery-overlay"),
127
+ modalBox = document.querySelector(".modal-box"),
128
+ modalImg = document.querySelector(".modal-box--image img"),
129
+ modalCaption = document.querySelector(".img-caption"),
130
+ closeImg = document.querySelector(".close-img");
131
+
132
+ for (let imgBox = 0; imgBox < imgBoxes.length; imgBox++) {
133
+ imgBoxes[imgBox].onclick = function () {
134
+ modalBox.classList.remove("invisible");
135
+ let imgSrc = this.querySelector("img").src;
136
+ modalImg.src = imgSrc;
137
+ let imgCaption = this.querySelector("img").alt;
138
+ modalCaption.innerHTML = imgCaption;
139
+ }
140
+ }
141
+ overlay.onclick = () => {
142
+ modalBox.classList.add("invisible");
143
+ }
144
+ window.onkeydown = (esc) => {
145
+ if (esc.keyCode === 27) {
146
+ modalBox.classList.add("invisible");
147
+ }
148
+ }
149
+ closeImg.onclick = () => {
150
+ modalBox.classList.add("invisible");
151
+ }
152
+ const hideGalleries = document.querySelectorAll(".hide-gallery");
153
+ for (let hideGallery = 0; hideGallery < hideGalleries.length; hideGallery++) {
154
+ hideGalleries[hideGallery].addEventListener("click", () => {
155
+ hideGalleries[hideGallery].nextElementSibling.classList.toggle("invisible");
156
+ if (hideGalleries[hideGallery].innerHTML === "Hide") {
157
+ hideGalleries[hideGallery].innerHTML = "Show";
158
+ } else {
159
+ hideGalleries[hideGallery].innerHTML = "Hide";
160
+ }
161
+ });
162
+ }
163
+ };
164
+ }
165
+ if (imageGallery) {
166
+ callImageGallery();
167
+ }
168
+
169
+ // Vocab list widget
170
+ const callVocabList = () => {
171
+ if (vocabCloseBtns) {
172
+ for(let btn = 0; btn < vocabCloseBtns.length; btn++) {
173
+ vocabCloseBtns[btn].addEventListener("click", () => {
174
+ for(let node = 0; node < vocabLists[btn].children.length;node++) {
175
+ if(vocabLists[btn].children[node].tagName == "DD") {
176
+ vocabLists[btn].children[node].removeAttribute("style");
177
+ }
178
+ if(vocabLists[btn].children[node].tagName == "DT") {
179
+ vocabLists[btn].children[node].removeAttribute("class");
180
+ }
181
+ }});
182
+ }
183
+ }
184
+ for (let activeTerm = 0; activeTerm < vocabTerms.length; activeTerm++) {
185
+ vocabTerms[activeTerm].addEventListener("click", function() {
186
+ this.classList.toggle("active");
187
+ let termPanel = this.nextElementSibling;
188
+ if (termPanel.style.display === "block") { termPanel.removeAttribute("style"); }
189
+ else { termPanel.style.display = "block"; }
190
+ });
191
+
192
+ vocabTerms[activeTerm].addEventListener("keydown", function(e) {
193
+ if(e.key === "Enter") {
194
+ this.classList.toggle("active");
195
+ let termPanel = this.nextElementSibling;
196
+ if (termPanel.style.display === "block") { termPanel.removeAttribute("style"); }
197
+ else { termPanel.style.display = "block"; }
198
+ }
199
+ });
200
+ }
201
+ }
202
+ if (vocabListWidget) {callVocabList();}
203
+
204
+ //
205
+ const addMediaContainersAria = () => {
206
+ mediaContainers.forEach((eachContainer, index) => {
207
+ // loopID: find the current index value, convert it to its letter equivalent, then convert to lowercase
208
+ let loopId = String.fromCharCode(index + 65).toLowerCase();
209
+ let mediaObject = eachContainer.querySelector(".media-object");
210
+ let iframe = mediaObject.firstElementChild;
211
+ let mediaInfo = mediaObject.nextElementSibling;
212
+
213
+ // If element DOES NOT have "aria-describedby" && it DOES have a sibling element.
214
+ if (!iframe.hasAttribute("aria-describedby") && mediaInfo != null) {
215
+ iframe.setAttribute("aria-describedby", `${loopId}`);
216
+ mediaInfo.id = `${[loopId]}`;
217
+ }
218
+ });
219
+ }
220
+ if (mediaContainers) {addMediaContainersAria();}
221
+
222
+ //Tabs Widget
223
+ const callTabsWidget = () => {
224
+
225
+ let tabsWidgetsNum = 0;
226
+
227
+ tabsWidgets.forEach((tab,index) => {
228
+ let tabInputs = tab.querySelectorAll("input")
229
+ let tabLabels = tab.querySelectorAll("label")
230
+ let tabDivs = tab.querySelectorAll("div")
231
+
232
+ let groupNum = index + 1;
233
+
234
+ //Add region and aria-label to parent div
235
+ tab.setAttribute("role", "region");
236
+ tab.setAttribute("aria-label", `tab group ${groupNum}`)
237
+
238
+ for(tabIndex = 0; tabIndex < tabInputs.length; tabIndex++) {
239
+
240
+ let tabNum = tabsWidgetsNum + 1;
241
+
242
+ //Add class, id, name, and aria-described by for inputs
243
+ tabInputs[tabIndex].classList.add("tab-input");
244
+ tabInputs[tabIndex].setAttribute("type", "radio")
245
+ tabInputs[tabIndex].setAttribute("id", `tab${tabNum}`);
246
+ tabInputs[tabIndex].setAttribute("name", `hint-group-${groupNum}` )
247
+ tabInputs[tabIndex].setAttribute("aria-describedby", `tabHeading${tabNum}`)
248
+ //Add class and for for labels
249
+ tabLabels[tabIndex].classList.add("tab-header");
250
+ tabLabels[tabIndex].setAttribute("for", `tab${tabNum}`)
251
+ //Add class, tabindex, and id for divs
252
+ tabDivs[tabIndex].classList.add("tab-panel")
253
+ tabDivs[tabIndex].setAttribute("tabindex", 0)
254
+ tabDivs[tabIndex].setAttribute("id", `tabHeading${tabNum}`)
255
+ //Add attributes for hide tab
256
+ if(tabIndex + 1 == tabInputs.length) {
257
+ tabLabels[tabIndex].classList.add("hide-tab")
258
+ tabInputs[tabIndex].checked = true;
259
+ tabDivs[tabIndex].classList.add("hide-panel")
260
+ }
261
+ tabsWidgetsNum++;
262
+ }
263
+ })
264
+ }
265
+ if (tabsWidgets) {callTabsWidget();}
266
+
267
+ // Toggle footnotes
268
+ const toggleBtns = document.querySelectorAll(".toggle-btn, .toggle-footnotes");
269
+
270
+ if (document.querySelector(".toggle-btn") || document.querySelector(".toggle-footnotes")) {
271
+ for (let toggleBtn = 0; toggleBtn < toggleBtns.length; toggleBtn++) {
272
+ // Add tabindex
273
+ toggleBtns[toggleBtn].setAttribute("tabindex", "0");
274
+
275
+ // Show/hide on click
276
+ toggleBtns[toggleBtn].addEventListener("click", () => {
277
+ toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
278
+ })
279
+
280
+ // Show/hide on enter for users who use tab
281
+ toggleBtns[toggleBtn].addEventListener("keydown", (enter) => {
282
+ if (enter.keyCode === 13) {
283
+ toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
284
+ }
285
+ })
286
+ }
287
+ }
288
+
289
+ // Call function with jQuery scripts
290
+ const callJquery = () => {
291
+ // Toggle Button's Arrow Right Points Down on Click
292
+ $('.arrow-right').on('click', function () {
293
+ $(this).toggleClass('arrow-down');
294
+ });
295
+ // TOOLTIP
296
+ // Allows Screen readers to toggle a tooltip on click and to say if the tooltip is collapsed or expanded.
297
+ $(".tooltip").click(function () {
298
+ $(this).children(".tip-hover").toggle();
299
+ if ($(this).children(".tip-hover").is(':visible')) {
300
+ $(this).attr('aria-expanded', 'true');
301
+ $(this).removeClass('hidden');
302
+ } else {
303
+ $(this).attr('aria-expanded', 'false');
304
+ $(this).addClass('hidden');
305
+ }
306
+ });
307
+ let start = 999;
308
+ $('.tooltip').each(function (i) {
309
+ $(this).css('z-index', start--);
310
+ });
311
+ $(".tooltip .video-container").parent().css("width", "450px");
312
+ }
313
+ callJquery();
314
+
315
+ // Fancybox
316
+ if (document.querySelector(".fancybox")) {
317
+ $("[data-fancybox]").fancybox({
318
+ idleTime: false,
319
+ topRatio: 0.1,
320
+ helpers: {
321
+ title: {
322
+ type: 'inside'
323
+ },
324
+ }
325
+ });
326
+ }
327
327
  });