@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.
- package/README.md +12 -23
- package/dist/css/main.css +1 -1
- package/dist/css/plugins/alt-icons.css +1 -1
- package/dist/css/plugins/font-awesome.css +1 -1
- package/dist/css/routes.css +1 -1
- package/dist/css/themes/ait/styles.css +1 -1
- package/dist/css/themes/ajs/styles.css +1 -1
- package/dist/css/themes/ant/styles.css +1 -0
- package/dist/css/themes/art/styles.css +1 -1
- package/dist/css/themes/aviation/styles.css +1 -1
- package/dist/css/themes/bct/styles.css +1 -1
- package/dist/css/themes/bio/styles.css +1 -1
- package/dist/css/themes/business/styles.css +1 -1
- package/dist/css/themes/cad/styles.css +1 -1
- package/dist/css/themes/cards/styles.css +1 -1
- package/dist/css/themes/cas/styles.css +1 -0
- package/dist/css/themes/cda/styles.css +1 -1
- package/dist/css/themes/chm/styles.css +1 -0
- package/dist/css/themes/cis/styles.css +1 -1
- package/dist/css/themes/communication/styles.css +1 -1
- package/dist/css/themes/computer-information-systems/styles.css +1 -1
- package/dist/css/themes/culinary/styles.css +1 -1
- package/dist/css/themes/culinary/versions/black-marble.css +1 -1
- package/dist/css/themes/culinary/versions/stainless.css +1 -1
- package/dist/css/themes/culinary/versions/wood.css +1 -1
- package/dist/css/themes/dental/styles.css +1 -1
- package/dist/css/themes/ece/styles.css +1 -1
- package/dist/css/themes/ecn/styles.css +1 -1
- package/dist/css/themes/eng/styles.css +1 -1
- package/dist/css/themes/fashion/styles.css +1 -1
- package/dist/css/themes/fitness/styles.css +1 -1
- package/dist/css/themes/fsc/styles.css +1 -1
- package/dist/css/themes/geography/styles.css +1 -1
- package/dist/css/themes/geology/styles.css +1 -1
- package/dist/css/themes/health-it/styles.css +1 -1
- package/dist/css/themes/history/styles.css +1 -1
- package/dist/css/themes/hrm/styles.css +1 -1
- package/dist/css/themes/hrs/styles.css +1 -1
- package/dist/css/themes/journalism/styles.css +1 -1
- package/dist/css/themes/lang/styles.css +1 -1
- package/dist/css/themes/lgm/styles.css +1 -1
- package/dist/css/themes/machine/styles.css +1 -1
- package/dist/css/themes/math/styles.css +1 -1
- package/dist/css/themes/mgt/styles.css +1 -1
- package/dist/css/themes/minimalist/styles.css +1 -1
- package/dist/css/themes/mkt/styles.css +1 -0
- package/dist/css/themes/music/styles.css +1 -1
- package/dist/css/themes/nursing/styles.css +1 -0
- package/dist/css/themes/philosophy/styles.css +1 -1
- package/dist/css/themes/pht/styles.css +1 -1
- package/dist/css/themes/phy/styles.css +1 -0
- package/dist/css/themes/pos/styles.css +1 -0
- package/dist/css/themes/psy/styles.css +1 -1
- package/dist/css/themes/reading/styles.css +1 -0
- package/dist/css/themes/resort/styles.css +1 -1
- package/dist/css/themes/soc/styles.css +1 -1
- package/dist/css/themes/ss/styles.css +1 -1
- package/dist/css/themes/tps/styles.css +1 -0
- package/dist/css/themes/university/styles.css +1 -1
- package/dist/css/themes/vet/styles.css +1 -1
- package/dist/css/themes/welding/styles.css +1 -1
- package/dist/css/themes/writing/styles.css +1 -1
- package/dist/img/general/arrow-right-black.svg +1 -0
- package/dist/img/general/arrow-right-primary-blue.svg +1 -0
- package/dist/img/general/arrow-right-white.svg +1 -0
- package/dist/img/theme-images/ant/texture.png +0 -0
- package/dist/img/theme-images/cas/city-vector.svg +92 -0
- package/dist/img/theme-images/cas/farm-vector.svg +1 -0
- package/dist/img/theme-images/cas/ocean-vector.svg +1 -0
- package/dist/img/theme-images/cas/recycle-symbol.svg +1 -0
- package/dist/img/theme-images/chm/chem-letters/letter-a.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-b.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-c.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-d.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-e.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-f.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-g.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-h.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-i.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-j.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-k.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-l.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-m.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-n.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-o.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-p.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-q.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-r.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-s.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-t.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-u.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-v.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-w.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-x.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-y.png +0 -0
- package/dist/img/theme-images/chm/chem-letters/letter-z.png +0 -0
- package/dist/img/theme-images/mkt/blue/bluebars.svg +36 -0
- package/dist/img/theme-images/mkt/blue/blueheader.jpg +0 -0
- package/dist/img/theme-images/mkt/blue/bluepie.svg +42 -0
- package/dist/img/theme-images/mkt/green/greenbars.svg +36 -0
- package/dist/img/theme-images/mkt/green/greenheader.jpg +0 -0
- package/dist/img/theme-images/mkt/green/greenpie.svg +42 -0
- package/dist/img/theme-images/mkt/yellow/yellowbars.svg +36 -0
- package/dist/img/theme-images/mkt/yellow/yellowheader.jpg +0 -0
- package/dist/img/theme-images/mkt/yellow/yellowpie.svg +42 -0
- package/dist/img/theme-images/nursing/blue/bottomright-blue.svg +95 -0
- package/dist/img/theme-images/nursing/blue/topleft-blue.svg +111 -0
- package/dist/img/theme-images/nursing/green/bottomright-green.svg +95 -0
- package/dist/img/theme-images/nursing/green/topleft-green.svg +111 -0
- package/dist/img/theme-images/nursing/purple/bottomright-purple.svg +95 -0
- package/dist/img/theme-images/nursing/purple/topleft-purple.svg +111 -0
- package/dist/img/theme-images/nursing/teal/bottomright-teal.svg +95 -0
- package/dist/img/theme-images/nursing/teal/topleft-teal.svg +111 -0
- package/dist/img/theme-images/phy/background.svg +150 -0
- package/dist/img/theme-images/phy/tape-style1.svg +8 -0
- package/dist/img/theme-images/reading/bg10.jpg +0 -0
- package/dist/js/scripts2.js +1 -1018
- package/dist/js/themes/cas.js +1 -0
- package/dist/js/themes/chm.js +1 -0
- package/dist/js/themes/ecn.js +1 -13
- package/dist/js/themes/hrs.js +1 -19
- package/dist/js/themes/ss.js +1 -197
- package/dist/plugins/fancybox/fancybox-example.html +1 -1
- package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.js +2 -122
- package/dist/plugins/fancybox/helpers/jquery.fancybox-buttons.js.LICENSE.txt +15 -0
- package/dist/plugins/fancybox/helpers/jquery.fancybox-media.js +2 -201
- package/dist/plugins/fancybox/helpers/jquery.fancybox-media.js.LICENSE.txt +64 -0
- package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.js +2 -165
- package/dist/plugins/fancybox/helpers/jquery.fancybox-thumbs.js.LICENSE.txt +16 -0
- package/dist/plugins/fancybox/jquery.fancybox.js +2 -2018
- package/dist/plugins/fancybox/jquery.fancybox.js.LICENSE.txt +11 -0
- package/dist/plugins/fancybox/jquery.fancybox.pack.js +2 -46
- package/dist/plugins/fancybox/jquery.fancybox.pack.js.LICENSE.txt +1 -0
- package/dist/plugins/flashcards/flashcards-example.html +1 -1
- package/dist/plugins/flashcards/js/flash_cards.min.js +1 -12
- package/dist/plugins/flashcards/js/plugins/flash_cards.js +1 -62
- package/dist/plugins/flashcards/js/plugins/jquery.cycle.js +2 -1148
- package/dist/plugins/flashcards/js/plugins/jquery.cycle.js.LICENSE.txt +20 -0
- package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.js +2 -9404
- package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.js.LICENSE.txt +22 -0
- package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.min.js +2 -4
- package/dist/plugins/flashcards/js/vendor/jquery-1.7.2.min.js.LICENSE.txt +1 -0
- package/dist/plugins/flashcards/js/vendor/modernizr-2.5.3.min.js +1 -4
- package/dist/plugins/floating-particles/floating-particles.js +1 -68
- package/dist/plugins/global-homepage-overrides/global-homepage-overrides.js +1 -53
- package/dist/plugins/preview-banner/preview-banner.js +1 -57
- package/package.json +22 -11
- package/dist/js/jumpTo.js +0 -4
- package/dist/js/scripts.js +0 -327
package/dist/js/scripts2.js
CHANGED
@@ -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)})();
|