Files
integration/website/public/api/v1/gaufre.js
Emmanuel Pelletier 1618bb1d1b gaufre: hide it if the server is unavailable
use visiblity: hidden instead of display: none to prevent layout shifts.
2024-05-15 09:52:42 +02:00

137 lines
4.1 KiB
JavaScript

;(function () {
const BUTTON_CLASS = "js-lasuite-gaufre-btn"
let lastFocusedButton = null
window.document.documentElement.classList.add("lasuite--gaufre-loaded")
if ("requestIdleCallback" in window) {
requestIdleCallback(() => {
appendPopup()
})
}
document.body.addEventListener("click", (event) => {
if (!event.target.classList || !event.target.classList.contains(BUTTON_CLASS)) {
const buttons = document.querySelectorAll(`.${BUTTON_CLASS}`)
buttons.forEach((b) => b.classList.remove("lasuite--gaufre-opened"))
hidePopup()
return
}
const button = event.target
button.classList.toggle("lasuite--gaufre-opened")
if (button.classList.contains("lasuite--gaufre-opened")) {
showPopup(button)
} else {
hidePopup()
}
})
document.addEventListener("keyup", (event) => {
if (event.key === "Escape" && document.activeElement.closest(".lagaufre")) {
hidePopup()
}
})
window.addEventListener("resize", () => {
const popup = document.querySelector(`#lasuite-gaufre-popup.lasuite--gaufre-opened`)
if (!popup) {
return
}
const button = document.querySelector(`.${BUTTON_CLASS}.lasuite--gaufre-opened`)
if (!button) {
return
}
popup.style.cssText = getPopupPositionStyle(button)
})
const appendPopup = () => {
if (document.querySelector(`#lasuite-gaufre-popup`)) {
return Promise.resolve(document.querySelector(`#lasuite-gaufre-popup`))
}
const scriptTag = document.querySelector(`#lasuite-gaufre-script`)
if (!scriptTag) {
console.log(
"La Suite numérique: Gaufre script tag not found, make sure the script has id 'lasuite-gaufre-script'.",
)
return
}
const popup = document.createElement("div")
popup.id = "lasuite-gaufre-popup"
popup.width = "304"
popup.height = "360"
popup.style.cssText = "display: none !important"
const { host, protocol, searchParams, origin } = new URL(scriptTag.src)
const local = searchParams.get("type") === "local"
const lang = ["en"].includes(searchParams.get("lang")) ? searchParams.get("lang") : null
return fetch(
`${protocol}//${host}/api/v1/${(!!lang && `${lang}/`) || ""}gaufre${(!!local && "/local") || ""}`,
)
.then((res) => res.text())
.then((html) => {
html = html.replace(/(src=|href=|url\()"\//g, `$1"${origin}/`)
const parser = new DOMParser()
const popupDocument = parser.parseFromString(html, "text/html")
popup.innerHTML = popupDocument.body.innerHTML
document.body.appendChild(popup)
return popup
})
}
const getPopupPositionStyle = (button) => {
const buttonCoords = button.getBoundingClientRect()
const isSmallScreen = window.innerWidth <= 400
let leftPos = buttonCoords.right - 304 + document.documentElement.scrollLeft
leftPos = leftPos < 5 ? 5 : leftPos
return `
position: absolute !important;
top: ${buttonCoords.top + buttonCoords.height + 8}px;
${
isSmallScreen
? `
left: 5px;
right: 5px;
margin: 0 auto;
`
: `
left: ${leftPos}px;
width: 304px;`
}
border: 0 !important;
display: block !important;
z-index: 100000;
`
}
const showPopup = (button) => {
let popup = document.querySelector(`#lasuite-gaufre-popup`)
const show = (el) => {
el.style.cssText = getPopupPositionStyle(button)
el.classList.add("lasuite--gaufre-opened")
lastFocusedButton = button
setTimeout(() => {
el.querySelector(".js-lagaufre-keyboard-anchor").focus()
}, 0)
}
if (popup) {
show(popup)
} else {
appendPopup().then(show)
}
}
const hidePopup = () => {
const popup = document.querySelector(`#lasuite-gaufre-popup`)
if (popup) {
popup.style.cssText = "display: none !important"
popup.classList.remove("lasuite--gaufre-opened")
}
if (lastFocusedButton) {
lastFocusedButton.classList.remove("lasuite--gaufre-opened")
lastFocusedButton.focus()
lastFocusedButton = null
}
}
})()