1// Responsive specific javascript 2var lastsize = 2000; 3 4$(window).on('load', function () { 5 resized(); 6 accordion(); 7 loadWeather(); 8 loadAirQuality(); 9 // clipImages(); 10 loadDocumentManager(); 11 loadPrivacyOverlay(); 12}); 13 14$(window).resize(function () { 15 if ((Math.abs(lastsize - $(window).width())) > 100) { 16 lastsize = $(window).width(); 17 resized(); 18 } 19}); 20 21$(document).ready(function () { 22 const COOKIE_NAME = "ASP_NET_IFRAME_SESSION"; 23 // used for iframe resizing 24 if (document.getElementById("massForm")) { 25 window.addEventListener( 26 "message", 27 function (event) { 28 let iframe = document.getElementById("massForm"); 29 let { height } = JSON.parse(event.data); 30 if (height && height > 0 && iframe) { 31 iframe.height = height + "px"; 32 } 33 }, 34 false 35 ); 36 } 37}); 38 39function loadPrivacyOverlay() { 40 if (privacyOverlayEnabled === "True") { 41 if (document.cookie.indexOf("privacyAccepted=true") === -1) { 42 if (privacyOverlayText === undefined || privacyOverlayText.length === 0) { 43 privacyOverlayText = "We respect your privacy."; 44 } 45 if (privacyOverlayText2 === undefined || privacyOverlayText2.length === 0) { 46 privacyOverlayText2 = "By continuing, you agree to our use of your information as described in our Privacy Policy. We only collect what is needed to provide our services."; 47 } 48 $('body').append('<div class="privacyOverlay"><div class="privacyBox"><p> </p></div><div class="privacyBox"><button class="acceptCookies">Accept</button></div></div>'); 49 $('.privacyOverlay .privacyBox p').html('<h4>' + privacyOverlayText + '</h4>' + privacyOverlayText2); 50 if (privacyOverlayLink.length > 0) { 51 $('.privacyOverlay .privacyBox p').append('<span class="privacyPolicyLink"><a href="' + privacyOverlayLink + '" target="_blank">Privacy Policy</a></span>'); 52 } 53 $('.acceptCookies').click(function () { 54 $('.privacyOverlay').hide(); 55 document.cookie = "privacyAccepted=true; path=/; max-age=" + 60 * 60 * 24 * 365; 56 }); 57 } 58 } 59 else { 60 if (document.cookie.indexOf("privacyAccepted") !== -1) 61 document.cookie = "privacyAccepted=; -1"; 62 } 63} 64 65function resized() { 66 if ($(window).width() > 900) { 67 // reset the boxes, then size them according to the biggest for each group. 68 $('.mainContent .responsivebox').css('height', 'auto'); 69 var sec = $('.mainContent section.box').has('.responsivebox') 70 sec.each(function (index) { 71 Match.classMatch($(this).find('.responsivebox')); 72 }); 73 } 74 else { 75 $('.B_LIST .responsivebox').css('height', 'auto'); 76 } 77} 78 79function accordion() { 80 $('.accordion article h2.accordionheader').addClass('closed'); 81 $('.accordion article h2.accordionheader').click(function () { 82 if ($(this).hasClass('closed')) {
83 $(this).parent().parent().find('.description').slideUp(500); 84 $(this).parent().parent().find('h2.accordionheader.open').removeClass('open').addClass('closed'); 85 $(this).parent().parent().find('h2.accordionheader button').children('i.fa-minus-square-o').removeClass('fa-minus-square-o').addClass('fa-plus-square-o'); 86 $(this).find('i').removeClass('fa-plus-square-o').addClass('fa-minus-square-o'); 87 $(this).attr("aria-expanded", "true"); 88 $(this).siblings('.description').slideDown(500).attr("aria-hidden", "false"); 89 $(this).removeClass('closed').addClass('open'); 90 } 91 else { 92 $(this).attr("aria-expanded", "false"); 93 $(this).siblings('.description').slideUp(500).attr("aria-hidden", "true"); 94 $(this).removeClass('open').addClass('closed'); 95 $(this).find('i').removeClass('fa-minus-square-o').addClass('fa-plus-square-o'); 96 } 97 }); 98 $('.accordion .accordionall').click(function () { 99 if ($(this).html() == "Expand All") { 100 $(this).parent().find('article h2.accordionheader').attr("aria-expanded", "true").removeClass('closed').addClass('open'); 101 $(this).parent().find('article .description').slideDown(500).attr("aria-hidden", "false"); 102 $(this).parent().find('article h2.accordionheader button').children('i.fa-plus-square-o').removeClass('fa-plus-square-o').addClass('fa-minus-square-o'); 103 $(this).html('Collapse All'); 104 } 105 else { 106 $(this).parent().find('article h2.accordionheader').attr("aria-expanded", "false").removeClass('open').addClass('closed');
107 $(this).parent().find('article .description').slideUp(500).attr("aria-hidden", "true"); 108 $(this).parent().find('article h2.accordionheader button').children('i.fa-minus-square-o').removeClass('fa-minus-square-o').addClass('fa-plus-square-o'); 109 $(this).html('Expand All'); 110 } 111 }); 112 $('section .accordion').each(function (index) { 113 $(this).find('h2.accordionheader').first().click(); 114 }); 115} 116 117function loadWeather() { 118 var url = "/govofficeservices/api/weather/GetWeather.ashx"; 119 if ($('.openweather').length) { 120 $.getJSON(url, { format: "json" }) 121 .done(function (data) { 122 let currenttemp = Math.round(data.main.temp * 10) / 10; 123 let currentcond = data.weather[0].description; 124 let currentlink = 'https://openweathermap.org/city/' + data.id; 125 //$('.openweather').append('<a href="' + currentlink + '" target="_blank" aria-label="opens weather in a new tab">' + currenttemp + '° ' + currentcond + '</a>'); 126 $('.openweather').append('<a href="#" role="button">' + currenttemp + '° ' + currentcond + '</a>'); 127 }); 128 } 129} 130 131function loadAirQuality() { 132 var url = "/govofficeservices/api/weather/GetAirQuality.ashx"; 133 if ($('.airquality').length) { 134 $.getJSON(url, { format: "json" }) 135 .done(function (data) { 136 let aqi = data.list[0].main.aqi; 137 let q = 'Good'; 138 switch (aqi) { 139 case 2: q = 'Fair'; break; 140 case 3: q = 'Moderate'; break; 141 case 4: q = 'Poor'; break; 142 case 5: q = 'Very Poor'; break; 143 default: break; 144 } 145 $('.airquality').append(q); 146 }); 147 } 148} 149 150function clipImages() { 151 var clipImage = $('div.image.circle > img'); 152 var offset = 0; 153 clipImage.each(function (index) { 154 if ($(this).width() > $(this).height()) { 155 $(this).css('clip-path', 'circle(' + (($(this).height() / 2) + 'px at 50% 50%)')); 156 } 157 else { 158 $(this).css('clip-path', 'circle(' + (($(this).width() / 2) + 'px at 50% 50%)')); 159 } 160 }); 161 clipImage = $('div.image.square > img'); 162 clipImage.each(function (index) { 163 if ($(this).width() > $(this).height()) { 164 offset = ($(this).width() - $(this).height()) / 2; 165 $(this).css('clip-path', 'inset(0 ' + offset + 'px 0 ' + offset + 'px)'); 166 } 167 else { 168 offset = ($(this).height() - $(this).width()) / 2; 169 $(this).css('clip-path', 'inset(' + offset + 'px 0 ' + offset + 'px 0)'); 170 } 171 }); 172} 173 174let map; 175function initMap() { 176 let locations = document.getElementsByClassName("hidden location"); 177 let addresses = document.getElementsByClassName("hidden address"); 178 let loc = ''; 179 let first = ''; 180 // Get the first location with values to center the map 181 for (let i = 0; i < locations.length; i++) { 182 loc = locations[i].innerHTML; 183 if (loc.length > 0) { 184 first = loc; 185 break; 186 } 187 } 188 if (first.length > 0) { 189 let c = first.split(","); 190 let myLatLng = { lat: parseFloat(c[0]), lng: parseFloat(c[1]) }; 191 //let myLatLng = new google.maps.LatLng(locations[0].innerHTML); 192 map = new google.maps.Map(document.getElementById('dirmap'), { 193 center: myLatLng, 194 zoom: 12 195 }); 196 } 197 198 var markers = new Array(); 199 var infoWindow = new google.maps.InfoWindow(); 200 for (let i = 0; i < locations.length; i++) { 201 let loc = locations[i].innerHTML; 202 let addr = addresses[i].innerHTML; 203 if (loc.length > 0) { 204 let c = loc.split(","); 205 if (c.length > 2) { 206 let myLatLng = { lat: parseFloat(c[0]), lng: parseFloat(c[1]) }; 207 let cont = '<div class="info"><h3>' + c[2] + '</h3><div><p>' + addr + '</p></div></div>'; 208 const marker = new google.maps.Marker({ 209 position: myLatLng, 210 map: map 211 }); 212 markers[i] = marker; 213 (function (marker) { 214 google.maps.event.addListener(marker, "click", function (e) { 215 if (infoWindow) { 216 infoWindow.close(); 217 } 218 infoWindow.setContent(cont); 219 infoWindow.open(map, marker); 220 }); 221 })(marker); 222 } 223 } 224 } 225 $('.showonmap').click(function () { 226 let id = $(this).index('.showonmap'); 227 //console.log(j); 228 google.maps.event.trigger(markers[id], 'click'); 229 document.getElementById('dirmap').scrollIntoView({ behavior: 'smooth', block: 'center' }); 230 }); 231} 232 233$(document).ready(function() { 234 if ($('.namesearch').length) { 235 $('.namesearchbox i').click(function () { 236 if ($(this).hasClass('fa-magnifying-glass')) { 237 searchtitles(); 238 } 239 else { 240 resetsearchtitles(); 241 } 242 }); 243 $(document).on('keyup', function(e) { 244 if (e.key == "Enter") searchtitles(); 245 if (e.key == "Escape") resetsearchtitles(); 246 }); 247 } 248}); 249 250function searchtitles() { 251 let filter = $('.namesearch').val().toLowerCase(); 252 $('h2').each(function () { 253 if ($(this).text().toLowerCase().indexOf(filter) > -1) { 254 $(this).closest('article').addClass('found'); 255 } 256 else { 257 $(this).closest('article').addClass('filtered'); 258 } 259 }); 260 $('i.fa-magnifying-glass').addClass('fa-circle-xmark').removeClass('fa-magnifying-glass'); 261} 262 263function resetsearchtitles() { 264 $('i.fa-circle-xmark').addClass('fa-magnifying-glass').removeClass('fa-circle-xmark'); 265 $('.filtered').removeClass('filtered'); 266 $('.found').removeClass('found'); 267} 268 269// document manager 270function loadDocumentManager() { 271 if ($('.docmanfolder').length > 0) { 272 $('.docmanContainer').each(function () { 273 let c = $(this).attr('id'); 274 let f = c; 275 $(this).attr('currentfolder', f); 276 GetCurrentFolder(c, f); 277 }); 278 rebindDocMan(); 279 $('#docmanSearchButton').click(function () { 280 let c = $(this).closest('.docmanContainer').attr('id'); 281 let f = $(this).closest('.docmanContainer').attr('currentfolder'); 282 DocSearch(c, f); 283 }); 284 $('.docmanSearch i.fa-magnifying-glass').click(function () { 285 let c = $(this).closest('.docmanContainer').attr('id'); 286 let f = $(this).closest('.docmanContainer').attr('currentfolder'); 287 DocSearch(c, f); 288 }); 289 $('.docsearch').on('keyup', function (e) { 290 if (e.key == "Enter") { 291 let c = $(this).closest('.docmanContainer').attr('id'); 292 let f = $(this).closest('.docmanContainer').attr('currentfolder'); 293 DocSearch(c, f); 294 } 295 }); 296 } 297} 298 299function DocSearch(c, f) { 300 if ($('.docmanContainer#' + c + ' .docsearch').val().length > 0) { 301 $('.docmanContainer#' + c + ' .subfolders').html(''); 302 let s = $('.docmanContainer#' + c).attr('sec'); 303 let k = $('.docmanContainer#' + c + ' .docsearch').val(); 304 // k = k.replace(/'/g, ''); 305 // k = k.replace(/-/g, ''); 306 // k = k.replace(/"/g, ''); 307 $.ajax({
308 type: "GET", 309 url: "/admin/dm/Public/SearchFolder/?folderid=" + f + "&sec=" + s + "&search=" + k , 310 cache: false, 311 async: false, 312 contentType: "application/json; charset=utf-8", 313 dataType: "json", 314 success: function (data) { 315 let primary = '.docmanContainer#' + c; 316 if ($(primary + ' div.breadcrumb > div:contains("Search Results")').length == 0) { 317 $(primary + ' div.breadcrumb > div').append(' > <span id="s' + data.folderId + '">Search Results</span>'); 318 } 319 $(primary + ' .docmanfolder .subfolders').append('<div class="headings"><div><i class="fa-regular fa-arrow-up"></i>Name</div><div>Last Modified Date</div><div><i class="fa-regular fa-arrow-right"></i></div></div>'); 320 321 $.each(data, function (i, file) { 322 let df = String(file.fileDate); 323 df = df.substring(0, df.indexOf('T')); 324 if (df.startsWith('1900')) df = ''; 325 326 327 let fn = file.fileName; 328 if (file.FileTitle != null && file.FileTitle.length > 0) fn = file.FileTitle; 329 330 $(primary + ' .docmanfolder .subfolders').append('<div class="file" filename="' + fn + '" id="' + file.fileId + '"><div>' + GetFileIcon(file.fileType) + fn + '</div><div>' + df + '</div><div><i class="fa-solid fa-download"></i></div></div>'); 331 }); 332 rebindDocMan(); 333 }, 334 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 335 error: function (data) { console.log('error: ' + JSON.stringify(data)); } 336 }); 337 $('.docmanContainer#' + c + ' .docsearch').val(''); 338 } 339} 340 341function rebindDocMan() { 342 $('.docmanfolder .folder').unbind('click').on('click', function (e) { 343 let c = $(this).closest('.docmanContainer').attr('id'); 344 let f = $(this).attr('id'); 345 GetCurrentFolder(c, f); 346 }); 347 $('.docmanfolder .file').unbind('click').on('click', function (e) { 348 let clickedfileid = $(this).attr('id'); 349 let clickedfilename = $(this).attr('filename'); 350 window.open('/uploads/dm/' + clickedfileid + '/' + encodeForPath(clickedfilename), '_blank', 'noreferrer'); 351 }); 352 $('.docmanContainer .breadcrumb > div > span').unbind('click').on('click', function (e) { 353 let c = $(this).closest('.docmanContainer').attr('id'); 354 let f = $(this).attr('id').substring(1); 355 $(this).nextAll().remove(); 356 GetCurrentFolder(c, f); 357 }) 358} 359 360function GetCurrentFolder(c, f) { 361 $('.docmanContainer#' + c + ' .subfolders').html(''); 362 let primary = '.docmanContainer#' + c; 363 let s = $(primary).attr('sec'); 364 $(primary).attr('currentfolder', f); 365 $.ajax({ 366 type: "GET", 367 url: "/admin/dm/Public/GetFolderById/?folderid=" + f + "&sec=" + s, 368 cache: false, 369 async: false, 370 contentType: "application/json; charset=utf-8", 371 dataType: "json", 372 success: function (data) { 373 if (c == f) 374 $(primary + ' div.breadcrumb > div').html('<span id="s' + data.folderId + '">' + data.folderName + '</span>'); 375 else { 376 $active = $(primary + ' div.breadcrumb > div').find('#s' + f) 377 if ($active.length == 0) 378 $(primary + ' div.breadcrumb > div').append(' > <span id="s' + data.folderId + '">' + data.folderName + '</span>'); 379 } 380 $(primary + ' .docmanfolder .subfolders').append('<div class="headings"><div><i class="fa-regular fa-arrow-up"></i>Name</div><div>Last Modified Date</div><div><i class="fa-regular fa-arrow-right"></i></div></div>'); 381 382 $.each(data.dmfolders, function (i, subfolder) { 383 let d = String(subfolder.lastModified); 384 d = d.substring(0, d.indexOf('T')); 385 d = ''; 386 $(primary + ' .docmanfolder .subfolders').append('<div class="folder" id="' + subfolder.folderId + '"><div><i class="fa-solid fa-folder"></i>' + subfolder.folderName + '</div><div>' + d + '</div><div><i class="fa-regular fa-arrow-right"></i></div></div>'); 387 }); 388 $.each(data.dmfiles, function (i, file) { 389 let df = String(file.fileDate); 390 df = df.substring(0, df.indexOf('T')); 391 392 let fn = file.fileName; 393 if (file.FileTitle != null && file.FileTitle.length > 0) fn = file.FileTitle; 394 $(primary + ' .docmanfolder .subfolders').append('<div class="file" filename="' + fn + '" id="' + file.fileId + '"><div>' + GetFileIcon(file.fileType) + fn + '</div><div>' + df + '</div><div><i class="fa-solid fa-download"></i></div></div>'); 395 }); 396 rebindDocMan(); 397 }, 398 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 399 error: function (data) { 400 console.log('error: ' + JSON.stringify(data)); 401 if (data.status == 401) { 402 $('div.breadcrumb').html('You will need to authenticate to see this content.'); 403 $('div.searchContainer').hide(); 404 405 } 406 } 407 }); 408} 409 410function GetFileIcon(filetype) { 411 switch (filetype.toLowerCase()) { 412 case 'jpeg': 413 case 'jpg': 414 case 'png': 415 case 'gif': 416 return '<i class="fa-solid fa-file-image"></i>'; 417 case 'doc': 418 case 'docx': 419 return '<i class="fa-solid fa-file-word"></i>'; 420 case 'xls': 421 case 'xlsx': 422 return '<i class="fa-solid fa-file-excel"></i>'; 423 case 'pdf': 424 return '<i class="fa-solid fa-file-pdf"></i>'; 425 case 'zip': 426 case '7z': 427 return '<i class="fa-solid fa-file-zipper"></i>'; 428 case 'avi': 429 case 'm4v': 430 case 'mp4': 431 case 'mov': 432 case 'mkv': 433 return '<i class="fa-solid fa-file-video"></i>'; 434 case 'mp3': 435 case 'ogg': 436 case 'wav': 437 return '<i class="fa-solid fa-file-audio"></i>'; 438 default: 439 return '<i class="fa-solid fa-file"></i>'; 440 } 441} 442 443function taxcalc(containerId) { 444 // Attach event listener to the input field 445 document.getElementById(containerId).querySelector('.propValue').addEventListener('input', handleInputChange); 446 447 // Attach event listener to the radio buttons 448 var ratiosContainer = document.getElementById(containerId).querySelector('.Ratios'); 449 ratiosContainer.addEventListener('change', handleRatioChange); 450 451 452 // Attach event listener to the dropdown 453 var jurisdictionDropdown = document.getElementById(containerId).querySelector('.jurisdictionDropdown'); 454 jurisdictionDropdown.addEventListener('change', handleDropdownChange); 455 456 // Attach event listener to the base rate dropdown 457 var baseRatecont = document.getElementById(containerId).querySelector('.baseRatecont'); 458 baseRatecont.addEventListener('change', handleBaseRateChange); 459} 460 461function hideElements(arraykey) { 462 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 463 var dropdown = taxcontainer.querySelector(".jurisdictionDropdown"); 464 var jursCont = taxcontainer.querySelector(".jurisdictionDropdownCont"); 465 var middleCont = taxcontainer.querySelector(".middleCont"); 466 var baseFactorBody = taxcontainer.querySelector(".baseFactorBody"); 467 var baseFactor = taxcontainer.querySelector(".baseFactor"); 468 var baserate = taxcontainer.querySelector(".baseRates"); 469 var baseRatecont = taxcontainer.querySelector(".baseRatecont"); 470 var creditTableContainer = taxcontainer.querySelector(".credits"); 471 var tableCont = taxcontainer.querySelector(".taxes"); 472 var ratiocontainer = taxcontainer.querySelector(".radioOptions"); 473 var millcontainer = taxcontainer.querySelector(".millLeviesBody"); 474 var creditBody = taxcontainer.querySelector(".millLeviesCREDITBody"); 475 var juryCreditBody = taxcontainer.querySelector(".juryCreditBody"); 476 var juryBody = taxcontainer.querySelector(".juryBody"); 477 var CalcdAssessmentVal = taxcontainer.querySelector('.CalcdAssessmentVal'); 478 var ratioCreditBody = taxcontainer.querySelector(".ratioCreditBody"); 479 var ratioBody = taxcontainer.querySelector(".ratioBody"); 480 481 var ratioArray = ratioArrays[arraykey] || []; 482 var levyArray = levyArrays[arraykey] || []; 483 var jurLevyArray = jurLevyArrays[arraykey] || []; 484 485 if (ratioArray.length === 0) { 486 ratiocontainer.style.display = 'none'; 487 } 488 489 if (levyArray.length === 0 && millcontainer.childElementCount === 0 && ratioBody.childElementCount === 0 && juryBody.childElementCount === 0) { 490 tableCont.style.display = 'none'; 491 } else { 492 tableCont.style.display = 'inline-block'; 493 } 494 495 if (jurLevyArray.length === 0 && baseFactorBody.childElementCount === 0) { 496 middleCont.style.display = 'none'; 497 } else { 498 middleCont.style.display = 'inline-block'; 499 } 500 501 if (jurLevyArray.length === 0) { 502 jursCont.style.display = 'none'; 503 } else { 504 dropdown.style.display = 'inline-block'; 505 } 506 507 if (baseFactorBody.childElementCount != 0) { 508 baseFactor.style.display = 'inline-block'; 509 } else { 510 baseFactor.style.display = 'none'; 511 } 512 513 if (baserate.childElementCount === 0) { 514 baseRatecont.style.display = 'none'; 515 } else { 516 baseRatecont.style.display = 'inline-block'; 517 } 518 519 if (creditBody.childElementCount === 0 && ratioCreditBody.childElementCount === 0 && juryCreditBody.childElementCount === 0) { 520 creditTableContainer.style.display = 'none'; 521 } else { 522 creditTableContainer.style.display = 'inline-block'; 523 } 524 525} 526 527 528 529function calculate(arraykey) { 530 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 531 const calcResultElements = taxcontainer.querySelectorAll('.millLevy'); 532 const basefactorElement = taxcontainer.querySelector('.basefactor'); 533 const baseRateElement = getSelectedBaseRate(arraykey); 534 var assessedValue = getAssessedValue(arraykey); 535 if (ratioArrays[arraykey].length === 0) { 536 assessedValue = taxcontainer.querySelector('.propValue').value; 537 //assessedValue = parseFloat(assessedValue.replace(/,/g, '')); 538 } 539 540 let total = 0; 541 //use function to removed comma from input 542 //console.log("assessed value: ", assessedValue );
543 calcResultElements.forEach(function (element) { 544 const value = parseFloat(element.textContent); 545 if (!isNaN(value) && value != 0) { 546 total += value; 547 } 548 }); 549 550 total = total * assessedValue; 551 if (basefactorElement && total != 0) { 552 total = total * parseFloat(basefactorElement.textContent); 553 } 554 total = total.toFixed(2) / 1000; 555 if (baseRateElement ) { 556 total += (baseRateElement); 557 } 558 if (total === 0 && assessedValue) { 559 total = parseFloat(assessedValue); 560 } 561 if (total != 0 && !isNaN(total)) { 562 let roundedNum = Math.round(total * 100) / 100; //for 2 decimal places 563 total = roundedNum; 564 565 } 566 // Display total 567 const resultDiv = taxcontainer.querySelector('.results'); 568 resultDiv.textContent = "$" + total.toFixed(2); 569} 570 571function displayassessedVal(assessedVal, arraykey) { 572 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 573 var assessmentvalCont = taxcontainer.querySelector(".assessedValue"); 574 if (assessmentvalCont) { 575 assessmentvalCont.innerHTML = ''; // Clear existing content 576 // Create a new div element for assessed value 577 var assessValDiv = document.createElement('div'); 578 assessValDiv.className = 'calcdval'; 579 assessValDiv.innerHTML = '<span class="valSpan">' + assessedVal.toFixed(2) + '</span>'; 580 // Clear the container's contents 581 assessmentvalCont.innerHTML = ''; 582 583 // Append the new assessed value div to the container 584 assessmentvalCont.appendChild(assessValDiv); 585 } 586} 587function displayRatios(arraykey) { 588 var containerElement = document.querySelector("#" + arraykey); 589 if (!containerElement) { 590 console.error("Container element not found."); 591 return; 592 } 593 594 var currArray = ratioArrays[arraykey]; 595 if (!currArray) { 596 //console.error("Ratios array not found."); 597 return; 598 } 599 var ratiosContainer = containerElement.querySelector('.Ratios'); 600 if (!ratiosContainer) { 601 //console.error("Ratios container not found."); 602 return; 603 } 604 605 var select = containerElement.querySelector('.ratioDropdown'); 606 607 select.className = 'ratioSelect'; 608 609 // Populate options from currArray 610 currArray.forEach(function (item) { 611 var option = document.createElement('option'); 612 option.value = item.guid; 613 option.textContent = item.title + ": " + item.percent + "%"; 614 select.appendChild(option); 615 }); 616} 617 618function displayMillLevies() { 619 var containerElement = document.querySelector("#" + uniqueID); 620 if (!containerElement) { 621 console.error("Container element not found."); 622 return; 623 } 624 var currArray = levyArrays[uniqueID]; 625 if (!currArray) { 626 console.error("Levy array not found."); 627 return; 628 } 629 var millLeviesContainer = containerElement.querySelector('.leviesTableContainer'); 630 if (!millLeviesContainer) { 631 console.error("Mill levies container not found."); 632 return; 633 } 634 635 // Populate table rows with array data 636 currArray.forEach(function (item) { 637 // Create new table row 638 var row = document.createElement('tr'); 639 // Create and populate cells 640 var titleCell = document.createElement('td'); 641 titleCell.textContent = item.title; 642 var numberCell = document.createElement('td'); 643 numberCell.className = 'millLevy'; 644 numberCell.textContent = item.number; 645 var calcCell = document.createElement('td'); 646 calcCell.className = 'calcResult'; 647 calcCell.textContent = '0.00'; 648 // Append cells to row 649 row.appendChild(titleCell); 650 row.appendChild(numberCell); 651 row.appendChild(calcCell); 652 // Append row to the appropriate table body 653 if (item.number >= 0) { 654 var body = millLeviesContainer.querySelector(".millLeviesBody"); 655 body.appendChild(row); 656 } else { 657 var creditbody = millLeviesContainer.querySelector(".millLeviesCREDITBody"); 658 if (!creditbody) { 659 creditbody = document.createElement('tbody'); 660 creditbody.className = 'millLeviesCREDITBody'; 661 millLeviesContainer.appendChild(creditbody); 662 } 663 creditbody.appendChild(row); 664 } 665 }); 666} 667 668function displayRatioLevies(extraLevyArray, arraykey) { 669 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 670 var body = taxcontainer.querySelector(".ratioBody"); 671 // Clear existing content in millLeviesBody 672 body.innerHTML = ''; 673 var creditbody = taxcontainer.querySelector(".ratioCreditBody"); 674 // Clear existing content in millLeviesCREDITBody 675 creditbody.innerHTML = ''; 676 677 // Populate table rows with array data 678 extraLevyArray.forEach(function (item) { 679 //if item number is greater than or equal to 0, add to table 680 if (item.number >= 0) { 681 var row = body.insertRow(); 682 var titleCell = row.insertCell(); 683 titleCell.textContent = item.name; 684 var numberCell = row.insertCell(); 685 numberCell.className = 'millLevy'; 686 numberCell.textContent = item.number; 687 var calcCell = row.insertCell(); 688 calcCell.className = 'calcResult'; 689 var calcResult = calcMillLevy(item.number, arraykey); 690 calcCell.textContent = calcResult; 691 } else { 692 var row = creditbody.insertRow(); 693 var titleCell = row.insertCell(); 694 titleCell.textContent = item.name; 695 var numberCell = row.insertCell(); 696 numberCell.className = 'millLevy'; 697 numberCell.textContent = item.number; 698 var calcCell = row.insertCell(); 699 calcCell.className = 'calcResult'; 700 var calcResult = calcMillLevy(item.number, arraykey); 701 calcCell.textContent = calcResult; 702 } 703 }); 704 705 hideElements(arraykey); 706} 707 708function displayBaseRate(array, containerclass, uniqueId) { 709 var container = document.querySelector(`#${uniqueId} .${containerclass}`); 710 if (container) { 711 container.innerHTML = ''; // Clear existing content 712 713 // Create radio button options 714 array.forEach(function (item, index) { 715 var radioInput = document.createElement('input'); 716 radioInput.type = 'radio'; 717 radioInput.name = 'baseRate_' + uniqueId; 718 radioInput.value = item.number; // change the value attribute based data 719 var label = document.createElement('label'); 720 label.appendChild(radioInput); 721 label.appendChild(document.createTextNode(item.name + ": $" + item.number)); // adjust the text content based data 722 container.appendChild(label); 723 724 // Check the first radio button option 725 if (index === 0) { 726 radioInput.checked = true; 727 } 728 }); 729 } 730} 731 732 733function displayBaseFactor(Ratio, arraykey) { 734 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 735 var middleCont = taxcontainer.querySelector(".middleCont"); 736 var baseFactor = taxcontainer.querySelector(".baseFactor"); 737 var body = taxcontainer.querySelector(".baseFactorBody"); 738 739 // If Ratio has a factor, display the base factor table 740 if (Ratio.hasfactor === '1') { 741 if (middleCont && middleCont.length > 0) { 742 middleCont.style.display = 'inline-block'; 743 } 744 body.innerHTML = ''; 745 // Populate table rows with array data 746 var row = body.insertRow(); 747 var nameCell = row.insertCell(); 748 nameCell.textContent = Ratio.factorLabel; 749 var numberCell = row.insertCell(); 750 numberCell.className = 'basefactor'; 751 numberCell.textContent = Ratio.factor; 752 } 753 else { 754 // Clear existing content in baseFactorBody 755 body.innerHTML = ''; 756 hideElements(arraykey); 757 } 758} 759 760function displayJuryLevies(extraLevyArray,arraykey) { 761 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 762 var body = taxcontainer.querySelector(".juryBody"); 763 // Clear existing content in millLeviesBody 764 body.innerHTML = ''; 765 var creditbody = taxcontainer.querySelector(".juryCreditBody"); 766 // Clear existing content in millLeviesCREDITBody 767 creditbody.innerHTML = ''; 768 769 // Populate table rows with array data 770 extraLevyArray.forEach(function (item) { 771 //if item number is greater than or equal to 0, add to table 772 if (item.number >= 0) { 773 var row = body.insertRow(); 774 var titleCell = row.insertCell(); 775 titleCell.textContent = item.name; 776 var numberCell = row.insertCell(); 777 numberCell.className = 'millLevy'; 778 numberCell.textContent = item.number; 779 var calcCell = row.insertCell(); 780 calcCell.className = 'calcResult'; 781 var calcResult = calcMillLevy(item.number, arraykey); 782 calcCell.textContent = calcResult; 783 } else { 784 var row = creditbody.insertRow(); 785 var titleCell = row.insertCell(); 786 titleCell.textContent = item.name; 787 var numberCell = row.insertCell(); 788 numberCell.className = 'millLevy'; 789 numberCell.textContent = item.number; 790 var calcCell = row.insertCell(); 791 calcCell.className = 'calcResult'; 792 var calcResult = calcMillLevy(item.number, arraykey); 793 calcCell.textContent = calcResult; 794 } 795 }); 796 797 hideElements(arraykey); 798} 799 800// Function to update Ratio specific Levies based on the selected Ratio 801function updateRatioLevies(ratioguid, arraykey) { 802 var ratioArray = ratioArrays[arraykey]; 803 // Find the selected jurisdiction in the array 804 var selectedRatio = ratioArray.find(function (ratio) { 805 return ratio.guid === ratioguid; 806 }); 807 808 if (selectedRatio) { 809 // Check if selectedJurisdiction has the ExtraLevy property 810 if (selectedRatio.ExtraLevy) { 811 //get array of ExtraLevy for the selected jurisdiction 812 var extraLevyArray = selectedRatio.ExtraLevy; 813 // Call the displayJuryLevies function with the correct array name 814 displayRatioLevies(extraLevyArray, arraykey); 815 } else { 816 console.log("Selected ratio does not have ExtraLevy property"); 817 } 818 } else { 819 console.error("Selected ratio not found in the array"); 820 } 821} 822 823// Function to update Jurisdiction specific Levies based on the selected jurisdiction 824function updateBaseRate(ratioguid, arraykey) { 825 var ratioArray = ratioArrays[arraykey]; 826 var desiredRatio = ratioArray.find(function (ratio) { 827 return ratio.guid === ratioguid; 828 }); 829 830 // Check if the desired ratio exists 831 if (desiredRatio) { 832 // Access the BaseRate array of the desired ratio 833 var baseRateArray = desiredRatio.BaseRate; 834 displayBaseRate(baseRateArray, 'baseRates', arraykey); 835 } else { 836 console.error("Desired ratio not found."); 837 } 838} 839 840function updateMillLevies(arraykey) { 841 var levyArray = levyArrays[arraykey]; 842 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 843 var body = taxcontainer.querySelector(".millLeviesBody"); 844 // Clear existing content in millLeviesBody 845 body.innerHTML = ''; 846 847 var creditbody = taxcontainer.querySelector(".millLeviesCREDITBody"); 848 // Clear existing content in millLeviesCREDITBody 849 creditbody.innerHTML = ''; 850 851 // Populate table rows with array data 852 levyArray.forEach(function (item) { 853 //if item number is greater than or equal to 0, add to table 854 if (item.number >= 0) { 855 var row = body.insertRow(); 856 var titleCell = row.insertCell(); 857 titleCell.textContent = item.title; 858 var numberCell = row.insertCell(); 859 numberCell.className = 'millLevy'; 860 numberCell.textContent = item.number; 861 var calcCell = row.insertCell(); 862 calcCell.className = 'calcResult'; 863 var calcResult = calcMillLevy(item.number, arraykey); 864 calcCell.textContent = calcResult; 865 } else { 866 var row = creditbody.insertRow(); 867 var titleCell = row.insertCell(); 868 titleCell.textContent = item.title; 869 var numberCell = row.insertCell(); 870 numberCell.className = 'millLevy'; 871 numberCell.textContent = item.number; 872 var calcCell = row.insertCell(); 873 calcCell.className = 'calcResult'; 874 var calcResult = calcMillLevy(item.number, arraykey); 875 calcCell.textContent = calcResult; 876 } 877 }); 878} 879 880// Function to update Jurisdiction specific Levies based on the selected jurisdiction 881function updateJuryLevies(jurisdictionguid, arraykey) { 882 var jurylevyarray = jurLevyArrays[arraykey]; 883 // Find the selected jurisdiction in the array 884 var selectedJurisdiction = jurylevyarray.find(function (jurisdiction) { 885 return jurisdiction.guid === jurisdictionguid; 886 }); 887 888 if (selectedJurisdiction) { 889 // Check if selectedJurisdiction has the ExtraLevy property 890 if (selectedJurisdiction.ExtraLevy) { 891 //get array of ExtraLevy for the selected jurisdiction 892 var extraLevyArray = selectedJurisdiction.ExtraLevy; 893 // Call the displayJuryLevies function with the correct array name 894 displayJuryLevies(extraLevyArray, arraykey); 895 } else { 896 console.error("Selected jurisdiction does not have ExtraLevy property"); 897 } 898 } else { 899 console.error("Selected jurisdiction not found in the array"); 900 } 901} 902 903function updateBaseFactor(ratioguid, arraykey) { 904 var ratioArray = ratioArrays[arraykey]; 905 var selectedRatio = ratioArray.find(function (ratio) { 906 return ratio.guid === ratioguid; 907 }); 908 displayBaseFactor(selectedRatio, arraykey); 909} 910 911//function to handle input change event 912function handleInputChange(event) { 913 var propvalueInput = event.target.value; 914 propvalueInput = parseFloat(propvalueInput.replace(/,/g, '')); 915 var container = event.target.closest('.tax-calculator'); 916 var arraykey = container.id; 917 var selectedRatioguid = getSelectedRatio(arraykey); 918 //if the selected ratio and assessed value are not null 919 if (selectedRatioguid) { 920 calculateAssessedValue(selectedRatioguid, arraykey, propvalueInput); 921 updateRatioLevies(selectedRatioguid, arraykey); 922 923 } 924 updateMillLevies(arraykey); 925 926 if (getJurisdiction(arraykey)) { 927 updateJuryLevies(getJurisdiction(arraykey), arraykey); 928 } 929 hideElements(arraykey); 930 931 calculate(arraykey); 932} 933 934function handleRatioChange(event) { 935 var selectedRatioguid = event.target.value; 936 var container = event.target.closest('.tax-calculator'); 937 var arraykey = container.id; 938 var propertyvalue = getPropValue(arraykey); 939 if (selectedRatioguid != "null") { 940 updateBaseRate(selectedRatioguid, arraykey); 941 updateBaseFactor(selectedRatioguid, arraykey); 942 943 if (propertyvalue) { 944 propertyvalue = (propertyvalue.replace(/,/g, '')); 945 calculateAssessedValue(selectedRatioguid, arraykey, propertyvalue); 946 updateMillLevies(arraykey); 947 updateRatioLevies(selectedRatioguid, arraykey); 948 949 } 950 if (getJurisdiction(arraykey)) { 951 updateJuryLevies(getJurisdiction(arraykey), arraykey); 952 } 953 954 hideElements(arraykey); 955 calculate(arraykey);} 956} 957 958// Function to handle base rate radio change event 959function handleBaseRateChange(event) { 960 var container = event.target.closest('.tax-calculator'); 961 var arraykey = container.id; 962 calculate(arraykey); 963 hideElements(arraykey); 964 965} 966// Function to handle dropdown change event 967function handleDropdownChange(event) { 968 var jurisdistionguid = event.target.value; 969 var container = event.target.closest('.tax-calculator'); 970 var arraykey = container.id; 971 972 updateMillLevies(arraykey); 973 //var selectedJurisdiction = document.getElementsByClassName('jurisdictionDropdown').value; 974 975 if (getJurisdiction(arraykey)) { 976 updateJuryLevies(getJurisdiction(arraykey), arraykey); 977 } 978 hideElements(arraykey); 979 calculate(arraykey); 980} 981 982//function to get assessed value 983function getAssessedValue(arraykey) { 984 var assessedValue = null; 985 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 986 try { 987 // Get all elements with the class name 'valSpan' 988 var element = taxcontainer.querySelector('.valSpan'); 989 var value = element.textContent; 990 // If the value is not null or empty, parse it to a float 991 if (value) { 992 assessedValue = parseFloat(value).toFixed(2); 993 } 994 995 } catch (error) { 996 //console.error("Error in getAssessedValue:", error); 997 } 998return assessedValue; 999} 1000 1001//get input value 1002function getPropValue(arraykey) { 1003 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 1004 try { 1005 var propValue = taxcontainer.querySelector('.propValue').value; 1006 //propValue = parseFloat(propValue.replace(/,/g, '')); 1007 return propValue; 1008 } catch { } 1009} 1010 1011function getSelectedRatio(arraykey) { 1012 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 1013 try { 1014 // Get the dropdown element 1015 var dropdown = taxcontainer.querySelector('.ratioSelect'); 1016 // Get the selected value 1017 var selectedRatio = dropdown.value; 1018 //if selectRatio has no value, return null 1019 if (selectedRatio === "null") { 1020 return null; 1021 } 1022 return selectedRatio; 1023 } catch (error) { 1024 // Handle any potential errors here 1025 console.error("Error in getSelectedRatio:", error); 1026 return null; // Return null if an error occurs 1027 } 1028} 1029 1030function getSelectedBaseRate(arraykey) { 1031 var taxcontainer = document
1031.querySelector(`#${arraykey}.tax-calculator`); 1032 var selectedbaseRateInput = taxcontainer.querySelector('input[name="baseRate_' + arraykey + '"]:checked'); 1033 if (selectedbaseRateInput) { 1034 return parseFloat(selectedbaseRateInput.getAttribute('value')); 1035 } else { 1036 return null; 1037 } 1038} 1039 1040//function to get selected jurisdiction 1041function getJurisdiction(arraykey) { 1042 var taxcontainer = document.querySelector(`#${arraykey}.tax-calculator`); 1043 try { 1044 // Get the dropdown element 1045 var dropdown = taxcontainer.querySelector('.jurisdictionDropdown'); 1046 // Get the selected value 1047 var selectedJurisdiction = dropdown.value; 1048 return selectedJurisdiction; 1049 } catch (error) { 1050 // Handle any potential errors here 1051 console.error("Error in getJurisdiction:", error); 1052 return null; // Return null if an error occurs 1053 } 1054} 1055 1056function calculateAssessedValue(ratioguid, arraykey, propvalueInput) { 1057 var ratioArray = ratioArrays[arraykey]; 1058 var selectedRatio = ratioArray.find(function (ratio) { 1059 return ratio.guid === ratioguid; 1060 }); 1061 var assessedValue = propvalueInput * ((selectedRatio.percent) / 100); 1062 displayassessedVal(assessedValue, arraykey); 1063} 1064 1065//calc the mill levy * assessed value 1066function calcMillLevy(millLevy, arraykey) { 1067 var assessedValue = getAssessedValue(arraykey); 1068 if (ratioArrays[arraykey].length === 0) { 1069 assessedValue = document.querySelector(`#${arraykey}.tax-calculator .propValue`).value; 1070 } 1071 var tax = millLevy * assessedValue / 1000; 1072 //make tax two decimal places 1073 tax = tax.toFixed(2); 1074 return tax; 1075} 1076 1077window.addEventListener('load', initializeTaxCalculators); 1078 1079function initializeTaxCalculators() { 1080 var calculatorContainers = document.querySelectorAll('.tax-calculator'); 1081 calculatorContainers.forEach(function (container) { 1082 var containerId = container.id; 1083 uniqueID = containerId; 1084 taxcalc(containerId); 1085 displayRatios(containerId); 1086 displayMillLevies(); 1087 hideElements(containerId); 1088 }); 1089} 1090var ratioArrays = {}; 1091var levyArrays = {}; 1092var jurLevyArrays = {}; 1093var uniqueID = ''; 1094 1095//vehicle tax *********************************** 1096//initialize listeners 1097function taxcalcVehicle(containerId) { 1098 // Attach event listener to the input field 1099 document.getElementById(containerId).querySelector('.vehicleValue').addEventListener('input', handleVehicleInputChange); 1100 // Attach event listener to the radio buttons 1101 var ratiosContainer = document.getElementById(containerId).querySelector('.VehicleRatios'); 1102 ratiosContainer.addEventListener('change', handleVehicleRatioChange); 1103} 1104 1105function displayRatiosVehicle(arraykey) { 1106 var taxcontainer = document.querySelector(`#${arraykey}.vehicletax-calculator`); 1107 if (!taxcontainer) { 1108 console.error("Container element not found."); 1109 return; 1110 } 1111 1112 var currArray = vehicleRatioArrays[arraykey]; 1113 if (!currArray) { 1114 console.error("Ratios array not found."); 1115 return; 1116 } 1117 var ratiosContainer = taxcontainer.querySelector('.VehicleRatios'); 1118 if (!ratiosContainer) { 1119 console.error("Ratios container not found."); 1120 return; 1121 } 1122 var select = taxcontainer.querySelector('.ratioDropdown'); 1123 1124 select.className = 'ratioSelect'; 1125 1126 // Populate options from currArray 1127 currArray.forEach(function (item) { 1128 var option = document.createElement('option'); 1129 option.value = item.guid; 1130 option.textContent = item.title + ": " + item.percent + "%"; 1131 select.appendChild(option); 1132 }); 1133} 1134 1135function getSelectedRatioVehicle(arraykey) { 1136 var taxcontainer = document.querySelector(`#${arraykey}.vehicletax-calculator`); 1137 try { 1138 // Get the dropdown element 1139 var dropdown = taxcontainer.querySelector('.ratioSelect'); 1140 // Get the selected value 1141 var selectedRatio = dropdown.value; 1142 //if selectRatio has no value, return null 1143 if (selectedRatio === "null") { 1144 return null; 1145 } 1146 return selectedRatio; 1147 } catch (error) { 1148 // Handle any potential errors here 1149 console.error("Error in getSelectedRatioVehicle:", error); 1150 return null; // Return null if an error occurs 1151 } 1152} 1153 1154function handleVehicleRatioChange(event) { 1155 var arraykey = event.target.closest('.vehicletax-calculator').id; 1156 var selectedRatioguid = getSelectedRatioVehicle(arraykey); 1157 if (selectedRatioguid != null) { 1158 calculateAssessedVehicleValue(selectedRatioguid, arraykey); 1159 } 1160} 1161 1162function handleVehicleInputChange(event) { 1163 var vehilcevalueInput = event.target.value; 1164 var container = event.target.closest('.vehicletax-calculator'); 1165 var arraykey = container.id; 1166 var selectedRatioguid = getSelectedRatioVehicle(arraykey); 1167 //if the selected ratio and assessed value are not null 1168 if (selectedRatioguid ) { 1169 calculateAssessedVehicleValue(selectedRatioguid, arraykey); 1170 } 1171} 1172 1173function displayassessedValVehicle(assessedVal, arraykey) { 1174 var taxcontainer = document.querySelector(`#${arraykey}.vehicletax-calculator`); 1175 var assessmentvalCont = taxcontainer.querySelector(".assessedValue"); 1176 1177 if (assessmentvalCont) { 1178 assessmentvalCont.innerHTML = ''; // Clear existing content 1179 // Create a new div element for assessed value 1180 var assessValDiv = document.createElement('div'); 1181 assessValDiv.className = 'calcdval'; 1182 assessValDiv.innerHTML = '<span class="valSpan">' + assessedVal + '</span>'; 1183 // Clear the container's contents 1184 assessmentvalCont.innerHTML = ''; 1185 // Append the new assessed value div to the container 1186 assessmentvalCont.appendChild(assessValDiv); 1187 } 1188} 1189 1190function calculateAssessedVehicleValue(ratioguid, arraykey) { 1191 var taxcontainer = document.querySelector(`#${arraykey}.vehicletax-calculator`); 1192 var ratioArray = vehicleRatioArrays[arraykey]; 1193 var selectedRatio = ratioArray.find(function (ratio) { 1194 return ratio.guid === ratioguid; 1195 }); 1196 var vehicleValue = taxcontainer.querySelector('.vehicleValue').value; 1197 var assessedValue = vehicleValue * ((selectedRatio.percent) / 100); 1198 displayassessedValVehicle(assessedValue.toFixed(2), arraykey); 1199} 1200 1201window.addEventListener('load', vehicleinitializeTaxCalculators); 1202 1203function vehicleinitializeTaxCalculators() { 1204 var calculatorContainers = document.querySelectorAll('.vehicletax-calculator');
1205 calculatorContainers.forEach(function (container) { 1206 var containerId = container.id; 1207 arraykey = containerId; 1208 taxcalcVehicle(containerId); 1209 displayRatiosVehicle(arraykey); 1210 }); 1211} 1212 1213var vehicleRatioArrays = {}; 1214 1215function SetupCalendar(calendarId, sectionId) { 1216 let date=new Date(); 1217 let year=date.getFullYear(); 1218 let month = date.getMonth(); 1219 let calId = '#' + calendarId; 1220 let cal = document.querySelector(calId); 1221 let prenexIcons=cal.querySelectorAll(".calendar-nav"); 1222 let today = cal.querySelector(".today"); 1223 let viewicons = $('.calendar-container.g' + sectionId + ' .prolistswap'); 1224 let procallist = $('.calendar-container.g' + sectionId + ' .calendar-prolist'); 1225 let procalendar = $('.calendar-container.g' + sectionId + ' .calendar-body'); 1226 1227 // function to generate the calendar 1228 GetCategories(sectionId); 1229 UpdateCalendar(calId, year, month, sectionId); 1230 let callist = $('.procalendar.g' + sectionId + ' .calendar-list'); 1231 if (callist.length > 0) { 1232 GetUpcomingEvents(sectionId); 1233 } 1234 1235 prenexIcons.forEach(icon=> { 1236 icon.addEventListener('click', ()=> { 1237 month=icon.classList.contains("calendar-prev") ? month - 1 : month + 1; 1238 if (month < 0 || month > 11) { 1239 date=new Date(year, month, new Date().getDate()); 1240 year=date.getFullYear(); 1241 month=date.getMonth(); 1242 } 1243 else { 1244 date=new Date(); 1245 } 1246 UpdateCalendar(calId, year, month, sectionId); 1247 $('.procalendar.g' + sectionId + ' .categories').val('all'); 1248 }); 1249 }); 1250 today.addEventListener("click", ()=> { 1251 date=new Date(); 1252 year=date.getFullYear(); 1253 month=date.getMonth(); 1254 UpdateCalendar(calId, year, month, sectionId); 1255 $('.procalendar.g' + sectionId + ' .categories').val('all'); 1256 }); 1257 if (viewicons.length > 0) { 1258 viewicons.click( function () { 1259 $(this).parent().find('.active').removeClass('active'); 1260 $(this).addClass('active'); 1261 if ($(this).hasClass('calview')) { 1262 procallist.hide(); 1263 procalendar.show(); 1264 } 1265 else { 1266 procalendar.hide(); 1267 procallist.show(); 1268 } 1269 }); 1270 } 1271} 1272 1273function GetCategories(sectionId) { 1274 $.ajax({ 1275 type: "GET", 1276 method: 'GET', 1277 url: "/admin/dm/Item/GetCategoriesForSectionId/?sectionId=" + sectionId + "&IsPublic=true", 1278 cache: false, 1279 async: false, 1280 contentType: "application/json; charset=utf-8", 1281 dataType: "json", 1282 data: '', 1283 processData: false, 1284 timeout: 300000, 1285 crossDomain: true, 1286 success: function (data) { 1287 $('.procalendar.g' + sectionId + ' .thecats').html(JSON.stringify(data)); 1288 1289 $.each(data, function (i, p) { 1290 if (p.Title != 'None') { 1291 $('.procalendar.g' + sectionId + ' .categories').append($('<option>', { 1292 value: p.CategoryId, 1293 icon: p.FaIcon, 1294 text: p.Title 1295 })); 1296 } 1297 }); 1298 $('.procalendar.g' + sectionId + ' .categories').change(function () { 1299 let cat = $(this).val(); 1300 if (cat != 'all') { 1301 $('.procalendar.g' + sectionId + ' .calendar-dates li a').each(function () { 1302 if ($(this).attr('category') != cat) { $(this).hide(); } 1303 else { $(this).show(); } 1304 }); 1305 $('.procalendar.g' + sectionId + ' .eventlistitem').each(function () { 1306 if ($(this).attr('category') != cat) { $(this).addClass('hide'); } 1307 else { $(this).removeClass('hide'); } 1308 }); 1309 $('.g' + sectionId + ' .calendar-dates li button.more').hide(); 1310 $('.g' + sectionId + ' .calendar-dates li div.hide.moreevents').show(); 1311 } 1312 else { 1313 $('.procalendar.g' + sectionId + ' .calendar-dates li a').each(function () { 1314 $(this).show(); 1315 }); 1316 $('.procalendar.g' + sectionId + ' .eventlistitem').each(function () { 1317 $(this).removeClass('hide'); 1318 }); 1319 $('.g' + sectionId + ' .calendar-dates li button.more').show(); 1320 $('.g' + sectionId + ' .calendar-dates li div.hide.moreevents').hide(); 1321 } 1322 }); 1323 }, 1324 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 1325 error: function (data) { 1326 console.log('error: ' + JSON.stringify(data)); 1327 } 1328 }); 1329} 1330 1331function GetUpcomingEvents(sectionId) { 1332 let displayNum = $('.calendar-container.g' + sectionId).attr('displaynum'); 1333 if (displayNum == undefined) { displayNum = $('.procalendar.g' + sectionId).attr('displaynum'); } 1334 if (displayNum == undefined) { displayNum = 5; } 1335 if (displayNum == 0) { displayNum = 5; } 1336 // if (displayNum > 10) { displayNum = 10; } 1337 1338 $.ajax({
1339 type: "GET", 1340 method: 'GET', 1341 url: "/admin/dm/Item/GetUpcomingEvents/?sectionId=" + sectionId + "&numberofitems=" + displayNum, 1342 cache: false, 1343 async: false, 1344 contentType: "application/json; charset=utf-8", 1345 dataType: "json", 1346 data: '', 1347 processData: false, 1348 timeout: 300000, 1349 crossDomain: true, 1350 success: function (data) { 1351 let callist = $('.procalendar.g' + sectionId + ' .calendar-list'); 1352 if ($(`.procalendar.g${sectionId}.HA_ProCurrent`).length == 0) { 1353 callist.append('<h2>Current Events</h2>'); 1354 } 1355 callist.append('<div class="eventlistdialogs"></div>'); 1356 let listdialogs = $('.procalendar.g' + sectionId + ' .eventlistdialogs'); 1357 1358 let socialSharing = $('.calendar-container.g' + sectionId).attr('socialsharing'); 1359 let enableFacebook = $('.calendar-container.g' + sectionId).attr('enablefacebook'); 1360 let enableX = $('.calendar-container.g' + sectionId).attr('enablex'); 1361 let enableCopy = $('.calendar-container.g' + sectionId).attr('enablecopy'); 1362 let cats = JSON.parse($('.procalendar.g' + sectionId + ' .thecats').html()); 1363 1364 $.each(data, function (i, p) { 1365 let title = ''; let summary = ''; let description = ''; let dstart = ''; let dend = ''; 1366 let location = ''; let lname = ''; let directions = ''; let contactinfo = ''; let categoryid = ''; let latlng = ''; 1367 let links = ''; let images = ''; let documents = ''; let audios = ''; let videos = ''; 1368 let start = null; let end = null; 1369 1370 $.each(p.XmlData.Data.Property, function (j, q) { 1371 if (q["@name"] == 'title') title = q["@value"]; 1372 if (q["@name"] == 'summary') summary = q["@value"]; 1373 if (q["@name"] == 'description') description = q["@value"]; 1374 if (q["@name"] == 'displayStartTime') dstart = q["@value"]; 1375 if (q["@name"] == 'displayEndTime') dend = q["@value"]; 1376 if (q["@name"] == 'name' && q["@value"].length > 0) lname = q["@value"] + '<br/>'; 1377 if (q["@name"] == 'address1' && q["@value"].length > 0) location = q["@value"] + '<br/>'; 1378 if (q["@name"] == 'address2' && q["@value"].length > 0) location += q["@value"] + '<br/>'; 1379 if (q["@name"] == 'city' && q["@value"].length > 0) location += q["@value"] + ', '; 1380 if (q["@name"] == 'state' && q["@value"].length > 0) location += q["@value"] + ' '; 1381 if (q["@name"] == 'zip' && q["@value"].length > 0) location += q["@value"]; 1382 if (q["@name"] == 'latlng' && q["@value"].length > 0) latlng += q["@value"]; 1383 if (q["@name"] == 'directions' && q["@value"].length > 0) directions = q["@value"]; 1384 if (q["@name"] == 'contactInfo' && q["@value"].length > 0) contactinfo = q["@value"]; 1385 if (q["@name"] == 'category') categoryid = q["@value"]; 1386 if (q["@name"] == 'start') start = new Date(q["@value"]); 1387 if (q["@name"] == 'finish') end = new Date(q["@value"]); 1388 }); 1389 let startdate = start.getDate(); 1390 let displaystartdate = start.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }); 1391 let displayenddate = end.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }); 1392 let boxmonth = start.toLocaleString('en-US', { month: 'short' }); 1393 let boxday = startdate; 1394 let starttime = start.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); 1395 let endtime = end.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); 1396 let displaydatetimestart = start.toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); 1397 let displaydatetimeend = end.toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); 1398 1399 $.each(p.XmlData.Data, function (key, val) { 1400 if (key == 'RelatedLinks' && val != null) { 1401 $.each(val, function (j, q) { 1402 if (Array.isArray(q)) { 1403 $.each(q, function (k, r) { 1404 if (r["@intermediatepage"] == 'true') 1405 links += '<a href="/intermediate.asp?link=' + r["@url"] + '" '; 1406 else 1407 links += '<a href="' + r["@url"] + '" '; 1408 if (r["@targetNewWindow"] == 'true') 1409 links += 'target="_blank"'; 1410 links += '><i class="fa-solid fa-link"></i>' + r["@title"] + '</a><br/>'; 1411 });
1412 } 1413 else { 1414 if (q["@intermediatepage"] == 'true') 1415 links += '<a href="/intermediate.asp?link=' + q["@url"] + '" '; 1416 else 1417 links += '<a href="' + q["@url"] + '" '; 1418 if (q["@targetNewWindow"] == 'true') 1419 links += 'target="_blank"'; 1420 links += '><i class="fa-solid fa-link"></i>' + q["@title"] + '</a><br/>'; 1421 } 1422 }); 1423 } 1424 if (key == 'Images' && val != null) { 1425 let count = 0; 1426 $.each(val, function (j, q) { 1427 count++; 1428 if (Array.isArray(q)) { 1429 if (q[0]["@cropFilename"] != null) 1430 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q[0]["@cropFilename"] + '" alt="' + q[0]["@alt"] + '" /></div>'; 1431 else if (q[0]["@displayFilename"] != null) 1432 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q[0]["@displayFilename"] + '" alt="' + q[0]["@alt"] + '" /></div>'; 1433 } 1434 else { 1435 if (q["@cropFilename"] != null) 1436 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@cropFilename"] + '" alt="' + q["@alt"] + '" /></div>'; 1437 else if (q["@displayFilename"] != null) 1438 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@displayFilename"] + '" alt="' + q["@alt"] + '" /></div>'; 1439 } 1440 }); 1441 } 1442 if (key == 'Documents' && val != null) { 1443 $.each(val, function (j, q) { 1444 if (Array.isArray(q)) { 1445 $.each(q, function (k, r) { 1446 if (r["@dmDoc"] == 'True') { 1447 let displayName = r["@title"] == "" ? r["@filename"] : r["@title"]; 1448 documents += '<a target="_blank" href="/uploads/dm/' + r["@dmFileId"] + "/" + encodeForPath(displayName) + '"><i class="fa-solid fa-file"></i>' + displayName + '</a><br/>'; 1449 } else { 1450 documents += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '"><i class="fa-solid fa-file"></i>' + r["@title"] + '</a><br/>'; 1451 } 1452 });
1453 } 1454 else { 1455 if (q["@dmDoc"] == 'True') { 1456 let displayName = q["@title"] == "" ? q["@filename"] : q["@title"]; 1457 documents += '<a target="_blank" href="/uploads/dm/' + q["@dmFileId"] + "/" + encodeForPath(displayName) + '"><i class="fa-solid fa-file"></i>' + displayName + '</a><br/>'; 1458 } else { 1459 documents += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '"><i class="fa-solid fa-file"></i>' + q["@title"] + '</a><br/>'; 1460 } 1461 } 1462 }); 1463 } 1464 if (key == 'Audios' && val != null) { 1465 $.each(val, function (j, q) { 1466 if (Array.isArray(q)) { 1467 $.each(q, function (k, r) { 1468 audios += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '"><i class="fa-solid fa-volume"></i>' + r["@title"] + '</a><br/>'; 1469 }); 1470 } 1471 else { 1472 audios += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '" ><i class="fa-solid fa-volume"></i>' + q["@title"] + '</a><br/>'; 1473 } 1474 }); 1475 } 1476 if (key == 'Videos' && val != null) { 1477 $.each(val, function (j, q) { 1478 if (Array.isArray(q)) { 1479 $.each(q, function (k, r) { 1480 videos += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '" ><i class="fa-solid fa-video"></i>' + r["@title"] + '</a><br/>'; 1481 });
1482 } 1483 else { 1484 videos += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '" ><i class="fa-solid fa-video"></i>' + q["@title"] + '</a><br/>'; 1485 } 1486 }); 1487 } 1488 }); 1489 1490 let catclass = ''; let caticon = ''; let catname = ''; 1491 $.each(cats, function (cati, catp) { 1492 if (catp.CategoryId == categoryid) { 1493 catclass = catp.CssClass; 1494 caticon = catp.FaIcon; 1495 catname = catp.Title; 1496 } 1497 }); 1498 1499 if ($(`.procalendar.g${sectionId}.HA_ProCurrent`).length > 0) { 1500 callist.append(`<div class="eventlistitem" did="ld${p.DEId}" category="${categoryid}"></div>`) 1501 let callistitem = $(`.procalendar.g${sectionId} .eventlistitem[did="ld${p.DEId}"]`); 1502 if ($(`.procalendar.g${sectionId}.HA_ProCurrent`).attr('faicon') != undefined) { 1503 if ($(`.procalendar.g${sectionId}.HA_ProCurrent`).attr('faicon').length > 0) { 1504 let faicon = $(`.procalendar.g${sectionId}.HA_ProCurrent`).attr('faicon'); 1505 callistitem.append(`<div class="boxicon"><i class="fa-solid ${faicon}"></i></div>`); 1506 } else { 1507 callistitem.append(`<div class="boxicon ${catclass}"><i class="fa-solid ${caticon}"></i></div>`); 1508 } 1509 } else { 1510 callistitem.append(`<div class="boxicon ${catclass}"><i class="fa-solid ${caticon}"></i></div>`); 1511 } 1512 callistitem.append('<div class="rightside"></div>'); 1513 let callistitemright = $(`.procalendar.g${sectionId} .eventlistitem[did="ld${p.DEId}"] .rightside`); 1514 callistitemright.append(`<h3><a href="javascript:;" class="event" did="ld${p.DEId}">${title}</a></h3>`); 1515 if (dstart != 'none' && dstart != 'time') { 1516 callistitemright.append('<div class="eventdate" did="ld' + p.DEId + '">' + displaystartdate + '</div> '); 1517 } 1518 if (dstart != 'none' && dstart != 'date') { 1519 callistitemright.append('<div class="eventtime" did="ld' + p.DEId + '">' + starttime + '</div>'); 1520 } 1521 } 1522 else { 1523 callist.append('<div class="eventlistitem" did="ld' + p.DEId + '" category="' + categoryid + '"></div>')
1524 let callistitem = $('.procalendar.g' + sectionId + ' .eventlistitem[did="ld' + p.DEId + '"]'); 1525 callistitem.append('<div class="boxdate"><div class="month">' + boxmonth + '</div><div class="day">' + boxday + '</div></div>'); 1526 callistitem.append('<div class="rightside"></div>'); 1527 let callistitemright = $('.procalendar.g' + sectionId + ' .eventlistitem[did="ld' + p.DEId + '"] .rightside'); 1528 callistitemright.append('<h3><a href="javascript:;" class="event" did="ld' + p.DEId + '">' + title + '</a></h3>'); 1529 if (dstart != 'none' && dstart != 'date') { 1530 // callistitemright.append('<div class="eventdate" did="ld' + p.DEId + '">' + displaystartdate + '</div> '); 1531 callistitemright.append('<div class="eventtime" did="ld' + p.DEId + '">' + starttime + '</div>'); 1532 } 1533 } 1534 1535 // build dialogs 1536 listdialogs.append('<dialog id="ld' + p.DEId + '" class="event dialog"><button type="button" class="closedialog" aria-label="close dialog">Close <i class="fa-regular fa-x"></i></button></dialog>'); 1537 let $ld = listdialogs.find('dialog#ld' + p.DEId); 1538 $ld.append('<div class="beforemap"></div>'); 1539 let bmap = $ld.find('.beforemap'); 1540 1541 bmap.append('<h2>' + title + '</h2>'); 1542 1543 if (dstart != 'none' || dend != 'none') { 1544 bmap.append('<div class="eventtime"><span class="label"><i class="fa-solid fa-clock"></i> When: </span></div>'); 1545 let dt = $ld.find('.eventtime'); 1546 if (dstart == 'date') { dt.append(displaystartdate); } 1547 if (dstart == 'time') { dt.append(starttime); } 1548 if (dstart == 'full') { dt.append(displaydatetimestart); } 1549 if (dstart != 'none' && dend != 'none') { dt.append(' - '); } // add a dash between start and end 1550 if (dend == 'date') { dt.append(displayenddate); } 1551 if (dend == 'time') { dt.append(endtime); } 1552 if (dend == 'full') { dt.append(displaydatetimeend); } 1553 } 1554 1555 if (images.length > 0 || description.length > 0 || (caticon != undefined && caticon.length > 0) || links.length > 0 || documents.length > 0 || audios.length > 0 || videos.length > 0) { 1556 bmap.append('<hr/>'); 1557 } 1558 1559 if (caticon != undefined && caticon.length > 0) { 1560 bmap.append(`<div class="category ${catclass}"><span class="color"> </span><span class="label"><i class="fa-solid ${caticon}"></i> </span>${catname}</div>`); 1561 } 1562 1563 if (images.length > 0) { 1564 bmap.append('<div class="description">' + images + description + '</div>'); 1565 } 1566 else { 1567 bmap.append('<div class="description">' + description + '</div>'); 1568 } 1569 let desc = bmap.find('.description'); 1570 1571 if (links.length > 0 || documents.length > 0 || audios.length > 0 || videos.length > 0) { 1572 //desc.append('<div class="attachments"><span class="label"><i class="fa-solid fa-paperclip"></i> Attachments:</span><br/>' + links + documents + audios + videos + '</div>'); 1573 desc.append('<div class="attachments">' + links + documents + audios + videos + '</div>'); 1574 } 1575 1576 if (contactinfo.length > 0 || location.length > 0) { 1577 bmap.append('<hr/>'); 1578 } 1579 1580 bmap.append('<div class="sidebyside"></div>'); 1581 let sbs = $ld.find('.sidebyside'); 1582 if (contactinfo.length > 0) { 1583 sbs.append('<div class="contactinfo"><span class="label"><i class="fa-solid fa-user"></i> Contact:</span><br/>' + contactinfo + '</div>'); 1584 } 1585 if (lname.length > 0 || location.length > 0) { 1586 sbs.append('<div class="location"><span class="label"><i class="fa-solid fa-location-dot"></i> Where: </span><br/>' + lname + location + '</div>'); 1587 let loc = sbs.find('.location'); 1588 if (latlng.length > 0) 1589 loc.append('<br/><a href="https://www.google.com/maps/dir/?api=1&destination=' + latlng + '" target="_blank" class="maplink">Get Directions</a>'); 1590 } 1591 1592 if (latlng.length > 0) { 1593 $ld.append('<div class="mapcontainer"></div>'); 1594 let $thismap = $('.procalendar.g' + sectionId + ' dialog#ld' + p.DEId + ' .mapcontainer'); 1595 $thismap.append('<div id="lloc' + p.DEId + '" class="hidden coordinates">' + latlng + '</div>'); 1596 $thismap.append('<div id="lmap' + p.DEId + '" class="map"></div>'); 1597 } 1598 1599 $ld.append('<div class="aftermap"></div>'); 1600 let amap = $ld.find('.aftermap'); 1601 1602 if (directions.length > 0) { 1603 amap.append('<div class="directions"><span class="label"><i class="fa-solid fa-diamond-turn-right"></i> Directions:</span><br/>' + directions + '</div>'); 1604 } 1605 1606 //zach 1607 if (socialSharing != null && socialSharing == "True") { 1608 var siteUrl = window.location.protocol + "//" + window.location.host; 1609 var apiUrl = siteUrl + "/govofficeservices/api/content/ics.ashx?event=" + p.DEId + "§ion=" + sectionId; 1610 var eventUrl = (siteUrl + "/index.asp?SEC=" + sectionId + "&DE=" + p.DEId); 1611 //ICS button + sharing 1612 1613 amap.append(`<div class="eventics"><a href="${apiUrl}"><i class="fa-solid fa-calendar-plus"></i><span class="label">Save to your calendar</span></a></div>`); 1614 1615 if (enableFacebook != null && enableFacebook == "True") { 1616 amap.append(`<a class="modalBTNSocial facebook" href="https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(eventUrl)}" title="Share on Facebook" target="_blank"><i class="fab fa-facebook-f"></i>SHARE</a>`); 1617 amap.append(` `); 1618 } 1619 if (enableX != null && enableX == "True") { 1620 amap.append(`<a class="modalBTNSocial twitter" href="https://twitter.com/intent/tweet?url=${encodeURIComponent(eventUrl)}" title = "Post on X (formerly Twitter)" target = "_blank" > <i class="fab fa-x-twitter"></i>POST</a >`); 1621 amap.append(` `); 1622 } 1623 if (enableCopy != null && enableCopy == "True") 1624 amap.append(`<a class="modalBTNSocial copy" onclick="copyToClipboard('${eventUrl}', this, 'COPIED!')" title="Copy to your clipboard"><i class="fal fa-copy"></i>COPY</a>`); 1625 } 1626 1627 }); 1628 1629 if (callist.find('.eventlistitem').length == 0) { callist.append('<h3>No Current Events</h3>'); } 1630 1631 // event handlers 1632 $('.g' + sectionId + ' .eventlistitem').on("click", "a.event", function () { 1633 let ddd = document.getElementById($(this).attr('did')); 1634 ddd.showModal(); 1635 ddd.addEventListener("click", e => { 1636 const dialogDimensions = ddd.getBoundingClientRect() 1637 if ( 1638 e.clientX < dialogDimensions.left || e.clientX > dialogDimensions.right || 1639 e.clientY < dialogDimensions.top || e.clientY > dialogDimensions.bottom 1640 ) { 1641 ddd.close() 1642 } 1643 }); 1644 // display map here if it exists 1645 if (document.getElementById('lloc' + $(this).attr('did').substring(2)) != null) { 1646 let loc = document.getElementById('lloc' + $(this).attr('did').substring(2)).innerHTML; 1647 let mapid = 'lmap' + $(this).attr('did').substring(2); // get the map id 1648 //alert(mapid + ' - ' + loc); 1649 if (loc.length > 0 && mapid != '<!---->') { 1650 document.getElementById(mapid).classList.add("shown"); 1651 document.querySelector('.mapcoords').innerHTML = loc; 1652 document.querySelector('.mapid').innerHTML = mapid; 1653 initLocationMap(); 1654 } 1655 } 1656 }); 1657 1658 $('.eventlistdialogs').on("click", "button.closedialog", function () { 1659 dialogs = document.querySelectorAll('dialog');
1660 dialogs.forEach (function(d) { 1661 d.close(); 1662 }); 1663 }); 1664 1665 }, 1666 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 1667 error: function (data) { 1668 console.log('error: ' + JSON.stringify(data)); 1669 } 1670 }); 1671} 1672 1673function UpdateCalendar(calId, year, month, sectionId) { 1674 let date = new Date(); 1675 let cal = document.querySelector(calId); 1676 let grid = cal.querySelector('.calendar-dates'); 1677 let currdate = cal.querySelector('.calendar-current-date'); 1678 let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; 1679 1680 // get the first day of the month 1681 let dayone=new Date(year, month, 1).getDay(); 1682 // get the last date of the month 1683 let lastdate=new Date(year, month + 1, 0).getDate(); 1684 // get the day of the last date of the month 1685 let dayend=new Date(year, month, lastdate).getDay(); 1686 // get the last date of the previous month 1687 let monthlastdate=new Date(year, month, 0).getDate(); 1688 let newcal=""; // variable to store the generated calendar HTML 1689 // loop to add the last dates of the previous month 1690 for (let i=dayone; i > 0; i--) { newcal+=`<li class="inactive">${monthlastdate - i + 1}</li>`; } 1691 // loop to add the dates of the current month 1692 for (let i=1; i <=lastdate; i++) { 1693 // check if the current date is today 1694 let isToday = i === date.getDate() && month === new Date().getMonth() && year === new Date().getFullYear() ? " active" : ""; 1695 let displaydate = new Date(year, month, i).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }); 1696 newcal+=`<li class="d${i}${isToday}"><div class="day">${i}</div><div class="daylist"><h3>${displaydate}</h3><button type="button" class="close">Close</button></div></li>`; 1697 } 1698 // loop to add the first dates of the next month 1699 for (let i = dayend; i < 6; i++) { newcal += `<li class="inactive">${i - dayend + 1}</li>`; } 1700 // update the text of the current date element with the formatted current month and year 1701 currdate.innerText=`${months[month]} ${year}`; 1702 // update the HTML of the dates element with the generated calendar 1703 grid.innerHTML = newcal; 1704 1705 $('.procalendar.g' + sectionId + ' .dialogs dialog').remove(); 1706 GetMonthItems(sectionId, year, month + 1); 1707} 1708 1709/** 1710 * copyToClipboard - Copies text to clipboard and swaps the text on the element with the provided text. 1711 * @param {any} url - what to copy to clipboard, usually a URL 1712 * @param {any} element - the button/element that was clicked 1713 * @param {any} text - the text to swap with the element's innerHTML 1714 */ 1715window.copyToClipboard = function (url, element, text) { 1716 navigator.clipboard.writeText(url) 1717 .then(() => { 1718 const originalContent = element.innerHTML; 1719 const originalColor = element.style.backgroundColor; 1720 element.textContent = text; 1721 element.style.backgroundColor = '#338445'; 1722 1723 // Revert back to original content after a delay 1724 setTimeout(() => { 1725 element.innerHTML = originalContent; 1726 element.style.backgroundColor = originalColor; 1727 }, 3500); 1728 1729 }, function (err) { 1730 alert('Failed to copy text: ', err); 1731 }); 1732}; 1733 1734function GetMonthItems(sectionId, year, month) { 1735 let promo = ''; 1736 let APIurl = ''; 1737 if ($(`.procalendar.g${sectionId}.promo`).length > 0) { 1738 APIurl = "/admin/dm/Item/GetMonth/?sectionId=" + sectionId + "&Year=" + year + "&Month=" + month + "&IsPublic=true&IsPromo=true"; 1739 } else { 1740 APIurl = "/admin/dm/Item/GetMonth/?sectionId=" + sectionId + "&Year=" + year + "&Month=" + month + "&IsPublic=true"; 1741 } 1742 $.ajax({ 1743 type: "GET", 1744 method: 'GET', 1745 url: APIurl, 1746 cache: false, 1747 async: false, 1748 contentType: "application/json; charset=utf-8", 1749 dataType: "json", 1750 data: '', 1751 processData: false, 1752 timeout: 300000, 1753 crossDomain: true, 1754 success: function (data) { 1755 // let callist = $('.procalendar.g' + sectionId + ' .calendar-list'); 1756 let procallist = $('.procalendar.g' + sectionId + ' .calendar-prolist'); 1757 let currentMonth = new Date().getMonth() + 1; 1758 let displayNum = $('.calendar-container.g' + sectionId).attr('displaynum'); 1759 let showPastEvents = $('.calendar-container.g' + sectionId).attr('showpastevents'); 1760 let socialSharing = $('.calendar-container.g' + sectionId).attr('socialsharing'); 1761 let enableFacebook = $('.calendar-container.g' + sectionId).attr('enablefacebook'); 1762 let enableX = $('.calendar-container.g' + sectionId).attr('enablex'); 1763 let enableCopy = $('.calendar-container.g' + sectionId).attr('enablecopy'); 1764 // callist.html(''); 1765 procallist.html(''); 1766 let cats = JSON.parse($('.procalendar.g' + sectionId + ' .thecats').html()); 1767 1768 // put values into variables 1769 $.each(data, function (i, p) { 1770 let gd = new Date(p.GD); 1771 let adjustedEnd = new Date(p.EndDate); 1772 let title = ''; let summary = ''; let description = ''; let dstart = ''; let dend = ''; 1773 let location = ''; let lname = ''; let directions = ''; let contactinfo = ''; let categoryid = ''; let latlng = ''; 1774 let links = ''; let images = ''; let documents = ''; let audios = ''; let videos = ''; 1775 let start = null; let end = null; 1776 1777 $.each(p.XmlData.Data.Property, function (j, q) { 1778 if (q["@name"] == 'title') title = q["@value"]; 1779 if (q["@name"] == 'summary') summary = q["@value"]; 1780 if (q["@name"] == 'description') description = q["@value"]; 1781 if (q["@name"] == 'displayStartTime') dstart = q["@value"]; 1782 if (q["@name"] == 'displayEndTime') dend = q["@value"]; 1783 if (q["@name"] == 'name' && q["@value"].length > 0) lname = q["@value"] + '<br/>'; 1784 if (q["@name"] == 'address1' && q["@value"].length > 0) location = q["@value"] + '<br/>'; 1785 if (q["@name"] == 'address2' && q["@value"].length > 0) location += q["@value"] + '<br/>'; 1786 if (q["@name"] == 'city' && q["@value"].length > 0) location += q["@value"] + ', '; 1787 if (q["@name"] == 'state' && q["@value"].length > 0) location += q["@value"] + ' '; 1788 if (q["@name"] == 'zip' && q["@value"].length > 0) location += q["@value"]; 1789 if (q["@name"] == 'latlng' && q["@value"].length > 0) latlng += q["@value"]; 1790 if (q["@name"] == 'directions' && q["@value"].length > 0) directions = q["@value"]; 1791 if (q["@name"] == 'contactInfo' && q["@value"].length > 0) contactinfo = q["@value"]; 1792 if (q["@name"] == 'category') categoryid = q["@value"]; 1793 if (q["@name"] == 'start') start = new Date(q["@value"]); 1794 if (q["@name"] == 'finish') end = new Date(q["@value"]); 1795 }); 1796 let startdate = start.getDate(); 1797 let displaystartdate = start.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
1798 let displayenddate = end.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }); 1799 let boxmonth = start.toLocaleString('en-US', { month: 'short' }); 1800 let boxday = startdate; 1801 let starttime = start.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); 1802 let endtime = end.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); 1803 let displaydatetimestart = start.toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); 1804 let displaydatetimeend = end.toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); 1805 1806 $.each(p.XmlData.Data, function (key, val) { 1807 if (key == 'RelatedLinks' && val != null) { 1808 $.each(val, function (j, q) { 1809 if (Array.isArray(q)) { 1810 $.each(q, function (k, r) { 1811 if (r["@intermediatepage"] == 'true') 1812 links += '<a href="/intermediate.asp?link=' + r["@url"] + '" '; 1813 else 1814 links += '<a href="' + r["@url"] + '" '; 1815 if (r["@targetNewWindow"] == 'true') 1816 links += 'target="_blank"'; 1817 links += '><i class="fa-solid fa-link"></i>' + r["@title"] + '</a><br/>'; 1818 });
1819 } 1820 else { 1821 if (q["@intermediatepage"] == 'true') 1822 links += '<a href="/intermediate.asp?link=' + q["@url"] + '" '; 1823 else 1824 links += '<a href="' + q["@url"] + '" '; 1825 if (q["@targetNewWindow"] == 'true') 1826 links += 'target="_blank"'; 1827 links += '><i class="fa-solid fa-link"></i>' + q["@title"] + '</a><br/>'; 1828 } 1829 }); 1830 } 1831 if (key == 'Images' && val != null) { 1832 let count = 0; 1833 $.each(val, function (j, q) { 1834 count++; 1835 if (Array.isArray(q)) { 1836 if (q[0]["@cropFilename"] != null) 1837 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q[0]["@cropFilename"] + '" alt="' + q[0]["@alt"] + '" /></div>'; 1838 else if (q[0]["@displayFilename"] != null) 1839 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q[0]["@displayFilename"] + '" alt="' + q[0]["@alt"] + '" /></div>'; 1840 } 1841 else { 1842 if (q["@cropFilename"] != null) 1843 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@cropFilename"] + '" alt="' + q["@alt"] + '" /></div>'; 1844 else if (q["@displayFilename"] != null) 1845 images += '<div class="image left"><img src="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@displayFilename"] + '" alt="' + q["@alt"] + '" /></div>'; 1846 } 1847 }); 1848 } 1849 if (key == 'Documents' && val != null) { 1850 $.each(val, function (j, q) { 1851 if (Array.isArray(q)) { 1852 $.each(q, function (k, r) { 1853 if (r["@dmDoc"] == 'True') { 1854 let displayName = r["@title"] == "" ? r["@filename"] : r["@title"]; 1855 documents += '<a target="_blank" href="/uploads/dm/' + r["@dmFileId"] + "/" + encodeForPath(displayName) + '"><i class="fa-solid fa-file"></i>' + displayName + '</a><br/>'; 1856 } else { 1857 documents += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '"><i class="fa-solid fa-file"></i>' + r["@title"] + '</a><br/>'; 1858 } 1859 });
1860 } 1861 else { 1862 if (q["@dmDoc"] == 'True') { 1863 let displayName = q["@title"] == "" ? q["@filename"] : q["@title"]; 1864 documents += '<a target="_blank" href="/uploads/dm/' + q["@dmFileId"] + "/" + encodeForPath(displayName) + '"><i class="fa-solid fa-file"></i>' + displayName + '</a><br/>'; 1865 } else { 1866 documents += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '"><i class="fa-solid fa-file"></i>' + q["@title"] + '</a><br/>'; 1867 } 1868 } 1869 }); 1870 } 1871 if (key == 'Audios' && val != null) { 1872 $.each(val, function (j, q) { 1873 if (Array.isArray(q)) { 1874 $.each(q, function (k, r) { 1875 audios += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '"><i class="fa-solid fa-volume"></i>' + r["@title"] + '</a><br/>'; 1876 }); 1877 } 1878 else { 1879 audios += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '" ><i class="fa-solid fa-volume"></i>' + q["@title"] + '</a><br/>'; 1880 } 1881 }); 1882 } 1883 if (key == 'Videos' && val != null) { 1884 $.each(val, function (j, q) { 1885 if (Array.isArray(q)) { 1886 $.each(q, function (k, r) { 1887 videos += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + r["@filename"] + '" ><i class="fa-solid fa-video"></i>' + r["@title"] + '</a><br/>'; 1888 });
1889 } 1890 else { 1891 videos += '<a href="/vertical/sites/{' + p.SiteId + '}/uploads/' + q["@filename"] + '" ><i class="fa-solid fa-video"></i>' + q["@title"] + '</a><br/>'; 1892 } 1893 }); 1894 } 1895 }); 1896 1897 let catclass = ''; let caticon = ''; let catname = ''; 1898 $.each(cats, function (cati, catp) { 1899 if (catp.CategoryId == categoryid) { 1900 catclass = catp.CssClass; 1901 caticon = catp.FaIcon; 1902 catname = catp.Title; 1903 } 1904 }); 1905 1906 if (showPastEvents == 'True' || adjustedEnd > gd) { 1907 // add to calendar 1908 for (var d = start; d <= end; d.setDate(d.getDate() + 1)) { 1909 if (d.getMonth() + 1 == month) { 1910 let spandate = d.getDate(); 1911 1912 // add to daylist first 1913 $(`.g${sectionId} .calendar-dates li.d${spandate} .daylist button.close`).before(`<a href="javascript:;" class="event ${catclass}" id="l_${p.DEId}" did="d${p.DEId}" title="${title}" category="${categoryid}" aria-label="${displaydatetimestart} ${title}"><div><span class="ctitle">${title}</span><div class="datetime"></div></div></a>`); 1914 if (dstart == 'time' || dstart == 'full') 1915 $(`.g${sectionId} .calendar-dates li.d${spandate} .daylist a#l_${p.DEId} div.datetime`).append(`${starttime}`); 1916 if ((dstart == 'time' || dstart == 'full') && (dend == 'time' || dend == 'full')) 1917 $(`.g${sectionId} .calendar-dates li.d${spandate} .daylist a#l_${p.DEId} div.datetime`).append(` - `); 1918 if (dend == 'time' || dend == 'full') 1919 $(`.g${sectionId} .calendar-dates li.d${spandate} .daylist a#l_${p.DEId} div.datetime`).append(`${endtime}`); 1920 1921 // add to calendar date 1922 if ($(`.g${sectionId} .calendar-dates li.d${spandate} > a`).length < 2) { 1923 if (dstart == 'none' || dstart == 'date') 1924 $(`.g${sectionId} .calendar-dates li.d${spandate}`).append(`<a href="javascript:;" class="event ${catclass}" did="d${p.DEId}" title="${title}" category="${categoryid}" aria-label="${displaydatetimestart} ${title}"><div><span class="ctitle">${title}</span></div></a>`); 1925 else 1926 $(`.g${sectionId} .calendar-dates li.d${spandate}`).append(`<a href="javascript:;" class="event ${catclass}" did="d${p.DEId}" title="${title} ${starttime}" category="${categoryid}" aria-label="${displaydatetimestart} ${title}"><div><span class="ctitle">${title}</span><span class="cstarttime">${starttime}</span></div></a>`); 1927 } 1928 else { 1929 // add show more button 1930 if ($(`.g${sectionId} .calendar-dates li.d${spandate} button.more`).length == 0) 1931 $(`.g${sectionId} .calendar-dates li.d${spandate}`).append(`<button class="more">Show More</button>`); 1932 if ($(`.g${sectionId} .calendar-dates li.d${spandate} div.hide.moreevents`).length == 0) 1933 $(`.g${sectionId} .calendar-dates li.d${spandate}`).append(`<div class="hide moreevents"></div>`); 1934 if (dstart == 'none' || dstart == 'date') 1935 $(`.g${sectionId} .calendar-dates li.d${spandate} div.hide.moreevents`).append(`<a href="javascript:;" class="event ${catclass}" did="d${p.DEId}" title="${title}" category="${categoryid}"><div><span class="ctitle">${title}</span></div></a>`); 1936 else 1937 $(`.g${sectionId} .calendar-dates li.d${spandate} div.hide.moreevents`).append(`<a href="javascript:;" class="event ${catclass}" did="d${p.DEId}" title="${title} ${starttime}" category="${categoryid}"><div><span class="ctitle">${title}</span><span class="cstarttime">${starttime}</span></div></a>`); 1938 } 1939 $(`.g${sectionId} .calendar-dates li.d${spandate} button.more`).click(function () { 1940 $(`.g${sectionId} .calendar-dates li.d${spandate} div.daylist`).addClass('show'); 1941 let topOfOverlay = $(`.g${sectionId} .calendar-dates li.d${spandate} div.daylist > h3`); 1942 $('html, body').animate({ scrollTop: ($(topOfOverlay).offset().top - 60) }, 500); 1943 //$('.g' + sectionId + ' .calendar-dates li.d' + spandate + ' button.more').hide(); 1944 //$('.g' + sectionId + ' .calendar-dates li.d' + spandate + ' div.hide.moreevents').show(); 1945 });
1946 $(`.g${sectionId} .calendar-dates li button.close`).click(function () { 1947 $(`.g${sectionId} .calendar-dates li div.daylist`).removeClass('show'); 1948 }); 1949 } 1950 } 1951 1952 // build dialogs 1953 $(`.procalendar.g${sectionId} .dialogs`).append(`<dialog id="d${p.DEId}" class="event dialog"><button type="button" class="closedialog" aria-label="close dialog">Close <i class="fa-regular fa-x"></i></button></dialog>`); 1954 let $thisdialog = $(`.procalendar.g${sectionId} dialog#d${p.DEId}`); 1955 1956 $thisdialog.append('<div class="beforemap"></div>'); 1957 let bmap = $thisdialog.find('.beforemap'); 1958 1959 bmap.append('<h2>' + title + '</h2>'); 1960 1961 if (dstart != 'none' || dend != 'none') { 1962 bmap.append('<div class="eventtime"><span class="label"><i class="fa-solid fa-clock"></i> When: </span></div>'); 1963 let dt = bmap.find('.eventtime'); 1964 if (dstart == 'date') { dt.append(displaystartdate); } 1965 if (dstart == 'time') { dt.append(starttime); } 1966 if (dstart == 'full') { dt.append(displaydatetimestart); } 1967 if (dstart != 'none' && dend != 'none') { dt.append(' - '); } // add a dash between start and end 1968 if (dend == 'date') { dt.append(displayenddate); } 1969 if (dend == 'time') { dt.append(endtime); } 1970 if (dend == 'full') { dt.append(displaydatetimeend); } 1971 } 1972 1973 if (images.length > 0 || description.length > 0 || (caticon != undefined && caticon.length > 0) || links.length > 0 || documents.length > 0 || audios.length > 0 || videos.length > 0) { 1974 bmap.append('<hr/>'); 1975 } 1976 1977 if (caticon != undefined && caticon.length > 0) { 1978 bmap.append(`<div class="category ${catclass}"><span class="color"> </span><span class="label"><i class="fa-solid ${caticon}"></i> </span>${catname}</div>`); 1979 } 1980 1981 if (images.length > 0) { 1982 bmap.append('<div class="description">' + images + description + '</div>'); 1983 } 1984 else { 1985 bmap.append('<div class="description">' + description + '</div>'); 1986 } 1987 let desc = bmap.find('.description'); 1988 1989 if (links.length > 0 || documents.length > 0 || audios.length > 0 || videos.length > 0) { 1990 //desc.append('<div class="attachments"><span class="label"><i class="fa-solid fa-paperclip"></i> Attachments:</span><br/>' + links + documents + audios + videos + '</div>'); 1991 desc.append('<div class="attachments">' + links + documents + audios + videos + '</div>'); 1992 } 1993 1994 if (contactinfo.length > 0 || lname.length > 0 || location.length > 0) { 1995 bmap.append('<hr/>'); 1996 } 1997 1998 bmap.append('<div class="sidebyside"></div>'); 1999 let sbs = bmap.find('.sidebyside'); 2000 if (contactinfo.length > 0) { 2001 sbs.append('<div class="contactinfo"><span class="label"><i class="fa-solid fa-user"></i> Contact:</span><br/>' + contactinfo + '</div>'); 2002 } 2003 if (lname.length > 0 || location.length > 0) { 2004 sbs.append('<div class="location"><span class="label"><i class="fa-solid fa-location-dot"></i> Where: </span><br/>' + lname + location + '</div>'); 2005 let loc = sbs.find('.location'); 2006 if (latlng.length > 0) 2007 loc.append('<br/><a href="https://www.google.com/maps/dir/?api=1&destination=' + latlng + '" target="_blank" class="maplink">Get Directions</a>'); 2008 } 2009 2010 if (latlng.length > 0) { //location.length > 0 && 2011 $thisdialog.append('<div class="mapcontainer"></div>'); 2012 let $thismap = $('.procalendar.g' + sectionId + ' dialog#d' + p.DEId + ' .mapcontainer'); 2013 $('.mapcontainer').append('<div id="loc' + p.DEId + '" class="hidden coordinates">' + latlng + '</div>'); 2014 $thismap.append('<div id="map' + p.DEId + '" class="map"></div>'); 2015 } 2016 2017 $thisdialog.append('<div class="aftermap"></div>'); 2018 let amap = $thisdialog.find('.aftermap'); 2019 2020 if (directions.length > 0) { 2021 amap.append('<div class="directions"><span class="label"><i class="fa-solid fa-diamond-turn-right"></i> Directions:</span><br/>' + directions + '</div>'); 2022 } 2023 2024 //zach 2025 if (socialSharing != null && socialSharing == "True") { 2026 var siteUrl = window.location.protocol + "//" + window.location.host; 2027 var apiUrl = siteUrl + "/govofficeservices/api/content/ics.ashx?event=" + p.DEId + "§ion=" + sectionId; 2028 var eventUrl = (siteUrl + "/index.asp?SEC=" + sectionId + "&DE=" + p.DEId); 2029 //ICS button + sharing 2030 amap.append(`<div class="eventics"><a href="${apiUrl}"><i class="fa-solid fa-calendar-plus"></i><span class="label">Save to your calendar</span></a></div>`); 2031 2032 if (enableFacebook != null && enableFacebook == "True") { 2033 amap.append(`<a class="modalBTNSocial facebook" href="https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(eventUrl)}" title="Share on Facebook" target="_blank"><i class="fab fa-facebook-f"></i>SHARE</a>`); 2034 amap.append(` `); 2035 } 2036 if (enableX != null && enableX == "True") { 2037 amap.append(`<a class="modalBTNSocial twitter" href="https://twitter.com/intent/tweet?url=${encodeURIComponent(eventUrl)}" title = "Post on X (formerly Twitter)" target = "_blank" > <i class="fab fa-x-twitter"></i>POST</a >`); 2038 amap.append(` `); 2039 } 2040 if (enableCopy != null && enableCopy == "True") 2041 amap.append(`<a class="modalBTNSocial copy" onclick="copyToClipboard('${eventUrl}', this, 'COPIED!')" title="Copy to your clipboard"><i class="fal fa-copy"></i>COPY</a>`); 2042 } 2043 } 2044 2045 // pro calendar list (the big list of events with everything) 2046 if (procallist.length > 0) { 2047 if ((showPastEvents == 'True' || adjustedEnd > gd) && procallist.find('.eventlistitem').length < displayNum) { 2048 if (!$('.calendar-container.g' + sectionId + ' .calview').hasClass('active')) 2049 $('.calendar-container.g' + sectionId + ' .calendar-body').hide(); 2050 procallist.append('<div class="eventlistitem" did="d' + p.DEId + '" category="' + categoryid + '"></div>') 2051 let procallistitem = $(`.procalendar.g${sectionId} .eventlistitem[did="d${p.DEId}"]`); 2052 procallistitem.append(`<div class="boxdate"><div class="month">${boxmonth}</div><div class="day">${boxday}</div></div>`); 2053 procallistitem.append('<div class="rightside"></div>'); 2054 let procallistitemright = $(`.procalendar.g${sectionId} .eventlistitem[did="d${p.DEId}"] .rightside`); 2055 procallistitemright.append(`<h3><a href="/?SEC=${sectionId}&DE=${p.DEId}" class="event" did="d${p.DEId}">${title}</a></h3>`); 2056 2057 // date 2058 if (dstart != 'none' || dend != 'none') { 2059 procallistitemright.append('<div class="eventtime"><i class="fa-solid fa-clock"></i><span class="label">
2059When </span></div>'); 2060 let dt = procallistitemright.find('.eventtime'); 2061 if (dstart == 'date') { dt.append(displaystartdate); } 2062 if (dstart == 'time') { dt.append(starttime); } 2063 if (dstart == 'full') { dt.append(displaydatetimestart); } 2064 if (dstart != 'none' && dend != 'none') { dt.append(' - '); } // add a dash between start and end 2065 if (dend == 'date') { dt.append(displayenddate); } 2066 if (dend == 'time') { dt.append(endtime); } 2067 if (dend == 'full') { dt.append(displaydatetimeend); } 2068 } 2069 // image 2070 procallistitemright.append(images); 2071 // category 2072 let cats = JSON.parse($('.procalendar.g' + sectionId + ' .thecats').html()); 2073 $.each(cats, function (cati, catp) { 2074 if (catp.CategoryId == categoryid) { 2075 if (catp.Title != 'None') { 2076 procallistitemright.append('<div class="category ' + catclass + '"><i class="fa-solid ' + catp.FaIcon + '"></i><span class="category value">' + catp.Title + '</span></div>'); 2077 } 2078 } 2079 }); 2080 // summary 2081 if (summary.length > 0) { 2082 procallistitemright.append('<div class="summary">' + summary + '</div>'); 2083 } 2084 // bottom three 2085 procallistitemright.append('<div class="bottomthree"></div>'); 2086 let bottomthree = $('.procalendar.g' + sectionId + ' .eventlistitem[did="d' + p.DEId + '"] .bottomthree'); 2087 // contact 2088 if (contactinfo.length > 0) { 2089 bottomthree.append('<div class="contactinfo"><i class="fa-solid fa-user"></i><span class="label">Contact</span><br/>' + contactinfo + '</div>'); 2090 } 2091 // location 2092 if (location.length > 0) { 2093 bottomthree.append('<div class="location"><i class="fa-solid fa-location-dot"></i><span class="label">Location</span><br/>' + lname + location + '</div>'); 2094 } 2095 // attachments 2096 if (documents.length > 0 || audios.length > 0 || videos.length > 0) { 2097 bottomthree.append('<div class="attachments"><i class="fa-regular fa-paperclip-vertical"></i><span class="label">Attachments</span><br/>' + documents + audios + videos + '</div>'); 2098 } 2099 } 2100 } 2101 }); 2102 2103 if (procallist.find('.eventlistitem').length == 0) { procallist.append('<h3>No Items to Display</h3>'); } 2104 2105 // bind events 2106 $('.g' + sectionId + ' .calendar-dates').on("click", "a.event", function () { 2107 let ddd = document.getElementById($(this).attr('did')); 2108 ddd.showModal(); 2109 ddd.addEventListener("click", e => { 2110 const dialogDimensions = ddd.getBoundingClientRect() 2111 if ( 2112 e.clientX < dialogDimensions.left || e.clientX > dialogDimensions.right || 2113 e.clientY < dialogDimensions.top || e.clientY > dialogDimensions.bottom 2114 ) { 2115 ddd.close() 2116 } 2117 }); 2118 // display map here if it exists 2119 if (document.getElementById('loc' + $(this).attr('did').substring(1)) != null) { 2120 let loc = document.getElementById('loc' + $(this).attr('did').substring(1)).innerHTML; 2121 let mapid = 'map' + $(this).attr('did').substring(1); // get the map id 2122 if (loc.length > 0 && mapid != '<!---->') { 2123 document.getElementById(mapid).classList.add("shown"); 2124 //document.getElementById(mapid).scrollIntoView({ behavior: 'smooth', block: 'center' }); 2125 document.querySelector('.mapcoords').innerHTML = loc; 2126 document.querySelector('.mapid').innerHTML = mapid; 2127 initLocationMap(); 2128 } 2129 } 2130 }); 2131 2132 $('.dialogs').on("click", "button.closedialog", function () { 2133 dialogs = document.querySelectorAll('dialog');
2134 dialogs.forEach (function(d) { 2135 d.close(); 2136 }); 2137 }); 2138 $('.dialogs dialog').on("click", "button.readmore", function () { 2139 $(this).closest('dialog').find('.description').slideToggle(); 2140 $(this).text($(this).text() == 'Read More' ? 'Read Less' : 'Read More'); 2141 }); 2142 2143 }, 2144 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 2145 error: function (data) { 2146 console.log('error: ' + JSON.stringify(data)); 2147 } 2148 }); 2149} 2150 2151function initLocationMap() { 2152 let loc = ''; 2153 let mapid = ''; 2154 loc = document.querySelector('.mapcoords')?.innerHTML; 2155 if (!loc || loc.length == 0) { 2156 return; 2157 } 2158 loc = loc.replace(/\s/g, ''); // remove any spaces 2159 loc = loc.replace(/\n/g, ''); // remove any newlines 2160 loc = loc.replace(/\r/g, ''); // remove any carriage returns 2161 loc = loc.replace(/\t/g, ''); // remove any tabs 2162 loc = loc.replace(/[{()}]/g, ''); // remove any parentheses and curly braces 2163 mapid = document.querySelector('.mapid').innerHTML; 2164 2165 if (loc.length > 0 && mapid != '<!---->') { 2166 let c = loc.split(","); 2167 let myLatLng = { lat: parseFloat(c[0]), lng: parseFloat(c[1]) }; 2168 map = new google.maps.Map(document.getElementById(mapid), { 2169 center: myLatLng, 2170 zoom: 12, 2171 mapId: mapid 2172 }); 2173 var marker = new google.maps.marker.AdvancedMarkerElement({ 2174 position: myLatLng, 2175 map: map 2176 }); 2177 } 2178} 2179 2180function encodeForPath(str) { 2181 // Remove all characters except letters, numbers, and spaces 2182 str = str.replace(/[^a-zA-Z0-9\. ]/g, ''); 2183 2184 // Replace one or more spaces with underscores 2185 str = str.replace(/ +/g, '_'); 2186 2187 return str; 2188} 2189 2190/** 2191 * searchDM - Searches the Document Manager for documents matching the search string 2192 * This function is called on the searchResults.xsl page after the load 2193 * @param {any} str - the term to search for in the Document Manager 2194 */ 2195function searchDM(str) { 2196 $.ajax({ 2197 type: "GET", 2198 method: 'GET', 2199 url: "/admin/dm/Public/SearchAllFolders/?search=" + str, 2200 cache: false, 2201 async: true, 2202 contentType: "application/json; charset=utf-8", 2203 dataType: "json", 2204 data: '', 2205 processData: false, 2206 timeout: 300000, 2207 crossDomain: true, 2208 success: function (data) { 2209 document.getElementById('searchtabDMdocs').innerHTML = 'Document Manager (' + data.length + ')'; 2210 2211 if (data.length <= 0) { 2212 document.getElementById('dmSearchNote').innerHTML = 'No matching documents have been found.'; 2213 return; 2214 } 2215 2216 let html = ''; 2217 $.each(data, function (i, p) { 2218 let displayName = p["FileTitle"] ?? p["fileName"]; 2219 html += '<div class="dmsearchitem">'; 2220 html += '<a target="_blank" href="/uploads/dm/' + p["fileId"] + "/" + encodeForPath(displayName) + '"><i class="fa-solid fa-file"></i> ' + displayName + '</a><br/>'; 2221 html += '</div>'; 2222 }); 2223 document.getElementById('dmSearchNote').innerHTML = html; 2224 2225 }, 2226 failure: function (data) { console.log('failure: ' + JSON.stringify(data)); }, 2227 error: function (data) { 2228 console.log('error: ' + JSON.stringify(data)); 2229 } 2230 }); 2231} 2232 2233function grabCemeteries(sectionId) { 2234 2235 let params = new URLSearchParams(); 2236 if (sectionId) params.append('sectionID', sectionId); 2237 2238 $.ajax({ 2239 type: "GET", 2240 url: "/admin/dm/Public/GetCemeteriesBySection?" + params.toString(), 2241 cache: false, 2242 async: true, 2243 contentType: "application/json; charset=utf-8", 2244 dataType: "json", 2245 timeout: 0, 2246 success: function (data) { 2247 // populate cemetery dropdown 2248 const cemeterySelect = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' select[name="cemetery"]'); 2249 2250 if (cemeterySelect) { 2251 // Loop through options (skip index 0 which is "All Cemeteries") 2252 Array.from(cemeterySelect.options).forEach(function (option, index) { 2253 // Skip first option ("All Cemeteries") 2254 if (index === 0) return; 2255 2256 // Normalize both values for comparison (remove braces and convert to lowercase) 2257 const normalizedOptionValue = option.value.replace(/[{}]/g, '').toLowerCase(); 2258 const normalizedApiValues = data.map(id => id.toLowerCase()); 2259 2260 // Remove if not in the API response 2261 if (!normalizedApiValues.includes(normalizedOptionValue)) { 2262 option.remove(); 2263 } 2264 }); 2265 2266 if (Array.from(cemeterySelect.options).length <= 2) { 2267 // Only all cemeteries and one other option remains, disable the select 2268 const parentElement = cemeterySelect.parentElement; 2269 parentElement.remove(); 2270 } 2271 } 2272 } 2273 }); 2274} 2275 2276function searchCemetery(event) { 2277 event.preventDefault(); 2278 2279 // Get form values 2280 const form = event.target; 2281 const sectionId = form.sectionId.value; 2282 const cemetery = form.cemetery?.value || ''; 2283 const fname = form.fname.value.trim(); 2284 const lname = form.lname.value.trim(); 2285 const section = form.section?.value || ''; 2286 const block = form.block?.value || ''; 2287 const plot = form.plot?.value || ''; 2288 const birthDate = form.birthDate?.value || ''; 2289 const deathDate = form.deathDate?.value || ''; 2290 const buriedDate = form.buriedDate?.value || ''; 2291 2292 // Build query parameters matching your CemeteryEntry model 2293 let params = new URLSearchParams(); 2294 if (sectionId) params.append('sectionID', sectionId); 2295 if (cemetery) params.append('CemeteryID', cemetery); 2296 if (fname) params.append('FName', fname); 2297 if (lname) params.append('LName', lname); 2298 if (section) params.append('Section', section); 2299 if (block) params.append('Block', block); 2300 if (plot) params.append('Plot', plot); 2301 // Only add dates if they're valid 2302 if (birthDate && birthDate.length > 0) params.append('BirthDate', birthDate); 2303 if (deathDate && deathDate.length > 0) params.append('DeathDate', deathDate); 2304 if (buriedDate && buriedDate.length > 0) params.append('BuriedDate', buriedDate); 2305 2306 const pageSize = 50; 2307 params.append('pageSize', pageSize); 2308 let currentPage = 1; // start with first page 2309 params.append('pageNumber', currentPage); 2310 2311 getCemeteries(params, sectionId); 2312} 2313 2314function getCemeteries(params, sectionId, pagination=false) { 2315 // scroll up so its not too jarring 2316 const targetElement = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryFormButtons'); 2317 targetElement.scrollIntoView({ 2318 behavior: 'smooth', 2319 block: 'center',
2320 inline: 'nearest' 2321 }); 2322 2323 $.ajax({ 2324 type: "GET", 2325 url: "/admin/dm/Public/SearchCemeteryEntries/?" + params.toString(), 2326 cache: false, 2327 async: true, 2328 contentType: "application/json; charset=utf-8", 2329 dataType: "json", 2330 timeout: 0, 2331 beforeSend: function () { 2332 // Show loading indicator 2333 const resultsContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryResults'); 2334 const loadingDiv = document.createElement('div'); 2335 loadingDiv.className = 'loading-cemetery'; 2336 loadingDiv.innerHTML = '<div>Searching cemetery records...</div><div class="spinner" style="visibility: visible;"></div>'; 2337 resultsContainer.insertBefore(loadingDiv, resultsContainer.firstChild); 2338 2339 // if we are calling this from the pagination buttons, then leave them on screen 2340 if (!pagination) { 2341 const underCemteries = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #underCemteries'); 2342 underCemteries.style.visibility = 'hidden'; 2343 2344 const paginationContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryPaginatorButtons'); 2345 paginationContainer.style.visibility = 'hidden'; 2346 } 2347 }, 2348 success: function (data) { 2349 displayCemeteryResults(data, sectionId); 2350 dealWithPagination(data, params, sectionId) 2351 }, 2352 failure: function (data) { 2353 console.log('failure: ' + JSON.stringify(data)); 2354 }, 2355 error: function (data) { 2356 console.log('error: ' + JSON.stringify(data)); 2357 alert('Error searching cemetery records. Please try again.'); 2358 } 2359 }); 2360} 2361 2362function dealWithPagination(data, params, sectionId) { 2363 const underCemteries = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #underCemteries'); 2364 if (data.TotalCount === 0) { 2365 return; 2366 } 2367 2368 underCemteries.style.visibility = 'visible'; 2369 2370 const paginationContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryPaginatorButtons'); 2371 const infoContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryPaginationInfo'); 2372 const pageInfoContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryPageInfo'); 2373 2374 let first = ((data.PageNumber - 1) * data.PageSize) + 1; 2375 2376 infoContainer.innerHTML = '<span>Displaying ' + first + ' to ' + (first + data.Entries.length - 1) + ' of '+ data.TotalCount + ' total records.</span>'; 2377 pageInfoContainer.innerHTML = '<span>Page ' + data.PageNumber + ' of ' + data.TotalPages + '</span>'; 2378 2379 if(data.TotalCount > data.Entries.length) { 2380 // display pagination buttons 2381 paginationContainer.style.visibility = 'visible'; 2382 } 2383 2384 // add pagination params to original params 2385 const prevPageButton = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #prevPageButton'); 2386 const nextPageButton = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #nextPageButton'); 2387 const currentPageSelector = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #currentPageSelector'); 2388 2389 // Create page selector dropdown 2390 currentPageSelector.innerHTML = ''; 2391 for (let i = 1; i <= data.TotalPages; i++) { 2392 currentPageSelector.innerHTML += '<option value="' + i + '"' + (i === data.PageNumber ? ' selected' : '') + '>' + i + '</option>'; 2393 } 2394 2395 // on page selector change 2396 currentPageSelector.onchange = function() { 2397 let selectedPage = parseInt(this.value); 2398 params.set('pageNumber', selectedPage); 2399 getCemeteries(params, sectionId, true); 2400 } 2401 2402 // on prev page button click 2403 prevPageButton.onclick = function() { 2404 if (data.PageNumber > 1) { 2405 currentPageSelector.value = data.PageNumber - 1; 2406 currentPageSelector.dispatchEvent(new Event('change')); 2407 } 2408 } 2409 2410 // on next page button click 2411 nextPageButton.onclick = function() { 2412 if (data.PageNumber < data.TotalPages) { 2413 currentPageSelector.value = data.PageNumber + 1; 2414 currentPageSelector.dispatchEvent(new Event('change')); 2415 } 2416 } 2417} 2418 2419function getCemeteryName(cemeteryId) { 2420 const cemeteryElement = document.querySelector(`#cemeteryData .cemetery-item[data-id="${cemeteryId}"]`); 2421 return cemeteryElement ? cemeteryElement.getAttribute('data-name') : cemeteryId; 2422} 2423 2424function displayCemeteryResults(data, sectionId) { 2425 const resultsContainer = document.querySelector('#sec-' + sectionId.replace(/[{}]/g, '') + ' #cemeteryResults'); 2426 2427 if (!resultsContainer) { 2428 console.error('Results container not found'); 2429 return; 2430 } 2431 2432 if (data.Entries.length === 0) { 2433 resultsContainer.innerHTML = '<div class="no-results"><h2>No Results Found</h2><p>No records match your search criteria.</p></div>'; 2434 return; 2435 } 2436 2437 // Build results HTML matching XSL structure 2438 let html = '<div class="cemetery-results">'; 2439
2440 data.Entries.forEach(function(cemeteryEntry) { 2441 html += '<article class="summaryDisplay">'; 2442 html += '<hr /><br />'; 2443 2444 // Cemetery name 2445 html += '<div class="field cemeteryname">'; 2446 html += '<h3 class="value"><i class="fa-solid fa-tombstone-blank" aria-hidden="true"></i>'; 2447 html += getCemeteryName(cemeteryEntry.CemeteryID); 2448 html += '</h3></div>'; 2449 2450 // Person name 2451 html += '<div class="field inline position">'; 2452 html += '<h4 class="value">Name: ' + (cemeteryEntry.LName || '') + ', ' + (cemeteryEntry.FName || '') + '</h4>'; 2453 html += '</div>'; 2454 2455 // Details 2456 html += '<div class="cemetery-details">'; 2457 2458 // Left column 2459 html += '<div class="cemetery-column">'; 2460 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Section:</span> ' + (cemeteryEntry.Section || '') + '</div>'; 2461 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Block:</span> ' + (cemeteryEntry.Block || '') + '</div>'; 2462 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Plot:</span> ' + (cemeteryEntry.Plot || '') + '</div>'; 2463 html += '</div>'; 2464 2465 // Right column 2466 html += '<div class="cemetery-column">'; 2467 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Date of Birth:</span> ' + formatDate(cemeteryEntry.BirthDate) + '</div>'; 2468 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Date of Death:</span> ' + formatDate(cemeteryEntry.DeathDate) + '</div>'; 2469 html += '<div class="cemetery-detail-item"><span class="cemetery-detail-label">Date Buried:</span> ' + formatDate(cemeteryEntry.BuriedDate) + '</div>'; 2470 html += '</div>'; 2471 2472 html += '</div><br /></article>'; 2473 }); 2474 2475 html += '</div>'; 2476 2477 resultsContainer.innerHTML = html; 2478} 2479 2480var accessibilityDefaults = 2481 [ 2482 { "id": "acc_logs", "value": false }, 2483 { "id": "acc2020_01", "value": false }, 2484 { "id": "acc2020_02", "value": false }, 2485 { "id": "acc_pdf", "value": true }, 2486 { "id": "acc_2022_slider", "value": false }, 2487 { "id": "acc_2022_h1", "value": false }, 2488 { "id": "acc_2022_social", "value": true } 2489 ]; 2490 2491/** 2492 * loadAccessibilityOptions - Reads AccessibilityOptions stamped into the page 2493 * by the XSL from /PAGE/SiteInfo/AccessibilityOptions/AOption and merges any 2494 * present values over the accessibilityDefaults array. 2495 */ 2496function loadAccessibilityOptions() { 2497 console.log("loadAccessibilityOptions"); 2498 if (typeof accessibilityOptions === 'undefined') return; 2499 accessibilityDefaults.forEach(function (item) { 2500 if (accessibilityOptions.hasOwnProperty(item.id)) { 2501 item.value = accessibilityOptions[item.id] === '1'; 2502 } 2503 }); 2504} 2505 2506/** 2507 * getAccessibilityOption - Helper to look up an accessibility option value by id. 2508 * @param {string} id - the option id to look up 2509 * @returns {boolean} the value, or false if not found 2510 */ 2511function getAccessibilityOption(id) { 2512 var match = accessibilityDefaults.find(function (item) { return item.id === id; }); 2513 return match ? match.value : false; 2514} 2515 2516document.addEventListener('DOMContentLoaded', function () { 2517 loadAccessibilityOptions(); 2518 2519 var logs = getAccessibilityOption('acc_logs'); 2520 2521 //rule: acc2020_01 //default: off // case: moves slider and quicklink locations. 2522 if (getAccessibilityOption('acc2020_01')) { 2523 try { 2524 if (logs) { console.log("Applying accessibility rule: acc2020_01"); } 2525 var allContainer = document.querySelector('.allContainer'); 2526 var widthContainer = allContainer.querySelector(':scope > .widthContainer'); 2527 var mainEl = widthContainer.querySelector('main.container.content'); 2528 var slider = allContainer.querySelector(':scope > .slider_wrap1'); 2529 var filmstrip = allContainer.querySelector(':scope > .filmstrip_wrap1'); 2530 var contentBG = widthContainer.querySelector('.contentBG'); 2531 2532 widthContainer.setAttribute('role', 'main'); 2533 widthContainer.classList.add('acc2020_01'); 2534 widthContainer.parentElement.classList.add('acc2020_01'); 2535 mainEl.setAttribute('role', 'none'); 2536 2537 if (slider) widthContainer.insertBefore(slider, contentBG); 2538 if (filmstrip) widthContainer.insertBefore(filmstrip, contentBG); 2539 } catch (e) { if (logs) { console.warn("acc2020_01 skipped:", e.message); } } 2540 } 2541 2542 if (getAccessibilityOption('acc2020_02')) { 2543 try { 2544 if (logs) { console.log("Applying accessibility rule: acc2020_02"); } 2545 var main = document.querySelector('main'); 2546 var footer = document.querySelector('footer'); 2547 //var cardContainer = document.querySelector('.card-container'); 2548 var nogroup = document.querySelector('.nogroup.Below'); 2549 2550 //if (cardContainer) main.appendChild(cardContainer); 2551 if (nogroup) main.appendChild(nogroup); 2552 } catch (e) { if (logs) { console.warn("acc2020_02 skipped:", e.message); } } 2553 } 2554 2555 //rule: acc_pdf default: on. 2556 if (getAccessibilityOption('acc_pdf')) { 2557 try { 2558 if (logs) { console.log("Applying accessibility rule: acc_pdf"); } 2559 var pdfLinks = document.querySelectorAll('a[href$=".pdf"], a[href$=".PDF"]'); 2560 pdfLinks.forEach(function (link) { 2561 if (link.textContent.toLowerCase().includes('pdf') || 2562 link.querySelector('.sr-only')) return; 2563 2564 var srText = document.createElement('span'); 2565 srText.className = 'sr-only'; 2566 srText.textContent = ', opens PDF document'; 2567 link.appendChild(srText); 2568 }); 2569 } catch (e) { if (logs) { console.warn("acc_pdf skipped:", e.message); } } 2570 } 2571 2572 // For 2022 - Present designs 2573 try { 2574 var mainEl = document.getElementById('mainContent'); 2575 var container = mainEl.parentElement; 2576 var sliders = container.querySelectorAll(':scope > .nogroup.Top'); 2577 var firstChild = mainEl.firstChild; 2578 2579 //rule: acc_2022_slider default: off 2580 if (getAccessibilityOption('acc_2022_slider')) { 2581 try { 2582 if (logs) { console.log("Applying accessibility rule: acc_2022_slider"); }
2583 sliders.forEach(function (el) { 2584 mainEl.insertBefore(el, firstChild); 2585 }); 2586 } catch (e) { if (logs) { console.warn("acc_2022_slider skipped:", e.message); } } 2587 } 2588 2589 //rule: acc_2022_h1 default: off 2590 if (getAccessibilityOption('acc_2022_h1')) { 2591 try { 2592 if (logs) { console.log("Applying accessibility rule: acc_2022_h1"); } 2593 var main = document.querySelector('main#mainContent'); 2594 if (main) { 2595 main.removeAttribute('aria-label'); 2596 if (!main.querySelector('h1')) { 2597 var h1 = document.createElement('h1'); 2598 h1.className = 'sr-only'; 2599 h1.textContent = document.title || 'Main Content'; 2600 main.insertBefore(h1, main.firstChild); 2601 } 2602 } 2603 } catch (e) { if (logs) { console.warn("acc_2022_h1 skipped:", e.message); } } 2604 } 2605 } catch (e) { if (logs) { console.warn("2022 design block skipped:", e.message); } } 2606 2607 // Alert bar - global, ok. 2608 try { 2609 var alert = document.querySelector('.nogroup.Alert'); 2610 if (alert) { 2611 alert.setAttribute('role', 'region'); 2612 alert.setAttribute('aria-label', 'Alerts'); 2613 } 2614 } catch (e) { if (logs) { console.warn("Alert bar skipped:", e.message); } } 2615 2616 // Top navigation - global, ok. 2617 try { 2618 var topbar = document.querySelector('.topbar'); 2619 if (topbar) { 2620 topbar.setAttribute('role', 'navigation'); 2621 topbar.setAttribute('aria-label', 'Top navigation'); 2622 } 2623 } catch (e) { if (logs) { console.warn("Top navigation skipped:", e.message); } } 2624 2625 // Banner - global, ok. 2626 try { 2627 var topbar2 = document.querySelector('.topbar2'); 2628 if (topbar2) { 2629 topbar2.setAttribute('role', 'banner'); 2630 } 2631 } catch (e) { if (logs) { console.warn("Banner skipped:", e.message); } } 2632 2633 // acc_2022_social default: on 2634 if (getAccessibilityOption('acc_2022_social')) { 2635 try { 2636 if (logs) { console.log("Applying accessibility rule: acc_2022_social"); } 2637 var social = document.querySelector('.socialFixed'); 2638 if (social) social.setAttribute('aria-hidden', 'true'); 2639 } catch (e) { if (logs) { console.warn("acc_2022_social skipped:", e.message); } } 2640 } 2641 2642 // global, ok. 2643 try { 2644 var innerimage = document.querySelector('.innerimage'); 2645 if (innerimage) innerimage.setAttribute('aria-hidden', 'true'); 2646 } catch (e) { if (logs) { console.warn("innerimage skipped:", e.message); } } 2647 2648 // Quicklinks - global, ok. 2649 try { 2650 var nogroupTops = document.querySelectorAll('.nogroup.Top'); 2651 nogroupTops.forEach(function (el) { 2652 if (el.querySelector('.quicklinkscontainer')) { 2653 el.setAttribute('role', 'region'); 2654 el.setAttribute('aria-label', 'Quick links'); 2655 var linksOnly = el.querySelector('.owl-stage-outer'); 2656 if (linksOnly) { 2657 linksOnly.setAttribute('role', 'navigation'); 2658 linksOnly.setAttribute('aria-label', 'Quick links'); 2659 } 2660 } else if (el.querySelector('.slidercontainer')) { 2661 el.setAttribute('role', 'region'); 2662 el.setAttribute('aria-label', 'Image slidewhow'); 2663 } 2664 }); 2665 } catch (e) { if (logs) { console.warn("Quicklinks skipped:", e.message); } } 2666 2667 // Modern calendars - global, ok. 2668 try { 2669 var calTables = document.querySelectorAll('.calendarTable'); 2670 calTables.forEach(function (table) { 2671 try { 2672 var monthName = table.closest('.calMonth')?.querySelector('.calMonthName')?.textContent || ''; 2673 var year = table.closest('.calMonth')?.querySelector('.calYear')?.textContent || ''; 2674 2675 var caption = document.createElement('caption'); 2676 caption.className = 'sr-only'; 2677 caption.textContent = 'Calendar for ' + monthName + ' ' + year; 2678 table.insertBefore(caption, table.firstChild); 2679 2680 table.setAttribute('role', 'grid'); 2681 table.setAttribute('aria-label', 'Calendar for ' + monthName + ' ' + year); 2682 2683 var headerRow = table.querySelector('tr.calDayHeading'); 2684 if (headerRow) { 2685 headerRow.setAttribute('role', 'row'); 2686 headerRow.querySelectorAll('th').forEach(function (th) { 2687 th.setAttribute('role', 'columnheader'); 2688 }); 2689 } 2690 2691 table.querySelectorAll('tr:not(.calDayHeading)').forEach(function (row) { 2692 row.setAttribute('role', 'row'); 2693 row.querySelectorAll('td').forEach(function (td) { 2694 td.setAttribute('role', 'gridcell'); 2695 });
2696 }); 2697 } catch (e) { if (logs) { console.warn("calendarTable row skipped:", e.message); } } 2698 }); 2699 } catch (e) { if (logs) { console.warn("Modern calendars skipped:", e.message); } } 2700}); 2701 2702 2703function formatDate(dateStr) { 2704 if (!dateStr) return ''; 2705 2706 const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 2707 const date = new Date(dateStr); 2708 2709 return months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear(); 2710} 2711 2712 2713 2714 2715// end accessibility 2716 2717 2718// CMS suggestion button: called from news_resp.xsl / event_calendar_resp.xsl 2719// with the page id and resolved API/app hosts. On click, POSTs to token-init, 2720// sets the iframe src, opens the modal once the iframe finishes loading. 2721function initSuggestionButton(pageId, apiHost, appHost) { 2722 var btn = document.querySelector('.suggest-btn[data-page-id="' + pageId + '"]'); 2723 if (!btn || btn.getAttribute('data-suggest-bound') === '1') return; 2724 btn.setAttribute('data-suggest-bound', '1'); 2725 2726 var container = btn.closest('.submitContent'); 2727 if (!container) return; 2728 var modal = container.querySelector('.suggest-modal'); 2729 var iframe = container.querySelector('.suggest-iframe'); 2730 var cancelBtn = container.querySelector('.suggest-close-x'); 2731 if (!modal || !iframe || !cancelBtn) return; 2732 2733 cancelBtn.addEventListener('click', function () { modal.close(); }); 2734 2735 btn.addEventListener('click', function () { 2736 if (btn.classList.contains('is-loading')) return; 2737 btn.classList.add('is-loading'); 2738 btn.disabled = true; 2739 2740 fetch(apiHost + '/v2/workflow/cms/embed/token-init', { 2741 method: 'POST', 2742 headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, 2743 body: JSON.stringify({ pageId: pageId }) 2744 }) 2745 .then(function (res) { 2746 if (!res.ok) throw new Error('token-init ' + res.status); 2747 return res.json(); 2748 }) 2749 .then(function (payload) { 2750 var data = (payload && payload.data) ? payload.data : payload; 2751 if (!data || !data.embedToken) throw new Error('no embed token in response'); 2752 2753 function onIframeLoad() { 2754 iframe.removeEventListener('load', onIframeLoad); 2755 btn.classList.remove('is-loading'); 2756 btn.disabled = false; 2757 modal.showModal(); 2758 } 2759 iframe.addEventListener('load', onIframeLoad); 2760 console.log("token-init data: ", data); 2761 iframe.src = appHost + '/app/cms/suggest?t=' + encodeURIComponent(data.embedToken); 2762 }) 2763 .catch(function (err) { 2764 if (window.console) console.warn('[suggest] ' + err.message); 2765 btn.classList.remove('is-loading'); 2766 btn.disabled = false; 2767 }); 2768 }); 2769}
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.