1/* Accessibility Fixes Start */ 2 3 4/* If latest fix doesnt work, add this back */ 5/*document.addEventListener("click", (e) => { 6 const faqAccordion = e.target.closest(".faq-feed-accordion"); 7 if (!faqAccordion) return; 8 9 const trigger = e.target.closest(".accordion__nav"); 10 if (!trigger) return; 11 12 const panelId = trigger.getAttribute("aria-controls"); 13 const panel = panelId ? document.getElementById(panelId) : null; 14 if (!panel) return; 15 16 const isExpanded = trigger.getAttribute("aria-expanded") === "true"; 17 18 faqAccordion.querySelectorAll(".accordion__nav[aria-expanded='true']").forEach((btn) => { 19 if (btn === trigger) return; 20 btn.setAttribute("aria-expanded", "false"); 21 const otherPanel = document.getElementById(btn.getAttribute("aria-controls")); 22 if (otherPanel) otherPanel.hidden = true; 23 }); 24 25 trigger.setAttribute("aria-expanded", String(!isExpanded)); 26 panel.hidden = isExpanded; // if expanded -> hide; if collapsed -> show 27});*/ 28 29 30 31/* from accessibility page layout 32const megaMenuLinks = document.querySelectorAll('.nav-link.nav-main-link'); 33 34const removeClasse = (element, classAttr) => { 35 element.classList.remove(classAttr); 36} 37 38const toggleMegaMenu = e => { 39 const link = e.currentTarget; 40 if (link.classList.contains('active')) { 41 megaMenuLinks.forEach(link => removeClasse(link, 'active')); 42 megaMenuLinks.forEach(link => removeClasse(link.parentNode.lastElementChild, 'show')); 43 link.classList.add('active'); 44 link.parentNode.lastElementChild.classList.add('show'); 45 } else { 46 megaMenuLinks.forEach(link => removeClasse(link, 'active')); 47 megaMenuLinks.forEach(link => removeClasse(link.parentNode.lastElementChild, 'show')); 48 } 49} 50 51megaMenuLinks.forEach(link => { 52 link.addEventListener('click', e => toggleMegaMenu(e)) 53}) 54 55 56const closeMegaMenu = () => { 57 megaMenuLinks.forEach(link => removeClasse(link, 'active')); 58 megaMenuLinks.forEach(link => removeClasse(link.parentNode.lastElementChild, 'show')); 59 document.querySelector('body.menu-open').classList.remove('menu-open'); 60} 61 62const closeMegaMenuOnEsc = e => { 63 e.keyCode === 27 ? closeMegaMenu() : null 64} 65 66const closeMegaMenuOnOutsideClick = e => { 67 if (document.querySelector('.nav-link.nav-main-link.active')) { 68 !document.querySelector('.nav-link.nav-main-link.active').parentElement.contains(e.target) ? closeMegaMenu() : null 69 } 70} 71 72 73document.addEventListener('keydown', closeMegaMenuOnEsc); 74document.addEventListener('click', e => closeMegaMenuOnOutsideClick(e));*/ 75 76 77 78(function () { 79 function getFaqParts(trigger) { 80 var li = trigger.closest('li[role="listitem"]'); 81 if (!li) return null; 82 83 var panel = li.querySelector('.accordion__content'); 84 if (!panel) return null; 85 86 var accordion = trigger.closest(".faq-feed-accordion, .pre-footer-accordion"); 87 if (!accordion) return null; 88 89 return { li: li, panel: panel, accordion: accordion }; 90 } 91 92 function setItemState(trigger, open) { 93 var parts = getFaqParts(trigger); 94 if (!parts) return; 95 96 var li = parts.li; 97 var panel = parts.panel; 98 99 trigger.setAttribute('role', 'button'); 100 trigger.setAttribute('tabindex', '0'); 101 trigger.setAttribute('aria-expanded', open ? 'true' : 'false'); 102 103 if (!trigger.id) { 104 trigger.id = 'acc-btn-' + Math.random().toString(36).slice(2, 9); 105 } 106 if (!panel.id) { 107 panel.id = 'acc-panel-' + Math.random().toString(36).slice(2, 9); 108 } 109 110 trigger.setAttribute('aria-controls', panel.id); 111 panel.setAttribute('role', 'region'); 112 panel.setAttribute('aria-labelledby', trigger.id); 113 114 li.classList.toggle('expand', open); 115 116 if (open) { 117 panel.hidden = false; 118 panel.removeAttribute('hidden'); 119 panel.style.display = 'block'; 120 } else { 121 panel.hidden = true; 122 panel.setAttribute('hidden', ''); 123 panel.style.display = 'none'; 124 } 125 } 126 127 function closeSiblings(trigger) { 128 var parts = getFaqParts(trigger); 129 if (!parts) return; 130 131 parts.accordion.querySelectorAll('.accordion__nav').forEach(function (otherTrigger) { 132 if (otherTrigger !== trigger) { 133 setItemState(otherTrigger, false); 134 } 135 });
136 } 137 138 function toggleItem(trigger) { 139 var isOpen = trigger.getAttribute('aria-expanded') === 'true'; 140 closeSiblings(trigger); 141 setItemState(trigger, !isOpen); 142 } 143 144 function initFaqFeedA11y() { 145 document.querySelectorAll('.faq-feed-accordion .accordion__nav, .pre-footer-accordion .accordion__nav').forEach(function (trigger) { 146 var parts = getFaqParts(trigger); 147 if (!parts) return; 148 149 var startsOpen = parts.li.classList.contains('expand'); 150 setItemState(trigger, startsOpen); 151 152 trigger.addEventListener('click', function (e) { 153 e.preventDefault(); 154 e.stopPropagation(); 155 toggleItem(trigger); 156 }); 157 158 trigger.addEventListener('keydown', function (e) { 159 if (e.key === 'Enter' || e.key === ' ') { 160 e.preventDefault(); 161 e.stopPropagation(); 162 toggleItem(trigger); 163 } 164 }); 165 }); 166 } 167 168 if (document.readyState === 'loading') { 169 document.addEventListener('DOMContentLoaded', initFaqFeedA11y); 170 } else { 171 initFaqFeedA11y(); 172 } 173})(); 174 175 176 177 178 179(function () { 180 const search = document.querySelector('.search-bar'); 181 if (!search) return; 182 183 const enable = () => { 184 search.removeAttribute('inert'); 185 if (search.getAttribute('aria-hidden') === 'true') { 186 search.removeAttribute('aria-hidden'); 187 } 188 }; 189 190 enable(); 191 192 const mo = new MutationObserver(enable); 193 mo.observe(search, { attributes: true, attributeFilter: ['inert', 'aria-hidden'] }); 194})(); 195 196(function () { 197 const toggles = document.querySelectorAll('a.dropdown-link, .nav-menu-close > a[role="button"]'); 198 199 toggles.forEach((a, i) => { 200 a.setAttribute('href', a.getAttribute('href') || '#'); 201 a.setAttribute('role', 'button'); 202 a.setAttribute('tabindex', '0'); 203 const parentLi = a.closest('li'); 204 let submenu = null; 205 if (parentLi) { 206 submenu = parentLi.querySelector(':scope > ul.dropdown-menu'); 207 } 208 209 if (submenu) { 210 if (!submenu.id) submenu.id = `submenu-${i}`; 211 a.setAttribute('aria-controls', submenu.id); 212 213 /*const isOpen = 214 submenu.classList.contains('show') || 215 submenu.getAttribute('aria-hidden') === 'false' || 216 submenu.style.display === 'block';*/ 217 218 /* new accessibility additon v2 */ 219 const isOpen = submenu.classList.contains('show'); 220 221 222 a.setAttribute('aria-expanded', String(isOpen)); 223 submenu.setAttribute('aria-hidden', String(!isOpen)); 224 225 /* new accessibility additon v2 */ 226 const observer = new MutationObserver(() => syncAria(a)); 227observer.observe(submenu, { 228 attributes: true, 229 attributeFilter: ['class'] 230}); 231 232 /*} else { 233 if (!a.hasAttribute('aria-expanded')) a.setAttribute('aria-expanded', 'false'); 234 }*/ 235 236 /* new accessibility additon v2 */ 237 } else { 238 a.removeAttribute('aria-expanded'); 239} 240 241 a.addEventListener('click', (e) => { 242 e.preventDefault(); 243 e.stopPropagation(); 244 245 requestAnimationFrame(() => syncAria(a)); 246 }); 247 248 a.addEventListener('keydown', (e) => { 249 if (e.key === 'Enter' || e.key === ' ') { 250 e.preventDefault(); 251 e.stopPropagation(); 252 a.click(); 253 } 254 }); 255 }); 256 257 function syncAria(a) { 258 const parentLi = a.closest('li'); 259 const submenu = parentLi ? parentLi.querySelector(':scope > ul.dropdown-menu') : null; 260 if (!submenu) return; 261 262 /*const isOpen = 263 submenu.classList.contains('show') || 264 submenu.getAttribute('aria-hidden') === 'false' || 265 submenu.style.display === 'block';*/ 266 267 /* new accessibility additon v2 */ 268 const isOpen = submenu.classList.contains('show'); 269 270 a.setAttribute('aria-expanded', String(isOpen)); 271 submenu.setAttribute('aria-hidden', String(!isOpen)); 272 } 273})(); 274 275 276(function () { 277 const carousel = document.querySelector(".img-carousel__swiper-container"); 278 if (!carousel) return; 279 280 function setTabbable(root, enabled) { 281 const focusables = root.querySelectorAll(
282 'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])' 283 ); 284 focusables.forEach((el) => { 285 if (enabled) { 286 // restore previous tabindex if we stored it 287 if (el.hasAttribute("data-prev-tabindex")) { 288 el.setAttribute("tabindex", el.getAttribute("data-prev-tabindex")); 289 el.removeAttribute("data-prev-tabindex"); 290 } else { 291 el.removeAttribute("tabindex"); 292 } 293 } else { 294 if (el.hasAttribute("tabindex")) { 295 el.setAttribute("data-prev-tabindex", el.getAttribute("tabindex")); 296 } 297 el.setAttribute("tabindex", "-1"); 298 } 299 }); 300 } 301 302 function updateA11y() { 303 const slides = carousel.querySelectorAll(".swiper-slide"); 304 305 slides.forEach((slide) => { 306 const isDuplicate = 307 slide.classList.contains("swiper-slide-duplicate") || 308 slide.getAttribute("data-swiper-slide-index") === null; // safety 309 const isActive = slide.classList.contains("swiper-slide-active"); 310 311 // Rule 1: duplicates are always hidden 312 if (isDuplicate) { 313 slide.setAttribute("aria-hidden", "true"); 314 setTabbable(slide, false); 315 return; 316 } 317 318 // Rule 2: only active "real" slide is exposed 319 slide.setAttribute("aria-hidden", isActive ? "false" : "true"); 320 setTabbable(slide, isActive); 321 }); 322 } 323 324 updateA11y(); 325 326 if (carousel.swiper && carousel.swiper.on) { 327 carousel.swiper.on("init", updateA11y); 328 carousel.swiper.on("slideChange", updateA11y); 329 carousel.swiper.on("transitionEnd", updateA11y); 330 } else { 331 // fallback 332 const mo = new MutationObserver(updateA11y); 333 mo.observe(carousel, { subtree: true, attributes: true, attributeFilter: ["class"] }); 334 } 335})(); 336 337 338 339 340document.addEventListener("click", function (e) { 341 342 const navContainer = e.target.closest(".fact-sheet--middle"); 343 344 if (!navContainer) return; 345 346 const link = e.target.closest('.fact-sheet--middle a[href^="#contentId-"]'); 347 if (!link) return; 348 349 const id = link.getAttribute("href").slice(1); 350 const target = document.getElementById(id); 351 if (!target) return; 352 353 setTimeout(function () { 354 target.focus({ preventScroll: true }); 355 }, 0); 356 357}); 358 359 360 361(() => { 362 const openBtn = document.querySelector('.navbar-toggler'); 363 const closeBtn = document.querySelector('.btn-close-nav'); 364 const menu = document.querySelector('.navbar-collapse'); 365 const overlay = document.querySelector('#modal'); 366 367 if (!openBtn || !closeBtn || !menu) return; 368 369 const pageSiblings = [ 370 document.querySelector('main'), 371 document.querySelector('footer'), 372 document.querySelector('.breadcrumb'), 373 document.querySelector('.search-bar'), 374 document.querySelector('.header-placeholder') 375 ].filter(Boolean); 376 377 let lastFocusedEl = null; 378 379 const focusableSelector = [ 380 'a[href]', 381 'button:not([disabled])', 382 'input:not([disabled])', 383 'select:not([disabled])', 384 'textarea:not([disabled])', 385 '[tabindex]:not([tabindex="-1"])' 386 ].join(','); 387 388 function getFocusable(container) { 389 return Array.from(container.querySelectorAll(focusableSelector)) 390 /*.filter(el => !el.hasAttribute('disabled') && !el.getAttribute('aria-hidden'));*/ /* If latest fix doesnt work, add this back and remove below line */ 391 .filter(el => !el.hasAttribute('disabled') && el.getAttribute('aria-hidden') !== 'true'); 392 } 393 394 function setBackgroundDisabled(disabled) { 395 pageSiblings.forEach(el => { 396 if (disabled) { 397 el.setAttribute('inert', ''); 398 el.setAttribute('aria-hidden', 'true'); 399 } else { 400 el.removeAttribute('inert'); 401 el.removeAttribute('aria-hidden'); 402 } 403 }); 404 405 document.body.classList.toggle('menu-open', disabled); 406 407 if (overlay) overlay.classList.toggle('active', disabled); 408 } 409 410 function trapTabKey(e) { 411 if (e.key !== 'Tab') return; 412 413 const focusables = getFocusable(menu); 414 if (!focusables.length) return; 415 416 const first = focusables[0]; 417 const last = focusables[focusables.length - 1]; 418 419 if (e.shiftKey && document.activeElement === first) { 420 e.preventDefault(); 421 last.focus(); 422 } 423 else if (!e.shiftKey && document.activeElement === last) { 424 e.preventDefault(); 425 first.focus(); 426 } 427 } 428 429 function onEsc(e) { 430 if (e.key === 'Escape') closeMenu(); 431 } 432 433 function openMenu() { 434 lastFocusedEl = document.activeElement; 435 436 menu.classList.add('show'); 437 openBtn.setAttribute('aria-expanded', 'true'); 438
439 setBackgroundDisabled(true); 440 441 closeBtn.focus(); 442 443 document.addEventListener('keydown', trapTabKey); 444 document.addEventListener('keydown', onEsc); 445 } 446 447 function closeMenu() { 448 menu.classList.remove('show'); 449 openBtn.setAttribute('aria-expanded', 'false'); 450 451 setBackgroundDisabled(false); 452 453 document.removeEventListener('keydown', trapTabKey); 454 document.removeEventListener('keydown', onEsc); 455 456 (lastFocusedEl || openBtn).focus(); 457 } 458 459 openBtn.addEventListener('click', openMenu); 460 closeBtn.addEventListener('click', closeMenu); 461 462 if (overlay) overlay.addEventListener('click', closeMenu); 463})(); 464 465 466 467 468 469/* If latest fix doesnt work, add this back */ 470/*(function () { 471 function syncAccordionState(root) { 472 var items = root.querySelectorAll('.faq-feed-accordion li[role="listitem"]'); 473 items.forEach(function (li) { 474 var btn = li.querySelector('.accordion__nav[role="button"]'); 475 var panel = li.querySelector('.accordion__content'); 476 if (!btn || !panel) return; 477 478 var isOpen = li.classList.contains('expand'); 479 480 // Sync ARIA 481 btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false'); 482 483 panel.hidden = !isOpen; 484 }); 485 } 486 487 function initAccordionA11y() { 488 document.querySelectorAll('.faq-feed-accordion').forEach(function (accordion) { 489 490 syncAccordionState(accordion); 491 492 var mo = new MutationObserver(function (mutations) { 493 494 var needsSync = mutations.some(function (m) { 495 return m.type === 'attributes' && m.attributeName === 'class'; 496 }); 497 if (needsSync) syncAccordionState(accordion); 498 }); 499 500 accordion.querySelectorAll('li[role="listitem"]').forEach(function (li) { 501 mo.observe(li, { attributes: true, attributeFilter: ['class'] }); 502 }); 503 504 accordion.addEventListener('keydown', function (e) { 505 var target = e.target; 506 if (!target || !target.classList || !target.classList.contains('accordion__nav')) return; 507 508 509 if (e.key === ' ' || e.key === 'Enter') { 510 e.preventDefault(); 511 512 target.click(); 513 } 514 }, true); 515 516 accordion.addEventListener('click', function (e) { 517 var nav = e.target.closest && e.target.closest('.accordion__nav'); 518 if (!nav) return; 519 requestAnimationFrame(function () { syncAccordionState(accordion); }); 520 }); 521 }); 522 } 523 524 if (document.readyState === 'loading') { 525 document.addEventListener('DOMContentLoaded', initAccordionA11y); 526 } else { 527 initAccordionA11y(); 528 } 529})();*/ 530 531 532 533(function () { 534 let scheduled = false; 535 536 function updateContainer(container) { 537 const slides = container.querySelectorAll('.swiper-slide'); 538 slides.forEach((slide) => { 539 /*const isVisible = 540 slide.classList.contains('swiper-slide-active') || 541 slide.classList.contains('swiper-slide-visible');*/ 542 543 const isExpandedFeed = 544 container.classList.contains('slider-feed__swiper-container') && 545 container.classList.contains('swiper-container-multirow'); 546 547const isVisible = 548 isExpandedFeed || 549 slide.classList.contains('swiper-slide-active') || 550 slide.classList.contains('swiper-slide-visible'); 551 552 slide.setAttribute('aria-hidden', String(!isVisible)); 553 554 slide.querySelectorAll( 555 'a, button, input, select, textarea, [tabindex]' 556 ).forEach((el) => { 557 // Keep elements intentionally removed from tab order removed 558 const existing = el.getAttribute('tabindex'); 559 const hasExplicitTabindex = existing !== null; 560 561 if (!isVisible) { 562 // Store original tabindex once so we can restore it accurately 563 if (el.dataset.origTabindex === undefined) { 564 el.dataset.origTabindex = hasExplicitTabindex ? existing : ''; 565 } 566 el.setAttribute('tabindex', '-1'); 567 } else { 568 // Restore original tabindex 569 if (el.dataset.origTabindex !== undefined) { 570 if (el.dataset.origTabindex === '') el.removeAttribute('tabindex'); 571 else el.setAttribute('tabindex', el.dataset.origTabindex); 572 delete el.dataset.origTabindex; 573 } else { 574 // If we never touched it, leave it alone 575 } 576 } 577 }); 578 });
579 } 580 581 function scheduleUpdate() { 582 if (scheduled) return; 583 scheduled = true; 584 requestAnimationFrame(() => { 585 scheduled = false; 586 document.querySelectorAll('.swiper-container').forEach(updateContainer); 587 }); 588 } 589 590 window.addEventListener('load', () => { 591 // Initial pass 592 scheduleUpdate(); 593 594 // Observe only swipers, only class/style changes (Swiper toggles these) 595 document.querySelectorAll('.swiper-container').forEach((container) => { 596 const obs = new MutationObserver(() => scheduleUpdate()); 597 obs.observe(container, { 598 subtree: true, 599 attributes: true, 600 attributeFilter: ['class', 'style'] 601 }); 602 }); 603 604 // Also update on keyboard navigation as a fallback 605 document.addEventListener('focusin', (e) => { 606 if (e.target.closest && e.target.closest('.swiper-container')) { 607 scheduleUpdate(); 608 } 609 }); 610 }); 611})(); 612 613 614 615(function () { 616 function addSpectrumTextAlternative() { 617 const container = document.querySelector( 618 '.fact-sheet__bottom__article__img img[alt*="Electromagnetic spectrum"]' 619 )?.closest('.fact-sheet__bottom__article__img'); 620 621 if (!container) return; 622 if (container.querySelector('#em-spectrum-text')) return; 623 624 const img = container.querySelector('img'); 625 img.setAttribute('aria-describedby', 'em-spectrum-text'); 626 627 const details = document.createElement('details'); 628 details.id = 'em-spectrum-text'; 629 details.className = 'a11y-text-version'; 630 details.style.paddingLeft = '2rem'; 631 632 details.innerHTML = ` 633 <summary>Text version of the electromagnetic spectrum diagram</summary> 634 <div> 635 <p><strong>Title:</strong> The Electromagnetic Spectrum.</p> 636 637 <p><strong>Non-ionising section (left):</strong> examples shown include:</p> 638 <ul> 639 <li>Static electric and magnetic fields</li> 640 <li>Alternating electric and magnetic fields</li> 641 <li>Household electrical device example (hair dryer)</li> 642 <li>TV and radio broadcast</li> 643 <li>Mobile phones</li> 644 <li>Microwave links and radars</li> 645 <li>Visible sunlight</li> 646 <li>Ultraviolet</li> 647 </ul> 648 649 <p><strong>Ionising section (right):</strong> examples shown include:</p> 650 <ul> 651 <li>X-rays</li> 652 <li>Radioactive sources</li> 653 </ul> 654 655 <p><strong>Frequency markers shown on the diagram (left to right):</strong></p> 656 <ul> 657 <li>0 Hz</li> 658 <li>50 Hz</li> 659 <li>3 kHz</li> 660 <li>300 GHz</li> 661 <li>3000 THz</li> 662 <li>30 EHz</li> 663 </ul> 664 665 <p>The diagram also labels the left-hand portion as <strong>Electromagnetic Fields</strong>, with a wave illustration increasing in frequency across the spectrum.</p> 666 </div> 667 `; 668 669 container.appendChild(details); 670 671 if (!img.getAttribute('alt')) { 672 img.setAttribute('alt', 'Electromagnetic spectrum'); 673 } 674 } 675 676 if (document.readyState === 'loading') { 677 document.addEventListener('DOMContentLoaded', addSpectrumTextAlternative); 678 } else { 679 addSpectrumTextAlternative(); 680 } 681})(); 682 683 684 685 686 687 688 689(function () { 690 function fixFlourishTabbing() { 691 document 692 .querySelectorAll('.flourish-embed iframe[src*="flo.uri.sh"]') 693 .forEach(function (iframe) { 694 iframe.setAttribute('tabindex', '-1'); 695 }); 696 } 697 698 if (document.readyState === 'loading') { 699 document.addEventListener('DOMContentLoaded', fixFlourishTabbing); 700 } else { 701 fixFlourishTabbing(); 702 } 703})(); 704 705/* Accessibility Fixes End */ 706 707 708 709 710 711 712 713var href = window.location.href; 714$('.inner__sidebar__menu li a').each(function(){ 715 var currentHref = $(this).attr('href'); 716 if (currentHref == href){ 717 $(this).addClass('current-page'); 718 } 719}); 720 721var publications_cover_imgs = document.querySelectorAll('.publications__panel__img'); 722 723if (publications_cover_imgs) {
724 publications_cover_imgs.forEach(function (el) { 725 console.log(el) 726 727 if (!el.firstElementChild) { 728 el.insertAdjacentHTML( 729 'afterbegin', 730 '<img src="https://www.epa.ie/media/epa-2020/publications/EPA_blank_Publication.png" alt="EPA Publication Cover">' 731 ); 732 } 733 }); 734} 735 736/* PuBLICATION EXTENSION ICON JS */ 737 738function getExtension(url) { 739 var str = url; 740 var index = str.lastIndexOf('.'); 741 var extString = []; 742 if (index !== -1) { 743 extString = [str.slice(0, index), str.slice(index+1)] 744 } 745 746 return extString[1]; 747} 748 749function CT_publications() { 750 var publications = document.querySelector('.publications'); 751 752 if (publications) { 753 var links = document.querySelectorAll('.publications__download__link'); 754 var filesizes = document.querySelectorAll('.publications__card__filesize'); 755 links.forEach(function (el) { 756 var url_icon = el.querySelector('.publications__card__img'); 757 var url = el.getAttribute('href'); 758 759 switch (getExtension(url)) { 760 case 'pdf': 761 url_icon.classList.add('pdf-file'); 762 break; 763 764 case 'xlsx': 765 url_icon.classList.add('excel-file'); 766 break; 767 768 case 'xlt': 769 url_icon.classList.add('excel-file'); 770 break; 771 772 case 'pptx': 773 url_icon.classList.add('ppt-file'); 774 break; 775 776 case 'ppt': 777 url_icon.classList.add('ppt-file'); 778 break; 779 780 case 'docx': 781 url_icon.classList.add('word-file'); 782 break; 783 784 case 'doc': 785 url_icon.classList.add('word-file'); 786 break; 787 788 case 'accdb': 789 url_icon.classList.add('access-file'); 790 break; 791 792 case 'bmp': 793 url_icon.classList.add('bmp-file'); 794 break; 795 796 case 'csv': 797 url_icon.classList.add('csv-file'); 798 break; 799 800 case 'gif': 801 url_icon.classList.add('gif-file'); 802 break; 803 804 case 'jpg': 805 url_icon.classList.add('jpeg-file'); 806 break; 807 808 case 'jpeg': 809 url_icon.classList.add('jpeg-file'); 810 break; 811 812 case 'JPG': 813 url_icon.classList.add('jpeg-file'); 814 break; 815 816 case 'mpp': 817 url_icon.classList.add('mpp-file'); 818 break; 819 820 case 'tiff': 821 url_icon.classList.add('tiff-file'); 822 break; 823 824 case 'TIF': 825 url_icon.classList.add('tiff-file'); 826 break; 827 828 case 'visio': 829 url_icon.classList.add('visio-file'); 830 break; 831 832 case 'xls': 833 url_icon.classList.add('xls-file'); 834 break; 835 836 case 'zip': 837 url_icon.classList.add('zip-file'); 838 break; 839 840 case 'png': 841 url_icon.classList.add('png-file'); 842 break; 843 844 case 'PNG': 845 url_icon.classList.add('png-file'); 846 break; 847 848 default: 849 return false; 850 } 851 });
852 filesizes.forEach(function (el) { 853 var kiloBytesToMegaBytes = function kiloBytesToMegaBytes(kilobytes) { 854 // Convert value to integer and remove potential comma 855 var intConvertedVal = parseFloat(kilobytes.replace(/,/g, '')); // Convert kb to bytes 856 857 var bytes = intConvertedVal * 1000; // Return values to megabytes 858 859 return (bytes / (1024 * 1024)).toFixed(3); 860 }; 861 862 el.innerHTML = kiloBytesToMegaBytes(el.innerHTML) + ' Mb'; 863 }); 864 } 865}; 866 867CT_publications(); 868 869const fadeIn = (element, display)=> { 870 element.style.opacity = 0; 871 element.style.display = display; 872 873 (function fade() { 874 let val = parseFloat(element.style.opacity); 875 if (!((val += .1) > 1)) { 876 element.style.opacity = val; 877 requestAnimationFrame(fade); 878 } 879 })(); 880} 881const fadeOut = (element)=> { 882 element.style.opacity = 1; 883 884 (function fade() { 885 if ((element.style.opacity -= .1) < 0) { 886 element.style.display = "none"; 887 } else { 888 requestAnimationFrame(fade); 889 } 890 })(); 891} 892const modalPopUp = ()=> { 893 const modalTriggers = document.querySelectorAll('.popup-trigger'); 894 const bodyBlackout = document.querySelector('.body-blackout'); 895 const modalPopup = document.getElementsByClassName('popup-modal'); 896 897 modalTriggers.forEach(trigger => { 898 trigger.addEventListener('click', (e) => { 899 const {popupTrigger} = trigger.dataset;
900 const popupModal = document.querySelector(`[data-popup-modal="${popupTrigger}"]`); 901 902 e.preventDefault(); 903 904 fadeIn(popupModal, 'block'); 905 bodyBlackout.classList.add('is-blacked-out'); 906 907 popupModal.querySelector('.popup-modal__close').addEventListener('click', () => { 908 fadeOut(popupModal); 909 bodyBlackout.classList.remove('is-blacked-out'); 910 }); 911 912 bodyBlackout.addEventListener('click', () => { 913 fadeOut(popupModal); 914 bodyBlackout.classList.remove('is-blacked-out'); 915 }); 916 }); 917 }); 918 919 const modalOpen = document.getElementById('modal'); 920 921 document.addEventListener('keydown', (e)=> { 922 let keyCode = e.keyCode; 923 if (keyCode === 27) { 924 if (modalOpen.classList.contains('is-blacked-out')){ 925 modalOpen.classList.remove('is-blacked-out'); 926 modalPopup.forEach(modalClose => { 927 fadeOut(modalClose); 928 }); 929 } 930 } 931 }); 932} 933modalPopUp(); 934 935if($('.banner-search-bar-with-filter.purple-bg').length) { 936 $('.banner-search-bar-with-filter--heading').addClass('purple-bg'); 937} 938 939/* toggle search modal */ 940 941updateModal(); 942$(window).on('resize', function(){ 943 updateModal(); 944}); 945 946function updateModal() { 947 var win = $(this); 948 if (win.width() < 1200) { 949 if (!$(".search-bar-modal").prev().is(".navbar-nav")) { 950 $(".search-bar-modal").detach().insertAfter(".navbar-nav"); 951 } 952 } else { 953 if (!$(".search-bar-modal").prev().is("header nav")) { 954 $(".search-bar-modal").detach().insertAfter("header nav"); 955 } 956 957 $(".btn-open-modal").off("click").on("click", function () { 958 $(this).toggleClass("opened"); 959 if ($(this).hasClass("opened")) { 960 $("body").addClass("menu-open"); 961 } else { 962 $("body").removeClass("menu-open"); 963 } 964 $(".search-bar-modal").toggleClass("show"); 965 }); 966 967 $(".nav-main-link").off("click").on("click", function () { 968 $(".search-bar-modal").removeClass("show"); 969 $(".btn-open-modal").removeClass("opened"); 970 }); 971 972 // Close modal when clicking outside of it 973 $(document).off("click.searchModal").on("click.searchModal", function (event) { 974 // Check if the clicked element is not the modal or its children, or the open button 975 if ( 976 !$(event.target).closest(".search-bar-modal, .btn-open-modal").length 977 ) { 978 $(".search-bar-modal").removeClass("show"); 979 $(".btn-open-modal").removeClass("opened"); 980 $("body").removeClass("menu-open"); 981 } 982 }); 983 } 984} 985 986 987/* 988$(".standard-content-link a").on('click',function() { 989 if ($(this).parents('.fact-sheet--sticky').length) { 990 var href = $(this).attr('href'); 991 if (href.indexOf("preview") >= 0) { 992 var target = href.split('#'); 993 var aTag = $("a[name='"+ target[1] +"']"); 994 $('html,body').animate({scrollTop: aTag.offset().top - 220},'slow'); 995 } else { 996 var target = href.split('/#'); 997 var aTag = $("a[name='"+ target[1] +"']"); 998 $('html,body').animate({scrollTop: aTag.offset().top - 220},'slow'); 999 } 1000 } else { 1001 var href = $(this).attr('href'); 1002 if (href.indexOf("preview") >= 0) { 1003 var target = href.split('#'); 1004 var aTag = $("a[name='"+ target[1] +"']"); 1005 $('html,body').animate({scrollTop: aTag.offset().top - 500},'slow'); 1006 } else { 1007 var target = href.split('/#'); 1008 var aTag = $("a[name='"+ target[1] +"']"); 1009 $('html,body').animate({scrollTop: aTag.offset().top - 500},'slow'); 1010 } 1011 } 1012}); 1013$(".fact-sheet__middle__item").not('.standard-content-link').find('a').on('click',function(event) {}).prop("onclick", null ); 1014$(".fact-sheet__middle__item").not('.standard-content-link').find('a').on('click',function(event) { 1015 if ($(this).parents('.fact-sheet--sticky').length) { 1016 event.preventDefault(); 1017 event.stopPropagation(); 1018 var href = $(this).attr('href'); 1019 var target = href.split('#'); 1020 var aTag = $("article[id='"+ target[1] +"']"); 1021 $('html,body').animate({scrollTop: aTag.offset().top - 220},'slow'); 1022 } else { 1023 event.preventDefault(); 1024 event.stopPropagation(); 1025 var href = $(this).attr('href'); 1026 var target = href.split('#'); 1027 var aTag = $("article[id='"+ target[1] +"']"); 1028 $('html,body').animate({scrollTop: aTag.offset().top - 500},'slow'); 1029 } 1030}); 1031*/ 1032 1033$(document).ready(function() { 1034 setTimeout(function(){ 1035 if($('.header-shrink').length) { 1036 $('.breadcrumb').addClass('header-shrink-applied'); 1037 } 1038 }, 500); 1039 $('.general-content img').each(function(){ 1040 var styleCheck = $(this).attr('style'); 1041 var strLeft = 'left'; 1042 var strRight = 'right'; 1043 var strExact = 'border : ; padding : ; margin : ; float : ;'; 1044 1045 if(styleCheck.indexOf(strRight) != -1){ 1046 $(this).addClass('floated-image'); 1047 } 1048 if(styleCheck.indexOf(strLeft) != -1){ 1049 $(this).addClass('floated-image'); 1050 }
1051 if(styleCheck == strExact){ 1052 $(this).css('width','auto'); 1053 } 1054 }); 1055 $('#tsandcs_Box').on('click',function(){ 1056 newAction = $('#subscribeCategory :selected').attr('data-url'); 1057 $('.subscribe form').attr('action', newAction); 1058 }); 1059}); 1060 1061/* 1062(function( $ ) { 1063 $.fn.replaceTag = function(newTag) { 1064 var originalElement = this[0]; 1065 //commented out due to error 1066 //originalTag = originalElement.tagName; 1067 var originalTag = originalElement; 1068 var startRX = new RegExp('^<'+originalTag, 'i') 1069 , endRX = new RegExp(originalTag+'>$', 'i') 1070 , startSubst = '<'+newTag 1071 , endSubst = newTag+'>' 1072 , newHTML = originalElement.outerHTML 1073 .replace(startRX, startSubst) 1074 .replace(endRX, endSubst); 1075 this.replaceWith(newHTML); 1076 }; 1077})(jQuery); 1078$('.content-carousel span.swiper-notification').replaceTag('li') 1079*/ 1080 1081function replaceTag(element, newTag) { 1082 let newElement = document.createElement(newTag); 1083 for (let attr of element.attributes) { 1084 newElement.setAttribute(attr.name, attr.value); 1085 } 1086 1087 while (element.firstChild) { 1088 newElement.appendChild(element.firstChild); 1089 } 1090 1091 element.replaceWith(newElement); 1092} 1093 1094document.querySelectorAll('.content-carousel span.swiper-notification').forEach(el => { 1095 replaceTag(el, 'li'); 1096}); 1097 1098 1099 1100/*A11y fixes*/ 1101document.querySelectorAll('.fact-sheet ul[role="list"] li').forEach(li => 1102 li.getAttribute('role') === 'group' ? li.setAttribute('role', 'listitem') : null 1103); 1104 1105 1106/*psrr 47872 ga lang tag*/ 1107function wrapGaeilgeLinks() { 1108 const breadcrumb = document.querySelector('.breadcrumb'); 1109 if (!breadcrumb) return; 1110 1111 const links = breadcrumb.querySelectorAll('ul li a'); 1112 let foundGaeilge = false; 1113 1114 links.forEach(link => { 1115 if (link.textContent.trim() === 'Gaeilge') { 1116 foundGaeilge = true; 1117 } 1118 1119 if (foundGaeilge) { 1120 const span = document.createElement('span'); 1121 span.lang = 'ga'; 1122 span.textContent = link.textContent; 1123 link.textContent = ''; 1124 link.appendChild(span); 1125 } 1126 }); 1127} 1128 1129function wrapSidebarGaeilgeLinks() { 1130 const sidebar = document.querySelector('.inner__sidebar .inner__sidebar__content'); 1131 if (!sidebar) return; 1132 1133 const links = sidebar.querySelectorAll('ul li a'); 1134 1135 links.forEach(link => { 1136 if (link.textContent.trim() === 'Gaeilge') { 1137 const span = document.createElement('span'); 1138 span.lang = 'ga'; 1139 span.textContent = link.textContent; 1140 link.textContent = ''; 1141 link.appendChild(span); 1142 1143 const parentLi = link.closest('li'); 1144 const hasCurrentPage = link.classList.contains('current-page') || 1145 parentLi.querySelector('.multilevel-linkul-0 li a.current-page'); 1146 1147 if (hasCurrentPage) { 1148 const childLinks = parentLi.querySelectorAll('.multilevel-linkul-0 li a'); 1149 childLinks.forEach(childLink => { 1150 const childSpan = document.createElement('span'); 1151 childSpan.lang = 'ga'; 1152 childSpan.textContent = childLink.textContent; 1153 childLink.textContent = ''; 1154 childLink.appendChild(childSpan); 1155 }); 1156 } 1157 } 1158 }); 1159} 1160 1161wrapGaeilgeLinks(); 1162 1163wrapSidebarGaeilgeLinks(); 1164 1165 1166 1167 1168 1169/*(function () { 1170 function updateAllSwipers() { 1171 document.querySelectorAll('.swiper-container').forEach((container) => { 1172 const slides = container.querySelectorAll('.swiper-slide'); 1173 slides.forEach((slide) => { 1174 const isVisible = 1175 slide.classList.contains('swiper-slide-active') || 1176 slide.classList.contains('swiper-slide-visible'); 1177 1178 slide.setAttribute('aria-hidden', String(!isVisible)); 1179 1180 slide.querySelectorAll( 1181 'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])' 1182 ).forEach((el) => { 1183 if (!isVisible) el.setAttribute('tabindex', '-1'); 1184 else el.removeAttribute('tabindex'); 1185 }); 1186 }); 1187 }); 1188 } 1189 1190 // Run once after load 1191 window.addEventListener('load', () => { 1192 updateAllSwipers(); 1193 1194 // Re-run whenever Swiper mutates classes/styles during slide movement 1195 const obs = new MutationObserver(() => updateAllSwipers()); 1196 obs.observe(document.body, { 1197 subtree: true, 1198 attributes: true, 1199 attributeFilter: ['class', 'style', 'aria-hidden'] 1200 });
1201 }); 1202})(); 1203*/ 1204 1205 1206 1207/* County Map Widget */ 1208(function () { 1209 const widgets = document.querySelectorAll(".county-map-widget"); 1210 if (!widgets.length) return; 1211 1212 const sourceMap = {}; 1213 widgets.forEach(widget => { 1214 const source = widget.dataset.source; 1215 if (!source) return; 1216 if (!sourceMap[source]) sourceMap[source] = []; 1217 sourceMap[source].push(widget); 1218 }); 1219 1220 function renderMap(container, county) { 1221 container.innerHTML = ` 1222 <iframe 1223 title="${county.label} map" 1224 src="https://datawrapper.dwcdn.net/${county.id}/1/" 1225 width="100%" 1226 height="600" 1227 frameborder="0" 1228 scrolling="no" 1229 style="border:none; overflow:hidden;"> 1230 </iframe> 1231 `; 1232 } 1233 1234 // Responsive iframe height via datawrapper postMessage API 1235 window.addEventListener("message", function (e) { 1236 if (typeof e.data !== "object" || !e.data["datawrapper-height"]) return; 1237 var heights = e.data["datawrapper-height"]; 1238 widgets.forEach(function (widget) { 1239 var iframe = widget.querySelector("iframe"); 1240 if (!iframe) return; 1241 Object.keys(heights).forEach(function (id) { 1242 if (iframe.src.indexOf(id) > -1) { 1243 iframe.style.height = heights[id] + "px"; 1244 } 1245 }); 1246 }); 1247 }); 1248 1249 async function init() { 1250 for (const [source, group] of Object.entries(sourceMap)) { 1251 let countyMaps; 1252 try { 1253 const response = await fetch(source); 1254 countyMaps = await response.json(); 1255 } catch (error) { 1256 console.error(`Error loading ${source}:`, error); 1257 group.forEach(w => { 1258 w.querySelector(".county-select").innerHTML = '<option value="">Unable to load options</option>'; 1259 }); 1260 continue; 1261 } 1262 1263 const entries = Object.entries(countyMaps); 1264 1265 group.forEach(widget => { 1266 const select = widget.querySelector(".county-select"); 1267 const container = widget.querySelector(".map-container"); 1268 1269 // If placeholder dataset empty, no placeholder option is shown. 1270 const placeholder = widget.dataset.placeholder; 1271 select.innerHTML = ""; 1272 if (placeholder) { 1273 select.innerHTML = `<option value="">${placeholder}</option>`; 1274 } 1275 1276 entries.forEach(([key, county]) => { 1277 const option = document.createElement("option"); 1278 option.value = key; 1279 option.textContent = county.label; 1280 select.appendChild(option); 1281 }); 1282 1283 select.addEventListener("change", function () { 1284 const selected = this.value; 1285 if (!selected) { container.innerHTML = ""; return; } 1286 renderMap(container, countyMaps[selected]); 1287 }); 1288 1289 // Default to first item on load 1290 if (entries.length) { 1291 select.value = entries[0][0]; 1292 renderMap(container, entries[0][1]); 1293 } 1294 }); 1295 } 1296 } 1297 1298 if (document.readyState === "loading") { 1299 document.addEventListener("DOMContentLoaded", init); 1300 } else { 1301 init(); 1302 } 1303})(); 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
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.