@pimaonline/pimaonline-themepack 3.10.13 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. package/README.md +12 -23
  2. package/dist/css/main.css +1 -1
  3. package/dist/css/plugins/alt-icons.css +1 -1
  4. package/dist/css/plugins/font-awesome.css +1 -1
  5. package/dist/css/routes.css +1 -1
  6. package/dist/css/themes/ait/styles.css +1 -1
  7. package/dist/css/themes/ajs/styles.css +1 -1
  8. package/dist/css/themes/ant/styles.css +1 -0
  9. package/dist/css/themes/art/styles.css +1 -1
  10. package/dist/css/themes/aviation/styles.css +1 -1
  11. package/dist/css/themes/bct/styles.css +1 -1
  12. package/dist/css/themes/bio/styles.css +1 -1
  13. package/dist/css/themes/business/styles.css +1 -1
  14. package/dist/css/themes/cad/styles.css +1 -1
  15. package/dist/css/themes/cards/styles.css +1 -1
  16. package/dist/css/themes/cas/styles.css +1 -0
  17. package/dist/css/themes/cda/styles.css +1 -1
  18. package/dist/css/themes/chm/styles.css +1 -0
  19. package/dist/css/themes/cis/styles.css +1 -1
  20. package/dist/css/themes/communication/styles.css +1 -1
  21. package/dist/css/themes/computer-information-systems/styles.css +1 -1
  22. package/dist/css/themes/culinary/styles.css +1 -1
  23. package/dist/css/themes/culinary/versions/black-marble.css +1 -1
  24. package/dist/css/themes/culinary/versions/stainless.css +1 -1
  25. package/dist/css/themes/culinary/versions/wood.css +1 -1
  26. package/dist/css/themes/dental/styles.css +1 -1
  27. package/dist/css/themes/ece/styles.css +1 -1
  28. package/dist/css/themes/ecn/styles.css +1 -1
  29. package/dist/css/themes/eng/styles.css +1 -1
  30. package/dist/css/themes/fashion/styles.css +1 -1
  31. package/dist/css/themes/fitness/styles.css +1 -1
  32. package/dist/css/themes/fsc/styles.css +1 -1
  33. package/dist/css/themes/geography/styles.css +1 -1
  34. package/dist/css/themes/geology/styles.css +1 -1
  35. package/dist/css/themes/health-it/styles.css +1 -1
  36. package/dist/css/themes/history/styles.css +1 -1
  37. package/dist/css/themes/hrm/styles.css +1 -1
  38. package/dist/css/themes/hrs/styles.css +1 -1
  39. package/dist/css/themes/journalism/styles.css +1 -1
  40. package/dist/css/themes/lang/styles.css +1 -1
  41. package/dist/css/themes/lgm/styles.css +1 -1
  42. package/dist/css/themes/machine/styles.css +1 -1
  43. package/dist/css/themes/math/styles.css +1 -1
  44. package/dist/css/themes/mgt/styles.css +1 -1
  45. package/dist/css/themes/minimalist/styles.css +1 -1
  46. package/dist/css/themes/mkt/styles.css +1 -0
  47. package/dist/css/themes/music/styles.css +1 -1
  48. package/dist/css/themes/nursing/styles.css +1 -0
  49. package/dist/css/themes/philosophy/styles.css +1 -1
  50. package/dist/css/themes/pht/styles.css +1 -1
  51. package/dist/css/themes/phy/styles.css +1 -0
  52. package/dist/css/themes/pos/styles.css +1 -0
  53. package/dist/css/themes/psy/styles.css +1 -1
  54. package/dist/css/themes/reading/styles.css +1 -0
  55. package/dist/css/themes/resort/styles.css +1 -1
  56. package/dist/css/themes/soc/styles.css +1 -1
  57. package/dist/css/themes/ss/styles.css +1 -1
  58. package/dist/css/themes/tps/styles.css +1 -0
  59. package/dist/css/themes/university/styles.css +1 -1
  60. package/dist/css/themes/vet/styles.css +1 -1
  61. package/dist/css/themes/welding/styles.css +1 -1
  62. package/dist/css/themes/writing/styles.css +1 -1
  63. package/dist/img/general/arrow-right-black.svg +1 -0
  64. package/dist/img/general/arrow-right-primary-blue.svg +1 -0
  65. package/dist/img/general/arrow-right-white.svg +1 -0
  66. package/dist/img/theme-images/ant/texture.png +0 -0
  67. package/dist/img/theme-images/cas/city-vector.svg +92 -0
  68. package/dist/img/theme-images/cas/farm-vector.svg +1 -0
  69. package/dist/img/theme-images/cas/ocean-vector.svg +1 -0
  70. package/dist/img/theme-images/cas/recycle-symbol.svg +1 -0
  71. package/dist/img/theme-images/chm/chem-letters/letter-a.png +0 -0
  72. package/dist/img/theme-images/chm/chem-letters/letter-b.png +0 -0
  73. package/dist/img/theme-images/chm/chem-letters/letter-c.png +0 -0
  74. package/dist/img/theme-images/chm/chem-letters/letter-d.png +0 -0
  75. package/dist/img/theme-images/chm/chem-letters/letter-e.png +0 -0
  76. package/dist/img/theme-images/chm/chem-letters/letter-f.png +0 -0
  77. package/dist/img/theme-images/chm/chem-letters/letter-g.png +0 -0
  78. package/dist/img/theme-images/chm/chem-letters/letter-h.png +0 -0
  79. package/dist/img/theme-images/chm/chem-letters/letter-i.png +0 -0
  80. package/dist/img/theme-images/chm/chem-letters/letter-j.png +0 -0
  81. package/dist/img/theme-images/chm/chem-letters/letter-k.png +0 -0
  82. package/dist/img/theme-images/chm/chem-letters/letter-l.png +0 -0
  83. package/dist/img/theme-images/chm/chem-letters/letter-m.png +0 -0
  84. package/dist/img/theme-images/chm/chem-letters/letter-n.png +0 -0
  85. package/dist/img/theme-images/chm/chem-letters/letter-o.png +0 -0
  86. package/dist/img/theme-images/chm/chem-letters/letter-p.png +0 -0
  87. package/dist/img/theme-images/chm/chem-letters/letter-q.png +0 -0
  88. package/dist/img/theme-images/chm/chem-letters/letter-r.png +0 -0
  89. package/dist/img/theme-images/chm/chem-letters/letter-s.png +0 -0
  90. package/dist/img/theme-images/chm/chem-letters/letter-t.png +0 -0
  91. package/dist/img/theme-images/chm/chem-letters/letter-u.png +0 -0
  92. package/dist/img/theme-images/chm/chem-letters/letter-v.png +0 -0
  93. package/dist/img/theme-images/chm/chem-letters/letter-w.png +0 -0
  94. package/dist/img/theme-images/chm/chem-letters/letter-x.png +0 -0
  95. package/dist/img/theme-images/chm/chem-letters/letter-y.png +0 -0
  96. package/dist/img/theme-images/chm/chem-letters/letter-z.png +0 -0
  97. package/dist/img/theme-images/mkt/blue/bluebars.svg +36 -0
  98. package/dist/img/theme-images/mkt/blue/blueheader.jpg +0 -0
  99. package/dist/img/theme-images/mkt/blue/bluepie.svg +42 -0
  100. package/dist/img/theme-images/mkt/green/greenbars.svg +36 -0
  101. package/dist/img/theme-images/mkt/green/greenheader.jpg +0 -0
  102. package/dist/img/theme-images/mkt/green/greenpie.svg +42 -0
  103. package/dist/img/theme-images/mkt/yellow/yellowbars.svg +36 -0
  104. package/dist/img/theme-images/mkt/yellow/yellowheader.jpg +0 -0
  105. package/dist/img/theme-images/mkt/yellow/yellowpie.svg +42 -0
  106. package/dist/img/theme-images/nursing/blue/bottomright-blue.svg +95 -0
  107. package/dist/img/theme-images/nursing/blue/topleft-blue.svg +111 -0
  108. package/dist/img/theme-images/nursing/green/bottomright-green.svg +95 -0
  109. package/dist/img/theme-images/nursing/green/topleft-green.svg +111 -0
  110. package/dist/img/theme-images/nursing/purple/bottomright-purple.svg +95 -0
  111. package/dist/img/theme-images/nursing/purple/topleft-purple.svg +111 -0
  112. package/dist/img/theme-images/nursing/teal/bottomright-teal.svg +95 -0
  113. package/dist/img/theme-images/nursing/teal/topleft-teal.svg +111 -0
  114. package/dist/img/theme-images/phy/background.svg +150 -0
  115. package/dist/img/theme-images/phy/tape-style1.svg +8 -0
  116. package/dist/img/theme-images/reading/bg10.jpg +0 -0
  117. package/dist/js/scripts2.js +1 -1018
  118. package/dist/js/themes/cas.js +1 -0
  119. package/dist/js/themes/chm.js +1 -0
  120. package/dist/js/themes/ecn.js +1 -13
  121. package/dist/js/themes/hrs.js +1 -19
  122. package/dist/js/themes/ss.js +1 -197
  123. package/dist/plugins/fancybox/fancybox-example.html +1 -1
  124. package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.js +2 -122
  125. package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.js.LICENSE.txt +15 -0
  126. package/dist/plugins/fancybox/helpers/jquery.fancybox-media.js +2 -201
  127. package/dist/plugins/fancybox/helpers/jquery.fancybox-media.js.LICENSE.txt +64 -0
  128. package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.js +2 -165
  129. package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.js.LICENSE.txt +16 -0
  130. package/dist/plugins/fancybox/jquery.fancybox.js +2 -2018
  131. package/dist/plugins/fancybox/jquery.fancybox.js.LICENSE.txt +11 -0
  132. package/dist/plugins/fancybox/jquery.fancybox.pack.js +2 -46
  133. package/dist/plugins/fancybox/jquery.fancybox.pack.js.LICENSE.txt +1 -0
  134. package/dist/plugins/flashcards/flashcards-example.html +1 -1
  135. package/dist/plugins/flashcards/js/flash_cards.min.js +1 -12
  136. package/dist/plugins/flashcards/js/plugins/flash_cards.js +1 -62
  137. package/dist/plugins/flashcards/js/plugins/jquery.cycle.js +2 -1148
  138. package/dist/plugins/flashcards/js/plugins/jquery.cycle.js.LICENSE.txt +20 -0
  139. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.js +2 -9404
  140. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.js.LICENSE.txt +22 -0
  141. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.min.js +2 -4
  142. package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.min.js.LICENSE.txt +1 -0
  143. package/dist/plugins/flashcards/js/vendor/modernizr-2.5.3.min.js +1 -4
  144. package/dist/plugins/floating-particles/floating-particles.js +1 -68
  145. package/dist/plugins/global-homepage-overrides/global-homepage-overrides.js +1 -53
  146. package/dist/plugins/preview-banner/preview-banner.js +1 -57
  147. package/package.json +22 -11
  148. package/dist/js/jumpTo.js +0 -4
  149. package/dist/js/scripts.js +0 -327
@@ -1,1018 +1 @@
1
- const columnWidget = document.querySelector("#column-widget");
2
- const contentLockInstructions = document.querySelectorAll(".instructions");
3
- const contentUnlockBtns = document.querySelectorAll(".unlock-btn");
4
- const contentWrapper = document.querySelector("#content-wrapper");
5
- const courseBody = document.querySelector("body");
6
- const docHead = document.querySelector("head");
7
- const flipCards = document.querySelectorAll(".flip-card-group");
8
- const focusReaderTooltipText = "Highlight text as you scroll";
9
- const galleryWrappers = document.querySelectorAll(".gallery-wrapper");
10
- const h5pIframes = document.querySelectorAll("iframe");
11
- const h5pResizer = document.createElement("script");
12
- const h5pResizerExists = docHead.querySelector("script[src='https://pima.h5p.com/js/h5p-resizer.js']");
13
- // This array contains CDNs for Bootstrap and Remix icon libraries stored as objects
14
- const iconClasses = [
15
- { class: "bi-", cdn: "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" },
16
- { class: "ri-", cdn: "https://cdn.jsdelivr.net/npm/remixicon@4.0.1/fonts/remixicon.css" }
17
- ];
18
- const imageGallery = document.querySelector(".image-gallery");
19
- const imgBoxes = document.querySelectorAll(".image-box");
20
- const imgGalleries = document.querySelectorAll(".image-gallery");
21
- const lockedContent = document.querySelectorAll(".locked-content");
22
- const mediaContainers = document.querySelectorAll(".media-container");
23
- const rolePres = document.querySelectorAll('[role="presentation"]');
24
- const secondColumn = document.querySelector("#second-column");
25
- const tables = document.querySelectorAll(".display, .display-lg")
26
- const tabsWidgets = document.querySelectorAll(".tabs");
27
- const thirdColumn = document.querySelector("#third-column");
28
- const vocabCloseBtns = document.querySelectorAll("dl.vocab-list button");
29
- const vocabDefs = document.querySelectorAll("dl.vocab-list dd");
30
- const vocabListWidget = document.querySelector("dl.vocab-list");
31
- const vocabLists = document.querySelectorAll("dl[class^='vocab-list']");
32
- const vocabTerms = document.querySelectorAll("dl.vocab-list dt");
33
- const videoWrapper = document.querySelector("#video-wrapper");
34
- // JS to add role and aria-label to content-wrapper, second-column, and third-column
35
- const addAria = () => {
36
- if (contentWrapper) {
37
- contentWrapper.setAttribute("role", "main");
38
- } else if (!contentWrapper) {
39
- console.log("Document error: does not contain #content-wrapper.");
40
- }
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
- const addGrid = () => {
52
- if (contentWrapper && secondColumn && thirdColumn) {
53
- courseBody.id = "three-column";
54
- } else if (contentWrapper && secondColumn && !columnWidget) {
55
- courseBody.id = "two-column";
56
- } else if (contentWrapper && secondColumn && columnWidget) {
57
- courseBody.id = "two-col-widget";
58
- } else if ((contentWrapper && videoWrapper)) {
59
- courseBody.id = "video-grid";
60
- } else if (contentWrapper && !secondColumn && !thirdColumn && !columnWidget && !videoWrapper) {
61
- courseBody.id = "one-column";
62
- } else if (contentWrapper && !secondColumn && (thirdColumn || columnWidget)) {
63
- console.log("Document error: <body> is missing id because #second-column doesn't exist.");
64
- } else {
65
- console.log("Document error: unable to determine the page layout for setting <body> id.");
66
- }
67
-
68
- const topLevelElements = document.body.children;
69
- let foundNestedElement = false;
70
-
71
- // Check for additional content outside #content-wrapper, #second-column, #third-column, or footer
72
- for (let i = 0; i < topLevelElements.length; i++) {
73
- const element = topLevelElements[i];
74
-
75
- if (
76
- element.id !== "content-wrapper" &&
77
- element.id !== "second-column" &&
78
- element.id !== "third-column" &&
79
- element.id !== "column-widget" &&
80
- element.tagName !== "HEADER" &&
81
- element.tagName !== "FOOTER" &&
82
- element.tagName !== "SCRIPT" &&
83
- element.id !== "loom-companion-mv3" &&
84
- element.className !== "focus-reader-switches"
85
- ) {
86
- foundNestedElement = true;
87
- break;
88
- }
89
- }
90
-
91
- if (foundNestedElement) {
92
- console.log("Document error: Additional content outside #content-wrapper, #second-column, #third-column, or footer.");
93
- }
94
- };
95
- addGrid();
96
- // Media Container
97
- const addMediaContainersAria = () => {
98
- mediaContainers.forEach((eachContainer, index) => {
99
- // loopID: find the current index value, convert it to its letter equivalent, then convert to lowercase
100
- let loopId = String.fromCharCode(index + 65).toLowerCase();
101
- let mediaObject = eachContainer.querySelector(".media-object");
102
- let iframe = eachContainer.querySelector("iframe");
103
- let mediaInfo = eachContainer.querySelector(".media-info");
104
-
105
- // Check if media container items are present
106
- if (!iframe) {
107
- console.log("Document error: no iframe found for media container");
108
- }
109
- if (!mediaObject) {
110
- console.log("Document error: no media object found for media container");
111
- }
112
-
113
- // If element DOES NOT have "aria-describedby" && it DOES have a sibling element.
114
- if (!iframe.hasAttribute("aria-describedby") && mediaInfo != null) {
115
- iframe.setAttribute("aria-describedby", `${loopId}`);
116
- mediaInfo.id = `${[loopId]}`;
117
- }
118
- });
119
- }
120
- if (mediaContainers) { addMediaContainersAria(); }
121
- // -------- Add CDNs for Bootstrap and Remix icon libraries ---------
122
-
123
- // The respective CDN will be added to <head> only if a page contains an icon with a prefix specific to that library. We use forEach to loop through iconClasses because that's more efficient than using multiple if statements to make sure only the necessary CDNs are added.
124
-
125
- iconClasses.forEach(icon => {
126
- const iconElement = document.querySelector(`[class*='${icon.class}']`);
127
- if (iconElement) {
128
- const metaTagRef = docHead.querySelector("meta[name='viewport']");
129
- //Check if viewport meta tag exists
130
- if (!metaTagRef) {
131
- console.log("Document error: could not find viewport meta tag");
132
- }
133
-
134
- const iconCDN = document.createElement("link");
135
- iconCDN.setAttribute("href", icon.cdn);
136
- iconCDN.setAttribute("rel", "stylesheet");
137
-
138
- // Stylesheets are added after meta tag and before themepack stylesheets and scripts to ensure proper styling override
139
- docHead.insertBefore(iconCDN, metaTagRef.nextSibling);
140
- }
141
- });
142
- // Check if parent of .gallery-wrapper has .image-gallery class
143
- const checkGalleryWrapperParent = () => {
144
- galleryWrappers.forEach((galleryWrapper) => {
145
- if (!galleryWrapper.parentNode.classList.contains("image-gallery")) {
146
- console.log(`Document error: parent of .gallery-wrapper does not have the .image-gallery class.`);
147
- }
148
- });
149
- };
150
- checkGalleryWrapperParent();
151
-
152
- // Check if parent of .image-box has .gallery-wrapper class
153
- const checkImageBoxParent = () => {
154
- imgBoxes.forEach((imgBox) => {
155
- if (!imgBox.parentNode.classList.contains("gallery-wrapper")) {
156
- console.log(`Document error: parent of .image-box does not have the .gallery-wrapper class.`);
157
- }
158
- });
159
- };
160
- checkImageBoxParent();
161
-
162
- // Check if direct children of .gallery-wrapper have .image-box class
163
- const checkGalleryWrapperChildren = () => {
164
- galleryWrappers.forEach((galleryWrapper) => {
165
- let directChildren = Array.from(galleryWrapper.children).every(child => child.classList.contains("image-box"));
166
-
167
- if (!directChildren) {
168
- console.log(`Document error: not all direct children of .gallery-wrapper have the .image-box class.`);
169
- }
170
- });
171
- };
172
- checkGalleryWrapperChildren();
173
-
174
- // Function to add Font Awesome CDN to the head
175
- const addFontAwesomeCdn = () => {
176
- const fontAwesomeCdn = document.createElement("link");
177
- fontAwesomeCdn.rel = "stylesheet";
178
- fontAwesomeCdn.href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css";
179
- docHead.appendChild(fontAwesomeCdn);
180
- };
181
-
182
- // Function to create modal box HTML string
183
- const createModalBox = () => {
184
- return `<div class="modal-box invisible">
185
- <div class="gallery-overlay"></div>
186
- <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>
187
- </div>
188
- <button class="hide-gallery">Hide</button>`;
189
- };
190
-
191
- // Function to initialize the image gallery
192
- const callImageGallery = () => {
193
- // Insert modal box HTML at the beginning of each image gallery
194
- imgGalleries.forEach((gallery) => {
195
- gallery.insertAdjacentHTML("afterbegin", createModalBox());
196
- });
197
-
198
- // Select necessary elements for later use
199
- const overlay = document.querySelector(".gallery-overlay"),
200
- modalBox = document.querySelector(".modal-box"),
201
- modalImg = document.querySelector(".modal-box--image img"),
202
- modalCaption = document.querySelector(".img-caption"),
203
- closeImg = document.querySelector(".close-img"),
204
- hideGalleries = document.querySelectorAll(".hide-gallery");
205
-
206
- // Function to show modal with specified image source and caption
207
- const showModal = (imgSrc, imgCaption) => {
208
- modalBox.classList.remove("invisible");
209
- modalImg.src = imgSrc;
210
- modalCaption.innerHTML = imgCaption;
211
- };
212
-
213
- // Function to hide the modal
214
- const hideModal = () => {
215
- modalBox.classList.add("invisible");
216
- };
217
-
218
- // Attach event listeners to each image box
219
- imgBoxes.forEach((imgBox) => {
220
- // Show modal on click
221
- imgBox.addEventListener("click", function () {
222
- showModal(this.querySelector("img").src, this.querySelector("img").alt);
223
- });
224
-
225
- // Make images tab-able and show modal on Enter key press
226
- imgBox.setAttribute("tabindex", "0");
227
- imgBox.addEventListener("keydown", function (event) {
228
- if (event.key === "Enter") {
229
- showModal(this.querySelector("img").src, this.querySelector("img").alt);
230
- }
231
- });
232
- });
233
-
234
- // Attach event listeners for overlay, Escape key, and close button to hide the modal
235
- overlay.onclick = hideModal;
236
- window.onkeydown = (event) => {
237
- if (event.keyCode === 27) {
238
- hideModal();
239
- }
240
- };
241
- closeImg.onclick = hideModal;
242
-
243
- // Attach event listeners for "Hide/Show" button to toggle gallery visibility
244
- hideGalleries.forEach((hideGallery) => {
245
- hideGallery.addEventListener("click", () => {
246
- hideGallery.nextElementSibling.classList.toggle("invisible");
247
- hideGallery.innerHTML = hideGallery.innerHTML === "Hide" ? "Show" : "Hide";
248
- });
249
- });
250
- };
251
-
252
- // Check if imageGallery exists before initializing the image gallery
253
- if (imageGallery) {
254
- // Add Font Awesome CDN and initialize the image gallery
255
- addFontAwesomeCdn();
256
- callImageGallery();
257
- }
258
- //Tabs Widget
259
- const callTabsWidget = () => {
260
-
261
- let tabsWidgetsNum = 0;
262
-
263
- tabsWidgets.forEach((tab, index) => {
264
- let tabInputs = tab.querySelectorAll("input");
265
- let tabLabels = tab.querySelectorAll("label");
266
- let tabDivs = tab.querySelectorAll("div");
267
-
268
- //Check that there are more than just one tab
269
- if (tabInputs.length < 2 || tabLabels.length < 2 || tabDivs.length < 2) {
270
- console.log("Document error: please add more than just one tab for tabs widget");
271
- }
272
-
273
- // Check amount of tab elements present
274
- if (tabInputs.length < tabLabels.length || tabInputs.length < tabDivs.length) {
275
- console.log("Document error: missing tab input(s) in tab widget");
276
- }
277
-
278
- if (tabLabels.length < tabInputs.length || tabLabels.length < tabDivs.length) {
279
- console.log("Document error: missing tab label(s) in tab widget");
280
- }
281
-
282
- let groupNum = index + 1;
283
-
284
- //Add region and aria-label to parent div
285
- tab.setAttribute("role", "region");
286
- tab.setAttribute("aria-label", `tab group ${groupNum}`)
287
-
288
- for (tabIndex = 0; tabIndex < tabInputs.length; tabIndex++) {
289
-
290
- let tabNum = tabsWidgetsNum + 1;
291
-
292
- // Check on present variables
293
- if (tabInputs == null) {
294
- console.log("Document error: no inputs found for tabs widget");
295
- }
296
-
297
- if (tabLabels == null) {
298
- console.log("Document error: no labels found for tabs widget");
299
- }
300
-
301
- if (tabInputs == null) {
302
- console.log("Document error: no divs (tab panels) found for tabs widget");
303
- }
304
-
305
- //Add class, id, name, and aria-described by for inputs
306
- tabInputs[tabIndex].classList.add("tab-input");
307
- tabInputs[tabIndex].setAttribute("type", "radio")
308
- tabInputs[tabIndex].setAttribute("id", `tab${tabNum}`);
309
- tabInputs[tabIndex].setAttribute("name", `hint-group-${groupNum}`);
310
- tabInputs[tabIndex].setAttribute("aria-describedby", `tabHeading${tabNum}`);
311
-
312
- //Add class and for for labels
313
- tabLabels[tabIndex].classList.add("tab-header");
314
- tabLabels[tabIndex].setAttribute("for", `tab${tabNum}`);
315
-
316
- //Add class, tabindex, and id for divs
317
- if (tabDivs[tabIndex]) {
318
- tabDivs[tabIndex].classList.add("tab-panel");
319
- tabDivs[tabIndex].setAttribute("tabindex", 0);
320
- tabDivs[tabIndex].setAttribute("id", `tabHeading${tabNum}`);
321
- }
322
-
323
- //Add attributes for hide tab
324
- if (tabIndex + 1 == tabInputs.length) {
325
- tabLabels[tabIndex].classList.add("hide-tab");
326
- tabInputs[tabIndex].checked = true;
327
- if (tabDivs[tabIndex]) {
328
- tabDivs[tabIndex].classList.add("hide-panel");
329
- }
330
- }
331
- tabsWidgetsNum++;
332
- }
333
- })
334
- }
335
- if (tabsWidgets) { callTabsWidget(); }
336
- // Vocab list widget
337
- const callVocabList = () => {
338
-
339
- const handleVocabClose = (vocabItem) => {
340
- if (vocabItem) {
341
- let listDefinitions = vocabItem.querySelectorAll("dd");
342
- let listTerms = vocabItem.querySelectorAll("dt");
343
-
344
- // If the button is clicked and it is the DD - then hide it
345
- listDefinitions.forEach((definition) => {
346
- definition.style.display = "none";
347
- })
348
-
349
- // If the button is clicked and it is the DT - then remove active class
350
- listTerms.forEach((term) => {
351
- term.classList.remove("active");
352
- })
353
- }
354
- }
355
-
356
- // Check if the vocab list has one or multiple items within
357
- vocabLists.forEach((list) => {
358
-
359
- //Count and ensure it has more than 1 term and definition
360
- let terms = 0;
361
- let definitions = 0;
362
- let closeBtnPresent = false;
363
-
364
- // If the list contains more than one set of <dt> and <dd> tags then add a close button
365
- for (let listIndex = 0; listIndex < list.children.length; listIndex++) {
366
- // Count terms
367
- if (list.children[listIndex].tagName == "DT") {
368
- list.children[listIndex].setAttribute("tabindex", "0");
369
- terms++;
370
- }
371
- // Count definitions
372
- if (list.children[listIndex].tagName == "DD") {
373
- definitions++;
374
- }
375
-
376
- //Check for close all button
377
- if (list.children[listIndex].tagName == "BUTTON") {
378
- closeBtnPresent = true;
379
- }
380
- }
381
-
382
- // Check for terms and definitions in the vocab list
383
- if (terms < 1) {
384
- console.log("Document error: no terms found in vocab list");
385
- }
386
-
387
- if (definitions < 1) {
388
- console.log("Document error: no definitions found in vocab list");
389
- }
390
-
391
- if (terms > definitions) {
392
- console.log("Document error: more terms than definitions in vocab list")
393
- }
394
-
395
- // If there are more than 2 terms and 2 definitions, then check for a button
396
- if (terms >= 2 && definitions >= 2) {
397
-
398
- // If there isn't a close button then add one
399
- if (!closeBtnPresent) {
400
- // Add a close button
401
- const closeButton = document.createElement("button");
402
- closeButton.textContent = "Close All"; // Set the button text as needed
403
- // Add click event listener for button
404
- closeButton.addEventListener("click", () => handleVocabClose(list))
405
-
406
- // Add keydown event listener for button
407
- closeButton.addEventListener("keydown", (event) => {
408
- if (event.key == "Enter") {
409
- handleVocabClose(list);
410
- }
411
- })
412
- // Append the button to the end of the list
413
- list.appendChild(closeButton);
414
- }
415
- // If button is present, remove it
416
- else {
417
- let closeBtn = list.querySelector("button");
418
-
419
- // Add the same event listeners as if you were to add a new button
420
- closeBtn.addEventListener("click", () => handleVocabClose(list))
421
-
422
- closeBtn.addEventListener("keydown", (event) => {
423
- if (event.key == "Enter") {
424
- handleVocabClose(list);
425
- }
426
- })
427
-
428
- }
429
- } else {
430
-
431
- // List does not have more than 2 pairs of terms and definitions
432
-
433
- // Don't add a close button since there is only one term, but remove the button if it is present
434
- for (let listIndex = 0; listIndex < list.children.length; listIndex++) {
435
-
436
- //Check for close all button
437
- if (list.children[listIndex].tagName == "BUTTON") {
438
- closeBtnPresent = true;
439
- }
440
- }
441
-
442
- if (closeBtnPresent) {
443
- let closeBtn = list.querySelector("button");
444
- closeBtn.style.display = "none";
445
- }
446
- }
447
- })
448
-
449
- // Loop through all the terms and apply click and keydown event
450
- for (let activeTerm = 0; activeTerm < vocabTerms.length; activeTerm++) {
451
- // Add click event for toggling vocab terms
452
- vocabTerms[activeTerm].addEventListener("click", function () {
453
- // When clicked, toggle the active class
454
- this.classList.toggle("active");
455
-
456
- // Target the definition <dd> element
457
- let termPanel = this.nextElementSibling;
458
-
459
- // Toggle the display from none to block
460
- if (termPanel.style.display === "block") {
461
- termPanel.style.display = "none";
462
- } else {
463
- termPanel.style.display = "block";
464
- }
465
-
466
- // Start a while loop to continue through the DOM
467
- while (termPanel.nextElementSibling) {
468
- // Move to the next sibling element
469
- termPanel = termPanel.nextElementSibling;
470
-
471
- // Check if the current element is a <dd>
472
- if (termPanel.tagName === "DD") {
473
- // Toggle the display from none to block
474
- if (termPanel.style.display === "block") {
475
- termPanel.style.display = "none";
476
- } else {
477
- termPanel.style.display = "block";
478
- }
479
- } else {
480
- // Stop the loop if the current element is not a <dd>
481
- break;
482
- }
483
- }
484
- });
485
-
486
-
487
- // Add keydown event for toggling vocab terms
488
- vocabTerms[activeTerm].addEventListener("keydown", function (e) {
489
-
490
- // When user hits enter, toggle the active class
491
- if (e.key === "Enter") {
492
- // When clicked, toggle the active class
493
- this.classList.toggle("active");
494
-
495
- // Target the definition <dd> element
496
- let termPanel = this.nextElementSibling;
497
-
498
- // Toggle the display from none to block
499
- if (termPanel.style.display === "block") {
500
- termPanel.style.display = "none";
501
- } else {
502
- termPanel.style.display = "block";
503
- }
504
- // Start a while loop to continue through the DOM
505
- while (termPanel.nextElementSibling) {
506
- // Move to the next sibling element
507
- termPanel = termPanel.nextElementSibling;
508
-
509
- // Check if the current element is a <dd>
510
- if (termPanel.tagName === "DD") {
511
- // Toggle the display from none to block
512
- if (termPanel.style.display === "block") {
513
- termPanel.style.display = "none";
514
- } else {
515
- termPanel.style.display = "block";
516
- }
517
- } else {
518
- // Stop the loop if the current element is not a <dd>
519
- break;
520
- }
521
- }
522
- }
523
- });
524
- }
525
- }
526
- if (vocabListWidget) { callVocabList(); }
527
- // Clean up HTML
528
- const cleanMarkup = () => {
529
- // Remove role="presentation" attr from any element that has it
530
- if (rolePres) {
531
- rolePres.forEach((roleElem) => roleElem.removeAttribute("role"));
532
- }
533
- // Set functino to remove atrributes from elements
534
- const discardAttributes = (element, ...attributes) => {
535
- attributes.forEach((attribute) => element.removeAttribute(attribute));
536
- }
537
- // Remove attributes from tables
538
- const tableElems = document.querySelectorAll("table, thead, tbody, tr, th, td");
539
- tableElems.forEach((elem) => {
540
- discardAttributes(elem, "cellspacing", "cellpadding", "width", "style");
541
- });
542
- };
543
- cleanMarkup();
544
- // Content Lock Widget
545
-
546
- // Save text content of unlock button
547
- const unlockContent = [];
548
-
549
- contentUnlockBtns.forEach((button) => {
550
- unlockContent.push(button.textContent)
551
- })
552
-
553
- // Create an object that keeps track of keys and their statuses
554
- let contentLockData = JSON.parse(localStorage.getItem("contentLockData")) || {};
555
-
556
- if (lockedContent) {
557
-
558
- // Checks the URL for the course number
559
- const currentURL = window.parent.location.href;
560
- const match = currentURL.match(/\/content\/(\d+)/);
561
- const courseNumber = match ? match[1] : null;
562
-
563
- // Add event listener for storage changes
564
- window.addEventListener("storage", (event) => {
565
- if (courseNumber) {
566
- handleLocalStorageUpdate(event, courseNumber);
567
- }
568
- });
569
-
570
- if (courseNumber) {
571
-
572
- // Check if the course data object has the course number
573
- if (!contentLockData.hasOwnProperty(courseNumber)) {
574
- contentLockData[courseNumber] = {
575
- keys: {},
576
- id: 0,
577
- };
578
- } else {
579
- // Reset the id count to 0 when the page is loaded
580
- contentLockData[courseNumber].id = 0;
581
- }
582
-
583
- // Get key number for each content area
584
- lockedContent.forEach((contentArea, index) => {
585
- let keyNum = contentArea.getAttribute("data-key");
586
-
587
- // Check if key already exists within the course, if it doesn't, add the key
588
- if (!contentLockData[courseNumber].keys[keyNum]) {
589
-
590
- // Add the key to the course keys
591
- contentLockData[courseNumber].keys[keyNum] = false;
592
- }
593
- });
594
-
595
- // Go through each show/hide button and add click listener
596
- contentUnlockBtns.forEach((button, index) => {
597
-
598
- button.tabIndex = 0;
599
-
600
- button.addEventListener("click", function () {
601
- let keyNum = lockedContent[index].getAttribute("data-key");
602
-
603
- // Add alert to ensure the user confirms the action to unlock the content
604
- let confirmed = window.confirm(`Please confirm: ${unlockContent[index]}`)
605
-
606
- if (confirmed) {
607
-
608
- // Toggle the key status
609
- contentLockData[courseNumber].keys[keyNum] = !contentLockData[courseNumber].keys[keyNum];
610
-
611
- // Toggle classes based on key status
612
- if (contentLockData[courseNumber].keys[keyNum]) {
613
- lockedContent[index].classList.add("open");
614
- contentLockInstructions[index].classList.add("complete");
615
- } else {
616
- lockedContent[index].classList.remove("open");
617
- contentLockInstructions[index].classList.remove("complete");
618
- }
619
-
620
- // Save the updated contentLockData object to local storage
621
- localStorage.setItem("contentLockData", JSON.stringify(contentLockData));
622
-
623
- // Update the hidden content based on the key status
624
- checkHiddenContent(courseNumber);
625
- }
626
- });
627
-
628
- button.addEventListener("keydown", function (e) {
629
- if (e.key == "Enter") {
630
- let keyNum = lockedContent[index].getAttribute("data-key");
631
-
632
- // Add alert to ensure the user confirms the action to unlock the content
633
- let confirmed = window.confirm(`Please confirm: ${unlockContent[index]}`)
634
-
635
- if (confirmed) {
636
-
637
- // Toggle the key status
638
- contentLockData[courseNumber].keys[keyNum] = !contentLockData[courseNumber].keys[keyNum];
639
-
640
- // Toggle classes based on key status
641
- if (contentLockData[courseNumber].keys[keyNum]) {
642
- lockedContent[index].classList.add("open");
643
- contentLockInstructions[index].classList.add("complete");
644
- } else {
645
- lockedContent[index].classList.remove("open");
646
- contentLockInstructions[index].classList.remove("complete");
647
- }
648
-
649
- // Save the updated contentLockData object to local storage
650
- localStorage.setItem("contentLockData", JSON.stringify(contentLockData));
651
-
652
- // Update the hidden content based on the key status
653
- checkHiddenContent(courseNumber);
654
- }
655
- }
656
- });
657
-
658
- // Apply initial classes based on key status
659
- let keyNum = lockedContent[index].getAttribute("data-key");
660
-
661
- // Make sure contentLockData[courseNumber] is initialized
662
- if (!contentLockData[courseNumber]) {
663
- contentLockData[courseNumber] = {
664
- keys: {},
665
- id: 0
666
- };
667
- }
668
-
669
- if (contentLockData[courseNumber].keys[keyNum]) {
670
- lockedContent[index].classList.add("open");
671
- contentLockInstructions[index].classList.add("complete");
672
- }
673
- });
674
-
675
- // Call the checkHiddenContent function initially
676
- checkHiddenContent(courseNumber);
677
-
678
- // Save the updated contentLockData object to local storage
679
- localStorage.setItem("contentLockData", JSON.stringify(contentLockData));
680
- }
681
- }
682
-
683
- // Function to run when local storage is updated
684
- function handleLocalStorageUpdate(event, courseNumber) {
685
- if (event && event.key === "contentLockData" && event.newValue) {
686
- // Update contentLockData variable
687
- contentLockData = JSON.parse(event.newValue);
688
- // Run your code here
689
- checkHiddenContent(courseNumber);
690
- }
691
- }
692
-
693
- // Check content areas function
694
-
695
- function checkHiddenContent(courseNumber) {
696
-
697
- // Get key number for each content area
698
- lockedContent.forEach((contentArea, index) => {
699
- let keyNum = contentArea.getAttribute("data-key");
700
- // Toggle classes based on key status
701
- if (contentLockData[courseNumber].keys[keyNum]) {
702
- lockedContent[index].classList.add("open");
703
- contentLockInstructions[index].classList.add("complete");
704
- } else {
705
- lockedContent[index].classList.remove("open");
706
- contentLockInstructions[index].classList.remove("complete");
707
- }
708
- });
709
- }
710
- // Flip Card Widget
711
- function callFlipCardWidget() {
712
- // Loop through each card
713
- flipCards.forEach((flipCardGroup) => {
714
-
715
- let flipCard = flipCardGroup.querySelectorAll(".flip-card");
716
- let innerFlipCard = flipCardGroup.querySelectorAll(".inner-card");
717
- let numOfCardsInGroup = flipCardGroup.children.length;
718
-
719
- // Check to ensure each card has the .flip-card class
720
- if (numOfCardsInGroup !== flipCard.length) {
721
- console.log("Document error: missing .flip-card class for flip card widget");
722
- }
723
- // Check to ensure each card has the .inner-card class
724
- if (numOfCardsInGroup !== innerFlipCard.length) {
725
- console.log("Document error: missing .inner-card class for flip card widget");
726
- }
727
-
728
- flipCard.forEach((card) => {
729
- let innerFlipCard = card.querySelectorAll(".inner-card");
730
-
731
- innerFlipCard.forEach((innerCard) => {
732
- innerCard.setAttribute("tabindex", 0); // Add tab index to allow flip cards to be tabbable
733
- innerCard.addEventListener("click", () => {
734
- innerCard.offsetHeight; // Force reflow by accessing the offsetHeight property
735
- innerCard.classList.toggle("flip");
736
- })
737
-
738
-
739
- // Add a keydownevent event to each card
740
- innerCard.addEventListener("keydown", (event) => {
741
- if (event.key === "Enter") {
742
- // Force reflow by accessing the offsetHeight property
743
- innerCard.offsetHeight;
744
- innerCard.classList.toggle("flip");
745
- }
746
- })
747
- })
748
- })
749
- })
750
- }
751
-
752
- // If flip cards are present in the file, run this code
753
- if (flipCards) { callFlipCardWidget() }
754
- if (document.querySelector("body[focus-reader]")) {
755
-
756
- // Initializations
757
- let focusOn = false;
758
-
759
- const fr_contentWrapper = document.querySelector("#content-wrapper");
760
- const fr_thisBody = document.querySelector("body[focus-reader]");
761
-
762
- // Add fontAwesome to header
763
- const fr_pageHead = document.querySelector("head");
764
- const fontAweLink = document.createElement("link");
765
- fontAweLink.rel = "stylesheet";
766
- fontAweLink.href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css";
767
- fr_pageHead.append(fontAweLink);
768
-
769
- // add intersection observer to head tag
770
- const observerScript = document.createElement("script");
771
- observerScript.setAttribute("src", "https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver");
772
- fr_pageHead.append(observerScript);
773
-
774
- // Create Switches container
775
- const fr_switchesContainer = document.createElement("div");
776
- fr_switchesContainer.className = "focus-reader-switches";
777
- fr_thisBody.append(fr_switchesContainer);
778
-
779
- // Focus-text container
780
- const fr_focusTextContainer = document.createElement("div");
781
- fr_switchesContainer.append(fr_focusTextContainer);
782
-
783
- // Focus-text Icon
784
- const fr_focusTextIcon = document.createElement("p");
785
- fr_focusTextIcon.innerHTML = "Focus Text"
786
- fr_focusTextContainer.append(fr_focusTextIcon);
787
-
788
- // info icon
789
- const fr_infoIcon = document.createElement("i");
790
- fr_infoIcon.classList.add("fa-solid");
791
- fr_infoIcon.classList.add("fa-circle-info");
792
- fr_focusTextContainer.append(fr_infoIcon);
793
-
794
- // info tooltip
795
- const fr_infoTooltip = document.createElement("span");
796
- const focusReaderTooltipText = "Highlight text as you scroll";
797
- fr_infoTooltip.classList.add("info-tooltip");
798
- fr_infoTooltip.innerHTML = focusReaderTooltipText;
799
- fr_infoIcon.append(fr_infoTooltip);
800
-
801
- // Focus-text switch button
802
- const fr_focusTextSwitch = document.createElement("button");
803
- fr_focusTextSwitch.id = "focus-text";
804
- fr_focusTextSwitch.innerHTML = (focusOn) ? `<i class="fas fa-toggle-on"></i>` : `<i class="fas fa-toggle-off"></i>`;
805
- fr_focusTextContainer.append(fr_focusTextSwitch);
806
-
807
- // Focus-text logic
808
- fr_focusTextSwitch.addEventListener("click", () => {
809
- if (focusOn) {
810
- focusOn = !focusOn;
811
- fr_contentWrapper.removeAttribute("on");
812
- fr_focusTextSwitch.innerHTML = (focusOn) ? `<i class="fas fa-toggle-on"></i>` : `<i class="fas fa-toggle-off"></i>`;
813
- removeSpans(fr_contentWrapper);
814
- } else {
815
- focusOn = !focusOn;
816
- fr_contentWrapper.setAttribute("on", "");
817
- fr_focusTextSwitch.innerHTML = (focusOn) ? `<i class="fas fa-toggle-on"></i>` : `<i class="fas fa-toggle-off"></i>`;
818
- const elements = document.querySelectorAll("#content-wrapper .content-body :is(p, li, dd, dt, blockquote)");
819
- elements.forEach(element => {
820
- traverseAndWrapTextInSpans(element, focusText);
821
- });
822
- }
823
- });
824
-
825
- const options = {
826
- root: null,
827
- rootMargin: '-48.9% 0px',
828
- threshold: 0.00
829
- };
830
-
831
- const focusText = new IntersectionObserver(entries => {
832
- entries.forEach(entry => {
833
- if (entry.isIntersecting) {
834
- entry.target.closest("span").classList.add("focus-text");
835
- } else {
836
- entry.target.closest("span").classList.remove("focus-text");
837
- }
838
- });
839
- }, options);
840
-
841
-
842
- }
843
-
844
- function traverseAndWrapTextInSpans(node, focusText) {
845
- if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '') {
846
- // Split the text into words
847
- const words = node.textContent.split(' ');
848
-
849
- // Wrap each word in a span
850
- words.forEach(word => {
851
- if (word !== '') {
852
- const span = document.createElement("span");
853
- span.textContent = word + ' '; // Add a space after the word to preserve spacing
854
-
855
- // Observe the span
856
- focusText.observe(span);
857
-
858
- // Insert the span before the text node
859
- node.parentNode.insertBefore(span, node);
860
- }
861
- });
862
-
863
- // Remove the original text node
864
- node.parentNode.removeChild(node);
865
- } else if (node.nodeType === Node.ELEMENT_NODE) {
866
- // Recursively process child nodes
867
- Array.from(node.childNodes).forEach(childNode => {
868
- traverseAndWrapTextInSpans(childNode, focusText);
869
- });
870
- }
871
- }
872
-
873
- function removeSpans(node) {
874
- if (node.nodeType === Node.ELEMENT_NODE) {
875
- // If the node is a span with the class 'focus-text', an empty class attribute, is empty, or has no attributes, replace it with a text node
876
- if (node.tagName === 'SPAN' && (node.className === 'focus-text' || node.className === '' || node.textContent.trim() === '' || node.attributes.length === 0)) {
877
- const textNode = document.createTextNode(node.textContent);
878
- node.parentNode.insertBefore(textNode, node);
879
- node.parentNode.removeChild(node);
880
- } else {
881
- // Recursively process child nodes
882
- Array.from(node.childNodes).forEach(childNode => {
883
- removeSpans(childNode);
884
- });
885
- }
886
- }
887
- }
888
- // Change footnotes from 'show' to 'hide'
889
- const footnotes = document.querySelector(".toggle-footnotes");
890
-
891
- if (footnotes) {
892
- footnotes.addEventListener("click", () => {
893
- footnotes.innerHTML = (footnotes.innerHTML === "[Show Footnotes]") ? "[Hide Footnotes]" : "[Show Footnotes]";
894
- })
895
- }
896
- // Add h5p resizer dynamically
897
- h5pResizer.setAttribute("src", "https://pima.h5p.com/js/h5p-resizer.js");
898
- h5pResizer.setAttribute("charset", "UTF-8");
899
- h5pResizer.setAttribute("defer", "");
900
-
901
- // If any iframes are detected run this function
902
- function checkIframes() {
903
- h5pIframes.forEach(function (h5pIframe) {
904
- const src = h5pIframe.getAttribute("src");
905
- if (src.includes("/d2l/common/dialogs/quickLink") || src.includes("https://pima.h5p.com/content") || src.includes("h5p") && !h5pResizerExists) {
906
- docHead.appendChild(h5pResizer);
907
- }
908
- });
909
- }
910
-
911
- // Call function if iframes exist
912
- if (h5pIframes) { checkIframes() }
913
-
914
-
915
- // Helper JS for Responsive Tables
916
- const initResponsiveTables = () => {
917
- for (let table = 0; table < tables.length; table++) {
918
- let headertext = [],
919
- headers = tables[table].querySelectorAll(".display table th, table.display th, .display-lg table th, table.display-lg th"),
920
- tablebody = tables[table].querySelector(".display table tbody, table.display tbody, .display-lg table tbody, table.display-lg tbody");
921
- for (let header = 0; header < headers.length; header++) {
922
- let current = headers[header];
923
- headertext.push(current.textContent.replace(/\r?\n|\r/, ""));
924
- }
925
- for (let y = 0, row; row = tablebody.rows[y]; y++) {
926
- for (let j = 0, col; col = row.cells[j]; j++) {
927
- col.setAttribute("data-th", headertext[j]);
928
- }
929
- }
930
- }
931
- }
932
- if (tables) {
933
- initResponsiveTables();
934
- }
935
- // Call function with jQuery scripts
936
- const callJquery = () => {
937
- // Toggle Button's Arrow Right Points Down on Click
938
- $('.arrow-right').on('click', function () {
939
- $(this).toggleClass('arrow-down');
940
- });
941
- // TOOLTIP
942
- // Allows Screen readers to toggle a tooltip on click and to say if the tooltip is collapsed or expanded.
943
- $(".tooltip").click(function () {
944
- $(this).children(".tip-hover").toggle();
945
- if ($(this).children(".tip-hover").is(':visible')) {
946
- $(this).attr('aria-expanded', 'true');
947
- $(this).removeClass('hidden');
948
- } else {
949
- $(this).attr('aria-expanded', 'false');
950
- $(this).addClass('hidden');
951
- }
952
- });
953
- let start = 999;
954
- $('.tooltip').each(function (i) {
955
- $(this).css('z-index', start--);
956
- });
957
- $(".tooltip .video-container").parent().css("width", "450px");
958
- }
959
- callJquery();
960
- // This is called by anchor links via onlick="" in the HTML
961
- // Added because default anchor links don't work on all browsers using D2L
962
- const jumpTo = (anchor) => {
963
- document.getElementById(anchor).scrollIntoView();
964
- }
965
- // Array for all themes that require theme specific js
966
- const customJsThemes = ["ecn", "hrs", "ss"];
967
-
968
- //Search links for theme styles
969
- const themeJsCheck = () => {
970
-
971
- const links = document.querySelectorAll("link");
972
-
973
- links.forEach((link) => {
974
- const href = link.getAttribute("href");
975
- customJsThemes.forEach((theme) => {
976
- // If theme requires custom js, run addThemeScript()
977
- if (href && href.includes(`/${theme}/styles.css`)) {
978
- addThemeScript(theme);
979
- }
980
- });
981
- });
982
-
983
- // Adds a script to the head for that particular theme
984
- function addThemeScript(theme) {
985
- let themeScript = document.createElement("script");
986
- // URL references theme-specific js module from CDN
987
- themeScript.src = `https://cdn.jsdelivr.net/npm/@pimaonline/pimaonline-themepack/dist/js/themes/${theme}.js`;
988
- document.head.appendChild(themeScript);
989
- }
990
- }
991
-
992
- themeJsCheck()
993
- // Toggle footnotes
994
- const toggleBtns = document.querySelectorAll(".toggle-btn, .toggle-footnotes");
995
-
996
- if (toggleBtns) {
997
- if (document.querySelector(".toggle-btn") || document.querySelector(".toggle-footnotes")) {
998
- for (let toggleBtn = 0; toggleBtn < toggleBtns.length; toggleBtn++) {
999
- // Add tabindex
1000
- toggleBtns[toggleBtn].setAttribute("tabindex", "0");
1001
- // Show/hide on click
1002
- toggleBtns[toggleBtn].addEventListener("click", () => {
1003
- if (toggleBtns[toggleBtn].nextElementSibling) {
1004
- toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
1005
- }
1006
- })
1007
-
1008
- // Show/hide on enter for users who use tab
1009
- toggleBtns[toggleBtn].addEventListener("keydown", (enter) => {
1010
- if (enter.keyCode === 13) {
1011
- if (toggleBtns[toggleBtn].nextElementSibling) {
1012
- toggleBtns[toggleBtn].nextElementSibling.classList.toggle("show");
1013
- }
1014
- }
1015
- })
1016
- }
1017
- }
1018
- }
1
+ (()=>{"use strict";var e={152:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.discardAttributes=void 0,t.discardAttributes=(e,...t)=>{t.forEach((t=>e.removeAttribute(t)))}},80:(e,t,o)=>{o(271),o(381),o(34),o(645),o(71),o(0),o(161),o(609),o(795),o(308),o(721),o(121),o(81),o(786),o(407),o(952),o(174),o(433),o(709),o(393)},271:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0});const n=o(79),r=[{class:"bi-",cdn:new URL("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css")},{class:"ri-",cdn:new URL("https://cdn.jsdelivr.net/npm/remixicon@4.0.1/fonts/remixicon.css")}];document.querySelectorAll(r.map((e=>`[class*='${e.class}']`)).join(", ")).length>0&&r.forEach((e=>{var t;if(document.querySelector(`[class*='${e.class}']`)){const o=null!==(t=null===n.docHead||void 0===n.docHead?void 0:n.docHead.querySelector("meta[name='viewport']"))&&void 0!==t?t:null;o||console.warn("Document error: could not find viewport meta tag");const r=document.createElement("link");r.setAttribute("href",e.cdn.toString()),r.setAttribute("rel","stylesheet"),o&&(null===n.docHead||void 0===n.docHead||n.docHead.insertBefore(r,o.nextSibling))}}))},381:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0});const n=o(79);n.contentWrapper?n.contentWrapper.setAttribute("role","main"):n.contentWrapper||console.log("Document error: does not contain #content-wrapper."),n.secondColumn&&(n.secondColumn.setAttribute("role","region"),n.secondColumn.setAttribute("aria-label","Second column")),n.thirdColumn&&(n.thirdColumn.setAttribute("role","region"),n.thirdColumn.setAttribute("aria-label","Third column"))},34:()=>{const e=document.querySelectorAll(".arrow-right");e.length>0&&e.forEach((e=>{(e=>{e.addEventListener("click",(t=>{e.classList.toggle("arrow-down")})),e.addEventListener("keydown",(t=>{"Enter"!==t.key&&" "!==t.key||e.classList.toggle("arrow-down")}))})(e)}))},645:()=>{const e=document.querySelectorAll("dl.vocab-list dt"),t=(document.querySelectorAll("dl.vocab-list dd"),document.querySelectorAll("dl.vocab-list")),o=(document.querySelectorAll("dl.vocab-list button"),e=>{e.classList.toggle("active");let t=e.nextElementSibling instanceof HTMLElement?e.nextElementSibling:null;for(t&&"block"===t.style.display?t.style.display="none":t&&(t.style.display="block");t&&t.nextElementSibling;){const e=t.nextElementSibling;if(e instanceof HTMLElement){if(t=e,!t||"DD"!==t.tagName)break;"block"===t.style.display?t.style.display="none":t.style.display="block"}}}),n=e=>{if(e){let t=e.querySelectorAll("dd"),o=e.querySelectorAll("dt");t.forEach((e=>{e.style.display="none"})),o.forEach((e=>{e.classList.remove("active")}))}};t.length>0&&(()=>{t.forEach((e=>{let t=0,o=0,r=!1;for(let n=0;n<e.children.length;n++)"DT"==e.children[n].tagName&&(e.children[n].setAttribute("tabindex","0"),t++),"DD"==e.children[n].tagName&&o++,"BUTTON"==e.children[n].tagName&&(r=!0);if(t<1&&console.warn("Document error: no terms found in vocab list"),o<1&&console.warn("Document error: no definitions found in vocab list"),t>o&&console.warn("Document error: more terms than definitions in vocab list"),t>=2&&o>=2)if(r){let t=e.querySelector("button");null==t||t.addEventListener("click",(()=>n(e)))}else{const t=document.createElement("button");t.textContent="Close All",t.addEventListener("click",(()=>n(e))),e.appendChild(t)}else{for(let t=0;t<e.children.length;t++)"BUTTON"==e.children[t].tagName&&(r=!0);if(r){let t=e.querySelector("button");t&&(t.style.display="none")}}}));for(let t=0;t<e.length;t++)e[t].addEventListener("click",(n=>{o(e[t])})),e[t].addEventListener("keydown",(n=>{"Enter"===n.key&&o(e[t])}))})()},71:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.cleanMarkup=void 0;const n=o(79),r=o(152);t.cleanMarkup=()=>{n.rolePres&&n.rolePres.forEach((e=>e.removeAttribute("role"))),document.querySelectorAll(l.join(",")).forEach((e=>{(0,r.discardAttributes)(e,...c)})),n.jqueryScript&&n.jqueryScript.remove()};const l=["table","thead","tbody","tr","th","td"],c=["cellspacing","cellpadding","width","style"];var i;(n.rolePres&&n.rolePres.length>0||(i=c,l.some((e=>i.some((t=>null!==document.querySelector(`${e}[${t}]`))))))||n.jqueryScript)&&(0,t.cleanMarkup)()},0:()=>{const e=document.querySelectorAll(".content-lock-widget"),t=document.querySelectorAll(".locked-content"),o=document.querySelectorAll(".instructions"),n=[],r=e=>{const r=(e,n,r)=>{u[n].keys[e]=!0,u[n].keys[e]?(t[r].classList.add("open"),o[r].classList.add("complete")):(t[r].classList.remove("open"),o[r].classList.remove("complete")),localStorage.setItem("contentLockData",JSON.stringify(u)),c(n)},l=(e,t)=>{let o=e.querySelector(".error-container"),n=document.createElement("span");o&&(o.innerHTML="",o.appendChild(n)),n.textContent="",setTimeout((function(){n.textContent=t,o&&o.appendChild(n)}),200)},c=e=>{t.forEach(((n,r)=>{let l=n.getAttribute("data-key");if(l){let n=parseInt(l,10);u[e].keys[n]?(t[r].classList.add("open"),o[r].classList.add("complete")):(t[r].classList.remove("open"),o[r].classList.remove("complete"))}}))},i=window.parent.location.href.match(/\/content\/(\d+)/),s=i?i[1]:null,a=["a","b","c","d","e","f","g","h","i"],d=localStorage.getItem("contentLockData");let u=d?JSON.parse(d):{};if(s){const i=parseInt(s,10);window.addEventListener("storage",(e=>{s&&((e,t)=>{e&&"contentLockData"===e.key&&e.newValue&&(u=JSON.parse(e.newValue),c(t))})(e,i)}));let d=1;e.forEach(((e,o)=>{let n=e.querySelector(".quiz form");if(t){if(n){let t=e.querySelector(".locked-content"),r=e.querySelector(".quiz .correct-answer");if(r&&(t||console.warn(`Document error: missing the locked-content class for widget number ${o+1} on this page`),r||console.warn(`Document error: missing correct-answer for content lock quiz for widget number ${o+1} on this page`),n.id=`quiz${d}`,!e.querySelector(".error-container"))){let t=document.createElement("div");t.classList.add("error-container");let n=e.querySelector("input[value='Submit']");n?n.insertAdjacentHTML("beforebegin",t.outerHTML):console.warn(`Document error: quiz is missing an input with value 'Submit' for widget number ${o+1} on this page.`)}}d++}else e.querySelector(".unlock-btn")||console.warn(`Document error: locked content area (that is not using a quiz) is missing <a> with .unlock-btn for widget number ${o+1} on this page.`)})),new Promise(((e,t)=>{let o=document.querySelectorAll(".quiz form");o&&o.forEach((e=>{e.querySelectorAll("input").forEach(((e,t)=>{e.getAttribute("value")?"Submit"==e.getAttribute("value")&&(e.setAttribute("type","button"),e.classList.add("unlock-btn")):(e.setAttribute("value",a[t]),e.setAttribute("name","options"),e.setAttribute("type","radio"))}))})),e()})).then((()=>{(()=>{const e=new Map;t.forEach((t=>{const o=t.getAttribute("data-key");if(o)if(e.has(o)){const t=e.get(o)||0;e.set(o,t+1)}else e.set(o,1)}));let o=!1;e.forEach(((e,t)=>{e>1&&(console.warn(`Document error: multiple quizzes found with the same data key (${t})`),o=!0)}))})();const e=document.querySelectorAll(".unlock-btn");u.hasOwnProperty(s)||(u[i]={keys:{}}),t.forEach(((e,t)=>{let o=e.getAttribute("data-key");if(o){let n=parseInt(o,10),r=e.parentElement;r?r.classList.contains("content-lock-widget")||console.warn(`Document error: content lock widget wrapper is missing .content-lock-widget class for widget number ${t+1} on this page`):console.warn(`Document error: content lock widget is missing parent container for widget number ${t+1} on this page`);let l=e.nextElementSibling;if(l)if(l.classList.contains("instructions")&&"DIV"===l.tagName){if(!l.querySelector(".unlock-btn")){let e=l.nextElementSibling;e?e.classList.contains("quiz")||console.warn(`Document error: missing .quiz class after locked-content ${t+1} on this page`):console.warn(`Document error: missing .unlock-btn class inside instructions ${t+1} on this page`)}}else console.warn(`Document error: instructions <div> is missing .instructions class for widget number ${t+1} on this page`);else console.warn(`Document error: locked content area is missing <div> with instructions for widget number ${t+1} on this page`);u[i].keys[n]||(u[i].keys[n]=!1)}else o||console.warn(`Document error: missing data-key for locked content for widget number ${t+1} on this page`)})),e.forEach(((e,c)=>{let s=t[c].getAttribute("data-key");if(s){let a=parseInt(s,10);null!==e.textContent&&n.push(e.textContent),e.setAttribute("tabIndex","0"),e.addEventListener("click",(()=>((e,t,o,n,c)=>{let i=!1,s=!1;"INPUT"===t.tagName&&(i=!0),i?(s=(e=>{let t=document.getElementById(`quiz${e}`);if(t){let e=t.querySelector("input[name='options']:checked"),o=t.querySelector("input.correct-answer"),n="";return e?o?e.value===o.value?(alert("Correct response"),!0):(n="Incorrect response. Please try again.",l(t,n),!1):(console.warn("Document error: no .correct-answer class applied"),!1):(n="Please select an option before submitting.",l(t,n),!1)}return console.warn("Document error: quiz id for content lock quiz, not being applied"),!1})(e),s&&r(e,c,o)):(s=window.confirm(`Please confirm: ${n[o]}`),s&&r(e,c,o))})(a,e,c,n,i))),u[i]||(u[i]={keys:{},id:0}),u[i].keys[a]&&(t[c].classList.add("open"),o[c].classList.add("complete"))}})),c(i),localStorage.setItem("contentLockData",JSON.stringify(u))})).catch((e=>{console.warn("Document error: error occurred during applyAttributesToQuiz:",e)}))}else console.warn("Document error: No course number found")};document.addEventListener("DOMContentLoaded",(()=>{e.length>0&&r(e)}))},161:()=>{const e=document.querySelectorAll(".flip-card-widget, .flip-card-group");e.length>0&&e.forEach((e=>{let t=e.querySelectorAll(".flip-card"),o=e.querySelectorAll(".inner-card"),n=e.children.length;n!==t.length&&console.warn("Document error: missing .flip-card class for flip card widget"),n!==o.length&&console.warn("Document error: missing .inner-card class for flip card widget"),t.forEach((e=>{e.querySelectorAll(".inner-card").forEach((e=>{e.setAttribute("tabindex","0"),e.addEventListener("click",(()=>{e.offsetHeight,e.classList.toggle("flip")})),e.addEventListener("keydown",(t=>{"Enter"===t.key&&(e.offsetHeight,e.classList.toggle("flip"))}))}))}))}))},609:()=>{if(document.querySelector("body[focus-reader]")){let o=!1;const n=document.querySelector("#content-wrapper"),r=document.querySelector("body[focus-reader]"),l=document.querySelector("head"),c=document.createElement("link");c.rel="stylesheet",c.href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css",l&&l.append(c);const i=document.createElement("script");i.src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver",l&&l.append(i);const s=document.createElement("div");s.className="focus-reader-switches",r&&r.append(s);const a=document.createElement("div");s.append(a);const d=document.createElement("p");d.innerHTML="Focus Text",a.append(d);const u=document.createElement("i");u.classList.add("fa-solid"),u.classList.add("fa-circle-info"),a.append(u);const m=document.createElement("span");m.classList.add("info-tooltip"),m.innerHTML="Highlight text as you scroll",u.append(m);const p=document.createElement("button");p.id="focus-text",p.innerHTML=o?'<i class="fas fa-toggle-on"></i>':'<i class="fas fa-toggle-off"></i>',a.append(p),p.addEventListener("click",(()=>{o?(o=!o,n&&(n.removeAttribute("on"),p.innerHTML=o?'<i class="fas fa-toggle-on"></i>':'<i class="fas fa-toggle-off"></i>',t(n))):(o=!o,n&&(n.setAttribute("on",""),p.innerHTML=o?'<i class="fas fa-toggle-on"></i>':'<i class="fas fa-toggle-off"></i>',document.querySelectorAll("#content-wrapper .content-body :is(p, li, dd, dt, blockquote)").forEach((t=>{e({node:t,focusText:g})}))))}));const g=new IntersectionObserver((e=>{e.forEach((e=>{var t,o;e.isIntersecting?null===(t=e.target.closest("span"))||void 0===t||t.classList.add("focus-text"):null===(o=e.target.closest("span"))||void 0===o||o.classList.remove("focus-text")}))}),{root:null,rootMargin:"-48.9% 0px",threshold:0})}function e({node:t,focusText:o}){var n,r;t.nodeType===Node.TEXT_NODE&&""!==(null===(n=t.textContent)||void 0===n?void 0:n.trim())?(t.textContent.split(" ").forEach((e=>{var n;if(""!==e){const r=document.createElement("span");r.textContent=e+" ",o.observe(r),null===(n=t.parentNode)||void 0===n||n.insertBefore(r,t)}})),null===(r=t.parentNode)||void 0===r||r.removeChild(t)):t.nodeType===Node.ELEMENT_NODE&&Array.from(t.childNodes).forEach((t=>{e({node:t,focusText:o})}))}function t(e){var o,n,r;if(e.nodeType===Node.ELEMENT_NODE){const l=e;if(l instanceof HTMLElement&&"SPAN"===l.tagName&&("focus-text"===l.className||""===l.className||!(null===(o=l.textContent)||void 0===o?void 0:o.trim())||0===l.attributes.length)){const e=document.createTextNode(l.textContent||"");null===(n=l.parentNode)||void 0===n||n.insertBefore(e,l),null===(r=l.parentNode)||void 0===r||r.removeChild(l)}else Array.from(l.childNodes).forEach((e=>{t(e)}))}}},795:()=>{const e=document.querySelector(".toggle-footnotes");e&&(e=>{var t;const o=document.createElement("button");o.classList.add("toggle-footnotes"),o.textContent="[Show Footnotes]",null===(t=e.parentNode)||void 0===t||t.replaceChild(o,e),o.addEventListener("click",(()=>{o.textContent="[Show Footnotes]"===o.textContent?"[Hide Footnotes]":"[Show Footnotes]";const e=o.nextElementSibling;e&&e.classList.toggle("show")}))})(e)},308:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0});const n=o(79);(()=>{if(null!==n.courseBody){n.contentWrapper&&n.secondColumn&&n.thirdColumn?n.courseBody.id="three-column":n.contentWrapper&&n.secondColumn&&!n.columnWidget?n.courseBody.id="two-column":n.contentWrapper&&n.secondColumn&&n.columnWidget?n.courseBody.id="two-col-widget":n.contentWrapper&&n.videoWrapper?n.courseBody.id="video-grid":!n.contentWrapper||n.secondColumn||n.thirdColumn||n.columnWidget||n.videoWrapper?n.contentWrapper&&!n.secondColumn&&(n.thirdColumn||n.columnWidget)?console.log("Document error: <body> is missing id because #second-column doesn't exist."):console.log("Document error: unable to determine the page layout for setting <body> id."):n.courseBody.id="one-column";const e=document.body.children;let t=!1;for(let o=0;o<e.length;o++){const n=e[o];if("content-wrapper"!==n.id&&"second-column"!==n.id&&"third-column"!==n.id&&"column-widget"!==n.id&&"HEADER"!==n.tagName&&"FOOTER"!==n.tagName&&"SCRIPT"!==n.tagName&&"loom-companion-mv3"!==n.id&&"focus-reader-switches"!==n.className){t=!0;break}}t&&console.log("Document error: Additional content outside #content-wrapper, #second-column, #third-column, or footer.")}else console.log("Document error: no <body> element found.")})()},721:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0});const n=o(79),r=document.createElement("script");r.setAttribute("src","https://pima.h5p.com/js/h5p-resizer.js"),r.setAttribute("charset","UTF-8"),r.setAttribute("defer","");const l=document.querySelectorAll("iframe"),c=null===n.docHead||void 0===n.docHead?void 0:n.docHead.querySelector("script[src='https://pima.h5p.com/js/h5p-resizer.js']");l.length>0&&l.forEach((e=>{const t=e.getAttribute("src");t&&(t.includes("/d2l/common/dialogs/quickLink")||t.includes("https://pima.h5p.com/content")||t.includes("h5p"))&&!c&&n.docHead&&n.docHead.appendChild(r)}))},121:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0});const n=o(79),r=document.querySelectorAll(".gallery-wrapper"),l=document.querySelectorAll(".image-box"),c=document.querySelectorAll(".image-gallery");r.length>0&&r.forEach((e=>{const t=e.parentNode;t instanceof Element&&t.classList.contains("image-gallery")||console.warn("Document error: parent of .gallery-wrapper does not have the .image-gallery class.")})),l.length>0&&l.forEach((e=>{const t=e.parentNode;t instanceof Element&&t.classList.contains("gallery-wrapper")||console.log("Document error: parent of .image-box does not have the .gallery-wrapper class.")})),r.length>0&&r.forEach((e=>{Array.from(e.children).every((e=>e instanceof HTMLElement&&e.classList.contains("image-box")))||console.warn("Document error: not all direct children of .gallery-wrapper have the .image-box class.")}));c.length>0&&((()=>{const e=document.createElement("link");e.rel="stylesheet",e.href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css",null===n.docHead||void 0===n.docHead||n.docHead.appendChild(e)})(),(()=>{c.forEach((e=>{e.insertAdjacentHTML("afterbegin",'<div class="modal-box invisible">\n <div class="gallery-overlay"></div>\n <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>\n </div>\n <button class="hide-gallery">Hide</button>')}));const e=document.querySelector(".gallery-overlay"),t=document.querySelector(".modal-box"),o=document.querySelector(".modal-box--image img"),n=document.querySelector(".img-caption"),r=document.querySelector(".close-img"),i=document.querySelectorAll(".hide-gallery"),s=e=>{null==t||t.classList.remove("invisible"),o&&(o.src=e.imgSrc),n&&(n.innerHTML=e.imgCaption)},a=()=>{null==t||t.classList.add("invisible")};l.forEach((e=>{e.addEventListener("click",(function(){var e,t;s({imgSrc:(null===(e=this.querySelector("img"))||void 0===e?void 0:e.src)||"",imgCaption:(null===(t=this.querySelector("img"))||void 0===t?void 0:t.alt)||""})})),e.setAttribute("tabindex","0"),e.addEventListener("keydown",(function(e){var t,o;"Enter"===e.key&&s({imgSrc:(null===(t=this.querySelector("img"))||void 0===t?void 0:t.src)||"",imgCaption:(null===(o=this.querySelector("img"))||void 0===o?void 0:o.alt)||""})}))})),e&&(e.onclick=a),window.onkeydown=e=>{"Escape"===e.key&&a()},r&&(r.onclick=a),i.forEach((e=>{e.addEventListener("click",(()=>{var t;null===(t=e.nextElementSibling)||void 0===t||t.classList.toggle("invisible"),e.innerHTML="Hide"===e.innerHTML?"Show":"Hide"}))}))})())},81:()=>{document.addEventListener("DOMContentLoaded",(()=>{document.querySelectorAll("a[href^='#']").forEach((e=>{var t;const o=null===(t=e.getAttribute("href"))||void 0===t?void 0:t.substring(1);o&&e.setAttribute("onclick",`jumpTo("${o}")`)}))}))},786:()=>{const e=document.querySelectorAll(".media-container");e.length>0&&e.forEach(((e,t)=>{let o=String.fromCharCode(t+65).toLowerCase(),n=e.querySelector(".media-object"),r=e.querySelector("iframe"),l=e.querySelector(".media-info");r||console.warn("Document error: no iframe found for media container"),n||console.warn("Document error: no media object found for media container"),r&&!r.hasAttribute("aria-describedby")&&l&&(r.setAttribute("aria-describedby",`${o}`),l.id=`${[o]}`)}))},407:()=>{const e=document.querySelectorAll(".display, .display-lg");e.length>0&&[...e].forEach((e=>{const t=e.querySelectorAll(".display table th, table.display th, .display-lg table th, table.display-lg th"),o=e.querySelector(".display table tbody, table.display tbody, .display-lg table tbody, table.display-lg tbody");if(t.length>0){const e=[...t].map((e=>{var t;return(null===(t=e.textContent)||void 0===t?void 0:t.replace(/\r?\n|\r/,""))||""}));o?[...o.rows].forEach((t=>{[...t.cells].forEach(((t,o)=>{t.setAttribute("data-th",e[o])}))})):console.warn("Document error: no table <tbody> found")}else console.warn("Document error: no table headers <th> found")}))},393:()=>{const e=document.querySelectorAll(".slider-widget");e.length>0&&(()=>{[...e].forEach((e=>{[...e.children].every((e=>e.classList.contains("slider-item")))||console.warn("Document error: not all direct children of .slider have the .slider-item class.")}));const t=(e,t,o)=>{e.forEach(((e,t)=>{e.style.display=t===o?"block":"none"})),t.forEach(((e,t)=>{e.classList.toggle("active",t===o)}))},o=(e,o,n)=>{t(e,o,n)},n=e=>{const t=document.createElement("button");return t.className=e,t.setAttribute("tabindex","-1"),t},r=e=>{let t=0;for(let o=0;o<e.children.length;o++){const n=e.children[o];n instanceof HTMLElement&&(t+=n.offsetHeight)}if(t<300&&!e.querySelector(".media-container")){const t=document.createElement("div");for(;e.firstChild;)t.appendChild(e.firstChild);e.appendChild(t),e.classList.add("short-content")}};document.querySelectorAll(".slider-widget").forEach(((e,l)=>{e.setAttribute("tabindex","0"),e.setAttribute("role","group");const c=document.createElement("span");c.id=`slider-label-${l+1}`,c.textContent="Interactive Slider",c.hidden=!0,e.prepend(c),e.setAttribute("aria-labelledby",`slider-label-${l+1}`);let i=0;const s=Array.from(e.querySelectorAll(".slider-item")),a=document.createElement("div");a.className="slider-dots-bar",e.appendChild(a);let d=[];s.forEach(((e,o)=>{const n=document.createElement("span");n.className="slider-dot",n.addEventListener("click",(()=>{i=o,t(s,d,i),s[i].style.display="block",n.classList.add("active"),r(s[i])})),a.appendChild(n),d.push(n),e.style.display=o!==i?"none":"block",o===i&&n.classList.add("active")}));const u=n("slider-arrow icon-chevron-left"),m=n("slider-arrow icon-chevron-right");e.appendChild(u),e.appendChild(m),u.addEventListener("click",(()=>{i=i>0?i-1:s.length-1,o(s,d,i),r(s[i])})),m.addEventListener("click",(()=>{i=i<s.length-1?i+1:0,o(s,d,i),r(s[i])})),e.addEventListener("keydown",(t=>{switch(t.key){case"ArrowLeft":i=i>0?i-1:s.length-1;break;case"ArrowRight":i=i<s.length-1?i+1:0;break;default:return}o(s,d,i),r(s[i]),t.preventDefault(),c.textContent=`Interactive Slide: slide ${i+1} of ${s.length}`,e.focus()}));let p=0,g=0;e.addEventListener("touchstart",(e=>{p=e.changedTouches[0].screenX}),!1),e.addEventListener("touchend",(e=>{g=e.changedTouches[0].screenX,h()}),!1);const h=()=>{let t=g-p;Math.abs(t)>50&&(i=t>0?i>0?i-1:s.length-1:i<s.length-1?i+1:0,o(s,d,i),r(s[i]),e.focus())}})),e.forEach(((e,t)=>{((e,t)=>{const o=e.querySelector(".icon-chevron-right"),n=e.querySelector(".icon-chevron-left"),r=e.querySelector(".slider-dots-bar");o||console.warn(`Document error: next button is missing for slider ${t+1}.`),n||console.warn(`Document error: previous button is missing for slider ${t+1}.`),r||console.warn(`Document error: dots bar is missing for slider ${t+1}.`)})(e,t)})),e.forEach(((e,t)=>{Array.from(e.querySelectorAll(".slider-item")).forEach(((e,o)=>{Array.from(e.childNodes).every((e=>e.nodeType===Node.COMMENT_NODE||e.nodeType===Node.TEXT_NODE&&!e.textContent.trim()))&&console.warn(`Document error: .slider-item at index ${o} in slider ${t+1} is empty.`)}))}))})()},952:()=>{const e=document.querySelectorAll(".tabs, .tabs-widget");e.length>0&&(()=>{let t=0;e.forEach(((e,o)=>{var n,r,l,c,i,s,a,d,u,m,p,g;let h=e.querySelectorAll("input"),f=e.querySelectorAll("label"),y=e.querySelectorAll("div");if((h.length<2||f.length<2||y.length<2)&&console.warn("Document error: add more than just one tab for tabs widget"),h.length<3||f.length<3||y.length<3){let e=f[1].querySelector("span");e&&("Hide"!==e.textContent&&""!==e.textContent||console.warn("Document error: add more tabs, than just 1 tab and the hide tab"))}let b=f[f.length-1].querySelector("span");b&&"Hide"!==b.textContent&&console.warn("Document error: ensure last tab is a hide tab and label text is 'Hide'"),(h.length<f.length||h.length<y.length)&&console.warn("Document error: missing tab input(s) in tab widget"),(f.length<h.length||f.length<y.length)&&console.warn("Document error: missing tab label(s) in tab widget");let v=o+1;e.setAttribute("role","region"),e.setAttribute("aria-label",`tab group ${v}`);for(let e=0;e<h.length;e++){"Hide"===(null===(r=null===(n=f[e])||void 0===n?void 0:n.textContent)||void 0===r?void 0:r.trim())&&f[e].classList.add("hide-tab");let o=t+1;h&&y||(console.warn("Document error: no inputs found for tabs widget"),console.warn("Document error: no divs (tab panels) found for tabs widget")),f||console.warn("Document error: no labels found for tabs widget"),null===(l=h[e])||void 0===l||l.classList.add("tab-input"),null===(c=h[e])||void 0===c||c.setAttribute("type","radio"),null===(i=h[e])||void 0===i||i.setAttribute("id",`tab${o}`),null===(s=h[e])||void 0===s||s.setAttribute("name",`hint-group-${v}`),null===(a=h[e])||void 0===a||a.setAttribute("aria-describedby",`tabHeading${o}`),null===(d=f[e])||void 0===d||d.classList.add("tab-header"),null===(u=f[e])||void 0===u||u.setAttribute("for",`tab${o}`),y[e]&&(null===(m=y[e])||void 0===m||m.classList.add("tab-panel"),null===(p=y[e])||void 0===p||p.setAttribute("tabindex","0"),null===(g=y[e])||void 0===g||g.setAttribute("id",`tabHeading${o}`)),h[e].checked=0===e,e+1==h.length&&(f[e].classList.add("hide-tab"),y[e]&&y[e].classList.add("hide-panel")),t++}}))})()},174:()=>{const e=["cas","ecn","hrs","ss","chm"];document.querySelectorAll("link").forEach((t=>{const o=t.getAttribute("href");e.forEach((e=>{o&&o.includes(`/${e}/styles.css`)&&function(e){let t=document.createElement("script");t.src=`https://cdn.jsdelivr.net/npm/@pimaonline/pimaonline-themepack/dist/js/themes/${e}.js`,document.head.appendChild(t)}(e)}))}))},433:()=>{const e=document.querySelectorAll(".toggle-btn");e.length>0&&(()=>{if(document.querySelector(".toggle-btn"))for(let t=0;t<e.length;t++)e[t].setAttribute("tabindex","0"),e[t].addEventListener("click",(()=>{const o=e[t].nextElementSibling;o&&o.classList.toggle("show")})),e[t].addEventListener("keydown",(o=>{if("Enter"===o.key){const o=e[t].nextElementSibling;o&&o.classList.toggle("show")}}))})()},709:()=>{const e="toolTip",t="toolTipHover",o=document.querySelectorAll(".tooltip");o.length>0&&(()=>{const n=(e,t)=>{t.style.display="block",e.classList.toggle("hidden",!1)},r=(e,t)=>{t.style.display="none",e.setAttribute("aria-expanded","false"),e.classList.toggle("hidden",!0)};o.forEach(((o,l)=>{let c=l+1;o.id=`${e}${c}`,o.role="tooltip",o.tabIndex=0,o.setAttribute("aria-expanded","false"),o.setAttribute("aria-controls",`${t}${c.toString()}`);const i=o.querySelector(".tip-hover");i?(i.id=`${t}${c}`,i.setAttribute("aria-describedby",`${e}${c.toString()}`),o.addEventListener("mouseover",(()=>n(o,i))),o.addEventListener("mouseout",(()=>r(o,i))),o.addEventListener("focus",(()=>n(o,i))),o.addEventListener("blur",(()=>r(o,i))),o.addEventListener("touchstart",(()=>n(o,i))),o.addEventListener("touchend",(()=>r(o,i)))):console.warn("Document error: tooltip is missing .tip-hover class");let s=30-c;o.style.zIndex=s.toString()})),document.querySelectorAll(".tooltip .video-container, .tooltip .video-container").forEach((e=>{const t=e.parentElement;t&&(t.style.width="450px")}))})()},79:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.jqueryScript=t.videoWrapper=t.rolePres=t.thirdColumn=t.secondColumn=t.docHead=t.courseBody=t.contentWrapper=t.columnWidget=void 0,t.columnWidget=document.querySelector("#column-widget"),t.contentWrapper=document.querySelector("#content-wrapper"),t.courseBody=document.querySelector("body"),t.docHead=document.querySelector("head"),t.secondColumn=document.querySelector("#second-column"),t.thirdColumn=document.querySelector("#third-column"),t.rolePres=document.querySelectorAll('[role="presentation"]'),t.videoWrapper=document.querySelector("#video-wrapper"),t.jqueryScript=document.querySelector('script[src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"]')}},t={};!function o(n){var r=t[n];if(void 0!==r)return r.exports;var l=t[n]={exports:{}};return e[n](l,l.exports,o),l.exports}(80)})();