1const navContainer = document.getElementById('nav-container'); 2/* ~~~~~~~~~~~~~~~~~~~~~~~~ image SPECIFIC FUNCTION ~~~~~~~~~~~~~~~~~~~~~~~~ */ 3const lazyImages = document.getElementsByClassName('lazyload'); 4const closeBtn = document.getElementsByClassName('close'); 5const compareInput = document.getElementsByClassName('compare-content'); 6const largeImages = document.getElementsByClassName("photo-container"); 7const remember = document.getElementById("remember"); 8const chatLink = document.getElementsByClassName("chat-link"); 9function lazyLoad(e){ 10 var imageBG; 11 if(e.getAttribute("data-src")) { 12 imageBG = e.getAttribute("data-src") 13 e.classList.remove('lazyload') 14 } 15 else if (e.getAttribute("data-src-sm") && window.innerWidth < 600) { 16 imageBG = e.getAttribute("data-src-sm"); 17 } 18 else if (e.getAttribute("data-src-lrg")) { 19 imageBG = e.getAttribute("data-src-lrg") 20 } 21 e.style.backgroundImage = "url('" + imageBG + "')"; 22} 23function imageLoop(){ 24 for (i=0;i<lazyImages.length; i++){ 25 if((window.pageYOffset - 200) <= lazyImages[i].offsetTop || lazyImages[i].offsetTop < 200 ){ 26 lazyLoad(lazyImages[i]) 27 } 28 } 29} 30window.addEventListener("resize", imageLoop) 31window.addEventListener("scroll", imageLoop) 32imageLoop(); 33/* ~~~~~~~~~~~~~~~~~~~~~~~~ close box ~~~~~~~~~~~~~~~~~~~~~~~~ */ 34function hideParent(e){ 35 e.parentNode.classList.add('hide') 36} 37/* ~~~~~~~~~~~~~~~~~~~~~~~~ Holiday Hours and other downtime support for chat ~~~~~~~~~~~~~~~~~~~~~~~~ */ 38var chatHours = document.createElement("div"); 39chatHours.id = "chathours"; 40chatHours.style.display = "none"; 41chatHours.innerHTML = '<div id="preamble"><p>You may chat live with a Provident agent <b>Monday-Friday 7am - 7pm</b>, and <b>Saturday 9am-5pm</b>. Not available during holidays.</p><!-- This gets replaced by the JS --></div><h2>Holiday Schedule:</h2><table cellspacing="0" class="table" width="100%"><thead><th style="text-align:left">Date</th><th style="text-align:left">Holiday</th></thead><tbody></tbody></table>'; 42document.body.appendChild(chatHours) 43/* ~~~~~~~~~~~~~~~~~~~~~~~~ Event Listeners ~~~~~~~~~~~~~~~~~~~~~~~~ */ 44/*nav */ 45if(remember) { 46 remember.addEventListener('click', function(event){ 47 event.target.checked ? event.target.parentNode.classList.add('selected') : event.target.parentNode.classList.remove('selected') 48 }) 49} 50document.addEventListener("DOMContentLoaded", function(){ 51 function checkGliaLoaded(ChatLink) { 52 if(typeof sm != "undefined" && typeof sm.getApi != "undefined"){ 53 upDateGliaChat(ChatLink) 54 } else { 55 setTimeout(checkGliaLoaded, 1000, ChatLink ) 56 } 57 } 58 59 for(i=0; i<chatLink.length;i++) { 60 let ChatLink = chatLink[i]; 61 if(typeof currentlyOpen != "undefined" && currentlyOpen) { 62 ChatLink.setAttribute('data-sm-show-media-selection-on', 'click'); 63 checkGliaLoaded(ChatLink); 64 } else { 65 ChatLink.addEventListener('click', function(event){ 66 popDetails(document.getElementById('chathours').innerHTML, 'Chat is Closed', 650, 550, false, false); 67 event.preventDefault(); 68 }) 69 } 70 } 71}) 72function upDateGliaChat(ChatLink){ 73 sm.getApi({version: 'v1'}).then(function(glia) { 74 glia.removeEventListener(glia.EVENTS.QUEUE_STATE_UPDATE, onQueueStateUpdateForChat) 75 function onQueueStateUpdateForChat(queueState) { 76 if (queueState.state !== queueState.QUEUE_STATES.CAN_QUEUE) { 77 if(ChatLink) ChatLink.classList.add("disabled"); 78 } else { 79 if(ChatLink) ChatLink.classList.remove("disabled"); 80 } 81 } 82 glia.addEventListener(glia.EVENTS.QUEUE_STATE_UPDATE, onQueueStateUpdateForChat); 83 }); 84} 85 86for (i=0;i<closeBtn.length;i++){ 87 closeBtn[i].addEventListener("click", function(event) { 88 hideParent(event.target) 89 if(document.getElementsByClassName("slider-controls")[0]) { 90 document.getElementsByClassName("slider-controls")[0].focus(); 91 } 92 }); 93} 94 95imageLoop() 96/* ~~~~~~~~~~~~~~ alert script ~~~~~~~~~~~~~~~~~~~~~ */ 97const downtimeAlert = document.getElementsByClassName("downtime")[0] 98const signOn = document.getElementById("action-links-container").getElementsByTagName("LI")[0] 99if(downtimeAlert) { 100 signOn.style.opacity = ".5" 101 signOn.getElementsByTagName("A")[0].style.cursor = "default" 102 signOn.getElementsByTagName("A")[0].setAttribute("href", "#") 103 document.getElementById("signon").style.display = "none" 104} 105/* ~~~~~~~~~~~~~~~~~~~~~~~~ NAV SPECIFIC FUNCTION ~~~~~~~~~~~~~~~~~~~~~~~~ */ 106const nav = document.getElementsByTagName('nav')[0]; 107const dropNav = document.getElementsByClassName('drop-nav'); 108const topNav = document.getElementsByClassName('top-nav'); 109const burgerMenu = document.getElementById("burger-menu"); 110const mainNavContainer = document.getElementById("nav-link-container"); 111const searchButton = document.getElementById('search-bar'); 112const topNavWidget = document.getElementsByClassName('top-navigation-widget')[0]; 113if(typeof focusableElements == "undefined"){ 114 var focusableElements = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not
114([tabindex^="-"])']; 115} 116const focEl = document.querySelectorAll(focusableElements); // not used? 117function deselectTopNav(){ 118 topNavWidget.classList.remove('expand'); 119 document.getElementsByTagName('body')[0].classList.remove('expand'); 120 for(i=0; i < topNav.length;i++){ 121 topNav[i].querySelector('button').classList.remove('open'); 122 topNav[i].querySelector('.drop-nav').classList.remove('open'); 123 topNav[i].classList.remove('open'); 124 } 125} 126function hightlightNav(event) { 127 deselectTopNav(); 128 event.target.classList.add('open'); 129 event.target.nextElementSibling.classList.add('open'); 130 topNavWidget.classList.add('open'); 131 topNavWidget.classList.add('expand'); 132 document.getElementsByTagName('body')[0].classList.add('expand'); 133 event.target.closest(".top-nav").classList.add('open'); 134} 135/* ~~~~~~~~~~~~~~~~~~~~~~~~ search ~~~~~~~~~~~~~~~~~~~~~~~~ */ 136const navSearch = document.getElementById('nav-search') 137const searchField = document.getElementById('SearchInput') 138function openSearch(e){ 139 navSearch.classList.toggle('open'); 140 if(navSearch.classList.contains('open')) setTimeout(function() { searchField.focus()}, 501); 141 e.preventDefault(); 142} 143if(navSearch) navSearch.getElementsByTagName("A")[0].addEventListener('click', openSearch); 144/* ~~~~~~~~~~~~~~~~~~~~~~~~ dropdown ~~~~~~~~~~~~~~~~~~~~~~~~ */ 145for (i=0; i< topNav.length;i++){ 146 topNav[i].firstElementChild.addEventListener("click", function(event) { 147 if (event.target.tagName !="A"){ 148 navContainer.classList.add('open'); 149 burgerMenu.classList.add('open'); 150 topNavWidget.classList.add('open'); 151 hightlightNav(event); 152 } 153 }); 154} 155if(burgerMenu){ 156 burgerMenu.addEventListener('click', function(event){ 157 burgerMenu.classList.toggle('open'); 158 navContainer.classList.toggle('open'); 159 topNavWidget.classList.toggle('open'); 160 if(burgerMenu.classList != "expand") { 161 topNavWidget.classList.remove('expand'); 162 document.getElementsByTagName('body')[0].classList.remove('expand'); 163 } 164 }) 165} 166/* outside of the nav */ 167Element.prototype.parents = function(selector){ 168 // returns all ancestor elements, or optionally all that match the selector. If none, returns false 169 var elements = []; 170 var elem = this; 171 var useSelector = selector !== undefined; 172 while ((elem = elem.parentElement) !== null){ 173 if(elem.nodeType !== Node.ELEMENT_NODE) continue; 174 if(!useSelector || elem.matches(selector)) elements.push(elem); 175 } 176 if(elements.length == 0) elements = false 177 return elements; 178 } 179Element.prototype.matchingParent = function(selector){ 180 // returns first matching ancestor element (or parentElement if no selector). If none, returns false 181 var elem = this; 182 var useSelector = selector !== undefined; 183 while ((elem = elem.parentElement) !== null){ 184 if(elem.nodeType !== Node.ELEMENT_NODE) continue; 185 if(!useSelector || elem.matches(selector)) return elem; 186 } 187 return false; 188} 189/* IE polyfill for matches() */ 190if (!Element.prototype.matches) { 191 Element.prototype.matches = 192 Element.prototype.matchesSelector || 193 Element.prototype.mozMatchesSelector || 194 Element.prototype.msMatchesSelector || 195 Element.prototype.oMatchesSelector || 196 Element.prototype.webkitMatchesSelector || 197 function(s) { 198 var matches = (this.document || this.ownerDocument).querySelectorAll(s), 199 i = matches.length; 200 while (--i >= 0 && matches.item(i) !== this) {} 201 return i > -1; 202 }; 203} 204/* IE polyfill for forEach() */ 205if (window.NodeList && !NodeList.prototype.forEach) { 206 NodeList.prototype.forEach = Array.prototype.forEach; 207} 208document.querySelectorAll(focusableElements).forEach(function(focEl){ 209 let mq = window.matchMedia('(max-width: 768px)'); 210 focEl.addEventListener("focus", function(event){ 211 let inTopNav = (event.target).classList.contains("bar") || (event.target) == document.getElementById("nav-chat-link") || (event.target).matchingParent(".top-nav") || (event.target) == burgerMenu || (event.target).matchingParent('#burger-menu') || (event.target).matchingParent('.search-bar') || (event.target).matchingParent("iframe") || (event.target).matchingParent("#nav-search") || (mq.matches && (event.target).matchingParent("#action-links-container")); 212 let inSearch = (event.target).matchingParent("#nav-search"); 213 if(!inTopNav){ 214 deselectTopNav() 215 if(navContainer) { 216 navContainer.classList.remove("open"); 217 } 218 if(burgerMenu) { 219 burgerMenu.classList.remove('open'); 220 } 221 topNavWidget.classList.remove('open'); 222 } 223 if (navSearch && !inSearch){ /* search exists and the click element was the seach*/ 224 if(event.target.classList.contains("focus-visible")) navSearch.classList.remove('open'); 225 } 226 }) 227}) 228let scrollEventNav = window.onscroll=function(){ 229 var initialY = window.pageYOffset; 230 var newY; 231 setTimeout(function () { 232 newY = window.pageYOffset 233 var scrollAmount = Math.abs(initialY - newY) 234 if(scrollAmount > 100) { 235 deselectTopNav() 236 burgerMenu.classList.remove('open'); 237 navSearch.classList.remove("open") 238 if(navContainer) navContainer.classList.remove("open") 239 } 240 } 241 ,500); 242} 243// function to change one type of element into another, while preserving contents and attributes (used in a11y.js, but probably useful elsewhere): 244function replaceElement(source, newType) { 245 const frag = document.createDocumentFragment(); 246 while (source.firstChild) { 247 frag.appendChild(source.firstChild); 248 } 249 const newElem = document.createElement(newType); 250 newElem.appendChild(frag); 251 252 if (source.hasAttributes()) { 253 let attrs = source.attributes; 254 for(let i = attrs.length - 1; i >= 0; i--) { 255 newElem.setAttribute( attrs[i].name, attrs[i].value ); 256 } 257 } 258 source.parentNode.replaceChild(newElem, source); 259} 260/* ~~~~~~~~~~~~~~~~~~~~~~~~ comparison ~~~~~~~~~~~~~~~~~~~~~~~~ */ 261let counter = 0; 262const allContainers = document.getElementsByClassName('compare'); 263const allSelected = document.getElementsByClassName('compare-selected'); 264const comparisonPopup = document.getElementById('comparisonButton'); 265const tableWidget = document.getElementsByClassName('table-widget')[0] 266const legalWidget = document.getElementsByClassName('legal-widget')[0] 267function visibleButtons(state){ 268 (state == true) ? comparisonPopup.removeAttribute("disabled") : comparisonPopup.setAttribute("disabled", "disabled"); 269}; 270//runs when a card is clicked 271function checkState(accountSelected) { 272 counter = 0 273 if(accountSelected.classList.contains('compare-selected')){ 274 accountSelected.classList.remove("compare-selected"); 275 } 276 else { 277 accountSelected.classList.add("compare-selected"); 278 } 279 for(i=0; i<allContainers.length; i++){ 280 if(allContainers[i].classList.contains('compare-selected')){
281 counter +=1 282 } 283 } 284 if(counter >1 && counter <= 3 ) { 285 visibleButtons(true) 286 } 287 else if (counter > 3){ 288 accountSelected.classList.remove("compare-selected") 289 alert ("Our comparison page supports up to three cards at a time. To compare this card please uncheck one of your previous choices.") 290 } 291 else { 292 visibleButtons(false) 293 } 294} 295function displayCompTable(showArr,hideArr){ 296 tableWidget.style.display = "block"; 297 if(legalWidget) { 298 legalWidget.style.display = "block"; 299 300 } 301 for(i=0; i <showArr.length;i++) { 302 let showCell = document.getElementsByClassName(showArr[i]) 303 for(j=0;j<showCell.length;j++) { 304 showCell[j].style.display = "table-cell" 305 } 306 } 307 for(i=0; i <hideArr.length;i++) { 308 let hideCell = document.getElementsByClassName(hideArr[i]) 309 for(j=0;j<hideCell.length;j++) { 310 hideCell[j].style.display = "none" 311 } 312 } 313} 314if(comparisonPopup) { 315 if(tableWidget) { 316 tableWidget.style.display = "none"; 317 } 318 if(legalWidget) { 319 legalWidget.style.display = "none"; 320 } 321 comparisonPopup.addEventListener('click', function (event){ 322 if(!comparisonPopup.getAttribute("disabled")) { 323 let comparisonArr = [] 324 let comparisonHide = [] 325 for(i=0;i<allContainers.length;i++) { 326 if(allContainers[i].classList.contains("compare-selected")){ 327 comparisonArr.push(allContainers[i].id) 328 } 329 else { 330 comparisonHide.push(allContainers[i].id) 331 } 332 } 333 displayCompTable(comparisonArr,comparisonHide) 334 comparisonArr = [] 335 comparisonHide = [] 336 337 } 338 }) 339} 340for(i = 0; i < allContainers.length; i++) { 341 allContainers[i].addEventListener("click", function(event){ 342 checkState(event.target) 343 }) 344 if(allContainers[i].classList.contains('compare-selected')) { 345 counter +=1; 346 } 347} 348if(counter > 1) { 349 visibleButtons(true) 350} 351/* ~~~~~~~~~~~~~~~~~~~~~~~~ accordion ~~~~~~~~~~~~~~~~~~~~~~~~ */ 352Array.prototype.slice.call(document.querySelectorAll('.accordion')).forEach(function (accordion) { 353 // Allow for multiple accordion sections to be expanded at the same time 354 var allowMultiple = accordion.hasAttribute('data-allow-multiple'); 355 // Allow for each toggle to both open and close individually 356 var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle'); 357 // Create the array of toggle elements for the accordion group 358 var triggers = Array.prototype.slice.call(accordion.querySelectorAll('.accordion-trigger')); 359 var panels = Array.prototype.slice.call(accordion.querySelectorAll('.Accordion-panel')); 360 accordion.addEventListener('click', function (event) { 361 var target = event.target; 362 if (target.classList.contains('accordion-trigger')) { 363 // Check if the current toggle is expanded. 364 var isExpanded = target.getAttribute('aria-expanded') == 'true'; 365 var active = accordion.querySelector('[aria-expanded="true"]'); 366 // without allowMultiple, close the open accordion 367 if (!allowMultiple && active && active !== target) { 368 // Set the expanded state on the triggering element 369 active.setAttribute('aria-expanded', 'false'); 370 // Hide the accordion sections, using aria-controls to specify the desired section 371 document.getElementById(active.getAttribute('aria-controls')).setAttribute('hidden', ''); 372 // When toggling is not allowed, clean up disabled state 373 if (!allowToggle) { 374 active.removeAttribute('aria-disabled'); 375 } 376 } 377 if (!isExpanded) { 378 // Set the expanded state on the triggering element 379 target.setAttribute('aria-expanded', 'true'); 380 // Hide the accordion sections, using aria-controls to specify the desired section 381 document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden'); 382 383 // If toggling is not allowed, set disabled state on trigger 384 if (!allowToggle) { 385 target.setAttribute('aria-disabled', 'true'); 386 } 387 } 388 else if (allowToggle && isExpanded) { 389 // Set the expanded state on the triggering element 390 target.setAttribute('aria-expanded', 'false'); 391 // Hide the accordion sections, using aria-controls to specify the desired section 392 document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', ''); 393 } 394 395 event.preventDefault(); 396 } 397 }); 398 399 // Bind keyboard behaviors on the main accordion container 400 accordion.addEventListener('keydown', function (event) { 401 var target = event.target; 402 var key = event.which.toString(); 403 404 var isExpanded = target.getAttribute('aria-expanded') == 'true'; 405 var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle'); 406 407 // 33 = Page Up, 34 = Page Down 408 var ctrlModifier = (event.ctrlKey && key.match(/33|34/)); 409 410 // Is this coming from an accordion header? 411 if (target.classList.contains('accordion-trigger')) { 412 // Up/ Down arrow and Control + Page Up/ Page Down keyboard operations 413 // 38 = Up, 40 = Down 414 if (key.match(/38|40/) || ctrlModifier) { 415 var index = triggers.indexOf(target); 416 var direction = (key.match(/34|40/)) ? 1 : -1; 417 var length = triggers.length; 418 var newIndex = (index + length + direction) % length; 419 420 triggers[newIndex].focus(); 421 422 event.preventDefault(); 423 } 424 else if (key.match(/35|36/)) { 425 // 35 = End, 36 = Home keyboard operations 426 switch (key) { 427 // Go to first accordion 428 case '36':
429 triggers[0].focus(); 430 break; 431 // Go to last accordion 432 case '35': 433 triggers[triggers.length - 1].focus(); 434 break; 435 } 436 event.preventDefault(); 437 } 438 } 439 }); 440 441 // These are used to style the accordion when one of the buttons has focus 442 accordion.querySelectorAll('.accordion-trigger').forEach(function (trigger) { 443 444 trigger.addEventListener('focus', function (event) { 445 accordion.classList.add('focus'); 446 }); 447 448 trigger.addEventListener('blur', function (event) { 449 accordion.classList.remove('focus'); 450 }); 451 452 }); 453 454 // Minor setup: will set disabled state, via aria-disabled, to an 455 // expanded/ active accordion which is not allowed to be toggled close 456 if (!allowToggle) { 457 // Get the first expanded/ active accordion 458 var expanded = accordion.querySelector('[aria-expanded="true"]'); 459 460 // If an expanded/ active accordion is found, disable 461 if (expanded) { 462 expanded.setAttribute('aria-disabled', 'true'); 463 } 464 } 465}); 466 //needed if there is more than 1 accordion on the page because the automatic numbering only accounts for a single accordion 467const accordions = document.getElementsByClassName("content-accordion"); 468if (accordions[1]){ 469 counter = 1 470 // find all of the accordion groups 471 for (i =0; i < accordions.length; i++) { 472 473 let accordionPanel = accordions[i].getElementsByClassName("Accordion-panel"); 474 // find all of the dropdowns in the group 475 for ( j = 0; j < accordionPanel.length; j++) { 476 let newAttribute = "section" + counter 477 accordionPanel[j].id = newAttribute 478 accordionPanel[j].previousElementSibling.querySelector("button").setAttribute("aria-controls", newAttribute) 479 counter += 1 480 } 481 } 482} 483var touching = false; 484var delayClockUpdate = false; 485function getCookie(timeOut) { 486 var name = timeOut + "="; 487 var decodedCookie = decodeURIComponent(document.cookie); 488 var ca = decodedCookie.split(';'); 489 for(var i = 0; i <ca.length; i++) { 490 var c = ca[i]; 491 while (c.charAt(0) == ' ') { 492 c = c.substring(1); 493 } 494 if (c.indexOf(name) == 0) { 495 return c.substring(name.length, c.length); 496 } 497 } 498 return ""; 499} 500let onlineBankingSignon = document.getElementsByClassName("ob-status")[0] 501let docBod = document.body 502 503const maxSeconds = 120; 504const nextTimeoutCookie = getCookie("nextTimeout"); 505let nextTimeout, leftOnlineBanking; 506if(nextTimeoutCookie && nextTimeoutCookie != ""){ 507 nextTimeout = nextTimeoutCookie.split("|")[0]; 508 leftOnlineBanking = nextTimeoutCookie.split("|")[1]; 509} else nextTimeout = ""; 510 511let viewableTickCount = 0; 512 513function sessionCountdownTick() { 514 let onlineBankingNotice = document.getElementById("signed-in") 515 let onlineBankingTimer = document.getElementById("online-banking-timer") 516 let dt = new Date(); 517 if (nextTimeout != "" && nextTimeout != "0" && onlineBankingNotice){ 518 let timeLeft = parseInt(nextTimeout) - dt.getTime(); 519 let timeSinceLeavingOLB = dt.getTime() - parseInt(leftOnlineBanking); 520 if (timeLeft > 0) { 521 onlineBankingSignon.setAttribute('href', 'https://accountmanager.providentcu.org/'); 522 523 if (!leftOnlineBanking || (timeSinceLeavingOLB / 1000 ) >= maxSeconds){ 524 docBod.classList.remove('signon-active') 525 } else { 526 docBod.classList.add('signon-active') 527 } 528 529 530 var minutes = Math.floor(timeLeft / 1000 / 60); 531 var seconds = Math.floor(timeLeft / 1000 % 60); 532 if (minutes < 0) { 533 minutes = 0; 534 } 535 var displayString = minutes + ":"; 536 537 if (seconds < 10) { 538 if (seconds < 0) { 539 seconds += "00"; 540 } 541 else { 542 seconds = "0" + seconds; 543 } 544 } 545 displayString += seconds; 546 onlineBankingTimer.textContent = displayString 547 setTimeout("sessionCountdownTick()", 1000); 548 } 549 else { 550 timeout() 551 } 552 } 553 else { 554 docBod.classList.remove('signon-active') 555 } 556} 557function timeout() { 558 var timer = document.getElementById('online-banking-timer') 559 timer.parentNode.innerHTML = "Your online banking session has expired."; 560 docBod.classList.add('expired') 561 document.cookie = "nextTimeout=; path=; SameSite=None; Secure; Domain=.providentcu.org" 562 onlineBankingSignon.setAttribute('href', 'https://accountmanager.providentcu.org/') 563 var messageBar = document.getElementById('signed-in') 564 messageBar.querySelector('a').setAttribute('href', 'https://accountmanager.providentcu.org/') 565 566} 567 568 569sessionCountdownTick()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.