PageSourceSearch

https://www.activesustainability.com/etc.clientlibs/accionacom/cli…-473eb10ad7d68e8f577237018705ad46-lc.min.js

js activesustainability.com collected 2026-10-02 04:07:05 UTC 154,197 bytes, 3,332 lines download raw bytes

1const A=(()=>{const e=[];let t=null;const o=e=>{"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)},r=()=>{clearInterval(t),t=null,e.forEach((e=>e()))};return o((()=>{t||(t=setInterval((()=>{document.querySelectorAll(".a-aem-module:not(.a-header, .a-main, .a-footer, .experiencefragment, .workday-reader-pagination) > *, a-mo-oferta, a-mo-wysiwyg").length&&0===document.querySelectorAll(".a-aem-module:not(.a-header, .a-main, .a-footer, .experiencefragment, .workday-reader-pagination) > *:not(.hydrated, div), a-mo-oferta:not(.hydrated), a-mo-wysiwyg:not(.hydrated)").length&&r()}),300))})),{ready:o,loaded:t=>{e.push(t)}}})();var refFn;A.loaded((()=>{const e=e=>"A"===e.tagName||e.matches("a-button-cta")||e.matches("a-button-action")||e.matches("a-button-icon")||e.matches("a-link")||e.matches("a-highlight-title")||e.matches("a-file-download"),t=t=>e(t)&&t.getAttribute("href")?.startsWith("http")&&"_blank"===t.getAttribute("target"),o=e=>e?.trim()?.toLowerCase()?.normalize("NFD")?.replace(/[\u0300-\u036f]/g,"")?.replace(/[\s,\-]+/g,"_")?.replace(/[^a-z0-9ñ_=|/]/g,""),r=e=>{if(!e)return null;const t=e.cloneNode(!0);return t.querySelectorAll(".cmp-link__screen-reader-only").forEach((e=>e.remove())),o(t.textContent)},a=e=>{const t=window.location.href.replace(window.location.origin,"").trim().toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[\s,]+/g,"_").replace(/[^a-z0-9ñ_/]/g,"");let o=e;for(;o;){const e=o.getRootNode();if(!(e instanceof ShadowRoot))break;o=e.host}for(;o&&!o.tagName?.toLowerCase().startsWith("a-");)o=o.parentElement;if(o){const e=o.querySelector('[slot="title"]'),t=e?.getAttribute("text");if(t)return t}return t},n=e=>e?.getAttribute("url")?.toLowerCase()||e?.getAttribute("href")?.toLowerCase(),l=e=>{if(e?.getAttribute("analytic")&&""!==e?.getAttribute("analytic")||e?.getAttribute("data-analytic")&&e?.getAttribute("data-analytic")){switch(e?.getAttribute("analytic")){case"go-to-offers":let t=document.querySelector("a-mo-oferta")?.querySelector('[slot="title"]')?.getAttribute("text");s(e,{event_name:"job_offers_goto_listing",title:t,location:!1,__forceTitle:!0},!0);break;case"go-to-offer-detail":let r=!1,l=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");l&&l.length>1&&(r=l[1]),s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:n(e),link_text:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),location:!1,option:r||void 0},!0);break;case"file-download":let c=e.getAttribute("href"),i=null,u=null;c&&(i=c.split("/").pop(),u=i.split(".").pop(),i=i.replace(`.${u}`,"")),s(e,{event_name:"file_download",file_name:o(i),file_extension:u,link_url:c,location:a(e),title:!1},!0);break;case"ruedas-action-button":let d=e.closest("a-mo-ruedas-content")?.querySelector('[slot="content"] a-text-header')?.getAttribute("text");s(e,{title:d},!0)}return!0}return!1},c=new Set,i=new WeakMap;let u=window.location.pathname.match(/\/[^\/]+$/)?.[0];u=u?.replace("/","")?.replace(/-/g,"_");const d=/\/[a-z]{2}$/.test(window.location.pathname),s=(e,t,o=!1)=>{const r="click";t&&i.set(e,t),o&&(e.removeEventListener(r,h),c.delete(e)),c.has(e)||(e.addEventListener(r,h,{capture:!0}),c.add(e))},m=(e,t)=>{let o=[],r=1===e.length,a=e[0];return t?.querySelectorAll(a).forEach((t=>{r&&o.push(t),!r&&t.shadowRoot&&(o=o.concat(m(e.slice(1),t.shadowRoot)))})),o};refFn=m;const h=o=>{let l={};new URLSearchParams(window.location.search).has("debug-tracking")&&(l._aem=!0,o.preventDefault());let c={};if(i.has(o.currentTarget)&&(c=i.get(o.currentTarget)),l.event="custom_event",l.event_name=c.event_name??(t(o.currentTarget)?"outbound_link":"internal_link"),c.link_text?l.link_text=c.link_text:e(o.currentTarget)&&r(o.currentTarget)&&(l.link_text=r(o.currentTarget)),e(o.currentTarget)){const e=n(o.currentTarget)||window.location.pathname;l.link_url=c.link_url??e.replace(window.location.origin,"")}if(e(o.currentTarget)&&c.file_name&&(l.file_name=c.file_name),e(o.currentTarget)&&c.file_extension&&(l.file_extension=c.file_extension),t(o.currentTarget)||!1===c.location||(l.location=c.location??a(o.currentTarget)),!t(o.currentTarget)&&!1!==c.title||c.__forceTitle){const e=r(o.currentTarget)||c.link_text;l.title=c.__forceTitle?c.title:c.title??e}c.option&&(l.option=c.option),dataLayer.push(l)};function f(e){const t=[];function o(r){r.shadowRoot&&(r.shadowRoot.querySelectorAll(e).forEach((e=>
1t.push(e))),Array.from(r.shadowRoot.children).forEach(o))}return document.querySelectorAll("*").forEach((e=>o(e))),t}const y=[...document.querySelectorAll("a-link"),...f("a-link")],p=[...document.querySelectorAll("a-highlight-title"),...f("a-highlight-title")],b=[...document.querySelectorAll("a-button-icon"),...f("a-button-icon")],S=[...document.querySelectorAll("a-button-cta"),...f("a-button-cta")],q=[...document.querySelectorAll(".acciona-richtext a"),...f(".acciona-richtext a")];if(document.querySelectorAll("a-mo-text a-mo-text-content a-link").forEach((e=>{l(e)||s(e,{title:o(e?.textContent),location:o(e.closest("a-mo-text")?.querySelector("a-text-header")?.textContent)||!1},!0)})),document.querySelectorAll("a-mo-text-boxes a-flex-boxes a-link").forEach((e=>{l(e)||s(e,{title:o(e.closest("a-flex-boxes")?.querySelector("div")?.querySelector("a-text-header")?.shadowRoot?.querySelector(".text-header").textContent),location:a(e)||!1},!0)})),element=document.querySelector(".jobdetail a-pa-path"),element&&element.shadowRoot){const e=element.shadowRoot.querySelector("slot[name='button-cta']");if(e){const t=e.assignedElements().find((e=>"A-BUTTON-CTA"===e.tagName));t&&!l(t)&&s(t,{event_name:"job_offers_start",title:r(t),title:o(document.querySelector("a-pa-path")?.getAttribute("header")),option:new URLSearchParams(window.location.search)?.get("id"),location:!1},!0)}}(()=>{let e;y.forEach((e=>{!l(e)&&s(e)})),p.forEach((e=>{!l(e)&&s(e)})),q.forEach((e=>{!l(e)&&s(e)})),S.forEach((e=>{!l(e)&&s(e)})),document.querySelectorAll("a-button-action").forEach((e=>{!l(e)&&s(e)})),b.forEach((e=>{!l(e)&&s(e)})),m(["a-list","a-link"],document).forEach((e=>{!l(e)&&s(e)})),m(["a-mo-visual-header","a-button-icon"],document).forEach((e=>{if("A-BUTTON-ICON"===e.tagName){let t=null,r=null,a=e.getAttribute("a-aria-label");if(e.shadowRoot){const o=e.shadowRoot.querySelector("a");o&&(t=o.getAttribute("href"))}const n=e.closest(".visual-header-item-content");if(n){const e=n.querySelector(".content-top-title");e&&(r=e?.textContent)}!l(e)&&s(e,{event_name:"click_cta",location:"hero_banner",link_text:o(a),link_url:t,title:o(r)},!0)}})),m(["a-mo-visual-header","a-slider","a-button-action"],document).forEach((e=>{!l(e)&&s(e,{event_name:"click_cta",location:"hero_banner",title:r(e.closest(".visual-header-item-content")?.querySelector(".content-top-title")?.textContent)},!0)})),m(["a-mo-horizontal-distributor","a-slider","a-button-action"],document).forEach((e=>{!l(e)&&s(e,{event_name:"click_cta",location:"hero_banner"})})),m(["a-mo-featured-distributor","a-slider","a-button-action"],document).forEach((e=>{s(e)})),document.querySelector(".a-header")&&m(["a-highlight-title"],document).forEach((e=>{s(e,{event_name:"click_menu",location:"main",title:!1},!0)})),m(["a-mo-distributor-list","a-highlight-title"],document.querySelector(".distributorlist.a-aem-module")).forEach((e=>{let t=null;if(e.shadowRoot){const o=e.shadowRoot.querySelector("a");o&&(t=o.getAttribute("href"))}s(e,{event_name:"click_cta",link_url:t,location:d?"home":a(e),title:!1},!0)})),m(["a-mo-distributor-list","a-highlight-title"],document.querySelector(".a-footer.a-aem-module")).forEach((e=>{let t=null;if(e.shadowRoot){const o=e.shadowRoot.querySelector("a");o&&(t=o.getAttribute("href"))}s(e,{event_name:"click_footer",link_url:t,location:"prefooter",title:!1},!0)})),m(["a-mo-distributor-list","a-mo-compartir-rrss"],document.querySelector(".a-footer.a-aem-module")).forEach((e=>{let t=null;if(e.shadowRoot){const o=e.shadowRoot.querySelector("a");o&&(t=o.getAttribute("href"))}s(e,{event_name:"click_footer",link_url:t,location:"prefooter"})})),document.querySelector(".a-footer.a-aem-module")&&document.querySelector("a-mo-newsletter")&&m(["a-mo-newsletter","a-input button"],document).forEach((e=>{s(e,{event_name:"click_footer",link_url:n(e),location:"prefooter"},!0)})),document.querySelector(".featuredproject")&&m(["a-mo-proyecto-destacado","a-button-icon"],document).forEach((e=>{const t=e.closest(".basicinfo-container")?.querySelector(".basicinfo-content-header")?.textContent;s(e,{location:a(e),link_url:e.shadowRoot.querySelector("a")?.href,title:o(t)},!0)})),document.addEventListener("a-aem:tracking",(e=>{dataLayer.push(e.detail)})),e=document.querySelector("a-mo-oferta")||document.querySelector("a-mo-oferta-v2"),e&&(m(["a-oferta","a-link"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getRootNode().querySelector("a.title-clickable")?.href,option:t??void 0,location:!1},!0)})),m(["a-oferta","a"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getAttribute("href"),link_text:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),option:t??void 0,location:!1},!0)})),m(["a-mo-oferta-v2","ul li a-oferta","a-link"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getRootNode().querySelector("a.title-clickable")?.href,option:t??void 0,location:!1},!0)})),m(["a-mo-oferta","ul li a-oferta","a-link"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getRootNode().querySelector("a.title-clickable")?.href,option:t??void 0,location:!1},!0)})),m(["a-mo-oferta","a-oferta","a"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getAttribute("href"),link_text:o(e.querySelector("a-text-header")?.getAttribute("text")),option:t??void 0,location:!1},!0)})),m(["a-mo-oferta-v2","a-oferta","a"],document).forEach((e=>{let t=!1,r=e.getRootNode().querySelector("a-link")?.shadowRoot.querySelector("a")?.href.split("?id=");r&&r.length>1&&(t=r[1]),!l(e)&&s(e,{event_name:"job_offers_view_detail",title:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),link_url:e.getAttribute("href"),link_text:o(e.getRootNode().querySelector("a.title-clickable")?.querySelector("a-text-header")?.shadowRoot?.querySelector("div")?.textContent),option:t??void 0,location:!1},!0)})))})()})),A.loaded((()=>{const e=e=>{let t=document.createElement("div");return t.id=`scroll-marker-${e}`,t.dataset.threshold=25*e,t.style.position="absolute",t.style.top=`calc(${25*e}% - 2px)`,t.style.left="0",t.style.width="1px",t.style.height="1px",t.style.zIndex="-1",t},t=new IntersectionObserver((e=>{e.forEach((e=>{e.isIntersecting&&e.intersectionRatio>=1&&(dataLayer.push({event:"custom_event",event_name:`scroll_${e.target.dataset.threshold}`,percent_scrolled:e.target.dataset.threshold}),t.unobserve(e.target),e.target.remove())}
1))}),{root:null,threshold:[1]});for(let o=1;o<=4;o++){let r=e(o);document.body.appendChild(r),t.observe(r)}})),A.ready((()=>{if(document.querySelector('a-video[src*="youtube"]')){let e=document.createElement("script");e.src="https://www.youtube.com/iframe_api",e.defer=!0,document.head.appendChild(e)}if(document.querySelector('a-video[src*="vimeo"]')){let e=document.createElement("script");e.src="https://player.vimeo.com/api/player.js",e.defer=!0,document.head.appendChild(e)}})),document.addEventListener("DOMContentLoaded",(function(){document.querySelectorAll('[data-action="openModal"]').forEach((function(e){e.addEventListener("aClick",(()=>{const t=e.getAttribute("data-modalid"),o=document.querySelector(`a-modal[a-id="${t}"]`),r=document.querySelector(`a-dialog[a-id="${t}"]`);if(o)o.open();else if(r){let e=document.querySelector(`a-dialog[a-id="${t}"]`).parentElement;e.style.position="relative",r.open(e)}else console.warn(`No se encontró el modal con ID "${t}".`)}))}))}));const newsletterComponent=document.querySelector("a-mo-newsletter"),checkboxComponent=newsletterComponent?.querySelector("a-checkbox"),link=checkboxComponent?.querySelector("div.acciona-richtext a");link&&link.addEventListener("click",(e=>{e.preventDefault();const t=document.querySelector("a-mo-newsletter + a-modal");t&&t.open()}));const gdprForm=document.querySelector("#gdpr-form"),checkboxGdpr=gdprForm?.querySelector("[name='gdpr-consent']"),linkGdpr=checkboxGdpr?.querySelector("p a");linkGdpr&&linkGdpr.addEventListener("click",(e=>{e.preventDefault();const t=document.querySelector("[name='gdpr-consent'] + a-modal");t&&t.open()}));const waterForm=document.querySelector("#water-form"),checkboxWater=waterForm?.querySelector("[name='water-consent']"),linkWater=checkboxWater?.querySelector("p a");linkWater&&linkWater.addEventListener("click",(e=>{e.preventDefault();const t=document.querySelector("[name='water-consent'] + a-modal");t&&t.open()}));let links=document.querySelectorAll('a[href^="#modal-"]');links.forEach((function(e){let t=e.getAttribute("href").replace("#",""),o=document.querySelector(`a-modal[a-id="${t}"]`);o&&(e.setAttribute("target","self"),e.addEventListener("click",(function(e){e.preventDefault(),o.open()})))})),A.ready((()=>{if(!document.querySelector("#gdpr-form"))return;let e=document.querySelector("#gdpr-form");async function t(){let t=new FormData(e),a=e.querySelectorAll("[required]"),n=!0;for(let e=0;e<a.length;e++)a[e].value||a[e].selectedValue||a[e].files&&a[e].files.length>0?a[e].setAttribute("has-error",!1):(a[e].setAttribute("has-error",!0),n=!1);if(e.querySelector('[name="gdpr-consent"]').checked||(e.querySelector('[name="gdpr-consent"]').setAttribute("has-error",!0),n=!1),!n)return;for(var l of t.entries());let c=[];document.querySelectorAll('a-checkbox-list[data-name="relation-type"] a-checkbox').forEach((e=>{e.checked&&c.push(e.value)})),t.append("relation-type[]",c.join(",")),e.querySelector('a-textarea[name="other-relation-type"]').value&&t.append("relation-type-other",e.querySelector('a-textarea[name="other-relation-type"]').value);let i=[];document.querySelectorAll('a-checkbox-list[data-name="areas"] a-checkbox').forEach((e=>{e.checked&&i.push(e.value)})),t.append("areas[]",i.join(",")),e.querySelector('a-textarea[name="other-areas"]').value&&t.append("areas-other",e.querySelector('a-textarea[name="other-areas"]').value);let u=[];document.querySelectorAll('a-checkbox-list[data-name="rights"] a-checkbox').forEach((e=>{e.checked&&u.push(e.value)})),t.append("rights[]",u.join(",")),e.querySelector('a-textarea[name="additional"]').value&&t.append("additional",e.querySelector('a-textarea[name="additional"]').value);let d=document.querySelector('a-file-uploader[name="files"]');if(d&&d.files.length>0)for(let e=0;e<d.files.length;e++)t.append(`files-${e}`,d.files[e]);let s=document.querySelector('a-file-uploader[name="on-behalf-of-personal-id"]');if(s&&s.files.length>0)for(let e=0;e<s.files.length;e++)t.append("on-behalf-of-personal-id",s.files[e]);try{let a=[location.protocol,"//",location.host,location.pathname].join("");a.endsWith(".html")&&(a=a.replace(".html","")),a+="/jcr:content.gdpr-send.json",fetch(a,{method:"POST",body:t,headers:{"CSRF-Token":await r()}}).then((e=>e.json())).then((t=>{t._result&&"success"===t._result&&(o(),e.dataset.redirect&&(window.location.href=e.dataset.redirect))}))}catch(e){}}function o(){document.querySelector("#gdpr-form").reset(),document.querySelectorAll("a-radio-button-list").forEach((e=>{e.selectedValue&&(e.selectedValue="")}
1)),document.querySelectorAll("a-radio-button").forEach((e=>{e.checked&&(e.checked=!1)})),document.querySelectorAll("a-file-uploader").forEach((e=>{e.files&&(e.files=[])})),document.querySelectorAll("a-input, a-textarea").forEach((e=>{e.value&&(e.value="")})),document.querySelectorAll("a-checkbox").forEach((e=>{e.checked&&(e.checked=!1)}))}async function r(){const e=await fetch("/libs/granite/csrf/token.json");return(await e.json()).token}document.getElementById("gdpr-form").addEventListener("submit",(e=>{e.preventDefault(),t()})),document.querySelector("#gdpr-form-submit-btn")?.addEventListener("click",(function(e){e.preventDefault(),t()})),document.querySelector("#gdpr-form-reset-btn")?.addEventListener("click",(function(e){e.preventDefault(),document.querySelector("#gdpr-form").reset(),o()}));const a=document.querySelector("#gdpr-form a-radio-button-list a-radio-button[value='yes']"),n=document.querySelector("#gdpr-form a-radio-button-list a-radio-button[value='no']");a.addEventListener("click",(t=>{e.querySelector('[name="on-behalf-of-name"]').removeAttribute("required"),e.querySelector('[name="on-behalf-of-name"]').removeAttribute("has-error"),e.querySelector('[name="on-behalf-of-surnames"]').removeAttribute("required"),e.querySelector('[name="on-behalf-of-surnames"]').removeAttribute("has-error"),e.querySelector('[name="on-behalf-of-personal-id"]').removeAttribute("required"),e.querySelector('[name="on-behalf-of-personal-id"]').removeAttribute("has-error")})),n.addEventListener("click",(t=>{e.querySelector('[name="on-behalf-of-name"]').setAttribute("required",!0),e.querySelector('[name="on-behalf-of-surnames"]').setAttribute("required",!0),e.querySelector('[name="on-behalf-of-personal-id"]').setAttribute("required",!0)}))})),A.ready((()=>{if(!document.querySelector("#water-form"))return;let e=document.querySelector("#water-form");async function t(){let t=new FormData(e),a=e.querySelectorAll("[required]"),n=!0;for(let e=0;e<a.length;e++)a[e].value||a[e].selectedValue?a[e].setAttribute("has-error",!1):(a[e].setAttribute("has-error",!0),n=!1);if(e.querySelector('[name="water-consent"]').checked||(e.querySelector('[name="water-consent"]').setAttribute("has-error",!0),n=!1),n){for(var l of t.entries())console.log(l[0]+", "+l[1]);e.querySelector('a-textarea[name="comments"]').value&&t.append("comments",e.querySelector('a-textarea[name="comments"]').value);try{let a=[location.protocol,"//",location.host,location.pathname].join("");a.endsWith(".html")&&(a=a.replace(".html","")),a+="/jcr:content.water-form-send.json",fetch(a,{method:"POST",body:t,headers:{"CSRF-Token":await r()}}).then((e=>e.json())).then((t=>{t._result&&"success"===t._result?(console.log("Success:",t),o(),e.dataset.redirect&&(window.location.href=e.dataset.redirect)):console.error("Error:",t)}))}catch(e){console.error("Error:",e)}}}function o(){document.querySelector("#water-form").reset(),document.querySelectorAll("a-input, a-textarea").forEach((e=>{e.value&&(e.value="")})),document.querySelectorAll("a-checkbox").forEach((e=>{e.checked&&(e.checked=!1)}))}async function r(){const e=await fetch("/libs/granite/csrf/token.json");return(await e.json()).token}document.getElementById("water-form").addEventListener("submit",(e=>{e.preventDefault(),t()})),document.querySelector("#water-form-submit-btn")?.addEventListener("click",(function(e){e.preventDefault(),console.log("submit"),t()})),document.querySelector("#water-form-reset-btn")?.addEventListener("click",(function(e){e.preventDefault(),console.log("reset"),document.querySelector("#water-form").reset(),o()}))})),A.ready((()=>{if(!document.querySelector("#turbine-form"))return;let e=document.querySelector("#turbine-form");function t(){document.querySelector("#turbine-form").reset(),document.querySelectorAll("a-input, a-textarea, a-select").forEach((e=>{e.value&&(e.value="")}))}async function o(){const e=await fetch("/libs/granite/csrf/token.json");return(await e.json()).token}document.querySelector("#turbine-form-submit-btn")?.addEventListener("click",(function(r){r.preventDefault(),async function(){let r=new FormData(e),a=e.querySelectorAll("[required]"),n=!0;for(let e=0;e<a.length;e++)a[e].value||a[e].selectedValue?a[e].setAttribute("has-error",!1):(a[e].setAttribute("has-error",!0),n=!1);if(n){e.querySelector('a-select[name="representingArea"]').value&&r.append("representation-area",e.querySelector('a-select[name="representingArea"]').value),e.querySelector('a-select[name="interestArea"]').value&&r.append("interest-area",e.querySelector('a-select[name="interestArea"]').value),e.querySelector('a-textarea[name="comments"]').value&&r.append("comments",e.querySelector('a-textarea[name="comments"]').value);try{let a=[location.protocol,"//",location.host,location.pathname].join("");a.endsWith(".html")&&(a=a.replace(".html","")),a+="/jcr:content.turbine-send.json",fetch(a,{method:"POST",body:r,headers:{"CSRF-Token":await o()}}).then((e=>e.json())).then((o=>{o._result&&"success"===o._result&&(t(),e.dataset.redirect&&(window.location.href=e.dataset.redirect))}))}catch(e){}}}()})),document.querySelector("#turbine-form-reset-btn")?.addEventListener("click",(function(e){e.preventDefault(),document.querySelector("#turbine-form").reset(),t()}))})),A.ready((()=>
1{if(!document.querySelector("#mx-form"))return;let e=document.querySelector("#mx-form");function t(){document.querySelector("#mx-form").reset(),document.querySelectorAll("a-input, a-textarea, a-select").forEach((e=>{e.value&&(e.value="")})),document.querySelectorAll("a-radio-button-list").forEach((e=>{e.selectedValue&&(e.selectedValue="")})),document.querySelectorAll("a-radio-button").forEach((e=>{e.checked&&(e.checked=!1)})),document.querySelectorAll("a-checkbox").forEach((e=>{e.checked&&(e.checked=!1)}))}async function o(){const e=await fetch("/libs/granite/csrf/token.json");return(await e.json()).token}document.querySelector("#mx-form-submit-btn")?.addEventListener("click",(function(r){r.preventDefault(),async function(){let r=new FormData(e),a=e.querySelectorAll("[required]"),n=!0;for(let e=0;e<a.length;e++)a[e].value||a[e].selectedValue?a[e].setAttribute("has-error",!1):(a[e].setAttribute("has-error",!0),n=!1);if(e.querySelector('[name="mx-consent"]').checked||(e.querySelector('[name="mx-consent"]').setAttribute("has-error",!0),n=!1),!n)return;e.querySelector('a-select[name="mensualPayment"]').value?r.append("mensualPayment",e.querySelector('a-select[name="mensualPayment"]').value):r.append("mensualPayment","no data");const l=e.querySelector('a-radio-button-list[data-name="radioButtonList"]'),c=l?l.getAttribute("selected-value"):null;l&&c?r.append("buyInterest",c):r.append("buyInterest","no data");try{let a=[location.protocol,"//",location.host,location.pathname].join("");a.endsWith(".html")&&(a=a.replace(".html","")),a+="/jcr:content.mx-send.json",fetch(a,{method:"POST",body:r,headers:{"CSRF-Token":await o()}}).then((e=>e.json())).then((o=>{o._result&&"success"===o._result&&(t(),e.dataset.redirect&&(window.location.href=e.dataset.redirect))}))}catch(e){}}()})),document.querySelector("#mx-form-reset-btn")?.addEventListener("click",(function(e){e.preventDefault(),document.querySelector("#mx-form").reset(),t()}))})),A.ready((()=>{const e=new MutationObserver((()=>{const t=document.querySelector("#custom-form");t&&t.shadowRoot&&(!function(){const e=document.querySelector("#custom-form");if(!e||!e.shadowRoot)return;const t=e.shadowRoot,a=setInterval((()=>{const n=t.querySelector("#custom-form-send"),l=t.querySelector("#custom-form-cancel");n&&l&&(clearInterval(a),n.addEventListener("click",(function(e){e.preventDefault(),o(t)})),l.addEventListener("click",(function(e){e.preventDefault(),r(t)})),e.addEventListener("submit",(e=>{e.preventDefault(),o(t)})))}),200)}(),e.disconnect())}));e.observe(document.body,{childList:!0,subtree:!0});let t=document.querySelector("#custom-form");async function o(e){let o=new FormData,n=t.querySelectorAll("[required]"),l=!0;var c=new Array;if(n.forEach((e=>{("A-CHECKBOX"!==e.tagName||e.checked)&&(e.selectedValue||e.value)?e.setAttribute("has-error",!1):(e.setAttribute("has-error",!0),l=!1)})),l){var i=t.querySelectorAll("a-selector");for(let e=0;e<i.length;e++)i[e].value&&(c.push(i[e].getAttribute("name")),o.append("selector-"+e+"-"+i[e].getAttribute("name"),i[e].value));var u=t.querySelectorAll("a-input");for(let e=0;e<u.length;e++)u[e].value&&(c.push(u[e].getAttribute("name")),o.append("input-"+e+"-"+u[e].getAttribute("name"),u[e].value));var d=t.querySelectorAll("a-textarea");for(let e=0;e<d.length;e++)d[e].value&&(c.push(d[e].getAttribute("name")),o.append("textarea-"+e+"-"+d[e].getAttribute("name"),d[e].value));var s=t.querySelectorAll("a-checkbox-list");for(let e=0;e<s.length;e++){var m=s[e].querySelectorAll("a-checkbox");c.push(s[e].getAttribute("name"));var h=!1;for(let t=0;t<m.length;t++)m[t].checked&&(c.push(m[t].getAttribute("name")),o.append("checkboxList-"+e+"-"+s[e].getAttribute("name"),m[t].value),m[t].getAttribute("class").includes("show-hidden-element")&&(h=!0));if(h){var f=t.querySelector('div[class="related-fields"]').querySelector("a-textarea");f&&(c.push(f.getAttribute("name")),o.append("checkboxList-"+e+"-textArea",f.value))}}var y=t.querySelectorAll("a-radio-button-list");for(let e=0;e<y.length;e++){var p=y[e].querySelectorAll("a-radio-button");c.push(y[e].getAttribute("name"));for(let t=0;t<p.length;t++)p[t].value===y[e].getAttribute("selected-value")&&(c.push(p[t].getAttribute("name")),o.append("radioButtonList-"+e+"-"+y[e].getAttribute("name"),y[e].getAttribute("selected-value")))}var b=t.querySelectorAll("a-file-uploader");if(b&&b.length>0)for(let e=0;e<b.length;e++){c.push(b[e].getAttribute("name"));for(let t=0;t<b[e].files.length;t++)o.append("fileUploader-"+e+"-"+b[e].getAttribute("name"),b[e].files[t])}s=t.querySelectorAll("a-checkbox");for(let e=0;e<s.length;e++)!c.includes(s[e].getAttribute("name"))&&s[e].checked&&(c.push(s[e].getAttribute("name")),o.append("checkbox-"+e+"-"+s[e].getAttribute("name"),s[e].value));y=t.querySelectorAll("a-radio-button");for(let e=0;e<y.length;e++)!c.includes(y[e].getAttribute("name"))&&y[e].checked&&(c.push(y[e].getAttribute("name")),o.append("radioButton-"+e+"-"+y[e].getAttribute("name"),y[e].value));try{let e=[location.protocol,"//",location.host,location.pathname].join("");e.endsWith(".html")&&(e=e.replace(".html","")),e+="/jcr:content.custom-form-send.json",fetch(e,{method:"POST",body:o,headers:{"CSRF-Token":await a()}}).then((e=>e.json())).then((e=>{e._result&&"success"===e._result&&(r(),t.dataset.redirect&&(window.location.href=t.dataset.redirect))}))}catch(e){console.error("Error:",e)}}}function r(e){document.querySelectorAll("a-input, a-textarea, a-select").forEach((e=>{e.value&&(e.value="")}
1)),document.querySelectorAll("a-radio-button-list").forEach((e=>{e.selectedValue&&(e.selectedValue="")})),document.querySelectorAll("a-radio-button").forEach((e=>{e.checked&&(e.checked=!1)})),document.querySelectorAll("a-checkbox").forEach((e=>{e.checked&&(e.checked=!1)})),document.querySelectorAll("a-file-uploader").forEach((e=>{e.value&&(e.value="")}))}async function a(){const e=await fetch("/libs/granite/csrf/token.json");return(await e.json()).token}}));
2/*******************************************************************************
3 * Copyright 2019 Adobe
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ******************************************************************************/
17
18/**
19 * Element.matches()
20 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill
21 */
22if (!Element.prototype.matches) {
23    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
24}
25
26// eslint-disable-next-line valid-jsdoc
27/**
28 * Element.closest()
29 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill
30 */
31if (!Element.prototype.closest) {
32    Element.prototype.closest = function(s) {
33        "use strict";
34        var el = this;
35        if (!document.documentElement.contains(el)) {
36            return null;
37        }
38        do {
39            if (el.matches(s)) {
40                return el;
41            }
42            el = el.parentElement || el.parentNode;
43        } while (el !== null && el.nodeType === 1);
44        return null;
45    };
46}
47
48/*******************************************************************************
49 * Copyright 2019 Adobe
50 *
51 * Licensed under the Apache License, Version 2.0 (the "License");
52 * you may not use this file except in compliance with the License.
53 * You may obtain a copy of the License at
54 *
55 *     http://www.apache.org/licenses/LICENSE-2.0
56 *
57 * Unless required by applicable law or agreed to in writing, software
58 * distributed under the License is distributed on an "AS IS" BASIS,
59 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
60 * See the License for the specific language governing permissions and
61 * limitations under the License.
62 ******************************************************************************/
63(function() {
64    "use strict";
65
66    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
67    if (!containerUtils) {
68        // eslint-disable-next-line no-console
69        console.warn("Accordion: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
70    }
71    var dataLayerEnabled;
72    var dataLayer;
73    var dataLayerName;
74    var delay = 100;
75
76    var NS = "cmp";
77    var IS = "accordion";
78
79    var keyCodes = {
80        ENTER: 13,
81        SPACE: 32,
82        END: 35,
83        HOME: 36,
84        ARROW_LEFT: 37,
85        ARROW_UP: 38,
86        ARROW_RIGHT: 39,
87        ARROW_DOWN: 40
88    };
89
90    var selectors = {
91        self: "[data-" + NS + '-is="' + IS + '"]'
92    };
93
94    var cssClasses = {
95        button: {
96            disabled: "cmp-accordion__button--disabled",
97            expanded: "cmp-accordion__button--expanded"
98        },
99        panel: {
100            hidden: "cmp-accordion__panel--hidden",
101            expanded: "cmp-accordion__panel--expanded"
102        }
103    };
104
105    var dataAttributes = {
106        item: {
107            expanded: "data-cmp-expanded"
108        }
109    };
110
111    var properties = {
112        /**
113         * Determines whether a single accordion item is forced to be expanded at a time.
114         * Expanding one item will collapse all others.
115         *
116         * @memberof Accordion
117         * @type {Boolean}
118         * @default false
119         */
120        "singleExpansion": {
121            "default": false,
122            "transform": function(value) {
123                return !(value === null || typeof value === "undefined");
124            }
125        }
126    };
127
128    /**
129     * Accordion Configuration.
130     *
131     * @typedef {Object} AccordionConfig Represents an Accordion configuration
132     * @property {HTMLElement} element The HTMLElement representing the Accordion
133     * @property {Object} options The Accordion options
134     */
135
136    /**
137     * Accordion.
138     *
139     * @class Accordion
140     * @classdesc An interactive Accordion component for toggling panels of related content
141     * @param {AccordionConfig} config The Accordion configuration
142     */
143    function Accordion(config) {
144        var that = this;
145
146        if (config && config.element) {
147            init(config);
148        }
149
150        /**
151         * Initializes the Accordion.
152         *
153         * @private
154         * @param {AccordionConfig} config The Accordion configuration
155         */
156        function init(config) {
157            that._config = config;
158
159            // prevents multiple initialization
160            config.element.removeAttribute("data-" + NS + "-is");
161
162            setupProperties(config.options);
163            cacheElements(config.element);
164
165            if (that._elements["item"]) {
166                // ensures multiple element types are arrays.
167                that._elements["item"] = Array.isArray(that._elements["item"]) ? that._elements["item"] : [that._elements["item"]];
168                that._elements["button"] = Array.isArray(that._elements["button"]) ? that._elements["button"] : [that._elements["button"]];
169                that._elements["panel"] = Array.isArray(that._elements["panel"]) ? that._elements["panel"] : [that._elements["panel"]];
170
171                if (that._properties.singleExpansion) {
172                    var expandedItems = getExpandedItems();
173                    // multiple expanded items annotated, display the last item open.
174                    if (expandedItems.length > 1) {
175                        toggle(expandedItems.length - 1);
176                    }
177                }
178
179                refreshItems();
180                bindEvents();
181                scrollToDeepLinkIdInAccordion();
182            }
183            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
184                /*
185                 * Editor message handling:
186                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
187                 * - check that the message data panel container type is correct and that the id (path) matches this specific Accordion component
188                 * - if so, route the "navigate" operation to enact a navigation of the Accordion based on index data
189                 */
190                window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
191                window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
192                    if (message.data && message.data.type === "cmp-accordion" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
193                        if (message.data.operation === "navigate") {
194                            // switch to single expansion mode when navigating in edit mode.
195                            var singleExpansion = that._properties.singleExpansion;
196                            that._properties.singleExpansion = true;
197                            toggle(message.data.index);
198
199                            // revert to the configured state.
200                            that._properties.singleExpansion = singleExpansion;
201                        }
202                    }
203                });
204            }
205        }
206
207        /**
208         * Displays the panel containing the element that corresponds to the deep link in the URI fragment
209         * and scrolls the browser to this element.
210         */
211        function scrollToDeepLinkIdInAccordion() {
212            if (containerUtils) {
213                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item");
214                if (deepLinkItemIdx > -1) {
215                    var deepLinkItem = that._elements["item"][deepLinkItemIdx];
216                    if (deepLinkItem && !deepLinkItem.hasAttribute(dataAttributes.item.expanded)) {
217                        // if single expansion: close all accordion items
218                        if (that._properties.singleExpansion) {
219                            for (var j = 0; j < that._elements["item"].length; j++) {
220                                if (that._elements["item"][j].hasAttribute(dataAttributes.item.expanded)) {
221                                    setItemExpanded(that._elements["item"][j], false, true);
222                                }
223                            }
224                        }
225                        // expand the accordion item containing the deep link
226                        setItemExpanded(deepLinkItem, true, true);
227                    }
228                    var hashId = window.location.hash.substring(1);
229                    if (hashId) {
230                        var hashItem = document.querySelector("[id='" + hashId + "']");
231                        if (hashItem) {
232                            hashItem.scrollIntoView();
233                        }
234                    }
235                }
236            }
237        }
238
239        /**
240         * Caches the Accordion elements as defined via the {@code data-accordion-hook="ELEMENT_NAME"} markup API.
241         *
242         * @private
243         * @param {HTMLElement} wrapper The Accordion wrapper element
244         */
245        function cacheElements(wrapper) {
246            that._elements = {};
247            that._elements.self = wrapper;
248            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
249
250            for (var i = 0; i < hooks.length; i++) {
251                var hook = hooks[i];
252                if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own accordion elements
253                    var capitalized = IS;
254                    capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
255                    var key = hook.dataset[NS + "Hook" + capitalized];
256                    if (that._elements[key]) {
257                        if (!Array.isArray(that._elements[key])) {
258                            var tmp = that._elements[key];
259                            that._elements[key] = [tmp];
260                        }
261                        that._elements[key].push(hook);
262                    } else {
263                        that._elements[key] = hook;
264                    }
265                }
266            }
267        }
268
269        /**
270         * Sets up properties for the Accordion based on the passed options.
271         *
272         * @private
273         * @param {Object} options The Accordion options
274         */
275        function setupProperties(options) {
276            that._properties = {};
277
278            for (var key in properties) {
279                if (Object.prototype.hasOwnProperty.call(properties, key)) {
280                    var property = properties[key];
281                    var value = null;
282
283                    if (options && options[key] != null) {
284                        value = options[key];
285
286                        // transform the provided option
287                        if (property && typeof property.transform === "function") {
288                            value = property.transform(value);
289                        }
290                    }
291
292                    if (value === null) {
293                        // value still null, take the property default
294                        value = properties[key]["default"];
295                    }
296
297                    that._properties[key] = value;
298                }
299            }
300        }
301
302        /**
303         * Binds Accordion event handling.
304         *
305         * @private
306         */
307        function bindEvents() {
308            window.addEventListener("hashchange", scrollToDeepLinkIdInAccordion, false);
309            var buttons = that._elements["button"];
310            if (buttons) {
311                for (var i = 0; i < buttons.length; i++) {
312                    (function(index) {
313                        buttons[i].addEventListener("click", function(event) {
314                            toggle(index);
315                            focusButton(index);
316                        });
317                        buttons[i].addEventListener("keydown", function(event) {
318                            onButtonKeyDown(event, index);
319                        });
320                    })(i);
321                }
322            }
323        }
324
325        /**
326         * Handles button keydown events.
327         *
328         * @private
329         * @param {Object} event The keydown event
330         * @param {Number} index The index of the button triggering the event
331         */
332        function onButtonKeyDown(event, index) {
333            var lastIndex = that._elements["button"].length - 1;
334
335            switch (event.keyCode) {
336                case keyCodes.ARROW_LEFT:
337                case keyCodes.ARROW_UP:
338                    event.preventDefault();
339                    if (index > 0) {
340                        focusButton(index - 1);
341                    }
342                    break;
343                case keyCodes.ARROW_RIGHT:
344                case keyCodes.ARROW_DOWN:
345                    event.preventDefault();
346                    if (index < lastIndex) {
347                        focusButton(index + 1);
348                    }
349                    break;
350                case keyCodes.HOME:
351                    event.preventDefault();
352                    focusButton(0);
353                    break;
354                case keyCodes.END:
355                    event.preventDefault();
356                    focusButton(lastIndex);
357                    break;
358                case keyCodes.ENTER:
359                case keyCodes.SPACE:
360                    event.preventDefault();
361                    toggle(index);
362                    focusButton(index);
363                    break;
364                default:
365                    return;
366            }
367        }
368
369        /**
370         * General handler for toggle of an item.
371         *
372         * @private
373         * @param {Number} index The index of the item to toggle
374         */
375        function toggle(index) {
376            var item = that._elements["item"][index];
377            if (item) {
378                if (that._properties.singleExpansion) {
379                    // ensure only a single item is expanded if single expansion is enabled.
380                    for (var i = 0; i < that._elements["item"].length; i++) {
381                        if (that._elements["item"][i] !== item) {
382                            var expanded = getItemExpanded(that._elements["item"][i]);
383                            if (expanded) {
384                                setItemExpanded(that._elements["item"][i], false);
385                            }
386                        }
387                    }
388                }
389                setItemExpanded(item, !getItemExpanded(item));
390
391                if (dataLayerEnabled) {
392                    var accordionId = that._elements.self.id;
393                    var expandedItems = getExpandedItems()
394                        .map(function(item) {
395                            return getDataLayerId(item);
396                        });
397
398                    var uploadPayload = { component: {} };
399                    uploadPayload.component[accordionId] = { shownItems: expandedItems };
400
401                    var removePayload = { component: {} };
402                    removePayload.component[accordionId] = { shownItems: undefined };
403
404                    dataLayer.push(removePayload);
405                    dataLayer.push(uploadPayload);
406                }
407            }
408        }
409
410        /**
411         * Sets an item's expanded state based on the provided flag and refreshes its internals.
412         *
413         * @private
414         * @param {HTMLElement} item The item to mark as expanded, or not expanded
415         * @param {Boolean} expanded true to mark the item expanded, false otherwise
416         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
417         */
418        function setItemExpanded(item, expanded, keepHash) {
419            if (expanded) {
420                item.setAttribute(dataAttributes.item.expanded, "");
421                var index = that._elements["item"].indexOf(item);
422                if (!keepHash && containerUtils) {
423                    containerUtils.updateUrlHash(that, "item", index);
424                }
425                if (dataLayerEnabled) {
426                    dataLayer.push({
427                        event: "cmp:show",
428                        eventInfo: {
429                            path: "component." + getDataLayerId(item)
430                        }
431                    });
432                }
433
434            } else {
435                item.removeAttribute(dataAttributes.item.expanded);
436                if (!keepHash && containerUtils) {
437                    containerUtils.removeUrlHash();
438                }
439                if (dataLayerEnabled) {
440                    dataLayer.push({
441                        event: "cmp:hide",
442                        eventInfo: {
443                            path: "component." + getDataLayerId(item)
444                        }
445                    });
446                }
447            }
448            refreshItem(item);
449        }
450
451        /**
452         * Gets an item's expanded state.
453         *
454         * @private
455         * @param {HTMLElement} item The item for checking its expanded state
456         * @returns {Boolean} true if the item is expanded, false otherwise
457         */
458        function getItemExpanded(item) {
459            return item && item.dataset && item.dataset["cmpExpanded"] !== undefined;
460        }
461
462        /**
463         * Refreshes an item based on its expanded state.
464         *
465         * @private
466         * @param {HTMLElement} item The item to refresh
467         */
468        function refreshItem(item) {
469            var expanded = getItemExpanded(item);
470            if (expanded) {
471                expandItem(item);
472            } else {
473                collapseItem(item);
474            }
475        }
476
477        /**
478         * Refreshes all items based on their expanded state.
479         *
480         * @private
481         */
482        function refreshItems() {
483            for (var i = 0; i < that._elements["item"].length; i++) {
484                refreshItem(that._elements["item"][i]);
485            }
486        }
487
488        /**
489         * Returns all expanded items.
490         *
491         * @private
492         * @returns {HTMLElement[]} The expanded items
493         */
494        function getExpandedItems() {
495            var expandedItems = [];
496
497            for (var i = 0; i < that._elements["item"].length; i++) {
498                var item = that._elements["item"][i];
499                var expanded = getItemExpanded(item);
500                if (expanded) {
501                    expandedItems.push(item);
502                }
503            }
504
505            return expandedItems;
506        }
507
508        /**
509         * Annotates the item and its internals with
510         * the necessary style and accessibility attributes to indicate it is expanded.
511         *
512         * @private
513         * @param {HTMLElement} item The item to annotate as expanded
514         */
515        function expandItem(item) {
516            var index = that._elements["item"].indexOf(item);
517            if (index > -1) {
518                var button = that._elements["button"][index];
519                var panel = that._elements["panel"][index];
520                button.classList.add(cssClasses.button.expanded);
521                // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
522                // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
523                setTimeout(function() {
524                    button.setAttribute("aria-expanded", true);
525                }, delay);
526                panel.classList.add(cssClasses.panel.expanded);
527                panel.classList.remove(cssClasses.panel.hidden);
528                panel.setAttribute("aria-hidden", false);
529            }
530        }
531
532        /**
533         * Annotates the item and its internals with
534         * the necessary style and accessibility attributes to indicate it is not expanded.
535         *
536         * @private
537         * @param {HTMLElement} item The item to annotate as not expanded
538         */
539        function collapseItem(item) {
540            var index = that._elements["item"].indexOf(item);
541            if (index > -1) {
542                var button = that._elements["button"][index];
543                var panel = that._elements["panel"][index];
544                button.classList.remove(cssClasses.button.expanded);
545                // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
546                // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
547                setTimeout(function() {
548                    button.setAttribute("aria-expanded", false);
549                }, delay);
550                panel.classList.add(cssClasses.panel.hidden);
551                panel.classList.remove(cssClasses.panel.expanded);
552                panel.setAttribute("aria-hidden", true);
553            }
554        }
555
556        /**
557         * Focuses the button at the provided index.
558         *
559         * @private
560         * @param {Number} index The index of the button to focus
561         */
562        function focusButton(index) {
563            var button = that._elements["button"][index];
564            button.focus();
565        }
566    }
567
568    /**
569     * Reads options data from the Accordion wrapper element, defined via {@code data-cmp-*} data attributes.
570     *
571     * @private
572     * @param {HTMLElement} element The Accordion element to read options data from
573     * @returns {Object} The options read from the component data attributes
574     */
575    function readData(element) {
576        var data = element.dataset;
577        var options = [];
578        var capitalized = IS;
579        capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
580        var reserved = ["is", "hook" + capitalized];
581
582        for (var key in data) {
583            if (Object.prototype.hasOwnProperty.call(data, key)) {
584                var value = data[key];
585
586                if (key.indexOf(NS) === 0) {
587                    key = key.slice(NS.length);
588                    key = key.charAt(0).toLowerCase() + key.substring(1);
589
590                    if (reserved.indexOf(key) === -1) {
591                        options[key] = value;
592                    }
593                }
594            }
595        }
596
597        return options;
598    }
599
600    /**
601     * Parses the dataLayer string and returns the ID
602     *
603     * @private
604     * @param {HTMLElement} item the accordion item
605     * @returns {String} dataLayerId or undefined
606     */
607    function getDataLayerId(item) {
608        if (item) {
609            if (item.dataset.cmpDataLayer) {
610                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
611            } else {
612                return item.id;
613            }
614        }
615        return null;
616    }
617
618    /**
619     * Document ready handler and DOM mutation observers. Initializes Accordion components as necessary.
620     *
621     * @private
622     */
623    function onDocumentReady() {
624        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
625        if (dataLayerEnabled) {
626            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
627            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
628        }
629
630        var elements = document.querySelectorAll(selectors.self);
631        for (var i = 0; i < elements.length; i++) {
632            new Accordion({ element: elements[i], options: readData(elements[i]) });
633        }
634
635        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
636        var body = document.querySelector("body");
637        var observer = new MutationObserver(function(mutations) {
638            mutations.forEach(function(mutation) {
639                // needed for IE
640                var nodesArray = [].slice.call(mutation.addedNodes);
641                if (nodesArray.length > 0) {
642                    nodesArray.forEach(function(addedNode) {
643                        if (addedNode.querySelectorAll) {
644                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
645                            elementsArray.forEach(function(element) {
646                                new Accordion({ element: element, options: readData(element) });
647                            });
648                        }
649                    });
650                }
651            });
652        });
653
654        observer.observe(body, {
655            subtree: true,
656            childList: true,
657            characterData: true
658        });
659    }
660
661    if (document.readyState !== "loading") {
662        onDocumentReady();
663    } else {
664        document.addEventListener("DOMContentLoaded", onDocumentReady);
665    }
666
667    if (containerUtils) {
668        window.addEventListener("load", containerUtils.scrollToAnchor, false);
669    }
670
671}());
672
673
674/*******************************************************************************
675 * Copyright 2018 Adobe
676 *
677 * Licensed under the Apache License, Version 2.0 (the "License");
678 * you may not use this file except in compliance with the License.
679 * You may obtain a copy of the License at
680 *
681 *     http://www.apache.org/licenses/LICENSE2.0
682 *
683 * Unless required by applicable law or agreed to in writing, software
684 * distributed under the License is distributed on an "AS IS" BASIS,
685 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
686 * See the License for the specific language governing permissions and
687 * limitations under the License.
688 ******************************************************************************/
689
690/**
691 * Element.matches()
692 * https://developer.mozilla.org/enUS/docs/Web/API/Element/matches#Polyfill
693 */
694if (!Element.prototype.matches) {
695    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
696}
697
698// eslint-disable-next-line valid-jsdoc
699/**
700 * Element.closest()
701 * https://developer.mozilla.org/enUS/docs/Web/API/Element/closest#Polyfill
702 */
703if (!Element.prototype.closest) {
704    Element.prototype.closest = function(s) {
705        "use strict";
706        var el = this;
707        if (!document.documentElement.contains(el)) {
708            return null;
709        }
710        do {
711            if (el.matches(s)) {
712                return el;
713            }
714            el = el.parentElement || el.parentNode;
715        } while (el !== null && el.nodeType === 1);
716        return null;
717    };
718}
719
720/*******************************************************************************
721 * Copyright 2018 Adobe
722 *
723 * Licensed under the Apache License, Version 2.0 (the "License");
724 * you may not use this file except in compliance with the License.
725 * You may obtain a copy of the License at
726 *
727 *     http://www.apache.org/licenses/LICENSE-2.0
728 *
729 * Unless required by applicable law or agreed to in writing, software
730 * distributed under the License is distributed on an "AS IS" BASIS,
731 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
732 * See the License for the specific language governing permissions and
733 * limitations under the License.
734 ******************************************************************************/
735/* global
736    CQ
737 */
738(function() {
739    "use strict";
740
741    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
742    if (!containerUtils) {
743        // eslint-disable-next-line no-console
744        console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
745    }
746    var dataLayerEnabled;
747    var dataLayer;
748    var dataLayerName;
749
750    var NS = "cmp";
751    var IS = "tabs";
752
753    var keyCodes = {
754        END: 35,
755        HOME: 36,
756        ARROW_LEFT: 37,
757        ARROW_UP: 38,
758        ARROW_RIGHT: 39,
759        ARROW_DOWN: 40
760    };
761
762    var selectors = {
763        self: "[data-" + NS + '-is="' + IS + '"]',
764        active: {
765            tab: "cmp-tabs__tab--active",
766            tabpanel: "cmp-tabs__tabpanel--active"
767        }
768    };
769
770    /**
771     * Tabs Configuration
772     *
773     * @typedef {Object} TabsConfig Represents a Tabs configuration
774     * @property {HTMLElement} element The HTMLElement representing the Tabs
775     * @property {Object} options The Tabs options
776     */
777
778    /**
779     * Tabs
780     *
781     * @class Tabs
782     * @classdesc An interactive Tabs component for navigating a list of tabs
783     * @param {TabsConfig} config The Tabs configuration
784     */
785    function Tabs(config) {
786        var that = this;
787
788        if (config && config.element) {
789            init(config);
790        }
791
792        /**
793         * Initializes the Tabs
794         *
795         * @private
796         * @param {TabsConfig} config The Tabs configuration
797         */
798        function init(config) {
799            that._config = config;
800
801            // prevents multiple initialization
802            config.element.removeAttribute("data-" + NS + "-is");
803
804            cacheElements(config.element);
805            that._active = getActiveIndex(that._elements["tab"]);
806
807            if (that._elements.tabpanel) {
808                refreshActive();
809                bindEvents();
810                scrollToDeepLinkIdInTabs();
811            }
812
813            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
814                /*
815                 * Editor message handling:
816                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
817                 * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
818                 * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
819                 */
820                CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
821                CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
822                    if (message.data && message.data.type === "cmp-tabs" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
823                        if (message.data.operation === "navigate") {
824                            navigate(message.data.index);
825                        }
826                    }
827                });
828            }
829        }
830
831        /**
832         * Displays the panel containing the element that corresponds to the deep link in the URI fragment
833         * and scrolls the browser to this element.
834         */
835        function scrollToDeepLinkIdInTabs() {
836            if (containerUtils) {
837                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "tab", "tabpanel");
838                if (deepLinkItemIdx > -1) {
839                    var deepLinkItem = that._elements["tab"][deepLinkItemIdx];
840                    if (deepLinkItem && that._elements["tab"][that._active].id !== deepLinkItem.id) {
841                        navigateAndFocusTab(deepLinkItemIdx, true);
842                    }
843                    var hashId = window.location.hash.substring(1);
844                    if (hashId) {
845                        var hashItem = document.querySelector("[id='" + hashId + "']");
846                        if (hashItem) {
847                            hashItem.scrollIntoView();
848                        }
849                    }
850                }
851            }
852        }
853
854        /**
855         * Returns the index of the active tab, if no tab is active returns 0
856         *
857         * @param {Array} tabs Tab elements
858         * @returns {Number} Index of the active tab, 0 if none is active
859         */
860        function getActiveIndex(tabs) {
861            if (tabs) {
862                for (var i = 0; i < tabs.length; i++) {
863                    if (tabs[i].classList.contains(selectors.active.tab)) {
864                        return i;
865                    }
866                }
867            }
868            return 0;
869        }
870
871        /**
872         * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API
873         *
874         * @private
875         * @param {HTMLElement} wrapper The Tabs wrapper element
876         */
877        function cacheElements(wrapper) {
878            that._elements = {};
879            that._elements.self = wrapper;
880            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
881
882            for (var i = 0; i < hooks.length; i++) {
883                var hook = hooks[i];
884                if (hook.closest("." + NS + "-" + IS) === that._elements.self) { // only process own tab elements
885                    var capitalized = IS;
886                    capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
887                    var key = hook.dataset[NS + "Hook" + capitalized];
888                    if (that._elements[key]) {
889                        if (!Array.isArray(that._elements[key])) {
890                            var tmp = that._elements[key];
891                            that._elements[key] = [tmp];
892                        }
893                        that._elements[key].push(hook);
894                    } else {
895                        that._elements[key] = hook;
896                    }
897                }
898            }
899        }
900
901        /**
902         * Binds Tabs event handling
903         *
904         * @private
905         */
906        function bindEvents() {
907            window.addEventListener("hashchange", scrollToDeepLinkIdInTabs, false);
908            var tabs = that._elements["tab"];
909            if (tabs) {
910                for (var i = 0; i < tabs.length; i++) {
911                    (function(index) {
912                        tabs[i].addEventListener("click", function(event) {
913                            navigateAndFocusTab(index);
914                        });
915                        tabs[i].addEventListener("keydown", function(event) {
916                            onKeyDown(event);
917                        });
918                    })(i);
919                }
920            }
921        }
922
923        /**
924         * Handles tab keydown events
925         *
926         * @private
927         * @param {Object} event The keydown event
928         */
929        function onKeyDown(event) {
930            var index = that._active;
931            var lastIndex = that._elements["tab"].length - 1;
932
933            switch (event.keyCode) {
934                case keyCodes.ARROW_LEFT:
935                case keyCodes.ARROW_UP:
936                    event.preventDefault();
937                    if (index > 0) {
938                        navigateAndFocusTab(index - 1);
939                    }
940                    break;
941                case keyCodes.ARROW_RIGHT:
942                case keyCodes.ARROW_DOWN:
943                    event.preventDefault();
944                    if (index < lastIndex) {
945                        navigateAndFocusTab(index + 1);
946                    }
947                    break;
948                case keyCodes.HOME:
949                    event.preventDefault();
950                    navigateAndFocusTab(0);
951                    break;
952                case keyCodes.END:
953                    event.preventDefault();
954                    navigateAndFocusTab(lastIndex);
955                    break;
956                default:
957                    return;
958            }
959        }
960
961        /**
962         * Refreshes the tab markup based on the current {@code Tabs#_active} index
963         *
964         * @private
965         */
966        function refreshActive() {
967            var tabpanels = that._elements["tabpanel"];
968            var tabs = that._elements["tab"];
969
970            if (tabpanels) {
971                if (Array.isArray(tabpanels)) {
972                    for (var i = 0; i < tabpanels.length; i++) {
973                        if (i === parseInt(that._active)) {
974                            tabpanels[i].classList.add(selectors.active.tabpanel);
975                            tabpanels[i].removeAttribute("aria-hidden");
976                            tabs[i].classList.add(selectors.active.tab);
977                            tabs[i].setAttribute("aria-selected", true);
978                            tabs[i].setAttribute("tabindex", "0");
979                        } else {
980                            tabpanels[i].classList.remove(selectors.active.tabpanel);
981                            tabpanels[i].setAttribute("aria-hidden", true);
982                            tabs[i].classList.remove(selectors.active.tab);
983                            tabs[i].setAttribute("aria-selected", false);
984                            tabs[i].setAttribute("tabindex", "-1");
985                        }
986                    }
987                } else {
988                    // only one tab
989                    tabpanels.classList.add(selectors.active.tabpanel);
990                    tabs.classList.add(selectors.active.tab);
991                }
992            }
993        }
994
995        /**
996         * Focuses the element and prevents scrolling the element into view
997         *
998         * @param {HTMLElement} element Element to focus
999         */
1000        function focusWithoutScroll(element) {
1001            var x = window.scrollX || window.pageXOffset;
1002            var y = window.scrollY || window.pageYOffset;
1003            element.focus();
1004            window.scrollTo(x, y);
1005        }
1006
1007        /**
1008         * Navigates to the tab at the provided index
1009         *
1010         * @private
1011         * @param {Number} index The index of the tab to navigate to
1012         */
1013        function navigate(index) {
1014            that._active = index;
1015            refreshActive();
1016        }
1017
1018        /**
1019         * Navigates to the item at the provided index and ensures the active tab gains focus
1020         *
1021         * @private
1022         * @param {Number} index The index of the item to navigate to
1023         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
1024         */
1025        function navigateAndFocusTab(index, keepHash) {
1026            var exActive = that._active;
1027            if (!keepHash && containerUtils) {
1028                containerUtils.updateUrlHash(that, "tab", index);
1029            }
1030            navigate(index);
1031            focusWithoutScroll(that._elements["tab"][index]);
1032
1033            if (dataLayerEnabled) {
1034
1035                var activeItem = getDataLayerId(that._elements.tabpanel[index]);
1036                var exActiveItem = getDataLayerId(that._elements.tabpanel[exActive]);
1037
1038                dataLayer.push({
1039                    event: "cmp:show",
1040                    eventInfo: {
1041                        path: "component." + activeItem
1042                    }
1043                });
1044
1045                dataLayer.push({
1046                    event: "cmp:hide",
1047                    eventInfo: {
1048                        path: "component." + exActiveItem
1049                    }
1050                });
1051
1052                var tabsId = that._elements.self.id;
1053                var uploadPayload = { component: {} };
1054                uploadPayload.component[tabsId] = { shownItems: [activeItem] };
1055
1056                var removePayload = { component: {} };
1057                removePayload.component[tabsId] = { shownItems: undefined };
1058
1059                dataLayer.push(removePayload);
1060                dataLayer.push(uploadPayload);
1061            }
1062        }
1063    }
1064
1065    /**
1066     * Reads options data from the Tabs wrapper element, defined via {@code data-cmp-*} data attributes
1067     *
1068     * @private
1069     * @param {HTMLElement} element The Tabs element to read options data from
1070     * @returns {Object} The options read from the component data attributes
1071     */
1072    function readData(element) {
1073        var data = element.dataset;
1074        var options = [];
1075        var capitalized = IS;
1076        capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
1077        var reserved = ["is", "hook" + capitalized];
1078
1079        for (var key in data) {
1080            if (Object.prototype.hasOwnProperty.call(data, key)) {
1081                var value = data[key];
1082
1083                if (key.indexOf(NS) === 0) {
1084                    key = key.slice(NS.length);
1085                    key = key.charAt(0).toLowerCase() + key.substring(1);
1086
1087                    if (reserved.indexOf(key) === -1) {
1088                        options[key] = value;
1089                    }
1090                }
1091            }
1092        }
1093
1094        return options;
1095    }
1096
1097    /**
1098     * Parses the dataLayer string and returns the ID
1099     *
1100     * @private
1101     * @param {HTMLElement} item the accordion item
1102     * @returns {String} dataLayerId or undefined
1103     */
1104    function getDataLayerId(item) {
1105        if (item) {
1106            if (item.dataset.cmpDataLayer) {
1107                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
1108            } else {
1109                return item.id;
1110            }
1111        }
1112        return null;
1113    }
1114
1115    /**
1116     * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
1117     *
1118     * @private
1119     */
1120    function onDocumentReady() {
1121        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
1122        if (dataLayerEnabled) {
1123            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
1124            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
1125        }
1126
1127        var elements = document.querySelectorAll(selectors.self);
1128        for (var i = 0; i < elements.length; i++) {
1129            new Tabs({ element: elements[i], options: readData(elements[i]) });
1130        }
1131
1132        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
1133        var body = document.querySelector("body");
1134        var observer = new MutationObserver(function(mutations) {
1135            mutations.forEach(function(mutation) {
1136                // needed for IE
1137                var nodesArray = [].slice.call(mutation.addedNodes);
1138                if (nodesArray.length > 0) {
1139                    nodesArray.forEach(function(addedNode) {
1140                        if (addedNode.querySelectorAll) {
1141                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
1142                            elementsArray.forEach(function(element) {
1143                                new Tabs({ element: element, options: readData(element) });
1144                            });
1145                        }
1146                    });
1147                }
1148            });
1149        });
1150
1151        observer.observe(body, {
1152            subtree: true,
1153            childList: true,
1154            characterData: true
1155        });
1156    }
1157
1158    if (document.readyState !== "loading") {
1159        onDocumentReady();
1160    } else {
1161        document.addEventListener("DOMContentLoaded", onDocumentReady);
1162    }
1163
1164    if (containerUtils) {
1165        window.addEventListener("load", containerUtils.scrollToAnchor, false);
1166    }
1167
1168}());
1169
1170
1171/*******************************************************************************
1172 * Copyright 2022 Adobe
1173 *
1174 * Licensed under the Apache License, Version 2.0 (the "License");
1175 * you may not use this file except in compliance with the License.
1176 * You may obtain a copy of the License at
1177 *
1178 *     http://www.apache.org/licenses/LICENSE-2.0
1179 *
1180 * Unless required by applicable law or agreed to in writing, software
1181 * distributed under the License is distributed on an "AS IS" BASIS,
1182 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1183 * See the License for the specific language governing permissions and
1184 * limitations under the License.
1185 ******************************************************************************/
1186(function(document) {
1187    "use strict";
1188
1189    window.CMP = window.CMP || {};
1190    window.CMP.utils = (function() {
1191        var NS = "cmp";
1192
1193        /**
1194         * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes
1195         *
1196         * @param {HTMLElement} element The component element to read options data from
1197         * @param {String} is The component identifier
1198         * @returns {String[]} The options read from the component data attributes
1199         */
1200        var readData = function(element, is) {
1201            var data = element.dataset;
1202            var options = [];
1203            var capitalized = is;
1204            capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
1205            var reserved = ["is", "hook" + capitalized];
1206
1207            for (var key in data) {
1208                if (Object.prototype.hasOwnProperty.call(data, key)) {
1209                    var value = data[key];
1210
1211                    if (key.indexOf(NS) === 0) {
1212                        key = key.slice(NS.length);
1213                        key = key.charAt(0).toLowerCase() + key.substring(1);
1214
1215                        if (reserved.indexOf(key) === -1) {
1216                            options[key] = value;
1217                        }
1218                    }
1219                }
1220            }
1221            return options;
1222        };
1223
1224        /**
1225         * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand
1226         * @param {String[]} options the options to transform
1227         * @param {Object} properties object of properties of property functions
1228         * @returns {Object} transformed properties
1229         */
1230        var setupProperties = function(options, properties) {
1231            var transformedProperties = {};
1232
1233            for (var key in properties) {
1234                if (Object.prototype.hasOwnProperty.call(properties, key)) {
1235                    var property = properties[key];
1236                    if (options && options[key] != null) {
1237                        if (property && typeof property.transform === "function") {
1238                            transformedProperties[key] = property.transform(options[key]);
1239                        } else {
1240                            transformedProperties[key] = options[key];
1241                        }
1242                    } else {
1243                        transformedProperties[key] = properties[key]["default"];
1244                    }
1245                }
1246            }
1247            return transformedProperties;
1248        };
1249
1250
1251        return {
1252            readData: readData,
1253            setupProperties: setupProperties
1254        };
1255    }());
1256}(window.document));
1257
1258/*******************************************************************************
1259 * Copyright 2018 Adobe
1260 *
1261 * Licensed under the Apache License, Version 2.0 (the "License");
1262 * you may not use this file except in compliance with the License.
1263 * You may obtain a copy of the License at
1264 *
1265 *     http://www.apache.org/licenses/LICENSE-2.0
1266 *
1267 * Unless required by applicable law or agreed to in writing, software
1268 * distributed under the License is distributed on an "AS IS" BASIS,
1269 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1270 * See the License for the specific language governing permissions and
1271 * limitations under the License.
1272 ******************************************************************************/
1273(function() {
1274    "use strict";
1275
1276    var containerUtils = window.CQ && window.CQ.CoreComponents && window.CQ.CoreComponents.container && window.CQ.CoreComponents.container.utils ? window.CQ.CoreComponents.container.utils : undefined;
1277    if (!containerUtils) {
1278        // eslint-disable-next-line no-console
1279        console.warn("Tabs: container utilities at window.CQ.CoreComponents.container.utils are not available. This can lead to missing features. Ensure the core.wcm.components.commons.site.container client library is included on the page.");
1280    }
1281    var dataLayerEnabled;
1282    var dataLayer;
1283    var dataLayerName;
1284
1285    var NS = "cmp";
1286    var IS = "carousel";
1287
1288    var keyCodes = {
1289        SPACE: 32,
1290        END: 35,
1291        HOME: 36,
1292        ARROW_LEFT: 37,
1293        ARROW_UP: 38,
1294        ARROW_RIGHT: 39,
1295        ARROW_DOWN: 40
1296    };
1297
1298    var selectors = {
1299        self: "[data-" + NS + '-is="' + IS + '"]'
1300    };
1301
1302    var properties = {
1303        /**
1304         * Determines whether the Carousel will automatically transition between slides
1305         *
1306         * @memberof Carousel
1307         * @type {Boolean}
1308         * @default false
1309         */
1310        "autoplay": {
1311            "default": false,
1312            "transform": function(value) {
1313                return !(value === null || typeof value === "undefined");
1314            }
1315        },
1316        /**
1317         * Duration (in milliseconds) before automatically transitioning to the next slide
1318         *
1319         * @memberof Carousel
1320         * @type {Number}
1321         * @default 5000
1322         */
1323        "delay": {
1324            "default": 5000,
1325            "transform": function(value) {
1326                value = parseFloat(value);
1327                return !isNaN(value) ? value : null;
1328            }
1329        },
1330        /**
1331         * Determines whether automatic pause on hovering the carousel is disabled
1332         *
1333         * @memberof Carousel
1334         * @type {Boolean}
1335         * @default false
1336         */
1337        "autopauseDisabled": {
1338            "default": false,
1339            "transform": function(value) {
1340                return !(value === null || typeof value === "undefined");
1341            }
1342        }
1343    };
1344
1345    /**
1346     * Carousel Configuration
1347     *
1348     * @typedef {Object} CarouselConfig Represents a Carousel configuration
1349     * @property {HTMLElement} element The HTMLElement representing the Carousel
1350     * @property {*[]} options The Carousel options
1351     */
1352
1353    /**
1354     * Carousel
1355     *
1356     * @class Carousel
1357     * @classdesc An interactive Carousel component for navigating a list of generic items
1358     * @param {CarouselConfig} config The Carousel configuration
1359     */
1360    function Carousel(config) {
1361        var that = this;
1362
1363        if (config && config.element) {
1364            init(config);
1365        }
1366
1367        /**
1368         * Initializes the Carousel
1369         *
1370         * @private
1371         * @param {CarouselConfig} config The Carousel configuration
1372         */
1373        function init(config) {
1374            that._config = config;
1375
1376            // prevents multiple initialization
1377            config.element.removeAttribute("data-" + NS + "-is");
1378
1379            setupProperties(config.options);
1380            cacheElements(config.element);
1381
1382            that._active = 0;
1383            that._paused = false;
1384
1385            if (that._elements.item) {
1386                initializeActive();
1387                bindEvents();
1388                resetAutoplayInterval();
1389                refreshPlayPauseActions();
1390                scrollToDeepLinkIdInCarousel();
1391            }
1392
1393            // TODO: This section is only relevant in edit mode and should move to the editor clientLib
1394            if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
1395                /*
1396                 * Editor message handling:
1397                 * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
1398                 * - check that the message data panel container type is correct and that the id (path) matches this specific Carousel component
1399                 * - if so, route the "navigate" operation to enact a navigation of the Carousel based on index data
1400                 */
1401                window.CQ = window.CQ || {};
1402                window.CQ.CoreComponents = window.CQ.CoreComponents || {};
1403                window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
1404                window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function(message) {
1405                    if (message.data && message.data.type === "cmp-carousel" && message.data.id === that._elements.self.dataset["cmpPanelcontainerId"]) {
1406                        if (message.data.operation === "navigate") {
1407                            navigate(message.data.index);
1408                        }
1409                    }
1410                });
1411            }
1412        }
1413
1414        /**
1415         * Displays the slide containing the element that corresponds to the deep link in the URI fragment
1416         * and scrolls the browser to this element.
1417         */
1418        function scrollToDeepLinkIdInCarousel() {
1419            if (containerUtils) {
1420                var deepLinkItemIdx = containerUtils.getDeepLinkItemIdx(that, "item", "item");
1421                if (deepLinkItemIdx > -1) {
1422                    var deepLinkItem = that._elements["item"][deepLinkItemIdx];
1423                    if (deepLinkItem && that._elements["item"][that._active].id !== deepLinkItem.id) {
1424                        navigateAndFocusIndicator(deepLinkItemIdx, true);
1425                        // pause the carousel auto-rotation
1426                        pause();
1427                    }
1428                    var hashId = window.location.hash.substring(1);
1429                    if (hashId) {
1430                        var hashItem = document.querySelector("[id='" + hashId + "']");
1431                        if (hashItem) {
1432                            hashItem.scrollIntoView();
1433                        }
1434                    }
1435                }
1436            }
1437        }
1438
1439        /**
1440         * Caches the Carousel elements as defined via the {@code data-carousel-hook="ELEMENT_NAME"} markup API
1441         *
1442         * @private
1443         * @param {HTMLElement} wrapper The Carousel wrapper element
1444         */
1445        function cacheElements(wrapper) {
1446            that._elements = {};
1447            that._elements.self = wrapper;
1448            var hooks = that._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
1449
1450            for (var i = 0; i < hooks.length; i++) {
1451                var hook = hooks[i];
1452                var capitalized = IS;
1453                capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
1454                var key = hook.dataset[NS + "Hook" + capitalized];
1455                if (that._elements[key]) {
1456                    if (!Array.isArray(that._elements[key])) {
1457                        var tmp = that._elements[key];
1458                        that._elements[key] = [tmp];
1459                    }
1460                    that._elements[key].push(hook);
1461                } else {
1462                    that._elements[key] = hook;
1463                }
1464            }
1465        }
1466
1467        /**
1468         * Sets up properties for the Carousel based on the passed options.
1469         *
1470         * @private
1471         * @param {Object} options The Carousel options
1472         */
1473        function setupProperties(options) {
1474            that._properties = {};
1475
1476            for (var key in properties) {
1477                if (Object.prototype.hasOwnProperty.call(properties, key)) {
1478                    var property = properties[key];
1479                    var value = null;
1480
1481                    if (options && options[key] != null) {
1482                        value = options[key];
1483
1484                        // transform the provided option
1485                        if (property && typeof property.transform === "function") {
1486                            value = property.transform(value);
1487                        }
1488                    }
1489
1490                    if (value === null) {
1491                        // value still null, take the property default
1492                        value = properties[key]["default"];
1493                    }
1494
1495                    that._properties[key] = value;
1496                }
1497            }
1498        }
1499
1500        /**
1501         * Binds Carousel event handling
1502         *
1503         * @private
1504         */
1505        function bindEvents() {
1506            window.addEventListener("hashchange", scrollToDeepLinkIdInCarousel, false);
1507            if (that._elements["previous"]) {
1508                that._elements["previous"].addEventListener("click", function() {
1509                    var index = getPreviousIndex();
1510                    navigate(index);
1511                    if (dataLayerEnabled) {
1512                        dataLayer.push({
1513                            event: "cmp:show",
1514                            eventInfo: {
1515                                path: "component." + getDataLayerId(that._elements.item[index])
1516                            }
1517                        });
1518                    }
1519                });
1520            }
1521
1522            if (that._elements["next"]) {
1523                that._elements["next"].addEventListener("click", function() {
1524                    var index = getNextIndex();
1525                    navigate(index);
1526                    if (dataLayerEnabled) {
1527                        dataLayer.push({
1528                            event: "cmp:show",
1529                            eventInfo: {
1530                                path: "component." + getDataLayerId(that._elements.item[index])
1531                            }
1532                        });
1533                    }
1534                });
1535            }
1536
1537            var indicators = that._elements["indicator"];
1538            if (indicators) {
1539                for (var i = 0; i < indicators.length; i++) {
1540                    (function(index) {
1541                        indicators[i].addEventListener("click", function(event) {
1542                            navigateAndFocusIndicator(index);
1543                            // pause the carousel auto-rotation
1544                            pause();
1545                        });
1546                    })(i);
1547                }
1548            }
1549
1550            if (that._elements["pause"]) {
1551                if (that._properties.autoplay) {
1552                    that._elements["pause"].addEventListener("click", onPauseClick);
1553                }
1554            }
1555
1556            if (that._elements["play"]) {
1557                if (that._properties.autoplay) {
1558                    that._elements["play"].addEventListener("click", onPlayClick);
1559                }
1560            }
1561
1562            that._elements.self.addEventListener("keydown", onKeyDown);
1563
1564            if (!that._properties.autopauseDisabled) {
1565                that._elements.self.addEventListener("mouseenter", onMouseEnter);
1566                that._elements.self.addEventListener("mouseleave", onMouseLeave);
1567            }
1568
1569            // for accessibility we pause animation when a element get focused
1570            var items = that._elements["item"];
1571            if (items) {
1572                for (var j = 0; j < items.length; j++) {
1573                    items[j].addEventListener("focusin", onMouseEnter);
1574                    items[j].addEventListener("focusout", onMouseLeave);
1575                }
1576            }
1577        }
1578
1579        /**
1580         * Handles carousel keydown events
1581         *
1582         * @private
1583         * @param {Object} event The keydown event
1584         */
1585        function onKeyDown(event) {
1586            var index = that._active;
1587            var lastIndex = that._elements["indicator"].length - 1;
1588
1589            switch (event.keyCode) {
1590                case keyCodes.ARROW_LEFT:
1591                case keyCodes.ARROW_UP:
1592                    event.preventDefault();
1593                    if (index > 0) {
1594                        navigateAndFocusIndicator(index - 1);
1595                    }
1596                    break;
1597                case keyCodes.ARROW_RIGHT:
1598                case keyCodes.ARROW_DOWN:
1599                    event.preventDefault();
1600                    if (index < lastIndex) {
1601                        navigateAndFocusIndicator(index + 1);
1602                    }
1603                    break;
1604                case keyCodes.HOME:
1605                    event.preventDefault();
1606                    navigateAndFocusIndicator(0);
1607                    break;
1608                case keyCodes.END:
1609                    event.preventDefault();
1610                    navigateAndFocusIndicator(lastIndex);
1611                    break;
1612                case keyCodes.SPACE:
1613                    if (that._properties.autoplay && (event.target !== that._elements["previous"] && event.target !== that._elements["next"])) {
1614                        event.preventDefault();
1615                        if (!that._paused) {
1616                            pause();
1617                        } else {
1618                            play();
1619                        }
1620                    }
1621                    if (event.target === that._elements["pause"]) {
1622                        that._elements["play"].focus();
1623                    }
1624                    if (event.target === that._elements["play"]) {
1625                        that._elements["pause"].focus();
1626                    }
1627                    break;
1628                default:
1629                    return;
1630            }
1631        }
1632
1633        /**
1634         * Handles carousel mouseenter events
1635         *
1636         * @private
1637         * @param {Object} event The mouseenter event
1638         */
1639        function onMouseEnter(event) {
1640            clearAutoplayInterval();
1641        }
1642
1643        /**
1644         * Handles carousel mouseleave events
1645         *
1646         * @private
1647         * @param {Object} event The mouseleave event
1648         */
1649        function onMouseLeave(event) {
1650            resetAutoplayInterval();
1651        }
1652
1653        /**
1654         * Handles pause element click events
1655         *
1656         * @private
1657         * @param {Object} event The click event
1658         */
1659        function onPauseClick(event) {
1660            pause();
1661            that._elements["play"].focus();
1662        }
1663
1664        /**
1665         * Handles play element click events
1666         *
1667         * @private
1668         * @param {Object} event The click event
1669         */
1670        function onPlayClick() {
1671            play();
1672            that._elements["pause"].focus();
1673        }
1674
1675        /**
1676         * Pauses the playing of the Carousel. Sets {@code Carousel#_paused} marker.
1677         * Only relevant when autoplay is enabled
1678         *
1679         * @private
1680         */
1681        function pause() {
1682            that._paused = true;
1683            clearAutoplayInterval();
1684            refreshPlayPauseActions();
1685        }
1686
1687        /**
1688         * Enables the playing of the Carousel. Sets {@code Carousel#_paused} marker.
1689         * Only relevant when autoplay is enabled
1690         *
1691         * @private
1692         */
1693        function play() {
1694            that._paused = false;
1695
1696            // If the Carousel is hovered, don't begin auto transitioning until the next mouse leave event
1697            var hovered = false;
1698            if (that._elements.self.parentElement) {
1699                hovered = that._elements.self.parentElement.querySelector(":hover") === that._elements.self;
1700            }
1701            if (that._properties.autopauseDisabled || !hovered) {
1702                resetAutoplayInterval();
1703            }
1704
1705            refreshPlayPauseActions();
1706        }
1707
1708        /**
1709         * Refreshes the play/pause action markup based on the {@code Carousel#_paused} state
1710         *
1711         * @private
1712         */
1713        function refreshPlayPauseActions() {
1714            setActionDisabled(that._elements["pause"], that._paused);
1715            setActionDisabled(that._elements["play"], !that._paused);
1716        }
1717
1718        /**
1719         * Initialize {@code Carousel#_active} based on the active item of the carousel.
1720         */
1721        function initializeActive() {
1722            var items = that._elements["item"];
1723            if (items && Array.isArray(items)) {
1724                for (var i = 0; i < items.length; i++) {
1725                    if (items[i].classList.contains("cmp-carousel__item--active")) {
1726                        that._active = i;
1727                        break;
1728                    }
1729                }
1730            }
1731        }
1732
1733        /**
1734         * Refreshes the item markup based on the current {@code Carousel#_active} index
1735         *
1736         * @private
1737         */
1738        function refreshActive() {
1739            var items = that._elements["item"];
1740            var indicators = that._elements["indicator"];
1741
1742            if (items) {
1743                if (Array.isArray(items)) {
1744                    for (var i = 0; i < items.length; i++) {
1745                        if (i === parseInt(that._active)) {
1746                            items[i].classList.add("cmp-carousel__item--active");
1747                            items[i].removeAttribute("aria-hidden");
1748                            indicators[i].classList.add("cmp-carousel__indicator--active");
1749                            indicators[i].setAttribute("aria-selected", true);
1750                            indicators[i].setAttribute("tabindex", "0");
1751                        } else {
1752                            items[i].classList.remove("cmp-carousel__item--active");
1753                            items[i].setAttribute("aria-hidden", true);
1754                            indicators[i].classList.remove("cmp-carousel__indicator--active");
1755                            indicators[i].setAttribute("aria-selected", false);
1756                            indicators[i].setAttribute("tabindex", "-1");
1757                        }
1758                    }
1759                } else {
1760                    // only one item
1761                    items.classList.add("cmp-carousel__item--active");
1762                    indicators.classList.add("cmp-carousel__indicator--active");
1763                }
1764            }
1765        }
1766
1767        /**
1768         * Focuses the element and prevents scrolling the element into view
1769         *
1770         * @param {HTMLElement} element Element to focus
1771         */
1772        function focusWithoutScroll(element) {
1773            var x = window.scrollX || window.pageXOffset;
1774            var y = window.scrollY || window.pageYOffset;
1775            element.focus();
1776            window.scrollTo(x, y);
1777        }
1778
1779        /**
1780         * Retrieves the next active index, with looping
1781         *
1782         * @private
1783         * @returns {Number} Index of the next carousel item
1784         */
1785        function getNextIndex() {
1786            return that._active === (that._elements["item"].length - 1) ? 0 : that._active + 1;
1787        }
1788
1789        /**
1790         * Retrieves the previous active index, with looping
1791         *
1792         * @private
1793         * @returns {Number} Index of the previous carousel item
1794         */
1795        function getPreviousIndex() {
1796            return that._active === 0 ? (that._elements["item"].length - 1) : that._active - 1;
1797        }
1798
1799        /**
1800         * Navigates to the item at the provided index
1801         *
1802         * @private
1803         * @param {Number} index The index of the item to navigate to
1804         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
1805         */
1806        function navigate(index, keepHash) {
1807            if (index < 0 || index > (that._elements["item"].length - 1)) {
1808                return;
1809            }
1810
1811            that._active = index;
1812            refreshActive();
1813
1814            if (!keepHash && containerUtils) {
1815                containerUtils.updateUrlHash(that, "item", index);
1816            }
1817
1818            if (dataLayerEnabled) {
1819                var carouselId = that._elements.self.id;
1820                var activeItem = getDataLayerId(that._elements.item[index]);
1821                var updatePayload = { component: {} };
1822                updatePayload.component[carouselId] = { shownItems: [activeItem] };
1823
1824                var removePayload = { component: {} };
1825                removePayload.component[carouselId] = { shownItems: undefined };
1826
1827                dataLayer.push(removePayload);
1828                dataLayer.push(updatePayload);
1829            }
1830
1831            // reset the autoplay transition interval following navigation, if not already hovering the carousel
1832            if (that._elements.self.parentElement) {
1833                if (that._elements.self.parentElement.querySelector(":hover") !== that._elements.self) {
1834                    resetAutoplayInterval();
1835                }
1836            }
1837        }
1838
1839        /**
1840         * Navigates to the item at the provided index and ensures the active indicator gains focus
1841         *
1842         * @private
1843         * @param {Number} index The index of the item to navigate to
1844         * @param {Boolean} keepHash true to keep the hash in the URL, false to update it
1845         */
1846        function navigateAndFocusIndicator(index, keepHash) {
1847            navigate(index, keepHash);
1848            focusWithoutScroll(that._elements["indicator"][index]);
1849
1850            if (dataLayerEnabled) {
1851                dataLayer.push({
1852                    event: "cmp:show",
1853                    eventInfo: {
1854                        path: "component." + getDataLayerId(that._elements.item[index])
1855                    }
1856                });
1857            }
1858        }
1859
1860        /**
1861         * Starts/resets automatic slide transition interval
1862         *
1863         * @private
1864         */
1865        function resetAutoplayInterval() {
1866            if (that._paused || !that._properties.autoplay) {
1867                return;
1868            }
1869            clearAutoplayInterval();
1870            that._autoplayIntervalId = window.setInterval(function() {
1871                if (document.visibilityState && document.hidden) {
1872                    return;
1873                }
1874                var indicators = that._elements["indicators"];
1875                if (indicators !== document.activeElement && indicators.contains(document.activeElement)) {
1876                    // if an indicator has focus, ensure we switch focus following navigation
1877                    navigateAndFocusIndicator(getNextIndex(), true);
1878                } else {
1879                    navigate(getNextIndex(), true);
1880                }
1881            }, that._properties.delay);
1882        }
1883
1884        /**
1885         * Clears/pauses automatic slide transition interval
1886         *
1887         * @private
1888         */
1889        function clearAutoplayInterval() {
1890            window.clearInterval(that._autoplayIntervalId);
1891            that._autoplayIntervalId = null;
1892        }
1893
1894        /**
1895         * Sets the disabled state for an action and toggles the appropriate CSS classes
1896         *
1897         * @private
1898         * @param {HTMLElement} action Action to disable
1899         * @param {Boolean} [disable] {@code true} to disable, {@code false} to enable
1900         */
1901        function setActionDisabled(action, disable) {
1902            if (!action) {
1903                return;
1904            }
1905            if (disable !== false) {
1906                action.disabled = true;
1907                action.classList.add("cmp-carousel__action--disabled");
1908            } else {
1909                action.disabled = false;
1910                action.classList.remove("cmp-carousel__action--disabled");
1911            }
1912        }
1913    }
1914
1915    /**
1916     * Parses the dataLayer string and returns the ID
1917     *
1918     * @private
1919     * @param {HTMLElement} item the accordion item
1920     * @returns {String} dataLayerId or undefined
1921     */
1922    function getDataLayerId(item) {
1923        if (item) {
1924            if (item.dataset.cmpDataLayer) {
1925                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
1926            } else {
1927                return item.id;
1928            }
1929        }
1930        return null;
1931    }
1932
1933    /**
1934     * Document ready handler and DOM mutation observers. Initializes Carousel components as necessary.
1935     *
1936     * @private
1937     */
1938    function onDocumentReady() {
1939        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
1940        if (dataLayerEnabled) {
1941            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
1942            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
1943        }
1944
1945        var elements = document.querySelectorAll(selectors.self);
1946        for (var i = 0; i < elements.length; i++) {
1947            new Carousel({ element: elements[i], options: CMP.utils.readData(elements[i], IS) });
1948        }
1949
1950        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
1951        var body = document.querySelector("body");
1952        var observer = new MutationObserver(function(mutations) {
1953            mutations.forEach(function(mutation) {
1954                // needed for IE
1955                var nodesArray = [].slice.call(mutation.addedNodes);
1956                if (nodesArray.length > 0) {
1957                    nodesArray.forEach(function(addedNode) {
1958                        if (addedNode.querySelectorAll) {
1959                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
1960                            elementsArray.forEach(function(element) {
1961                                new Carousel({ element: element, options: CMP.utils.readData(element, IS) });
1962                            });
1963                        }
1964                    });
1965                }
1966            });
1967        });
1968
1969        observer.observe(body, {
1970            subtree: true,
1971            childList: true,
1972            characterData: true
1973        });
1974    }
1975
1976    var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) {
1977        document.addEventListener("DOMContentLoaded", resolve);
1978    });
1979    Promise.all([documentReady]).then(onDocumentReady);
1980
1981    if (containerUtils) {
1982        window.addEventListener("load", containerUtils.scrollToAnchor, false);
1983    }
1984
1985}());
1986
1987
1988/*******************************************************************************
1989 * Copyright 2022 Adobe
1990 *
1991 * Licensed under the Apache License, Version 2.0 (the "License");
1992 * you may not use this file except in compliance with the License.
1993 * You may obtain a copy of the License at
1994 *
1995 *     http://www.apache.org/licenses/LICENSE-2.0
1996 *
1997 * Unless required by applicable law or agreed to in writing, software
1998 * distributed under the License is distributed on an "AS IS" BASIS,
1999 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2000 * See the License for the specific language governing permissions and
2001 * limitations under the License.
2002 ******************************************************************************/
2003(function(document) {
2004    "use strict";
2005
2006    window.CMP = window.CMP || {};
2007    window.CMP.utils = (function() {
2008        var NS = "cmp";
2009
2010        /**
2011         * Reads options data from the Component wrapper element, defined via {@code data-cmp-*} data attributes
2012         *
2013         * @param {HTMLElement} element The component element to read options data from
2014         * @param {String} is The component identifier
2015         * @returns {String[]} The options read from the component data attributes
2016         */
2017        var readData = function(element, is) {
2018            var data = element.dataset;
2019            var options = [];
2020            var capitalized = is;
2021            capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
2022            var reserved = ["is", "hook" + capitalized];
2023
2024            for (var key in data) {
2025                if (Object.prototype.hasOwnProperty.call(data, key)) {
2026                    var value = data[key];
2027
2028                    if (key.indexOf(NS) === 0) {
2029                        key = key.slice(NS.length);
2030                        key = key.charAt(0).toLowerCase() + key.substring(1);
2031
2032                        if (reserved.indexOf(key) === -1) {
2033                            options[key] = value;
2034                        }
2035                    }
2036                }
2037            }
2038            return options;
2039        };
2040
2041        /**
2042         * Set up the final properties of a component by evaluating the transform function or fall back to the default value on demand
2043         * @param {String[]} options the options to transform
2044         * @param {Object} properties object of properties of property functions
2045         * @returns {Object} transformed properties
2046         */
2047        var setupProperties = function(options, properties) {
2048            var transformedProperties = {};
2049
2050            for (var key in properties) {
2051                if (Object.prototype.hasOwnProperty.call(properties, key)) {
2052                    var property = properties[key];
2053                    if (options && options[key] != null) {
2054                        if (property && typeof property.transform === "function") {
2055                            transformedProperties[key] = property.transform(options[key]);
2056                        } else {
2057                            transformedProperties[key] = options[key];
2058                        }
2059                    } else {
2060                        transformedProperties[key] = properties[key]["default"];
2061                    }
2062                }
2063            }
2064            return transformedProperties;
2065        };
2066
2067
2068        return {
2069            readData: readData,
2070            setupProperties: setupProperties
2071        };
2072    }());
2073}(window.document));
2074
2075/*******************************************************************************
2076 * Copyright 2022 Adobe
2077 *
2078 * Licensed under the Apache License, Version 2.0 (the "License");
2079 * you may not use this file except in compliance with the License.
2080 * You may obtain a copy of the License at
2081 *
2082 *     http://www.apache.org/licenses/LICENSE-2.0
2083 *
2084 * Unless required by applicable law or agreed to in writing, software
2085 * distributed under the License is distributed on an "AS IS" BASIS,
2086 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2087 * See the License for the specific language governing permissions and
2088 * limitations under the License.
2089 ******************************************************************************/
2090(function(document) {
2091    "use strict";
2092
2093    window.CMP = window.CMP || {};
2094    window.CMP.image = window.CMP.image || {};
2095    window.CMP.image.dynamicMedia = (function() {
2096        var autoSmartCrops = {};
2097        var SRC_URI_TEMPLATE_WIDTH_VAR = "{.width}";
2098        var SRC_URI_TEMPLATE_DPR_VAR = "{dpr}";
2099        var SRC_URI_DPR_OFF = "dpr=off";
2100        var SRC_URI_DPR_ON = "dpr=on,{dpr}";
2101        var dpr = window.devicePixelRatio || 1;
2102        var config = {
2103            minWidth: 20
2104        };
2105
2106        /**
2107         * get auto smart crops from dm
2108         * @param {String} src the src uri
2109         * @returns {{}} the smart crop json object
2110         */
2111        var getAutoSmartCrops = function(src) {
2112            var request = new XMLHttpRequest();
2113            var url = src.split(SRC_URI_TEMPLATE_WIDTH_VAR)[0] + "?req=set,json";
2114            request.open("GET", url, false);
2115            request.onload = function() {
2116                if (request.status >= 200 && request.status < 400) {
2117                    // success status
2118                    var responseText = request.responseText;
2119                    var rePayload = new RegExp(/^(?:\/\*jsonp\*\/)?\s*([^()]+)\(([\s\S]+),\s*"[0-9]*"\);?$/gmi);
2120                    var rePayloadJSON = new RegExp(/^{[\s\S]*}$/gmi);
2121                    var resPayload = rePayload.exec(responseText);
2122                    var payload;
2123                    if (resPayload) {
2124                        var payloadStr = resPayload[2];
2125                        if (rePayloadJSON.test(payloadStr)) {
2126                            payload = JSON.parse(payloadStr);
2127                        }
2128
2129                    }
2130                    // check "relation" - only in case of smartcrop preset
2131                    if (payload && payload.set.relation && payload.set.relation.length > 0) {
2132                        for (var i = 0; i < payload.set.relation.length; i++) {
2133                            autoSmartCrops[parseInt(payload.set.relation[i].userdata.SmartCropWidth)] =
2134                                ":" + payload.set.relation[i].userdata.SmartCropDef;
2135                        }
2136                    }
2137                } else {
2138                    // error status
2139                }
2140            };
2141            request.send();
2142            return autoSmartCrops;
2143        };
2144
2145        /**
2146         * Build and return the srcset value based on the available auto smart crops
2147         * @param {String} src the src uri
2148         * @param {Object} smartCrops the smart crops object
2149         * @returns {String} the srcset
2150         */
2151        var getSrcSet = function(src, smartCrops) {
2152            var srcset;
2153            var keys = Object.keys(smartCrops);
2154            if (keys.length > 0) {
2155                srcset = [];
2156                for (var key in autoSmartCrops) {
2157                    srcset.push(src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, smartCrops[key]) + " " + key + "w");
2158                }
2159            }
2160            return  srcset.join(",");
2161        };
2162
2163        /**
2164         * Get the optimal width based on the available sizes
2165         * @param {[Number]} sizes the available sizes
2166         * @param {Number} width the element width
2167         * @returns {String} the optimal width
2168         */
2169        function getOptimalWidth(sizes, width) {
2170            var len = sizes.length;
2171            var key = 0;
2172
2173            while ((key < len - 1) && (sizes[key] < width)) {
2174                key++;
2175            }
2176
2177            return sizes[key] !== undefined ? sizes[key].toString() : width;
2178        }
2179
2180        /**
2181         * Get the width of an element or parent element if the width is smaller than the minimum width
2182         * @param {HTMLElement} component the image component
2183         * @param {HTMLElement | Node} parent the parent element
2184         * @returns {Number} the width of the element
2185         */
2186        var getWidth = function(component, parent) {
2187            var width = component.offsetWidth;
2188            while (width < config.minWidth && parent && !component._autoWidth) {
2189                width =  parent.offsetWidth;
2190                parent = parent.parentNode;
2191            }
2192            return width;
2193        };
2194
2195        /**
2196         * Set the src and srcset attribute for a Dynamic Media Image which auto smart crops enabled.
2197         * @param {HTMLElement} component the image component
2198         * @param {{}} properties the component properties
2199         */
2200        var setDMAttributes = function(component, properties) {
2201            // for v3 we first have to turn the dpr on
2202            var src = properties.src.replace(SRC_URI_DPR_OFF, SRC_URI_DPR_ON);
2203            src = src.replace(SRC_URI_TEMPLATE_DPR_VAR, dpr);
2204            var smartCrops = {};
2205            var width;
2206            if (properties["smartcroprendition"] === "SmartCrop:Auto") {
2207                smartCrops = getAutoSmartCrops(src);
2208            }
2209            var hasWidths = (properties.widths && properties.widths.length > 0) || Object.keys(smartCrops).length > 0;
2210            if (hasWidths) {
2211                var image = component.querySelector("img");
2212                var elemWidth = getWidth(component, component.parentNode);
2213                if (properties["smartcroprendition"] === "SmartCrop:Auto") {
2214                    image.setAttribute("srcset", CMP.image.dynamicMedia.getSrcSet(src, smartCrops));
2215                    width = getOptimalWidth(Object.keys(smartCrops, elemWidth));
2216                    image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, smartCrops[width]));
2217                } else {
2218                    width = getOptimalWidth(properties.widths, elemWidth);
2219                    image.setAttribute("src", CMP.image.dynamicMedia.getSrc(src, width));
2220                }
2221            }
2222        };
2223
2224        /**
2225         * Get the src attribute based on the optimal width
2226         * @param {String} src the src uri
2227         * @param {String} width the element width
2228         * @returns {String} the final src attribute
2229         */
2230        var getSrc = function(src, width) {
2231            if (src.indexOf(SRC_URI_TEMPLATE_WIDTH_VAR) > -1) {
2232                src = src.replace(SRC_URI_TEMPLATE_WIDTH_VAR, width);
2233            }
2234            return src;
2235        };
2236
2237
2238        return {
2239            getAutoSmartCrops: getAutoSmartCrops,
2240            getSrcSet: getSrcSet,
2241            getSrc: getSrc,
2242            setDMAttributes: setDMAttributes,
2243            getWidth: getWidth
2244        };
2245    }());
2246    document.dispatchEvent(new CustomEvent("core.wcm.components.commons.site.image.dynamic-media.loaded"));
2247}(window.document));
2248
2249/*******************************************************************************
2250 * Copyright 2022 Adobe
2251 *
2252 * Licensed under the Apache License, Version 2.0 (the "License");
2253 * you may not use this file except in compliance with the License.
2254 * You may obtain a copy of the License at
2255 *
2256 *     http://www.apache.org/licenses/LICENSE-2.0
2257 *
2258 * Unless required by applicable law or agreed to in writing, software
2259 * distributed under the License is distributed on an "AS IS" BASIS,
2260 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2261 * See the License for the specific language governing permissions and
2262 * limitations under the License.
2263 ******************************************************************************/
2264(function(document) {
2265
2266    "use strict";
2267
2268    window.CMP = window.CMP || {};
2269    window.CMP.image = window.CMP.image || {};
2270    window.CMP.image.v3 = (function() {
2271        var IS = "image";
2272
2273        var selectors = {
2274            self: "[data-cmp-hook-image='imageV3']"
2275        };
2276
2277        var properties = {
2278            "widths": {
2279                "default": [],
2280                "transform": function(value) {
2281                    var widths = [];
2282                    value.split(",").forEach(function(item) {
2283                        item = parseFloat(item);
2284                        if (!isNaN(item)) {
2285                            widths.push(item);
2286                        }
2287                    });
2288                    return widths;
2289                }
2290            },
2291            "dmimage": {
2292                "default": false,
2293                "transform": function(value) {
2294                    return !(value === null || typeof value === "undefined");
2295                }
2296            },
2297            "src": {
2298                "transform": function(value) {
2299                    return decodeURIComponent(value);
2300                }
2301            },
2302            "smartcroprendition": ""
2303        };
2304
2305        function Image(config) {
2306            var that = this;
2307            /**
2308             * Init the image if the image is from dynamic media
2309             * @param {HTMLElement} component the image component
2310             */
2311            that.initImage = function(component) {
2312                var options = CMP.utils.readData(component, IS);
2313                that._properties = CMP.utils.setupProperties(options, properties);
2314                if (that._properties.dmimage) {
2315                    // use encoded src for dynamic media
2316                    that._properties.src = options["src"];
2317                    CMP.image.dynamicMedia.setDMAttributes(component, that._properties);
2318                }
2319            };
2320            that.initImage(config.element);
2321        }
2322
2323        return {
2324            init: function() {
2325                var elements = document.querySelectorAll(selectors.self);
2326                for (var i = 0; i < elements.length; i++) {
2327                    new Image({ element: elements[i], options: CMP.utils.readData(elements[i], IS) });
2328                }
2329
2330                var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
2331                var body             = document.querySelector("body");
2332                var observer         = new MutationObserver(function(mutations) {
2333                    mutations.forEach(function(mutation) {
2334                        // needed for IE
2335                        var nodesArray = [].slice.call(mutation.addedNodes);
2336                        if (nodesArray.length > 0) {
2337                            nodesArray.forEach(function(addedNode) {
2338                                if (addedNode.querySelectorAll) {
2339                                    var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
2340                                    elementsArray.forEach(function(element) {
2341                                        new Image({ element: element, options: CMP.utils.readData(element, IS) });
2342                                    });
2343                                }
2344                            });
2345                        }
2346                    });
2347                });
2348
2349                observer.observe(body, {
2350                    subtree: true,
2351                    childList: true,
2352                    characterData: true
2353                });
2354            }
2355        };
2356    }());
2357
2358    var documentReady = document.readyState !== "loading" ? Promise.resolve() : new Promise(function(resolve) {
2359        document.addEventListener("DOMContentLoaded", resolve);
2360    });
2361    Promise.all([documentReady]).then(window.CMP.image.v3.init);
2362}(window.document));
2363
2364
2365/*******************************************************************************
2366 * Copyright 2022 Adobe
2367 *
2368 * Licensed under the Apache License, Version 2.0 (the "License");
2369 * you may not use this file except in compliance with the License.
2370 * You may obtain a copy of the License at
2371 *
2372 *     http://www.apache.org/licenses/LICENSE-2.0
2373 *
2374 * Unless required by applicable law or agreed to in writing, software
2375 * distributed under the License is distributed on an "AS IS" BASIS,
2376 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2377 * See the License for the specific language governing permissions and
2378 * limitations under the License.
2379 ******************************************************************************/
2380(function() {
2381    "use strict";
2382
2383    var NS = "cmp";
2384    var IS = "search";
2385
2386    var DELAY = 300; // time before fetching new results when the user is typing a search string
2387    var LOADING_DISPLAY_DELAY = 300; // minimum time during which the loading indicator is displayed
2388    var PARAM_RESULTS_OFFSET = "resultsOffset";
2389
2390    var keyCodes = {
2391        TAB: 9,
2392        ENTER: 13,
2393        ESCAPE: 27,
2394        ARROW_UP: 38,
2395        ARROW_DOWN: 40
2396    };
2397
2398    var selectors = {
2399        self: "[data-" + NS + '-is="' + IS + '"]',
2400        item: {
2401            self: "[data-" + NS + "-hook-" + IS + '="item"]',
2402            title: "[data-" + NS + "-hook-" + IS + '="itemTitle"]',
2403            focused: "." + NS + "-search__item--is-focused"
2404        }
2405    };
2406
2407    var properties = {
2408        /**
2409         * The minimum required length of the search term before results are fetched.
2410         *
2411         * @memberof Search
2412         * @type {Number}
2413         * @default 3
2414         */
2415        minLength: {
2416            "default": 3,
2417            transform: function(value) {
2418                value = parseFloat(value);
2419                return isNaN(value) ? null : value;
2420            }
2421        },
2422        /**
2423         * The maximal number of results fetched by a search request.
2424         *
2425         * @memberof Search
2426         * @type {Number}
2427         * @default 10
2428         */
2429        resultsSize: {
2430            "default": 10,
2431            transform: function(value) {
2432                value = parseFloat(value);
2433                return isNaN(value) ? null : value;
2434            }
2435        }
2436    };
2437
2438    var idCount = 0;
2439
2440    function readData(element) {
2441        var data = element.dataset;
2442        var options = [];
2443        var capitalized = IS;
2444        capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
2445        var reserved = ["is", "hook" + capitalized];
2446
2447        for (var key in data) {
2448            if (Object.prototype.hasOwnProperty.call(data, key)) {
2449                var value = data[key];
2450
2451                if (key.indexOf(NS) === 0) {
2452                    key = key.slice(NS.length);
2453                    key = key.charAt(0).toLowerCase() + key.substring(1);
2454
2455                    if (reserved.indexOf(key) === -1) {
2456                        options[key] = value;
2457                    }
2458                }
2459            }
2460        }
2461
2462        return options;
2463    }
2464
2465    function toggleShow(element, show) {
2466        if (element) {
2467            if (show !== false) {
2468                element.style.display = "block";
2469                element.setAttribute("aria-hidden", false);
2470            } else {
2471                element.style.display = "none";
2472                element.setAttribute("aria-hidden", true);
2473            }
2474        }
2475    }
2476
2477    function serialize(form) {
2478        var query = [];
2479        if (form && form.elements) {
2480            for (var i = 0; i < form.elements.length; i++) {
2481                var node = form.elements[i];
2482                if (!node.disabled && node.name) {
2483                    var param = [node.name, encodeURIComponent(node.value)];
2484                    query.push(param.join("="));
2485                }
2486            }
2487        }
2488        return query.join("&");
2489    }
2490
2491    function mark(node, regex) {
2492        if (!node || !regex) {
2493            return;
2494        }
2495
2496        // text nodes
2497        if (node.nodeType === 3) {
2498            var nodeValue = node.nodeValue;
2499            var match = regex.exec(nodeValue);
2500
2501            if (nodeValue && match) {
2502                var element = document.createElement("mark");
2503                element.className = NS + "-search__item-mark";
2504                element.appendChild(document.createTextNode(match[0]));
2505
2506                var after = node.splitText(match.index);
2507                after.nodeValue = after.nodeValue.substring(match[0].length);
2508                node.parentNode.insertBefore(element, after);
2509            }
2510        } else if (node.hasChildNodes()) {
2511            for (var i = 0; i < node.childNodes.length; i++) {
2512                // recurse
2513                mark(node.childNodes[i], regex);
2514            }
2515        }
2516    }
2517
2518    function localizeMessage(searchElementId, message, values = []) {
2519        const i18nMessages = JSON.parse(document.querySelector("#" + searchElementId).getAttribute("data-i18n-messages"));
2520        let translation = i18nMessages[message];
2521        // Insert values
2522        if (values.length > 0) {
2523            translation = translation.replace(/{(\d+)}/g, function(match, index) {
2524                return typeof values[index] !== "undefined" ? values[index] : match;
2525            });
2526        }
2527        return translation;
2528    }
2529
2530    // useful for Accessibility, helping users with low vision and users with cognitive disabilities to identify the change in results
2531    function updateSearchResultsStatusMessageElement(searchElementId, totalResults) {
2532        var searchResultsStatusMessage = document.querySelector("#" + searchElementId + "> .cmp_search__info");
2533        searchResultsStatusMessage.style.visibility = "visible";
2534        var searchResultsFoundMessage = localizeMessage(searchElementId, totalResults === 1 ? "{0} result" : "{0} results", [totalResults]);
2535        var searchResultsNotFoundMessage = localizeMessage(searchElementId, "No results");
2536        searchResultsStatusMessage.innerText = totalResults > 0 ? searchResultsFoundMessage : searchResultsNotFoundMessage;
2537    }
2538
2539    function Search(config) {
2540        if (config.element) {
2541            // prevents multiple initialization
2542            config.element.removeAttribute("data-" + NS + "-is");
2543        }
2544
2545        this._cacheElements(config.element);
2546        this._setupProperties(config.options);
2547
2548        this._action = this._elements.form.getAttribute("action");
2549        this._resultsOffset = 0;
2550        this._hasMoreResults = true;
2551
2552        this._elements.input.addEventListener("input", this._onInput.bind(this));
2553        this._elements.input.addEventListener("focus", this._onInput.bind(this));
2554        this._elements.input.addEventListener("keydown", this._onKeydown.bind(this));
2555        this._elements.clear.addEventListener("click", this._onClearClick.bind(this));
2556        document.addEventListener("click", this._onDocumentClick.bind(this));
2557        this._elements.results.addEventListener("scroll", this._onScroll.bind(this));
2558
2559        this._makeAccessible();
2560    }
2561
2562    Search.prototype._displayResults = function() {
2563        if (this._elements.input.value.length === 0) {
2564            toggleShow(this._elements.clear, false);
2565            this._cancelResults();
2566        } else if (this._elements.input.value.length < this._properties.minLength) {
2567            toggleShow(this._elements.clear, true);
2568        } else {
2569            this._updateResults();
2570            toggleShow(this._elements.clear, true);
2571        }
2572    };
2573
2574    Search.prototype._onScroll = function(event) {
2575        // fetch new results when the results to be scrolled down are less than the visible results
2576        if (this._elements.results.scrollTop + 2 * this._elements.results.clientHeight >= this._elements.results.scrollHeight) {
2577            this._resultsOffset += this._properties.resultsSize;
2578            this._displayResults();
2579        }
2580    };
2581
2582    Search.prototype._onInput = function(event) {
2583        var self = this;
2584        self._cancelResults();
2585        // start searching when the search term reaches the minimum length
2586        this._timeout = setTimeout(function() {
2587            self._displayResults();
2588        }, DELAY);
2589    };
2590
2591    Search.prototype._onKeydown = function(event) {
2592        var self = this;
2593
2594        switch (event.keyCode) {
2595            case keyCodes.TAB:
2596                if (self._resultsOpen()) {
2597                    toggleShow(self._elements.results, false);
2598                    self._elements.input.setAttribute("aria-expanded", "false");
2599                    this._hideSearchResultsStatusMessage();
2600                }
2601                break;
2602            case keyCodes.ENTER:
2603                event.preventDefault();
2604                if (self._resultsOpen()) {
2605                    var focused = self._elements.results.querySelector(selectors.item.focused);
2606                    if (focused) {
2607                        focused.click();
2608                    }
2609                }
2610                break;
2611            case keyCodes.ESCAPE:
2612                self._cancelResults();
2613                break;
2614            case keyCodes.ARROW_UP:
2615                if (self._resultsOpen()) {
2616                    event.preventDefault();
2617                    self._stepResultFocus(true);
2618                }
2619                break;
2620            case keyCodes.ARROW_DOWN:
2621                if (self._resultsOpen()) {
2622                    event.preventDefault();
2623                    self._stepResultFocus();
2624                } else {
2625                    // test the input and if necessary fetch and display the results
2626                    self._onInput();
2627                }
2628                break;
2629            default:
2630                return;
2631        }
2632    };
2633
2634    Search.prototype._onClearClick = function(event) {
2635        event.preventDefault();
2636        this._elements.input.value = "";
2637        toggleShow(this._elements.clear, false);
2638        toggleShow(this._elements.results, false);
2639        this._elements.input.setAttribute("aria-expanded", "false");
2640        this._hideSearchResultsStatusMessage();
2641    };
2642
2643    Search.prototype._onDocumentClick = function(event) {
2644        var inputContainsTarget =  this._elements.input.contains(event.target);
2645        var resultsContainTarget = this._elements.results.contains(event.target);
2646
2647        if (!(inputContainsTarget || resultsContainTarget)) {
2648            toggleShow(this._elements.results, false);
2649            this._elements.input.setAttribute("aria-expanded", "false");
2650            this._hideSearchResultsStatusMessage();
2651        }
2652    };
2653
2654    Search.prototype._resultsOpen = function() {
2655        return this._elements.results.style.display !== "none";
2656    };
2657
2658    Search.prototype._makeAccessible = function() {
2659        var id = NS + "-search-results-" + idCount;
2660        this._elements.input.setAttribute("aria-owns", id);
2661        this._elements.results.id = id;
2662        idCount++;
2663    };
2664
2665    Search.prototype._generateItems = function(data, results) {
2666        var self = this;
2667
2668        data.forEach(function(item) {
2669            var el = document.createElement("span");
2670            el.innerHTML = self._elements.itemTemplate.innerHTML;
2671            el.querySelectorAll(selectors.item.title)[0].appendChild(document.createTextNode(item.title));
2672            el.querySelectorAll(selectors.item.self)[0].setAttribute("href", self._safeHref(item.url));
2673            results.innerHTML += el.innerHTML;
2674        });
2675    };
2676
2677    Search.prototype._safeHref = function(href) {
2678        var a = document.createElement("a");
2679        a.href = href;
2680        return a.pathname;
2681    };
2682
2683    Search.prototype._markResults = function() {
2684        var nodeList = this._elements.results.querySelectorAll(selectors.item.self);
2685        var escapedTerm = this._elements.input.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
2686        var regex = new RegExp("(" + escapedTerm + ")", "gi");
2687
2688        for (var i = this._resultsOffset - 1; i < nodeList.length; ++i) {
2689            var result = nodeList[i];
2690            mark(result, regex);
2691        }
2692    };
2693
2694    Search.prototype._stepResultFocus = function(reverse) {
2695        var results = this._elements.results.querySelectorAll(selectors.item.self);
2696        var focused = this._elements.results.querySelector(selectors.item.focused);
2697        var newFocused;
2698        var index = Array.prototype.indexOf.call(results, focused);
2699        var focusedCssClass = NS + "-search__item--is-focused";
2700
2701        if (results.length > 0) {
2702
2703            if (!reverse) {
2704                // highlight the next result
2705                if (index < 0) {
2706                    results[0].classList.add(focusedCssClass);
2707                    results[0].setAttribute("aria-selected", "true");
2708                } else if (index + 1 < results.length) {
2709                    results[index].classList.remove(focusedCssClass);
2710                    results[index].setAttribute("aria-selected", "false");
2711                    results[index + 1].classList.add(focusedCssClass);
2712                    results[index + 1].setAttribute("aria-selected", "true");
2713                }
2714
2715                // if the last visible result is partially hidden, scroll up until it's completely visible
2716                newFocused = this._elements.results.querySelector(selectors.item.focused);
2717                if (newFocused) {
2718                    var bottomHiddenHeight = newFocused.offsetTop + newFocused.offsetHeight - this._elements.results.scrollTop - this._elements.results.clientHeight;
2719                    if (bottomHiddenHeight > 0) {
2720                        this._elements.results.scrollTop += bottomHiddenHeight;
2721                    } else {
2722                        this._onScroll();
2723                    }
2724                }
2725
2726            } else {
2727                // highlight the previous result
2728                if (index >= 1) {
2729                    results[index].classList.remove(focusedCssClass);
2730                    results[index].setAttribute("aria-selected", "false");
2731                    results[index - 1].classList.add(focusedCssClass);
2732                    results[index - 1].setAttribute("aria-selected", "true");
2733                }
2734
2735                // if the first visible result is partially hidden, scroll down until it's completely visible
2736                newFocused = this._elements.results.querySelector(selectors.item.focused);
2737                if (newFocused) {
2738                    var topHiddenHeight = this._elements.results.scrollTop - newFocused.offsetTop;
2739                    if (topHiddenHeight > 0) {
2740                        this._elements.results.scrollTop -= topHiddenHeight;
2741                    }
2742                }
2743            }
2744        }
2745    };
2746
2747    Search.prototype._updateResults = function() {
2748        var self = this;
2749        if (self._hasMoreResults) {
2750            var request = new XMLHttpRequest();
2751            var url = self._action + "?" + serialize(self._elements.form) + "&" + PARAM_RESULTS_OFFSET + "=" + self._resultsOffset;
2752
2753            request.open("GET", url, true);
2754            request.onload = function() {
2755                // when the results are loaded: hide the loading indicator and display the search icon after a minimum period
2756                setTimeout(function() {
2757                    toggleShow(self._elements.loadingIndicator, false);
2758                    toggleShow(self._elements.icon, true);
2759                }, LOADING_DISPLAY_DELAY);
2760                if (request.status >= 200 && request.status < 400) {
2761                    // success status
2762                    var data = JSON.parse(request.responseText);
2763                    updateSearchResultsStatusMessageElement(self._elements.self.id, data.length);
2764                    if (data.length > 0) {
2765                        self._generateItems(data, self._elements.results);
2766                        self._markResults();
2767                        toggleShow(self._elements.results, true);
2768                        self._elements.input.setAttribute("aria-expanded", "true");
2769                    } else {
2770                        self._hasMoreResults = false;
2771                    }
2772                    // the total number of results is not a multiple of the fetched results:
2773                    // -> we reached the end of the query
2774                    if (self._elements.results.querySelectorAll(selectors.item.self).length % self._properties.resultsSize > 0) {
2775                        self._hasMoreResults = false;
2776                    }
2777                } else {
2778                    // error status
2779                }
2780            };
2781            // when the results are loading: display the loading indicator and hide the search icon
2782            toggleShow(self._elements.loadingIndicator, true);
2783            toggleShow(self._elements.icon, false);
2784            request.send();
2785        }
2786    };
2787
2788    Search.prototype._cancelResults = function() {
2789        clearTimeout(this._timeout);
2790        this._elements.results.scrollTop = 0;
2791        this._resultsOffset = 0;
2792        this._hasMoreResults = true;
2793        this._elements.results.innerHTML = "";
2794        this._elements.input.setAttribute("aria-expanded", "false");
2795        this._hideSearchResultsStatusMessage();
2796    };
2797
2798    Search.prototype._hideSearchResultsStatusMessage = function() {
2799        var searchResultsStatusMessage = document.querySelector("#" + this._elements.self.id + "> .cmp_search__info");
2800        searchResultsStatusMessage.style.visibility = "hidden";
2801    };
2802
2803    Search.prototype._cacheElements = function(wrapper) {
2804        this._elements = {};
2805        this._elements.self = wrapper;
2806        var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS + "]");
2807
2808        for (var i = 0; i < hooks.length; i++) {
2809            var hook = hooks[i];
2810            var capitalized = IS;
2811            capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
2812            var key = hook.dataset[NS + "Hook" + capitalized];
2813            this._elements[key] = hook;
2814        }
2815    };
2816
2817    Search.prototype._setupProperties = function(options) {
2818        this._properties = {};
2819
2820        for (var key in properties) {
2821            if (Object.prototype.hasOwnProperty.call(properties, key)) {
2822                var property = properties[key];
2823                if (options && options[key] != null) {
2824                    if (property && typeof property.transform === "function") {
2825                        this._properties[key] = property.transform(options[key]);
2826                    } else {
2827                        this._properties[key] = options[key];
2828                    }
2829                } else {
2830                    this._properties[key] = properties[key]["default"];
2831                }
2832            }
2833        }
2834    };
2835
2836    function onDocumentReady() {
2837        var elements = document.querySelectorAll(selectors.self);
2838        for (var i = 0; i < elements.length; i++) {
2839            new Search({ element: elements[i], options: readData(elements[i]) });
2840        }
2841
2842        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
2843        var body = document.querySelector("body");
2844        var observer = new MutationObserver(function(mutations) {
2845            mutations.forEach(function(mutation) {
2846                // needed for IE
2847                var nodesArray = [].slice.call(mutation.addedNodes);
2848                if (nodesArray.length > 0) {
2849                    nodesArray.forEach(function(addedNode) {
2850                        if (addedNode.querySelectorAll) {
2851                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
2852                            elementsArray.forEach(function(element) {
2853                                new Search({ element: element, options: readData(element) });
2854                            });
2855                        }
2856                    });
2857                }
2858            });
2859        });
2860
2861        observer.observe(body, {
2862            subtree: true,
2863            childList: true,
2864            characterData: true
2865        });
2866    }
2867
2868    if (document.readyState !== "loading") {
2869        onDocumentReady();
2870    } else {
2871        document.addEventListener("DOMContentLoaded", onDocumentReady);
2872    }
2873
2874})();
2875
2876
2877/*******************************************************************************
2878 * Copyright 2016 Adobe
2879 *
2880 * Licensed under the Apache License, Version 2.0 (the "License");
2881 * you may not use this file except in compliance with the License.
2882 * You may obtain a copy of the License at
2883 *
2884 *     http://www.apache.org/licenses/LICENSE-2.0
2885 *
2886 * Unless required by applicable law or agreed to in writing, software
2887 * distributed under the License is distributed on an "AS IS" BASIS,
2888 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2889 * See the License for the specific language governing permissions and
2890 * limitations under the License.
2891 ******************************************************************************/
2892(function() {
2893    "use strict";
2894
2895    var NS = "cmp";
2896    var IS = "formText";
2897    var IS_DASH = "form-text";
2898    var SELF_SELECTOR = "[data-" + NS + '-is="' + IS + '"]';
2899
2900    var selectors = {
2901        self: SELF_SELECTOR,
2902        validationMessage: SELF_SELECTOR + " .cmp-form-text__validation-message"
2903    };
2904
2905    var displayValidationMessage = false;
2906
2907    var properties = {
2908        /**
2909         * A validation message to display if there is a type mismatch between the user input and expected input.
2910         *
2911         * @type {String}
2912         */
2913        constraintMessage: "",
2914        /**
2915         * A validation message to display if no input is supplied, but input is expected for the field.
2916         *
2917         * @type {String}
2918         */
2919        requiredMessage: ""
2920    };
2921
2922    function readData(element) {
2923        var data = element.dataset;
2924        var options = [];
2925        var capitalized = IS;
2926        capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
2927        var reserved = ["is", "hook" + capitalized];
2928
2929        for (var key in data) {
2930            if (Object.prototype.hasOwnProperty.call(data, key)) {
2931                var value = data[key];
2932
2933                if (key.indexOf(NS) === 0) {
2934                    key = key.slice(NS.length);
2935                    key = key.charAt(0).toLowerCase() + key.substring(1);
2936
2937                    if (reserved.indexOf(key) === -1) {
2938                        options[key] = value;
2939                    }
2940                }
2941            }
2942        }
2943
2944        return options;
2945    }
2946
2947    function FormText(config) {
2948        if (config.element) {
2949            // prevents multiple initialization
2950            config.element.removeAttribute("data-" + NS + "-is");
2951        }
2952
2953        this._cacheElements(config.element);
2954        this._setupProperties(config.options);
2955
2956        this._elements.input.addEventListener("invalid", this._onInvalid.bind(this));
2957        this._elements.input.addEventListener("input", this._onInput.bind(this));
2958        if (displayValidationMessage) {
2959            this._elements.input.checkValidity();
2960        }
2961    }
2962
2963    FormText.prototype._onInvalid = function(event) {
2964        event.target.setCustomValidity("");
2965        if (event.target.validity.typeMismatch) {
2966            if (this._properties.constraintMessage) {
2967                event.target.setCustomValidity(this._properties.constraintMessage);
2968            }
2969        } else if (event.target.validity.valueMissing) {
2970            if (this._properties.requiredMessage) {
2971                event.target.setCustomValidity(this._properties.requiredMessage);
2972            }
2973        }
2974        if (displayValidationMessage) {
2975            var validationMessage = event.target.parentElement.querySelector(".cmp-form-text__validation-message");
2976            if (validationMessage) {
2977                validationMessage.innerText = event.target.validationMessage;
2978            }
2979        }
2980    };
2981
2982    FormText.prototype._onInput = function(event) {
2983        event.target.setCustomValidity("");
2984        if (displayValidationMessage) {
2985            event.target.checkValidity();
2986        }
2987    };
2988
2989    FormText.prototype._cacheElements = function(wrapper) {
2990        this._elements = {};
2991        this._elements.self = wrapper;
2992        var hooks = this._elements.self.querySelectorAll("[data-" + NS + "-hook-" + IS_DASH + "]");
2993        for (var i = 0; i < hooks.length; i++) {
2994            var hook = hooks[i];
2995            var capitalized = IS;
2996            capitalized = capitalized.charAt(0).toUpperCase() + capitalized.slice(1);
2997            var key = hook.dataset[NS + "Hook" + capitalized];
2998            this._elements[key] = hook;
2999        }
3000    };
3001
3002    FormText.prototype._setupProperties = function(options) {
3003        this._properties = {};
3004
3005        for (var key in properties) {
3006            if (Object.prototype.hasOwnProperty.call(properties, key)) {
3007                var property = properties[key];
3008                if (options && options[key] != null) {
3009                    if (property && typeof property.transform === "function") {
3010                        this._properties[key] = property.transform(options[key]);
3011                    } else {
3012                        this._properties[key] = options[key];
3013                    }
3014                } else {
3015                    this._properties[key] = properties[key]["default"];
3016                }
3017            }
3018        }
3019    };
3020
3021    function onDocumentReady() {
3022        var validationMessages = document.querySelectorAll(selectors.validationMessage);
3023        if (validationMessages && validationMessages.length > 0) {
3024            displayValidationMessage = true;
3025        }
3026
3027        var elements = document.querySelectorAll(selectors.self);
3028        for (var i = 0; i < elements.length; i++) {
3029            new FormText({ element: elements[i], options: readData(elements[i]) });
3030        }
3031
3032        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
3033        var body = document.querySelector("body");
3034        var observer = new MutationObserver(function(mutations) {
3035            mutations.forEach(function(mutation) {
3036                // needed for IE
3037                var nodesArray = [].slice.call(mutation.addedNodes);
3038                if (nodesArray.length > 0) {
3039                    nodesArray.forEach(function(addedNode) {
3040                        if (addedNode.querySelectorAll) {
3041                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
3042                            elementsArray.forEach(function(element) {
3043                                new FormText({ element: element, options: readData(element) });
3044                            });
3045                        }
3046                    });
3047                }
3048            });
3049        });
3050
3051        observer.observe(body, {
3052            subtree: true,
3053            childList: true,
3054            characterData: true
3055        });
3056    }
3057
3058    if (document.readyState !== "loading") {
3059        onDocumentReady();
3060    } else {
3061        document.addEventListener("DOMContentLoaded", onDocumentReady);
3062    }
3063
3064})();
3065
3066
3067/*******************************************************************************
3068 * Copyright 2020 Adobe
3069 *
3070 * Licensed under the Apache License, Version 2.0 (the "License");
3071 * you may not use this file except in compliance with the License.
3072 * You may obtain a copy of the License at
3073 *
3074 *     http://www.apache.org/licenses/LICENSE-2.0
3075 *
3076 * Unless required by applicable law or agreed to in writing, software
3077 * distributed under the License is distributed on an "AS IS" BASIS,
3078 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3079 * See the License for the specific language governing permissions and
3080 * limitations under the License.
3081 ******************************************************************************/
3082(function() {
3083    "use strict";
3084
3085    var NS = "cmp";
3086    var IS = "pdfviewer";
3087    var SDK_URL = "https://acrobatservices.adobe.com/view-sdk/viewer.js";
3088    var SDK_READY_EVENT = "adobe_dc_view_sdk.ready";
3089
3090    var selectors = {
3091        self: "[data-" + NS + '-is="' + IS + '"]',
3092        sdkScript: 'script[src="' + SDK_URL + '"]'
3093    };
3094
3095    function initSDK() {
3096        var sdkIncluded = document.querySelectorAll(selectors.sdkScript).length > 0;
3097        if (!window.adobe_dc_view_sdk && !sdkIncluded) {
3098            var dcv = document.createElement("script");
3099            dcv.type = "text/javascript";
3100            dcv.src = SDK_URL;
3101            document.body.appendChild(dcv);
3102        }
3103    }
3104
3105    function previewPdf(component) {
3106        // prevents multiple initialization
3107        component.removeAttribute("data-" + NS + "-is");
3108
3109        // add the view sdk to the page
3110        initSDK();
3111
3112        // manage the preview
3113        if (component.dataset && component.id) {
3114            if (window.AdobeDC && window.AdobeDC.View) {
3115                dcView(component);
3116            } else {
3117                document.addEventListener(SDK_READY_EVENT, function() {
3118                    dcView(component);
3119                });
3120            }
3121        }
3122    }
3123
3124    function dcView(component) {
3125        var adobeDCView = new window.AdobeDC.View({
3126            clientId: component.dataset.cmpClientId,
3127            divId: component.id + "-content",
3128            reportSuiteId: component.dataset.cmpReportSuiteId,
3129            locale: typeof Granite !== "undefined" && Granite && Granite.I18n ? Granite.I18n.getLocale() : navigator.language || navigator.userLanguage
3130        });
3131        adobeDCView.previewFile({
3132            content: { location: { url: component.dataset.cmpDocumentPath } },
3133            metaData: { fileName: component.dataset.cmpDocumentFileName }
3134        }, JSON.parse(component.dataset.cmpViewerConfigJson));
3135    }
3136
3137    /**
3138     * Document ready handler and DOM mutation observers. Initializes Accordion components as necessary.
3139     *
3140     * @private
3141     */
3142    function onDocumentReady() {
3143        var elements = document.querySelectorAll(selectors.self);
3144        for (var i = 0; i < elements.length; i++) {
3145            previewPdf(elements[i]);
3146        }
3147
3148        var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
3149        var body = document.querySelector("body");
3150        var observer = new MutationObserver(function(mutations) {
3151            mutations.forEach(function(mutation) {
3152                // needed for IE
3153                var nodesArray = [].slice.call(mutation.addedNodes);
3154                if (nodesArray.length > 0) {
3155                    nodesArray.forEach(function(addedNode) {
3156                        if (addedNode.querySelectorAll) {
3157                            var elementsArray = [].slice.call(addedNode.querySelectorAll(selectors.self));
3158                            elementsArray.forEach(function(element) {
3159                                previewPdf(element);
3160                            });
3161                        }
3162                    });
3163                }
3164            });
3165        });
3166
3167        observer.observe(body, {
3168            subtree: true,
3169            childList: true,
3170            characterData: true
3171        });
3172
3173    }
3174
3175    if (document.readyState !== "loading") {
3176        onDocumentReady();
3177    } else {
3178        document.addEventListener("DOMContentLoaded", onDocumentReady);
3179    }
3180}());
3181
3182
3183
3184/*******************************************************************************
3185 * Copyright 2022 Adobe
3186 *
3187 * Licensed under the Apache License, Version 2.0 (the "License");
3188 * you may not use this file except in compliance with the License.
3189 * You may obtain a copy of the License at
3190 *
3191 *     http://www.apache.org/licenses/LICENSE-2.0
3192 *
3193 * Unless required by applicable law or agreed to in writing, software
3194 * distributed under the License is distributed on an "AS IS" BASIS,
3195 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3196 * See the License for the specific language governing permissions and
3197 * limitations under the License.
3198 ******************************************************************************/
3199(function() {
3200    "use strict";
3201
3202    var dataLayerEnabled;
3203    var dataLayer;
3204    var dataLayerName;
3205
3206    /**
3207     * Adds Click Event Listener to the main <div> of the Text Components
3208     */
3209    function addClickEventListenerToTextComponents() {
3210        var componentMainDivs = document.getElementsByClassName("cmp-text");
3211
3212        for (var i = 0; i < componentMainDivs.length; i++) {
3213            componentMainDivs[i].addEventListener("click", addClickedLinkToDataLayer);
3214        }
3215    }
3216
3217    /**
3218     * Adds clicked link contained by the Text Component to Data Layer
3219     *
3220     * @private
3221     * @param {Object} event The Click event
3222     */
3223    function addClickedLinkToDataLayer(event) {
3224        var element = event.currentTarget;
3225        var componentId = getDataLayerId(element);
3226
3227        if (event.target.tagName === "A") {
3228            dataLayer.push({
3229                event: "cmp:click",
3230                eventInfo: {
3231                    path: "component." + componentId,
3232                    link: event.target.getAttribute("href")
3233                }
3234            });
3235        }
3236    }
3237
3238    /**
3239     * Parses the dataLayer string and returns the ID
3240     *
3241     * @private
3242     * @param {HTMLElement} item, the Text item
3243     * @returns {String} dataLayerId or undefined
3244     */
3245    function getDataLayerId(item) {
3246        if (item) {
3247            if (item.dataset.cmpDataLayer) {
3248                return Object.keys(JSON.parse(item.dataset.cmpDataLayer))[0];
3249            } else {
3250                return item.id;
3251            }
3252        }
3253        return null;
3254    }
3255
3256    function onDocumentReady() {
3257        dataLayerEnabled = document.body.hasAttribute("data-cmp-data-layer-enabled");
3258        if (dataLayerEnabled) {
3259            dataLayerName = document.body.getAttribute("data-cmp-data-layer-name") || "adobeDataLayer";
3260            dataLayer = window[dataLayerName] = window[dataLayerName] || [];
3261
3262            addClickEventListenerToTextComponents();
3263        }
3264    }
3265
3266    if (document.readyState !== "loading") {
3267        onDocumentReady();
3268    } else {
3269        document.addEventListener("DOMContentLoaded", onDocumentReady);
3270    }
3271})();
3272
3273
3274/*******************************************************************************
3275 * Copyright 2022 Adobe
3276 *
3277 * Licensed under the Apache License, Version 2.0 (the "License");
3278 * you may not use this file except in compliance with the License.
3279 * You may obtain a copy of the License at
3280 *
3281 *     http://www.apache.org/licenses/LICENSE-2.0
3282 *
3283 * Unless required by applicable law or agreed to in writing, software
3284 * distributed under the License is distributed on an "AS IS" BASIS,
3285 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3286 * See the License for the specific language governing permissions and
3287 * limitations under the License.
3288 ******************************************************************************/
3289(function() {
3290    "use strict";
3291
3292    var linkAccessibilityClass = "cmp-link__screen-reader-only";
3293    var selectors = {
3294        linkAccessibility: "." + linkAccessibilityClass,
3295        linkAccessibilityEnabled: "[data-cmp-link-accessibility-enabled]",
3296        linkAccessibilityText: "[data-cmp-link-accessibility-text]"
3297    };
3298
3299    function getLinkAccessibilityText() {
3300        var linkAccessibilityEnabled = document.querySelectorAll(selectors.linkAccessibilityEnabled);
3301        if (!linkAccessibilityEnabled[0]) {
3302            return;
3303        }
3304        var linkAccessibilityTextElements = document.querySelectorAll(selectors.linkAccessibilityText);
3305        if (!linkAccessibilityTextElements[0]) {
3306            return;
3307        }
3308        return linkAccessibilityTextElements[0].dataset.cmpLinkAccessibilityText;
3309    }
3310
3311    function onDocumentReady() {
3312        var linkAccessibilityText = getLinkAccessibilityText();
3313        if (linkAccessibilityText) {
3314            document.querySelectorAll("a[target='_blank']").forEach(function(link) {
3315                if (!link.querySelector(selectors.linkAccessibility)) {
3316                    var linkAccessibilityElement = document.createElement("span");
3317                    linkAccessibilityElement.classList.add(linkAccessibilityClass);
3318                    linkAccessibilityElement.innerText = linkAccessibilityText;
3319                    link.insertAdjacentElement("beforeend", linkAccessibilityElement);
3320                }
3321            });
3322        }
3323    }
3324
3325    if (document.readyState !== "loading") {
3326        onDocumentReady();
3327    } else {
3328        document.addEventListener("DOMContentLoaded", onDocumentReady);
3329    }
3330
3331}());
3332

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.