PageSourceSearch

https://www.epa.ie/media/epa-2020/site-assets/javascript/t4-extra.js

js epa.ie collected 2026-10-01 09:19:37 UTC 38,541 bytes, 1,335 lines download raw bytes

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.