@cagovweb/state-template 1.0.0 → 1.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,18 +8,20 @@
8
8
  //@ts-check
9
9
 
10
10
  /* sticky header / hiding official header on scroll */
11
- (() => {
11
+ window.addEventListener("load", () => {
12
12
  const doc = document.documentElement;
13
13
 
14
14
  let prevScroll = window.scrollY || doc.scrollTop;
15
15
  let curScroll;
16
16
  let direction = 0;
17
17
  let prevDirection = 0;
18
+
18
19
  const headerAlert = document.querySelector("header .alert");
19
20
  const header = document.querySelector(".utility-header");
20
21
  const mainheader = document.querySelector("header");
22
+ if (!header || !mainheader) return;
21
23
 
22
- const checkScroll = () => {
24
+ window.addEventListener("scroll", () => {
23
25
  /*
24
26
  ** Find the direction of scroll
25
27
  ** 0 - initial, 1 - up, 2 - down
@@ -38,7 +40,7 @@
38
40
  // Toggle Header
39
41
  if (direction === 2 && curScroll > 40) {
40
42
  const hiddenheight =
41
- header.clientHeight + (headerAlert ? headerAlert.clientHeight : 0);
43
+ header.clientHeight + (headerAlert?.clientHeight || 0);
42
44
 
43
45
  mainheader.style.top = `-${hiddenheight}px`;
44
46
  prevDirection = direction;
@@ -52,10 +54,8 @@
52
54
  }
53
55
 
54
56
  prevScroll = curScroll;
55
- };
56
-
57
- window.addEventListener("scroll", checkScroll);
58
- })();
57
+ });
58
+ });
59
59
 
60
60
  // retain scroll position
61
61
 
@@ -139,12 +139,17 @@ class CaGovAccordion extends HTMLElement {
139
139
  };
140
140
  }
141
141
  }
142
- window.customElements.define("cagov-accordion", CaGovAccordion);
142
+ window.addEventListener("load", () => {
143
+ window.customElements.define("cagov-accordion", CaGovAccordion);
144
+ });
143
145
 
144
146
  //document.querySelector('head').appendChild(style);
145
147
 
146
148
  //@ts-check
147
- ((w, doc) => {
149
+ window.addEventListener("load", () => {
150
+ const w = window;
151
+ const doc = document;
152
+
148
153
  /**
149
154
  * Local object for method references
150
155
  * and define script meta-data
@@ -431,7 +436,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
431
436
  !doc.getElementById(thisAccordion).hasAttribute("data-multi")
432
437
  ) {
433
438
  // swap expanded when there is a single constant panel
434
- for (let trigger of triggers) {
439
+ for (const trigger of triggers)
435
440
  if (thisTrigger !== trigger) {
436
441
  isCurrent(trigger, false);
437
442
  const getID = trigger.getAttribute("aria-controls");
@@ -439,7 +444,6 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
439
444
  ariaExpanded(trigger, false);
440
445
  ariaHidden(doc.getElementById(getID), true);
441
446
  }
442
- }
443
447
  }
444
448
  }
445
449
  };
@@ -544,7 +548,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
544
548
 
545
549
  // go go JavaScript
546
550
  ARIAaccordion.init();
547
- })(window, document);
551
+ });
548
552
 
549
553
  //@ts-check
550
554
 
@@ -640,10 +644,8 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
640
644
  * @return {String} the value of attribute data-hashtooltip-id
641
645
  */
642
646
  const searchParentHashId = (el, hashId) => {
643
- let found = false;
644
-
645
647
  let parentElement = el;
646
- while (parentElement && !found) {
648
+ while (parentElement) {
647
649
  if (parentElement.hasAttribute(hashId)) {
648
650
  return parentElement.getAttribute(hashId);
649
651
  } else {
@@ -659,10 +661,8 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
659
661
  * @param {String} hashId
660
662
  */
661
663
  const searchParent = (el, parentClass, hashId) => {
662
- let found = false;
663
-
664
664
  let parentElement = el;
665
- while (parentElement && !found) {
665
+ while (parentElement) {
666
666
  if (
667
667
  parentElement.classList.contains(parentClass) &&
668
668
  parentElement.getAttribute(DATA_HASH_ID) === hashId
@@ -803,6 +803,8 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
803
803
 
804
804
  const indexHeaderLisible = index_header + 1;
805
805
  const accordionPanel = header_node.nextElementSibling;
806
+ if (!accordionPanel) return;
807
+
806
808
  const accordionHeaderText = header_node.innerHTML;
807
809
  const accordionButton = document.createElement("BUTTON");
808
810
  const accordionOpenedAttribute = header_node.hasAttribute(
@@ -1020,20 +1022,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1020
1022
  return plugin;
1021
1023
  };
1022
1024
 
1023
- // @ts-ignore
1024
- window.van11yAccessibleAccordionAria = main();
1025
-
1026
- const onLoad = function onLoad() {
1027
- // @ts-ignore
1028
- const expand_default = window.van11yAccessibleAccordionAria();
1029
- expand_default.attach();
1030
-
1031
- document.removeEventListener("DOMContentLoaded", onLoad);
1032
- };
1033
-
1034
- document.addEventListener("DOMContentLoaded", onLoad);
1035
-
1036
- function NavReset() {
1025
+ const NavReset = () => {
1037
1026
  //RESET
1038
1027
  document
1039
1028
  .querySelectorAll(".first-level-btn")
@@ -1059,18 +1048,14 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1059
1048
  const nav = document.querySelector("#navigation");
1060
1049
  nav.removeAttribute("aria-hidden");
1061
1050
  }
1062
- }
1063
-
1064
- const isDocumentReady = (
1065
- /** @type {{ (): void; (this: Document, ev: Event): any; }} */ callbackFunction
1066
- ) => {
1067
- if (document.readyState != "loading") callbackFunction();
1068
- else document.addEventListener("DOMContentLoaded", callbackFunction);
1069
1051
  };
1070
1052
 
1071
1053
  // Remove href if <a> has a link
1072
- isDocumentReady(() => {
1054
+ window.addEventListener("load", () => {
1055
+ main()().attach(); //This is way more abstract than it needs to be
1056
+
1073
1057
  const navigationJS = document.querySelector(".main-navigation");
1058
+ if (!navigationJS) return;
1074
1059
 
1075
1060
  const subnavbtnJS = document.querySelectorAll(
1076
1061
  ".main-navigation .nav-item a.has-sub-btn"
@@ -1094,15 +1079,21 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1094
1079
  ).filter(x => x.querySelector(".sub-nav"));
1095
1080
 
1096
1081
  navItemsJS.forEach(navItem => {
1082
+ /** @type {HTMLElement | null} */
1097
1083
  const link = navItem.querySelector(".first-level-btn, .first-level-link");
1084
+ if (link) {
1085
+ if (setActiveLinkByFolder && link.getAttribute("href")) {
1086
+ const arrNavLink = link.getAttribute("href")?.split("/");
1087
+ const arrCurrentURL = location.href.split("/");
1098
1088
 
1099
- if (setActiveLinkByFolder && link.getAttribute("href")) {
1100
- const arrNavLink = link.getAttribute("href").split("/");
1101
- const arrCurrentURL = location.href.split("/");
1102
-
1103
- if (arrNavLink.length > 4 && arrCurrentURL[3] === arrNavLink[3]) {
1104
- // folder of current URL matches this nav link
1105
- navItem.classList.add("active");
1089
+ if (
1090
+ arrNavLink &&
1091
+ arrNavLink.length > 4 &&
1092
+ arrCurrentURL[3] === arrNavLink[3]
1093
+ ) {
1094
+ // folder of current URL matches this nav link
1095
+ navItem.classList.add("active");
1096
+ }
1106
1097
  }
1107
1098
  }
1108
1099
  });
@@ -1114,7 +1105,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1114
1105
  // if the target of the click isn't the navigation container nor a descendant of the navigation
1115
1106
  if (
1116
1107
  navContainer !== e.target &&
1117
- !navContainer.contains(/**@type {Node} */ (e.target))
1108
+ !navContainer?.contains(/**@type {Node} */ (e.target))
1118
1109
  ) {
1119
1110
  NavReset();
1120
1111
  }
@@ -1125,7 +1116,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1125
1116
  const itemCount = el.querySelectorAll(".second-level-nav > li").length;
1126
1117
  if (itemCount <= 2) {
1127
1118
  const subnav = el.querySelector(".sub-nav");
1128
- subnav.classList.add("with-few-items");
1119
+ if (subnav) subnav.classList.add("with-few-items");
1129
1120
  }
1130
1121
  });
1131
1122
 
@@ -1147,18 +1138,22 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1147
1138
  el.appendChild(carrot);
1148
1139
  });
1149
1140
  }
1141
+
1142
+ addActive();
1150
1143
  });
1151
1144
 
1152
- // Do Navigation Reset function on window resize uless it's mobile device.
1145
+ // Do Navigation Reset function on window resize.
1153
1146
  window.addEventListener("resize", () => {
1154
1147
  document
1155
1148
  .querySelector(".toggle-menu")
1156
- .setAttribute("aria-expanded", "false");
1149
+ ?.setAttribute("aria-expanded", "false");
1157
1150
 
1158
1151
  //Collapse the nav when narrow
1159
- const nav = document.querySelector("#navigation");
1160
- nav.classList.remove("show");
1161
- nav.setAttribute("aria-hidden", "true");
1152
+ //const nav = document.querySelector("#navigation");
1153
+ //if (nav) {
1154
+ //nav.classList.remove("show"); //This was causing the desktop menu to stay hidden when resizing from mobile.
1155
+ //nav.setAttribute("aria-hidden", "true");
1156
+ //}
1162
1157
 
1163
1158
  NavReset();
1164
1159
  });
@@ -1186,15 +1181,77 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1186
1181
  }
1187
1182
  }
1188
1183
  };
1189
- addActive();
1190
1184
  })();
1191
1185
 
1192
1186
  //@ts-check
1193
1187
  /* -----------------------------------------
1194
1188
  SEARCH - /source/js/cagov/search.js
1195
1189
  ----------------------------------------- */
1196
- (() => {
1197
- /** @type {HTMLInputElement} */
1190
+
1191
+ window.addEventListener("load", () => {
1192
+ const setSearchContainerAriaHidden = () => {
1193
+ if (searchContainer) {
1194
+ if (featuredsearch) {
1195
+ searchContainer.removeAttribute("aria-hidden");
1196
+
1197
+ document.querySelector("[name='q']")?.removeAttribute("tabindex");
1198
+ document
1199
+ .querySelector(".gsc-search-button")
1200
+ ?.removeAttribute("tabindex");
1201
+ } else {
1202
+ searchContainer.setAttribute("aria-hidden", "true");
1203
+ }
1204
+ }
1205
+ };
1206
+
1207
+ const mobileControlVisible = () => {
1208
+ const mobileElement = document.querySelector(
1209
+ ".global-header .mobile-controls"
1210
+ );
1211
+
1212
+ if (mobileElement) {
1213
+ return getComputedStyle(mobileElement)["display"] !== "none";
1214
+ } else {
1215
+ return false; // or whatever is supposed to be returned when there is no header
1216
+ }
1217
+ };
1218
+
1219
+ const removeSearchResults = () => {
1220
+ document.body.classList.remove("active-search");
1221
+ if (searchText) searchText.value = "";
1222
+ if (searchContainer) {
1223
+ searchContainer.classList.remove("active");
1224
+ searchContainer.setAttribute("aria-hidden", "true");
1225
+ }
1226
+
1227
+ const resultsContainer = document.querySelector(
1228
+ ".search-results-container"
1229
+ );
1230
+ if (resultsContainer) {
1231
+ resultsContainer.classList.remove("visible");
1232
+ }
1233
+
1234
+ document
1235
+ .querySelectorAll(".ask-group")
1236
+ .forEach(a => a.classList.remove("fade-out"));
1237
+
1238
+ if (!featuredsearch) {
1239
+ // added aria expaned attr for accessibility
1240
+ const firstLevelBtn = document.querySelector("button.first-level-link");
1241
+ if (firstLevelBtn) firstLevelBtn.setAttribute("aria-expanded", "false");
1242
+ setSearchAttr();
1243
+ }
1244
+ // fire a scroll event to help update headers if need be
1245
+ window.dispatchEvent(new CustomEvent("scroll"));
1246
+
1247
+ // document.dispatchEvent('cagov.searchresults.hide'); // ???
1248
+
1249
+ if (mobileControlVisible()) {
1250
+ setSearchContainerAriaHidden();
1251
+ }
1252
+ };
1253
+
1254
+ /** @type {HTMLInputElement | null} */
1198
1255
  const searchText = document.querySelector(".search-textfield"); // search textfield, unique
1199
1256
  const searchInput = document.querySelector(
1200
1257
  "#head-search #Search .search-textfield"
@@ -1214,7 +1271,7 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1214
1271
 
1215
1272
  const searchlabel = document.querySelector("#SearchInput"); // label for textfield
1216
1273
 
1217
- /** @type {HTMLElement} */
1274
+ /** @type {HTMLElement | null} */
1218
1275
  const searchbox = document.querySelector(
1219
1276
  ".search-container:not(.featured-search)"
1220
1277
  ); // only on subpages, unique, same as #head-search
@@ -1222,9 +1279,9 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1222
1279
  // header, contains nav, search form, etc, unique
1223
1280
  const headerHeight = /** @type {HTMLElement} */ (
1224
1281
  document.querySelector(".global-header")
1225
- ).offsetHeight; // header height
1282
+ )?.offsetHeight; // header height
1226
1283
 
1227
- /** @type {HTMLElement} */
1284
+ /** @type {HTMLElement | null} */
1228
1285
  const utility = document.querySelector(".utility-header"); // utility header, unique
1229
1286
  const utilityHeight = utility?.offsetHeight || 0;
1230
1287
  // utility header height
@@ -1244,199 +1301,165 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1244
1301
  // Full width navigation
1245
1302
  const navigationHeight = document
1246
1303
  .querySelector(".navigation-search")
1247
- .classList.contains("full-width-nav")
1304
+ ?.classList.contains("full-width-nav")
1248
1305
  ? 82
1249
1306
  : 0;
1250
1307
 
1251
- const body = document.querySelector("body");
1308
+ if (searchText && searchContainer) {
1309
+ // Unfreeze search width when blured.
1310
+ const unfreezeSearchWidth = () => {
1311
+ searchContainer.classList.remove("focus");
1312
+ document.querySelector(".search-container")?.classList.add("focus"); // search-container is unique
1313
+ };
1314
+ searchText.addEventListener("blur", unfreezeSearchWidth, false);
1315
+ searchText.addEventListener("focus", unfreezeSearchWidth, false);
1316
+ const chgHandler = function () {
1317
+ if (this.value) {
1318
+ document.body.classList.add("active-search");
1319
+ }
1320
+ };
1321
+ searchText.addEventListener("change", chgHandler, false);
1322
+ searchText.addEventListener("keyup", chgHandler, false);
1323
+ searchText.addEventListener("paste", chgHandler, false);
1324
+ }
1252
1325
 
1253
- window.addEventListener("load", () => {
1254
- if (searchText) {
1255
- // Unfreeze search width when blured.
1256
- const unfreezeSearchWidth = () => {
1257
- searchContainer.classList.remove("focus");
1258
- document.querySelector(".search-container").classList.add("focus"); // search-container is unique
1259
- };
1260
- searchText.addEventListener("blur", unfreezeSearchWidth, false);
1261
- searchText.addEventListener("focus", unfreezeSearchWidth, false);
1262
- const chgHandler = function () {
1263
- if (this.value) {
1264
- body.classList.add("active-search");
1265
- }
1266
- };
1267
- searchText.addEventListener("change", chgHandler, false);
1268
- searchText.addEventListener("keyup", chgHandler, false);
1269
- searchText.addEventListener("paste", chgHandler, false);
1270
- }
1326
+ if (!featuredsearch) {
1327
+ // added aria expaned attr for accessibility
1328
+ const firstLevelBtn = document.querySelector("button.first-level-link");
1329
+ if (firstLevelBtn) firstLevelBtn.setAttribute("aria-expanded", "false");
1330
+ }
1271
1331
 
1272
- if (!featuredsearch) {
1273
- // added aria expaned attr for accessibility
1274
- const firstLevelBtn = document.querySelector("button.first-level-link");
1275
- if (firstLevelBtn) firstLevelBtn.setAttribute("aria-expanded", "false");
1332
+ // search box top position
1333
+ // TODO: Really close to searchTop() except for top size
1334
+ if (!mobileControlVisible()) {
1335
+ // calulation search box top position
1336
+ const searchtop =
1337
+ headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
1338
+ if (!mobileControlVisible() && searchbox) {
1339
+ searchbox.style.top = `${Math.max(searchtop, 82)}px`;
1276
1340
  }
1341
+ }
1277
1342
 
1278
- // search box top position
1279
- // TODO: Really close to searchTop() except for top size
1280
- if (!mobileView_for_search()) {
1281
- // calulation search box top position
1282
- const searchtop =
1283
- headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
1284
- if (!mobileView_for_search() && searchbox) {
1285
- searchbox.style.top = `${Math.max(searchtop, 82)}px`;
1286
- }
1287
- }
1343
+ // have the close button remove search results and the applied classes
1344
+ //resultsContainer.find('.close').on('click', removeSearchResults);
1345
+ const resContainClose = document.querySelector(
1346
+ ".search-results-container .close"
1347
+ );
1348
+ if (resContainClose)
1349
+ resContainClose.addEventListener("click", removeSearchResults, false);
1288
1350
 
1289
- // have the close button remove search results and the applied classes
1290
- //resultsContainer.find('.close').on('click', removeSearchResults);
1291
- const resContainClose = document.querySelector(
1292
- ".search-results-container .close"
1293
- );
1294
- if (resContainClose)
1295
- resContainClose.addEventListener("click", removeSearchResults, false);
1296
-
1297
- //searchContainer.find('.close').on('click', removeSearchResults);
1298
- const hsClose = document.querySelector("#head-search .close");
1299
- if (hsClose) hsClose.addEventListener("click", removeSearchResults, false);
1300
-
1301
- // Our special nav icon which we need to hook into for starting the search
1302
- // $('#nav-item-search')
1303
-
1304
- // so instead we are binding to what I'm assuming will always be the search
1305
- const searchButton = document.querySelector("#nav-item-search");
1306
- if (searchButton) {
1307
- searchButton.addEventListener(
1308
- "click",
1309
- function (e) {
1310
- e.preventDefault();
1311
- searchText.focus();
1351
+ //searchContainer.find('.close').on('click', removeSearchResults);
1352
+ const hsClose = document.querySelector("#head-search .close");
1353
+ if (hsClose) hsClose.addEventListener("click", removeSearchResults, false);
1312
1354
 
1313
- if (
1314
- !featuredsearch &&
1315
- document.querySelector(".search-container:not(.featured-search)")
1316
- ) {
1317
- document
1318
- .querySelector(".search-container:not(.featured-search)")
1319
- .classList.toggle("active");
1320
- }
1355
+ // Our special nav icon which we need to hook into for starting the search
1356
+ // $('#nav-item-search')
1321
1357
 
1322
- // hide Search form if it's not active
1323
- if (searchactive) {
1324
- // added aria expanded attr for accessibility
1325
- this.querySelector("button").setAttribute("aria-expanded", "true");
1326
- removeSearchAttr();
1327
- } else {
1328
- // added aria expaned attr for accessibility
1329
- this.querySelector("button").setAttribute("aria-expanded", "false");
1330
- setSearchAttr();
1331
- }
1358
+ // so instead we are binding to what I'm assuming will always be the search
1359
+ const searchButton = document.querySelector("#nav-item-search");
1360
+ if (searchButton && searchText) {
1361
+ searchButton.addEventListener(
1362
+ "click",
1363
+ function (e) {
1364
+ e.preventDefault();
1365
+ searchText.focus();
1366
+ //".search-container:not(.featured-search)"
1367
+ if (!featuredsearch && searchbox) {
1368
+ searchbox.classList.toggle("active");
1369
+ }
1370
+
1371
+ // hide Search form if it's not active
1372
+ if (searchactive) {
1373
+ // added aria expanded attr for accessibility
1374
+ this.querySelector("button").setAttribute("aria-expanded", "true");
1375
+ removeSearchAttr();
1376
+ } else {
1377
+ // added aria expaned attr for accessibility
1378
+ this.querySelector("button").setAttribute("aria-expanded", "false");
1379
+ setSearchAttr();
1380
+ }
1332
1381
 
1333
- if (featuredsearch) removeSearchAttr();
1382
+ if (featuredsearch) removeSearchAttr();
1334
1383
 
1335
- // let the user know the input box is where they should search
1384
+ // let the user know the input box is where they should search
1385
+ if (searchContainer) {
1336
1386
  searchContainer.classList.add("play-animation");
1337
1387
  searchContainer.addEventListener("animationend", () => {
1338
1388
  this.classList.remove("play-animation");
1339
1389
  });
1340
- },
1341
- false
1342
- );
1343
- }
1344
-
1345
- // Close search when close icon is clicked
1346
- if (searchReset) searchReset.addEventListener("click", removeSearchResults);
1347
-
1348
- function removeSearchResults() {
1349
- body.classList.remove("active-search");
1350
- searchText.value = "";
1351
- searchContainer.classList.remove("active");
1352
- searchContainer.setAttribute("aria-hidden", "true");
1353
-
1354
- const resultsContainer = document.querySelector(
1355
- ".search-results-container"
1356
- );
1357
- if (resultsContainer) {
1358
- resultsContainer.classList.remove("visible");
1359
- }
1360
-
1361
- document
1362
- .querySelectorAll(".ask-group")
1363
- .forEach(a => a.classList.remove("fade-out"));
1364
-
1365
- if (!featuredsearch) {
1366
- // added aria expaned attr for accessibility
1367
- document
1368
- .querySelector("button.first-level-link")
1369
- .setAttribute("aria-expanded", "false");
1370
- setSearchAttr();
1371
- }
1372
- // fire a scroll event to help update headers if need be
1373
- window.dispatchEvent(new CustomEvent("scroll"));
1390
+ }
1391
+ },
1392
+ false
1393
+ );
1394
+ }
1374
1395
 
1375
- // document.dispatchEvent('cagov.searchresults.hide'); // ???
1396
+ // Close search when close icon is clicked
1397
+ if (searchReset) searchReset.addEventListener("click", removeSearchResults);
1376
1398
 
1377
- if (mobileView_for_search()) {
1378
- ariaHidden();
1379
- }
1399
+ const removeSearchAttr = () => {
1400
+ if (searchInput) {
1401
+ searchInput.removeAttribute("tabindex");
1402
+ searchInput.removeAttribute("aria-hidden");
1403
+ }
1404
+ if (searchSubmit) {
1405
+ searchSubmit.removeAttribute("tabindex");
1406
+ searchSubmit.removeAttribute("aria-hidden");
1380
1407
  }
1408
+ if (searchReset) {
1409
+ searchReset.removeAttribute("tabindex");
1410
+ searchReset.removeAttribute("aria-hidden");
1411
+ }
1412
+ if (searchlabel) searchlabel.removeAttribute("aria-hidden");
1381
1413
 
1382
- function removeSearchAttr() {
1383
- if (searchInput) {
1384
- searchInput.removeAttribute("tabindex");
1385
- searchInput.removeAttribute("aria-hidden");
1386
- }
1387
- if (searchSubmit) {
1388
- searchSubmit.removeAttribute("tabindex");
1389
- searchSubmit.removeAttribute("aria-hidden");
1390
- }
1391
- if (searchReset) {
1392
- searchReset.removeAttribute("tabindex");
1393
- searchReset.removeAttribute("aria-hidden");
1394
- }
1395
- if (searchlabel) searchlabel.removeAttribute("aria-hidden");
1414
+ if (searchContainer) searchContainer.removeAttribute("aria-hidden");
1415
+ };
1396
1416
 
1397
- if (searchContainer) searchContainer.removeAttribute("aria-hidden");
1417
+ const setSearchAttr = () => {
1418
+ if (searchInput) {
1419
+ searchInput.setAttribute("tabindex", "-1");
1420
+ searchInput.setAttribute("aria-hidden", "true");
1398
1421
  }
1422
+ if (searchSubmit) {
1423
+ searchSubmit.setAttribute("tabindex", "-1");
1424
+ searchSubmit.setAttribute("aria-hidden", "true");
1425
+ }
1426
+ if (searchReset) {
1427
+ searchReset.setAttribute("tabindex", "-1");
1428
+ searchReset.setAttribute("aria-hidden", "true");
1429
+ }
1430
+ if (searchlabel) searchlabel.setAttribute("aria-hidden", "true");
1399
1431
 
1400
- function setSearchAttr() {
1401
- if (searchInput) {
1402
- searchInput.setAttribute("tabindex", "-1");
1403
- searchInput.setAttribute("aria-hidden", "true");
1404
- }
1405
- if (searchSubmit) {
1406
- searchSubmit.setAttribute("tabindex", "-1");
1407
- searchSubmit.setAttribute("aria-hidden", "true");
1408
- }
1409
- if (searchReset) {
1410
- searchReset.setAttribute("tabindex", "-1");
1411
- searchReset.setAttribute("aria-hidden", "true");
1412
- }
1413
- if (searchlabel) searchlabel.setAttribute("aria-hidden", "true");
1432
+ if (searchContainer) searchContainer.setAttribute("aria-hidden", "true");
1433
+ };
1414
1434
 
1415
- if (searchContainer) searchContainer.setAttribute("aria-hidden", "true");
1435
+ // Make Search form tabable if it's featured
1436
+ if (searchContainer) {
1437
+ if (searchContainer.classList.contains("featured-search")) {
1438
+ removeSearchAttr();
1439
+ } else {
1440
+ setSearchAttr();
1416
1441
  }
1442
+ }
1417
1443
 
1418
- // Make Search form tabable if it's featured
1419
- if (searchContainer) {
1420
- if (searchContainer.classList.contains("featured-search")) {
1421
- removeSearchAttr();
1422
- } else {
1423
- setSearchAttr();
1424
- }
1444
+ const setSearchTop = () => {
1445
+ // calulation search box top position
1446
+ const searchtop =
1447
+ headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
1448
+ if (!mobileControlVisible() && searchbox) {
1449
+ searchbox.style.top = `${Math.max(searchtop, 55)}px`;
1425
1450
  }
1451
+ };
1426
1452
 
1427
- // on alert close event
1428
- document.querySelectorAll(".alert-banner .close").forEach(oneClose => {
1429
- oneClose.addEventListener("click", searchTop);
1430
- });
1431
-
1432
- ariaHidden();
1453
+ // on alert close event
1454
+ document.querySelectorAll(".alert-banner .close").forEach(oneClose => {
1455
+ oneClose.addEventListener("click", setSearchTop);
1433
1456
  });
1434
1457
 
1435
1458
  // Calculation search box top property on the scroll for the fixed nav
1436
1459
  window.addEventListener("scroll", () => {
1437
- if (!mobileView_for_search()) {
1460
+ if (!mobileControlVisible()) {
1438
1461
  // setting timeout before calculating the search box top property otherwise it can take into account transitional values.
1439
- setTimeout(searchTop, 400);
1462
+ setTimeout(setSearchTop, 400);
1440
1463
 
1441
1464
  // remove featured search on scroll in desktop
1442
1465
  const FeaturedSearch = document.querySelector("nav ~ #head-search");
@@ -1455,45 +1478,14 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1455
1478
 
1456
1479
  // search box top position if browser window is resized
1457
1480
  window.addEventListener("resize", () => {
1458
- searchTop();
1459
- ariaHidden();
1481
+ setSearchTop();
1482
+ setSearchContainerAriaHidden();
1460
1483
  });
1461
1484
 
1462
- function searchTop() {
1463
- // calulation search box top position
1464
- const searchtop =
1465
- headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
1466
- if (!mobileView_for_search() && searchbox) {
1467
- searchbox.style.top = `${Math.max(searchtop, 55)}px`;
1468
- }
1469
- }
1470
-
1471
- function ariaHidden() {
1472
- if (searchContainer) {
1473
- if (featuredsearch) {
1474
- searchContainer.removeAttribute("aria-hidden");
1475
- document.querySelector("[name='q']").removeAttribute("tabindex");
1476
- document
1477
- .querySelector(".gsc-search-button")
1478
- .removeAttribute("tabindex");
1479
- } else {
1480
- searchContainer.setAttribute("aria-hidden", "true");
1481
- }
1482
- }
1483
- }
1485
+ setSearchContainerAriaHidden();
1486
+ });
1484
1487
 
1485
- const mobileView_for_search = () => {
1486
- const mobileElement = document.querySelector(
1487
- ".global-header .mobile-controls"
1488
- );
1489
-
1490
- if (mobileElement) {
1491
- return getComputedStyle(mobileElement)["display"] !== "none";
1492
- } else {
1493
- return false; // or whatever is supposed to be returned when there is no header
1494
- }
1495
- };
1496
- })(); // call out the function on the page load
1488
+ // call out the function on the page load
1497
1489
 
1498
1490
  //@ts-check
1499
1491
  /* -----------------------------------------
@@ -1502,68 +1494,73 @@ window.customElements.define("cagov-accordion", CaGovAccordion);
1502
1494
  ----------------------------------------- */
1503
1495
 
1504
1496
  // Displaying HTML Source code in HTML Page
1497
+ (() => {
1498
+ const entityMap = {
1499
+ "&": "&amp;",
1500
+ "<": "&lt;",
1501
+ ">": "&gt;",
1502
+ '"': "&quot;",
1503
+ "'": "&#39;",
1504
+ "/": "&#x2F;"
1505
+ };
1505
1506
 
1506
- const entityMap = {
1507
- "&": "&amp;",
1508
- "<": "&lt;",
1509
- ">": "&gt;",
1510
- '"': "&quot;",
1511
- "'": "&#39;",
1512
- "/": "&#x2F;"
1513
- };
1514
-
1515
- const escapeHtml = (/** @type {string} */ string) =>
1516
- string.replace(/[&<>"'/]/g, s => entityMap[s]);
1517
-
1518
- function copyCode(/** @type {Element} */ btnElem) {
1519
- const codeblock = btnElem.previousElementSibling;
1520
- if (codeblock) {
1521
- // copy the text
1522
- if (codeblock.tagName.toLowerCase() == "pre") {
1523
- navigator.clipboard.writeText(codeblock.querySelector("code").innerText);
1524
- } else {
1525
- //TextArea
1526
- navigator.clipboard.writeText(
1527
- /** @type { HTMLTextAreaElement} */ (codeblock).value
1528
- );
1507
+ const escapeHtml = (/** @type {string} */ string) =>
1508
+ string.replace(/[&<>"'/]/g, s => entityMap[s]);
1509
+
1510
+ function copyCode(/** @type {Element} */ btnElem) {
1511
+ const codeblock = btnElem.previousElementSibling;
1512
+ if (codeblock) {
1513
+ // copy the text
1514
+ if (codeblock.tagName.toLowerCase() == "pre") {
1515
+ navigator.clipboard.writeText(
1516
+ codeblock.querySelector("code").innerText
1517
+ );
1518
+ } else {
1519
+ //TextArea
1520
+ navigator.clipboard.writeText(
1521
+ /** @type { HTMLTextAreaElement} */ (codeblock).value
1522
+ );
1523
+ }
1524
+ // select the text
1525
+ const range = document.createRange();
1526
+ range.selectNode(codeblock);
1527
+ window.getSelection().removeAllRanges();
1528
+ window.getSelection().addRange(range);
1529
+ // replace the button icon
1530
+ //btnElem.querySelector("span").classList.remove("ca-gov-icon-copy");
1531
+ //btnElem.querySelector("span").classList.add("ca-gov-icon-check-mark");
1532
+ btnElem.innerHTML =
1533
+ '<span class="ca-gov-icon-check-mark"></span> Code copied';
1529
1534
  }
1530
- // select the text
1531
- const range = document.createRange();
1532
- range.selectNode(codeblock);
1533
- window.getSelection().removeAllRanges();
1534
- window.getSelection().addRange(range);
1535
- // replace the button icon
1536
- //btnElem.querySelector("span").classList.remove("ca-gov-icon-copy");
1537
- //btnElem.querySelector("span").classList.add("ca-gov-icon-check-mark");
1538
- btnElem.innerHTML =
1539
- '<span class="ca-gov-icon-check-mark"></span> Code copied';
1540
1535
  }
1541
- }
1542
1536
 
1543
- window.addEventListener("load", () => {
1544
- const codeblock = document.querySelectorAll("pre code, textarea.sourcecode");
1545
-
1546
- for (let i = 0, len = codeblock.length; i < len; i++) {
1547
- const dom = codeblock[i];
1548
- if (dom.tagName.toLowerCase() == "code") {
1549
- let html = dom.innerHTML;
1550
- html = escapeHtml(html);
1551
- dom.innerHTML = html;
1552
- }
1553
- // Create a 'copy code' button, insert it after the <pre> tag
1554
- const newDiv = document.createElement("button");
1555
- newDiv.onclick = function () {
1556
- copyCode(/** @type {HTMLElement} */ (this));
1557
- };
1558
- newDiv.classList.add("btn", "btn-outline-primary");
1559
- newDiv.innerHTML = "<span class='ca-gov-icon-copy'></span> Copy code";
1560
- if (dom.tagName.toLowerCase() == "code") {
1561
- dom.parentElement.after(newDiv);
1562
- } else {
1563
- dom.after(newDiv);
1537
+ window.addEventListener("load", () => {
1538
+ const codeblock = document.querySelectorAll(
1539
+ "pre code, textarea.sourcecode"
1540
+ );
1541
+
1542
+ for (let i = 0, len = codeblock.length; i < len; i++) {
1543
+ const dom = codeblock[i];
1544
+ if (dom.tagName.toLowerCase() == "code") {
1545
+ let html = dom.innerHTML;
1546
+ html = escapeHtml(html);
1547
+ dom.innerHTML = html;
1548
+ }
1549
+ // Create a 'copy code' button, insert it after the <pre> tag
1550
+ const newDiv = document.createElement("button");
1551
+ newDiv.onclick = function () {
1552
+ copyCode(/** @type {HTMLElement} */ (this));
1553
+ };
1554
+ newDiv.classList.add("btn", "btn-outline-primary");
1555
+ newDiv.innerHTML = "<span class='ca-gov-icon-copy'></span> Copy code";
1556
+ if (dom.tagName.toLowerCase() == "code") {
1557
+ dom.parentElement.after(newDiv);
1558
+ } else {
1559
+ dom.after(newDiv);
1560
+ }
1564
1561
  }
1565
- }
1566
- });
1562
+ });
1563
+ })();
1567
1564
 
1568
1565
  //@ts-check
1569
1566
 
@@ -1571,7 +1568,7 @@ window.addEventListener("load", () => {
1571
1568
  TABS -- custom accessible tabs
1572
1569
  ----------------------------------------- */
1573
1570
 
1574
- (function () {
1571
+ window.addEventListener("load", () => {
1575
1572
  // Get relevant elements and collections
1576
1573
  const allTabs = document.querySelectorAll(".tabs");
1577
1574
  allTabs.forEach(tabbed => {
@@ -1663,7 +1660,7 @@ window.addEventListener("load", () => {
1663
1660
  tabs[0].setAttribute("aria-selected", "true");
1664
1661
  panels[0].hidden = false;
1665
1662
  });
1666
- })();
1663
+ });
1667
1664
 
1668
1665
  //@ts-check
1669
1666
 
@@ -1737,15 +1734,30 @@ document.addEventListener("DOMContentLoaded", () => {
1737
1734
  });
1738
1735
 
1739
1736
  //@ts-check
1740
- const returnTop = document.querySelector(".return-top");
1737
+ window.addEventListener("load", () => {
1738
+ document.querySelectorAll(".return-top").forEach(returnTop =>
1739
+ returnTop.addEventListener("click", () => {
1740
+ document.body.scrollTop = 0; // For Safari
1741
+ document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
1742
+ })
1743
+ );
1741
1744
 
1742
- // Add on-click event
1743
- returnTop.addEventListener("click", goToTopFunction);
1745
+ // Back to top link in the global footer
1746
+ document
1747
+ .querySelectorAll("a[href='#skip-to-content']")
1748
+ .forEach(backToTop =>
1749
+ backToTop.addEventListener("click", backToTopFunction)
1750
+ );
1744
1751
 
1745
- function goToTopFunction() {
1746
- document.body.scrollTop = 0; // For Safari
1747
- document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
1748
- }
1752
+ /**
1753
+ * @param {Event} event
1754
+ */
1755
+ const backToTopFunction = event => {
1756
+ event.preventDefault();
1757
+ document.body.scrollTop = 0; // For Safari
1758
+ document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
1759
+ };
1760
+ });
1749
1761
 
1750
1762
  // If an user scrolls down the page for more than 400px activate back to top button
1751
1763
  // othervise keep it invisible
@@ -1757,6 +1769,8 @@ window.addEventListener(
1757
1769
  "scroll",
1758
1770
  () => {
1759
1771
  const returnTopButton = document.querySelector(".return-top");
1772
+ if (!returnTopButton) return;
1773
+
1760
1774
  const st = window.pageYOffset || document.documentElement.scrollTop;
1761
1775
  if (st > lastScrollTop) {
1762
1776
  // downscroll code
@@ -1787,27 +1801,13 @@ window.addEventListener(
1787
1801
  );
1788
1802
 
1789
1803
  // Hittin' rock bottom
1790
- window.onscroll = () => {
1804
+ window.addEventListener("scroll", () => {
1791
1805
  const returnTopButton = document.querySelector(".return-top");
1806
+ if (!returnTopButton) return;
1792
1807
  if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
1793
1808
  returnTopButton.classList.add("is-visible");
1794
1809
  }
1795
- };
1796
-
1797
- // Back to top link in the global footer
1798
- const backToTop = document.querySelector("a[href='#skip-to-content']");
1799
- if (backToTop) {
1800
- backToTop.addEventListener("click", backToTopFunction);
1801
- }
1802
-
1803
- /**
1804
- * @param {Event} event
1805
- */
1806
- function backToTopFunction(event) {
1807
- event.preventDefault();
1808
- document.body.scrollTop = 0; // For Safari
1809
- document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
1810
- }
1810
+ });
1811
1811
 
1812
1812
  //@ts-check
1813
1813
 
@@ -1815,35 +1815,36 @@ function backToTopFunction(event) {
1815
1815
  SIDE NAVIGATION - /source/js/cagov/side-navigation.js
1816
1816
  ----------------------------------------- */
1817
1817
 
1818
- (() => {
1818
+ window.addEventListener("load", () => {
1819
1819
  const siteHeader = document.querySelector("header");
1820
1820
  const sidenavigation = document.querySelector(".side-navigation");
1821
- let allSidenavLinks = sidenavigation?.querySelectorAll(".side-navigation a");
1822
- const mainContentSideNavCont = sidenavigation?.closest("div");
1823
- sidenavigation?.setAttribute("id", "side-navigation");
1821
+ if (!sidenavigation || !siteHeader) return;
1822
+ const allSidenavLinks = sidenavigation.querySelectorAll(".side-navigation a");
1823
+ const mainContentSideNavCont = sidenavigation.closest("div");
1824
+ sidenavigation.setAttribute("id", "side-navigation");
1824
1825
  const topposition = localStorage.getItem("sidebar-scroll");
1825
1826
  const mobileCntls = document.querySelector(".global-header .mobile-controls");
1826
- let mobileControlsDisplay = getComputedStyle(mobileCntls).display; // Side nav height vs viewport
1827
+ if (!mobileCntls) return;
1828
+ let mobileControlsDisplay = window.getComputedStyle(mobileCntls).display; // Side nav height vs viewport
1827
1829
  const siteHeaderHeight = siteHeader ? siteHeader.clientHeight : 0;
1828
1830
  const mobileView$3 = () =>
1829
- getComputedStyle(document.querySelector(".global-header .mobile-controls"))[
1830
- "display"
1831
- ] !== "none";
1831
+ getComputedStyle(mobileCntls)["display"] !== "none";
1832
1832
  let timeout = 0;
1833
1833
  const delay = 250; // delay between calls
1834
- let mobileSideNavDiv;
1835
- let mobileSideNavCont;
1836
- let sidenavToggleBtn;
1834
+ /** @type {HTMLElement} */
1835
+ let mobileSideNavDiv,
1836
+ /** @type {HTMLDivElement} */ mobileSideNavCont,
1837
+ /** @type {HTMLButtonElement} */ sidenavToggleBtn;
1837
1838
 
1838
- function createMobileSideNavButton() {
1839
+ const createMobileSideNavButton = () => {
1839
1840
  // get first side nav element
1840
- /** @type {HTMLAnchorElement} */
1841
+ /** @type {HTMLAnchorElement | null} */
1841
1842
  const sidenavTItle = document.querySelector(".side-navigation a, .sidenav");
1842
1843
 
1843
1844
  if (sidenavTItle) {
1844
1845
  // get text for the button for first side nav element
1845
1846
  let btnText = sidenavTItle.innerText;
1846
- const btnTextSpan = sidenavTItle.querySelector("span")?.innerText; // removing the sr-only span and it's content
1847
+ const btnTextSpan = sidenavTItle.querySelector("span")?.innerText || ""; // removing the sr-only span and it's content
1847
1848
  btnText = btnText.replace(btnTextSpan, "").trim();
1848
1849
  // create button container
1849
1850
  const sidenavMobile = document.createElement("aside");
@@ -1868,37 +1869,40 @@ function backToTopFunction(event) {
1868
1869
  // add click event
1869
1870
  sidenavToggleBtn.addEventListener("click", toggleSideNav);
1870
1871
  }
1871
- }
1872
+ };
1872
1873
 
1873
- function createmobileSideNavDiv() {
1874
+ const createmobileSideNavDiv = () => {
1874
1875
  mobileSideNavDiv = document.createElement("aside");
1875
1876
  mobileSideNavDiv.setAttribute("class", "mobile-sidenav");
1876
1877
  mobileSideNavCont = document.createElement("div");
1877
1878
  mobileSideNavCont.setAttribute("class", "container");
1878
1879
  mobileSideNavDiv.append(mobileSideNavCont);
1879
1880
  siteHeader.after(mobileSideNavDiv);
1880
- }
1881
+ };
1881
1882
 
1882
1883
  // MOBILE Side nav
1883
- function moveSideNavToHeader() {
1884
- mobileSideNavCont?.append(sidenavigation);
1884
+ const moveSideNavToHeader = () => {
1885
+ if (mobileSideNavCont) {
1886
+ mobileSideNavCont.append(sidenavigation);
1887
+ }
1888
+
1885
1889
  sidenavigation.setAttribute("aria-hidden", "true");
1886
1890
  allSidenavLinks?.forEach(el => {
1887
1891
  el.setAttribute("tabindex", "-1");
1888
1892
  });
1889
- }
1893
+ };
1890
1894
 
1891
1895
  // DESKTOP Side nav
1892
- function moveSideNavToMainContent() {
1896
+ const moveSideNavToMainContent = () => {
1893
1897
  mainContentSideNavCont?.append(sidenavigation);
1894
1898
  sidenavigation.removeAttribute("aria-hidden");
1895
1899
  allSidenavLinks?.forEach(el => {
1896
1900
  el.removeAttribute("tabindex");
1897
1901
  });
1898
- }
1902
+ };
1899
1903
 
1900
1904
  // Mobile Side Nav Button click function
1901
- function toggleSideNav() {
1905
+ const toggleSideNav = () => {
1902
1906
  mobileSideNavDiv.classList.toggle("visible");
1903
1907
  // Open
1904
1908
  if (mobileSideNavDiv.classList.contains("visible")) {
@@ -1916,7 +1920,7 @@ function backToTopFunction(event) {
1916
1920
  el.setAttribute("tabindex", "-1");
1917
1921
  });
1918
1922
  }
1919
- }
1923
+ };
1920
1924
 
1921
1925
  // Set active class on nav-heading links
1922
1926
  function addActiveClass() {
@@ -1929,14 +1933,14 @@ function backToTopFunction(event) {
1929
1933
  active_link[i].className += " active";
1930
1934
  }
1931
1935
 
1932
- function sidenavOverflow() {
1936
+ const sidenavOverflow = () => {
1933
1937
  if (!mobileView$3()) {
1934
1938
  const viewportheight = document.documentElement.clientHeight;
1935
1939
  const viewportMinusHeader = viewportheight - siteHeaderHeight - 100;
1936
1940
 
1937
1941
  if (
1938
1942
  viewportMinusHeader <=
1939
- document.querySelector(".side-navigation").clientHeight
1943
+ (document.querySelector(".side-navigation")?.clientHeight || 0)
1940
1944
  ) {
1941
1945
  sidenavigation.classList.add("overflow-auto"); // sidenavigation.setAttribute("style", "max-height:" + viewportMinusHeader + "px")
1942
1946
  } else {
@@ -1963,37 +1967,35 @@ function backToTopFunction(event) {
1963
1967
  sidenavigation.scrollTop.toString()
1964
1968
  );
1965
1969
  });
1966
- }
1970
+ };
1967
1971
 
1968
- if (sidenavigation) {
1969
- // ONLOAD
1970
- addActiveClass();
1971
- createmobileSideNavDiv();
1972
- createMobileSideNavButton();
1972
+ // ONLOAD
1973
+ addActiveClass();
1974
+ createmobileSideNavDiv();
1975
+ createMobileSideNavButton();
1973
1976
 
1977
+ if (mobileControlsDisplay == "block") {
1978
+ moveSideNavToHeader();
1979
+ }
1980
+ // on resize
1981
+ window.addEventListener("resize", () => {
1982
+ mobileControlsDisplay = getComputedStyle(mobileCntls).display; // clear the timeout
1983
+
1984
+ window.clearTimeout(timeout); // start timing for event "completion"
1985
+ timeout = window.setTimeout(sidenavOverflow, delay); // if mobile
1974
1986
  if (mobileControlsDisplay == "block") {
1975
- moveSideNavToHeader();
1987
+ moveSideNavToHeader(); // if desctop
1988
+ } else {
1989
+ moveSideNavToMainContent();
1976
1990
  }
1977
- // on resize
1978
- window.addEventListener("resize", () => {
1979
- mobileControlsDisplay = getComputedStyle(mobileCntls).display; // clear the timeout
1980
-
1981
- window.clearTimeout(timeout); // start timing for event "completion"
1982
- timeout = window.setTimeout(sidenavOverflow, delay); // if mobile
1983
- if (mobileControlsDisplay == "block") {
1984
- moveSideNavToHeader(); // if desctop
1985
- } else {
1986
- moveSideNavToMainContent();
1987
- }
1988
- });
1989
- sidenavOverflow();
1990
- }
1991
- })();
1991
+ });
1992
+ sidenavOverflow();
1993
+ });
1992
1994
 
1993
1995
  //@ts-check
1994
1996
 
1995
1997
  /* EXTERNAL LINK ICON */
1996
- function linkAnnotator() {
1998
+ window.addEventListener("load", () => {
1997
1999
  const ext = '<span class="external-link-icon" aria-hidden="true"></span>';
1998
2000
 
1999
2001
  // Check if link is external function
@@ -2026,15 +2028,13 @@ function linkAnnotator() {
2026
2028
  linkElement.innerHTML += ext; // += concatenates to external links
2027
2029
  }
2028
2030
  });
2029
- }
2030
-
2031
- linkAnnotator();
2031
+ });
2032
2032
 
2033
2033
  //@ts-check
2034
2034
  /* -----------------------------------------
2035
2035
  PAGE NAVIGATION - /source/js/cagov/page-navigation.js
2036
2036
  ----------------------------------------- */
2037
- (() => {
2037
+ window.addEventListener("load", () => {
2038
2038
  const headings = document.querySelectorAll("h2");
2039
2039
  const h2heading = document.querySelector("h2");
2040
2040
  const pagenav = document.querySelector(".page-navigation");
@@ -2082,7 +2082,7 @@ linkAnnotator();
2082
2082
  pagenav.appendChild(pagenavUL);
2083
2083
  pagenav.setAttribute("aria-labelledby", "on-this-page-navigation-label");
2084
2084
  }
2085
- })(); // call out the function on the page load
2085
+ }); // call out the function on the page load
2086
2086
 
2087
2087
  //@ts-check
2088
2088
  /* -----------------------------------------
@@ -2367,197 +2367,177 @@ class CAGovPagination extends HTMLElement {
2367
2367
  );
2368
2368
  }
2369
2369
  }
2370
-
2371
- window.customElements.define("cagov-pagination", CAGovPagination);
2372
-
2370
+ window.addEventListener("load", () => {
2371
+ window.customElements.define("cagov-pagination", CAGovPagination);
2372
+ });
2373
2373
  //export { CAGovPagination };
2374
2374
 
2375
2375
  //@ts-check
2376
2376
 
2377
- (() => {
2377
+ window.addEventListener("load", () => {
2378
2378
  // VARIABLES
2379
- const bodyCont = document.querySelector("body");
2380
- const mainNav = document.querySelector(".main-navigation");
2381
2379
  const navButton = document.querySelector(".toggle-menu");
2382
- const navSearchCont = document.querySelector(".navigation-search");
2383
- const mobileCntls = document.querySelector(".global-header .mobile-controls");
2384
- const mainCont = document.querySelector(".main-content");
2385
- const footerGlobal = document.querySelector("footer");
2386
- const footerSite = document.querySelector(".site-footer");
2387
- const headerutility = document.querySelector(".utility-header");
2388
- const regularHeader = document.querySelector("header");
2389
- const headerutilityLinksCont = document.querySelector(
2390
- ".utility-header .container .flex-row"
2391
- );
2392
- const navButtonCont = document.querySelector(
2393
- ".mobile-controls .main-nav-icons"
2394
- );
2395
- const siteBranding = document.querySelector(".branding");
2396
- const utilityLinks = document.querySelector(".settings-links");
2397
- let mobileControlsDisplay = getComputedStyle(mobileCntls).display;
2398
- let allNavLinks;
2399
- let allUtilityLinks;
2400
- // We need timeout here to make sure navigation is created first (becasue naviagion.js is creating button elements dynamicaly) and then we can assign all thise links to our variable
2401
- setTimeout(() => {
2402
- allNavLinks = document.querySelectorAll(
2380
+ if (!navButton) return;
2381
+
2382
+ const getAllNavLinks = () =>
2383
+ document.querySelectorAll(
2403
2384
  '.navigation-search a.first-level-link, .navigation-search button.first-level-btn, .navigation-search input, .navigation-search button, .navigation-search [tabindex]:not([tabindex="-1"])'
2404
2385
  );
2405
- allUtilityLinks = document.querySelectorAll(
2386
+
2387
+ const getAllUtilityLinks = () =>
2388
+ document.querySelectorAll(
2406
2389
  '.settings-links a, .settings-links button, .settings-links input, .settings-links select, .settings-links [tabindex]:not([tabindex="-1"])'
2407
2390
  );
2408
- }, 100);
2409
2391
 
2410
2392
  // all focusable elements other than navigation
2411
- const allBodyLinks = document.querySelectorAll(
2412
- '.utility-header .social-media-links a, .utility-header .social-media-links input, .utility-header .social-media-links button, .utility-header .social-media-links [tabindex]:not([tabindex="-1"]), .branding a, .branding button, .branding input, .branding select, .main-content a[href], .main-content button, .main-content input, .main-content textarea, .main-content select, .main-content details, .main-content [tabindex]:not([tabindex="-1"]), .site-footer a[href], .site-footer button, .site-footer input, .site-footer textarea, .site-footer select, .site-footer details, .site-footer [tabindex]:not([tabindex="-1"]), footer a[href], footer button, footer input, footer textarea, footer select, footer details, footer [tabindex]:not([tabindex="-1"])'
2413
- );
2393
+ const getAllBodyLinks = () =>
2394
+ document.querySelectorAll(
2395
+ '.utility-header .social-media-links a, .utility-header .social-media-links input, .utility-header .social-media-links button, .utility-header .social-media-links [tabindex]:not([tabindex="-1"]), .branding a, .branding button, .branding input, .branding select, .main-content a[href], .main-content button, .main-content input, .main-content textarea, .main-content select, .main-content details, .main-content [tabindex]:not([tabindex="-1"]), .site-footer a[href], .site-footer button, .site-footer input, .site-footer textarea, .site-footer select, .site-footer details, .site-footer [tabindex]:not([tabindex="-1"]), footer a[href], footer button, footer input, footer textarea, footer select, footer details, footer [tabindex]:not([tabindex="-1"])'
2396
+ );
2414
2397
 
2415
2398
  // create container for drawer mobile nav items
2416
2399
  const mobileItemsCont = document.createElement("div");
2417
2400
  mobileItemsCont.setAttribute("class", "nav-drawer");
2418
2401
 
2419
2402
  // move mobile navigation toggle button back into mobile controls container
2420
- function moveNavToggleButtonToMobileControlsContainer() {
2403
+ const moveNavToggleButtonToMobileControlsContainer = () => {
2404
+ const navButtonCont = document.querySelector(
2405
+ ".mobile-controls .main-nav-icons"
2406
+ );
2421
2407
  setTimeout(() => {
2422
2408
  navButton.setAttribute("aria-expanded", "false");
2423
2409
  navButtonCont?.append(navButton);
2424
2410
  }, 300);
2425
- }
2411
+ };
2426
2412
 
2427
- // ONLOAD
2428
- window.onload = function () {
2429
- // move duplicated logo to navigation drawer section
2430
- navSearchCont?.prepend(mobileItemsCont);
2413
+ const setHidden = (/** @type {boolean} */ hide) => {
2414
+ const mainCont = document.querySelector(".main-content");
2415
+ const footerGlobal = document.querySelector("footer");
2416
+ const footerSite = document.querySelector(".site-footer");
2417
+ const headerutility = document.querySelector(".utility-header");
2418
+ const siteBranding = document.querySelector(".branding");
2419
+ const regularHeader = document.querySelector("header");
2431
2420
 
2432
- // if mobile
2433
- if (mobileControlsDisplay == "block") {
2434
- mobileNavDefault();
2435
- // if desktop
2421
+ if (hide) {
2422
+ mainCont?.setAttribute("aria-hidden", "true");
2423
+ footerGlobal?.setAttribute("aria-hidden", "true");
2424
+ footerSite?.setAttribute("aria-hidden", "true");
2425
+ headerutility?.setAttribute("aria-hidden", "true");
2426
+ siteBranding?.setAttribute("aria-hidden", "true");
2427
+ regularHeader?.classList.add("nav-overlay");
2436
2428
  } else {
2437
- desktopNavDefault();
2429
+ //show
2430
+ mainCont?.removeAttribute("aria-hidden");
2431
+ footerGlobal?.removeAttribute("aria-hidden");
2432
+ footerSite?.removeAttribute("aria-hidden");
2433
+ headerutility?.removeAttribute("aria-hidden");
2434
+ siteBranding?.removeAttribute("aria-hidden");
2435
+ regularHeader?.classList.remove("nav-overlay");
2438
2436
  }
2439
2437
  };
2440
2438
 
2441
2439
  // Button click open and close menu function
2442
- function openMenu() {
2440
+ const openMenu = () => {
2443
2441
  mobileItemsCont.append(navButton);
2442
+ const navSearchCont = document.querySelector(".navigation-search");
2444
2443
  navSearchCont?.classList.toggle("visible");
2445
2444
  navSearchCont?.classList.toggle("not-visible");
2446
2445
  // Open
2447
2446
  if (navSearchCont?.classList.contains("visible")) {
2448
2447
  navButton.setAttribute("aria-expanded", "true");
2449
- bodyCont?.classList.add("overflow-hidden");
2448
+ document.body.classList.add("overflow-hidden");
2450
2449
  navSearchCont?.setAttribute("aria-hidden", "false");
2451
2450
  // make links focusable
2452
- allNavLinks?.forEach(el => {
2453
- el.removeAttribute("tabindex");
2454
- });
2455
- allUtilityLinks?.forEach(el => {
2456
- el.removeAttribute("tabindex");
2457
- });
2451
+ getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
2452
+ getAllUtilityLinks().forEach(el => el.removeAttribute("tabindex"));
2458
2453
  // make all the rest of the links not focusable
2459
- allBodyLinks?.forEach(el => {
2460
- el.setAttribute("tabindex", "-1");
2461
- });
2454
+ getAllBodyLinks().forEach(el => el.setAttribute("tabindex", "-1"));
2462
2455
  // Hide all the website areas (add aria-hidden)
2463
- mainCont?.setAttribute("aria-hidden", "true");
2464
- footerGlobal?.setAttribute("aria-hidden", "true");
2465
- footerSite?.setAttribute("aria-hidden", "true");
2466
- headerutility?.setAttribute("aria-hidden", "true");
2467
- siteBranding?.setAttribute("aria-hidden", "true");
2468
- regularHeader?.classList.add("nav-overlay");
2456
+ setHidden(true);
2457
+
2469
2458
  // Close
2470
2459
  } else {
2471
2460
  navButton.setAttribute("aria-expanded", "false");
2472
- bodyCont?.classList.remove("overflow-hidden");
2461
+ document.body.classList.remove("overflow-hidden");
2473
2462
  navSearchCont?.setAttribute("aria-hidden", "true");
2474
2463
  // removing focus
2475
- allNavLinks?.forEach(el => {
2476
- el.setAttribute("tabindex", "-1");
2477
- });
2478
- allUtilityLinks?.forEach(el => {
2479
- el.setAttribute("tabindex", "-1");
2480
- });
2481
- allBodyLinks?.forEach(el => {
2482
- el.removeAttribute("tabindex");
2483
- });
2464
+ getAllNavLinks().forEach(el => el.setAttribute("tabindex", "-1"));
2465
+ getAllUtilityLinks().forEach(el => el.setAttribute("tabindex", "-1"));
2466
+ getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
2484
2467
  // remove aria hidden for the rest of the site
2485
- mainCont?.removeAttribute("aria-hidden");
2486
- footerGlobal?.removeAttribute("aria-hidden");
2487
- footerSite?.removeAttribute("aria-hidden");
2488
- headerutility?.removeAttribute("aria-hidden");
2489
- siteBranding?.removeAttribute("aria-hidden");
2490
- regularHeader?.classList.remove("nav-overlay");
2468
+ setHidden(false);
2491
2469
  moveNavToggleButtonToMobileControlsContainer();
2492
2470
  }
2493
- }
2471
+ };
2494
2472
 
2495
2473
  // Default state for mobile
2496
- function mobileNavDefault() {
2474
+ const mobileNavDefault = () => {
2497
2475
  moveNavToggleButtonToMobileControlsContainer();
2498
- mainNav?.before(utilityLinks);
2499
- bodyCont?.classList.remove("overflow-hidden");
2476
+ const mainNav = document.querySelector(".main-navigation");
2477
+ const utilityLinks = document.querySelector(".settings-links");
2478
+ if (mainNav && utilityLinks) mainNav.before(utilityLinks);
2479
+ document.body.classList.remove("overflow-hidden");
2480
+
2481
+ const navSearchCont = document.querySelector(".navigation-search");
2500
2482
  navSearchCont?.classList.add("not-visible");
2501
2483
  navSearchCont?.classList.remove("visible");
2502
2484
  navSearchCont?.setAttribute("aria-hidden", "true");
2503
2485
  // removing focus
2504
- allNavLinks?.forEach(el => {
2505
- el.setAttribute("tabindex", "-1");
2506
- });
2507
- allUtilityLinks?.forEach(el => {
2508
- el.setAttribute("tabindex", "-1");
2509
- });
2510
- allBodyLinks?.forEach(el => {
2511
- el.removeAttribute("tabindex");
2512
- });
2486
+ getAllNavLinks().forEach(el => el.setAttribute("tabindex", "-1"));
2487
+ getAllUtilityLinks().forEach(el => el.setAttribute("tabindex", "-1"));
2488
+ getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
2513
2489
  // remove aria hidden for the rest of the site
2514
- mainCont?.removeAttribute("aria-hidden");
2515
- footerGlobal?.removeAttribute("aria-hidden");
2516
- footerSite?.removeAttribute("aria-hidden");
2517
- headerutility?.removeAttribute("aria-hidden");
2518
- siteBranding?.removeAttribute("aria-hidden");
2519
- regularHeader?.classList.remove("nav-overlay");
2520
- }
2490
+ setHidden(false);
2491
+ };
2521
2492
 
2522
2493
  // Default state for desktop
2523
- function desktopNavDefault() {
2494
+ const desktopNavDefault = () => {
2524
2495
  moveNavToggleButtonToMobileControlsContainer();
2525
- headerutilityLinksCont?.append(utilityLinks);
2526
- bodyCont?.classList.remove("overflow-hidden");
2496
+ const utilityLinks = document.querySelector(".settings-links");
2497
+ const headerutilityLinksCont = document.querySelector(
2498
+ ".utility-header .container .flex-row"
2499
+ );
2500
+ if (utilityLinks && headerutilityLinksCont)
2501
+ headerutilityLinksCont.append(utilityLinks);
2502
+ document.body.classList.remove("overflow-hidden");
2503
+ const navSearchCont = document.querySelector(".navigation-search");
2527
2504
  navSearchCont?.classList.remove("visible");
2528
2505
  navSearchCont?.classList.remove("not-visible");
2529
2506
  navSearchCont?.setAttribute("aria-hidden", "false");
2530
- allNavLinks?.forEach(el => {
2531
- el.removeAttribute("tabindex");
2532
- });
2533
- allUtilityLinks?.forEach(el => {
2534
- el.removeAttribute("tabindex");
2535
- });
2536
- allBodyLinks?.forEach(el => {
2537
- el.removeAttribute("tabindex");
2538
- });
2507
+ getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
2508
+ getAllUtilityLinks().forEach(el => el.removeAttribute("tabindex"));
2509
+ getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
2539
2510
  // remove aria hidden for the rest of the site
2540
- mainCont?.removeAttribute("aria-hidden");
2541
- footerGlobal?.removeAttribute("aria-hidden");
2542
- footerSite?.removeAttribute("aria-hidden");
2543
- headerutility?.removeAttribute("aria-hidden");
2544
- siteBranding?.removeAttribute("aria-hidden");
2545
- regularHeader?.classList.remove("nav-overlay");
2546
- }
2511
+ setHidden(false);
2512
+ };
2547
2513
 
2548
2514
  // Button Click event
2549
2515
  navButton.addEventListener("click", openMenu);
2550
2516
 
2551
- // on resize function (hide mobile nav)
2552
- window.addEventListener("resize", () => {
2553
- // set changing wariable in here
2554
- mobileControlsDisplay = getComputedStyle(mobileCntls).display;
2555
- // if mobile
2517
+ const mobileCheck = () => {
2518
+ const mobileCntls = document.querySelector(
2519
+ ".global-header .mobile-controls"
2520
+ );
2521
+
2522
+ const mobileControlsDisplay = mobileCntls
2523
+ ? window.getComputedStyle(mobileCntls).display
2524
+ : "";
2525
+
2556
2526
  if (mobileControlsDisplay == "block") {
2557
2527
  mobileNavDefault();
2558
- // if desctop
2528
+ // if desktop
2559
2529
  } else {
2560
2530
  desktopNavDefault();
2561
2531
  }
2562
- });
2563
- })();
2532
+ };
2533
+
2534
+ // on resize function (hide mobile nav)
2535
+ window.addEventListener("resize", mobileCheck);
2536
+
2537
+ // ONLOAD
2538
+ // move duplicated logo to navigation drawer section
2539
+ const navSearchCont = document.querySelector(".navigation-search");
2540
+ navSearchCont?.prepend(mobileItemsCont);
2541
+
2542
+ mobileCheck();
2543
+ });