{"version":3,"file":"helpers-9cad85ce.js","sources":["../../../src/js/modules/helpers.js"],"sourcesContent":["import FetchWrapper from './fetch-wrapper.js';\nconst thisWebsiteAPI = new FetchWrapper(`${window.location.protocol}//${window.location.host}`);\n\n/**\n * Returns the type of interactions the device supports (click / mouseover)\n * @returns {string}\n */\nexport function interactionType() {\n\tlet interactionType = 'mouseover';\n\n\tif( window.matchMedia('(hover: hover)') ) { // desktop\n\t\tinteractionType = 'mouseover'; }\n\tif( window.matchMedia('(hover: none) and (pointer: coarse)') ) { // touchscreen\n\t\tinteractionType = 'click'; }\n\tif( window.matchMedia('(hover: none) and (pointer: fine)') ) { // stylus\n\t\tinteractionType = 'click'; }\n\tif( window.matchMedia('(hover: hover) and (pointer: coarse)') ) { // Wii/Kinect/etc\n\t\tinteractionType = 'mouseover'; }\n\tif( window.matchMedia('(hover: hover) and (pointer: fine)') ) { // mouse\n\t\tinteractionType = 'mouseover'; }\n\n\treturn interactionType;\n}\n\n/**\n * Add and update a data attribute on the HTML element to indicate the state of the page's scroll\n */\nfunction windowHasScrolled() {\n\tconst html = document.querySelector('html');\n\n\tif (window.scrollY > 0) {\n\t\thtml.dataset.pageHasScrolled = 'true';\n\t} else {\n\t\thtml.dataset.pageHasScrolled = 'false';\n\t}\n}\n\n/**\n * Adds an event listener to the window which will indicate if the page has scrolled by updating `data-page-has-scrolled` to true or false.\n */\nexport function initWindowHasScrolled() {\n\twindow.addEventListener('scroll', function() {\n\t\twindowHasScrolled();\n\t});\n}\n\n/**\n * Finds HTML elements with a `data-scroll-reveal` attribute, and uses an IntersectionObserver to add a `data-in-viewport` attribute to that element when it's scrolled inside the viewport.\n * @param rootMargin - defaults to `0 0 -20% 0`\n */\nexport function scrollAnimatedBlocks(rootMargin = \"0px 0px -20% 0px\") {\n\tif (!!window.IntersectionObserver) {\n\t\tdocument.querySelector('html').dataset.supportsIntersectionObserver = 'true';\n\n\t\tlet observer = new IntersectionObserver((watchList, observer) => {\n\t\t\twatchList.forEach(watchedElement => {\n\t\t\t\tif (watchedElement.isIntersecting) {\n\t\t\t\t\twatchedElement.target.dataset.inViewport = 'true';\n\t\t\t\t\tobserver.unobserve(watchedElement.target);\n\t\t\t\t}\n\t\t\t});\n\t\t}, {\n\t\t\trootMargin: rootMargin\n\t\t});\n\n\t\tdocument.querySelectorAll('[data-scroll-reveal]').forEach(watchTarget => {\n\t\t\tobserver.observe(watchTarget);\n\t\t});\n\t}\n\telse {\n\t\tconsole.log(`Browser doesn't support IntersectionObserver`)\n\t}\n}\n\n/**\n * Indicate to users that Sprig forms are doing something when submitted.\n */\nexport function sprigFormWatcher() {\n\tdocument.querySelectorAll('form[sprig]').forEach(sprigForm => {\n\t\tsprigForm.insertAdjacentHTML('beforeend', `\n\t\t\t\n\t\t`);\n\n\t\tlet dialog = sprigForm.querySelector('.sprigActionFeedback');\n\n\t\tdialog.querySelector('button').addEventListener('click', () => {\n\t\t\tdialog.close();\n\t\t});\n\n\t\tsprigForm.addEventListener('submit', () => {\n\t\t\tdialog.showModal();\n\t\t});\n\t});\n}\n\n/**\n * For images on our website.\n * @param {Node} popupLink\n */\nfunction handlePopupImageLink(popupLink) {\n\tpopupLink.addEventListener('click', (e) => {\n\t\te.preventDefault();\n\t\tlet parser = new DOMParser();\n\n\t\tlet clickedLink = e.currentTarget;\n\t\tclickedLink.dataset.fetchStatus = \"loading\";\n\n\t\tthisWebsiteAPI\n\t\t\t.getHtml(clickedLink.getAttribute('href'))\n\t\t\t.then(response => {\n\t\t\t\tlet responseAsDom = parser.parseFromString(response, \"text/html\");\n\t\t\t\tlet imageWeWant = responseAsDom.querySelector('#ajaxcontent').outerHTML;\n\n\t\t\t\tdocument.querySelector('body').insertAdjacentHTML('afterbegin', `\n\t\t\t\t\t\n\t\t\t\t`);\n\n\t\t\t\tlet lightbox = document.querySelector('#lightbox');\n\t\t\t\tlightbox.showModal();\n\t\t\t\tclickedLink.dataset.fetchStatus = 'loaded';\n\n\t\t\t\t// remove the entire thing from the DOM when closed, getting us back to where we were before clicked\n\t\t\t\tdocument.querySelector('#lightbox').addEventListener(\"close\", e => {\n\t\t\t\t\te.target.remove();\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch(error => {\n\t\t\t\tconsole.error(error);\n\t\t\t});\n\t})\n}\n\n/**\n * For links to youtube\n * @param {Node} popupLink\n */\nfunction handlePopupYoutubeLink(popupLink) {\n\tpopupLink.addEventListener('click', (e) => {\n\t\te.preventDefault();\n\t\tlet clickedLink = e.currentTarget;\n\t\tlet clickedUrl = new URL(clickedLink.href);\n\t\tlet videoId = clickedUrl.searchParams.get('v');\n\t\tlet videoWeWant = `\n\t\t\t\n\t\t`;\n\n\t\tclickedLink.dataset.fetchStatus = \"loading\";\n\n\t\tdocument.querySelector('body').insertAdjacentHTML('afterbegin', `\n\t\t\t\n\t\t`);\n\n\t\tlet lightbox = document.querySelector('#lightbox') ?? null;\n\t\tlet theVideo = document.querySelector('#lightbox iframe');\n\n\t\tlightbox.showModal();\n\t\tclickedLink.dataset.fetchStatus = \"loaded\";\n\n\t\t// remove the entire thing from the DOM when closed, to stop the video from continuing to play\n\t\tdocument.querySelector('#lightbox').addEventListener(\"close\", e => {\n\t\t\te.target.remove();\n\t\t});\n\t});\n}\n\n/**\n * Activate all anchor links that have a `data-popup=\"image\"` attribute.\n */\nexport function initPopupImages() {\n\tdocument.querySelectorAll('a[data-popup=\"image\"]').forEach( popupLink => {\n\t\thandlePopupImageLink( popupLink );\n\t});\n}\n\n/**\n * Activate all anchor links that have a `data-popup=\"youtube\"` attribute.\n */\nexport function initPopupYoutube() {\n\tdocument.querySelectorAll('a[data-popup=\"youtube\"]').forEach( popupLink => {\n\t\thandlePopupYoutubeLink( popupLink );\n\t});\n}\n\n/**\n * Adds a relative age in days to DOM elements that are annotated with some sort of date\n *\n * @param {string} targetElement - The selector of the element we're matching against\n * @param {string} outputTarget - The selector of the sub-element we append a relative time to\n *\n * @example data-date-posted=\"2023-06-23T09:43:58+01:00\"\n */\nexport function relativeAges(targetElement, outputTarget) {\n\tconst utcDate = new Date();\n\tconst isoDate = utcDate.toISOString();\n\tconst rtf1 = new Intl.RelativeTimeFormat(\n\t\t'en-GB',\n\t\t{ numeric: 'auto' }\n\t);\n\n\tdocument\n\t\t.querySelectorAll( targetElement )\n\t\t.forEach(item => {\n\t\t\tconst prodDate = new Date(item.dataset.dateCreated);\n\t\t\tconst dateInUTC = new Date(isoDate);\n\n\t\t\tlet differenceInDays = Math.abs(dateInUTC.getDate() - prodDate.getDate());\n\t\t\tlet output = rtf1.format(0 - differenceInDays, 'day')\n\n\t\t\tif (differenceInDays > 6) {\n\t\t\t\titem\n\t\t\t\t\t.querySelector(':scope ' + outputTarget)\n\t\t\t\t\t.insertAdjacentHTML(\n\t\t\t\t\t\t'beforeend',\n\t\t\t\t\t\t`(${output})`\n\t\t\t\t\t);\n\t\t\t}\n\t\t});\n}\n\n/**\n * Adds a Dismiss button and behaviour to CMS generated Flash messages\n */\nexport function dismissNotice() {\n\tlet theNotice = document.querySelector(\"#notice\");\n\n\tif (theNotice) {\n\t\ttheNotice.insertAdjacentHTML('beforeend', ``);\n\t\ttheNotice.querySelector('button').addEventListener('click', e => {\n\t\t\te.preventDefault();\n\t\t\ttheNotice.remove();\n\t\t});\n\t}\n}\n\n\n/* Fire functions on load */\ninitPopupImages();\ninitPopupYoutube();\ninitWindowHasScrolled();\nsprigFormWatcher();\nscrollAnimatedBlocks();\nrelativeAges('[data-date-posted]','.meta');\n"],"names":["thisWebsiteAPI","FetchWrapper","windowHasScrolled","html","initWindowHasScrolled","scrollAnimatedBlocks","rootMargin","observer","watchList","watchedElement","watchTarget","sprigFormWatcher","sprigForm","dialog","handlePopupImageLink","popupLink","e","parser","clickedLink","response","imageWeWant","error","handlePopupYoutubeLink","videoWeWant","lightbox","initPopupImages","initPopupYoutube","relativeAges","targetElement","outputTarget","isoDate","rtf1","item","prodDate","dateInUTC","differenceInDays","output"],"mappings":"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"}