ldc-le-gaulois-pro/resources/ts/libs/ldcweb-cookies.ts
2022-09-08 11:36:15 +02:00

589 lines
21 KiB
TypeScript

/**
* LDC Service Web Cookies
* Version 2.1.0
*/
enum LdcwebCookieStatus {
true = "true",
false = "false",
wait = "wait",
}
type LdcwebCookieStatusString = keyof typeof LdcwebCookieStatus;
type LdcwebCnOptions = {
name: string;
description: string;
link: string;
labelLink: string;
cookies: string[];
/**
* Fonction qui sert à initialiser la fonctionnalité
* conduisant à la génération du cookie
* @return void
*/
script: () => void;
/**
* Fonction qui sert à informer l'utilisateur
* sur chaque élèment que le cookie
* associé à la fonctionnalité
* est désactivé et propose un lien sur
* cookie notice pour l'activer
* @return void
*/
fallback: () => void | null;
};
export class LdcwebCn {
config: Record<string, LdcwebCnOptions>;
cookieContainer: HTMLDivElement;
bannerContainer: HTMLDivElement;
bannerBtn: HTMLButtonElement;
ldcwebBtn: HTMLButtonElement;
ldcwebBannerParaP: HTMLParagraphElement;
ldcwebBannerContent: HTMLDivElement;
ldcwebBannerDetails: HTMLDivElement;
ldcwebBannerBtnDetails: HTMLDivElement;
modalContainer: HTMLDivElement;
acceptAllBtnBanner: HTMLButtonElement;
denyAllBtnBanner: HTMLButtonElement;
personalizeBtnBanner: HTMLButtonElement;
changeBtn: HTMLCollectionOf<HTMLElement>;
cookiesList: HTMLUListElement;
cookieLink: HTMLElement;
modalDetails: HTMLDivElement;
template: HTMLDivElement;
modalBtnBoolean: boolean;
bannerBtnTextBoolean: boolean;
constructor(config: Record<string, LdcwebCnOptions>) {
// * INITIALIZE VARS
this.config = config;
let cookieContainer: HTMLDivElement | null = null;
if (!(cookieContainer = document.querySelector("#ldcweb-cn"))) {
throw new Error("Cannot find #ldcweb-cn");
}
this.cookieContainer = cookieContainer;
this.bannerContainer = document.querySelector(
".ldcweb-cn-banner"
) as HTMLDivElement;
this.bannerBtn = document.querySelector(
"button.ldcweb-banner-btn-details-p"
) as HTMLButtonElement;
this.ldcwebBtn = document.querySelector(
"button.ldcweb-btn"
) as HTMLButtonElement;
this.ldcwebBannerParaP = document.querySelector(
".ldcweb-banner-para-p"
) as HTMLParagraphElement;
this.ldcwebBannerContent = document.querySelector(
".ldcweb-banner-content"
) as HTMLDivElement;
this.ldcwebBannerDetails = document.querySelector(
".ldcweb-banner-details"
) as HTMLDivElement;
this.ldcwebBannerBtnDetails = document.querySelector(
".ldcweb-banner-btn-details"
) as HTMLDivElement;
this.modalContainer = document.getElementById(
"ldcweb-cn-modal"
) as HTMLDivElement;
this.acceptAllBtnBanner = document.getElementById(
"ldcweb-cn-accept-banner"
) as HTMLButtonElement;
this.denyAllBtnBanner = document.getElementById(
"ldcweb-cn-deny-banner"
) as HTMLButtonElement;
this.personalizeBtnBanner = document.querySelector(
".ldcweb-cn-personalize"
) as HTMLButtonElement;
this.changeBtn = document.getElementsByClassName(
"ldcweb-cn-change"
) as HTMLCollectionOf<HTMLElement>;
this.cookiesList = document.getElementById(
"ldcweb-cn-list"
) as HTMLUListElement;
this.cookieLink = document.querySelector(
".ldcweb-cn-cookie-link"
) as HTMLAnchorElement;
this.modalDetails = document.querySelector(
".modal-details"
) as HTMLDivElement;
this.modalBtnBoolean = false;
this.bannerBtnTextBoolean = false;
let template: HTMLDivElement | null = null;
if (!(template = document.querySelector("#template"))) {
throw new Error("Cannot find 'template' element");
}
this.template = template;
const memoryTemplate = this.template.cloneNode(true) as HTMLDivElement;
this.template.remove();
this.template = memoryTemplate;
// * LOGIC
const self = this;
const cookies = this.getLDCWebCookie("ldcwebcn-init");
if (cookies === undefined) {
const newCookie: string[] = [];
for (const [key] of Object.entries(this.config)) {
newCookie.push(key + "=wait");
}
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
this.saveLDCWebCookie(newCookie.join(","));
} else {
const test = cookies.split(",");
test.forEach((elm) => {
const test = elm.split("=");
if (test[1] === "wait") {
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
}
});
}
/**
* Accept a specific cookie
*/
const accept = function (e: { preventDefault: () => void }) {
e.preventDefault();
for (const [key, value] of Object.entries(self.config)) {
self.addCookie(key, value);
}
for (const acceptLabel of self.cookieContainer.querySelectorAll(
".accept > label"
)) {
acceptLabel.classList.add("active");
}
for (const denyLabel of self.cookieContainer.querySelectorAll(
".deny > label"
)) {
denyLabel.classList.remove("active");
}
self.bannerContainer.classList.remove("ldcweb-cn-banner-open");
}.bind(this);
this.acceptAllBtnBanner.addEventListener("click", accept);
/**
* Deny a specific cookie
*/
const deny = function (e: { preventDefault: () => void }) {
e.preventDefault();
for (const [key, value] of Object.entries(self.config)) {
self.removeCookie(key, value);
}
for (const acceptLabel of self.cookieContainer.querySelectorAll(
".accept > label"
)) {
acceptLabel.classList.remove("active");
}
for (const denyLabel of self.cookieContainer.querySelectorAll(
".deny > label"
)) {
denyLabel.classList.add("active");
}
self.bannerContainer.classList.remove("ldcweb-cn-banner-open");
}.bind(this);
this.denyAllBtnBanner.addEventListener("click", deny);
const openLdcwebCookies = function (e: { preventDefault: () => void }) {
e.preventDefault();
self.openModal();
}.bind(this);
this.cookieLink.addEventListener("click", openLdcwebCookies);
/**
* Show the modal with the list of all cookies
*/
const hideModal = function (e: { preventDefault: () => void }) {
e.preventDefault();
self.ldcwebBannerContent.classList.toggle("visibility");
self.ldcwebBannerDetails.classList.toggle("visibility");
self.ldcwebBannerBtnDetails.classList.toggle("visibility");
self.modalContainer.classList.toggle("visibility");
self.setCookieList();
}.bind(this);
this.personalizeBtnBanner.addEventListener("click", hideModal);
this.personalizeBtnBanner.addEventListener("click", (e) => {
e.preventDefault();
self.modalDetails.scrollTop = 0;
if (!self.modalBtnBoolean) {
if (!self.personalizeBtnBanner.dataset.openModal) {
throw new Error("Cannot find attribute data-open-modal");
}
self.personalizeBtnBanner.innerHTML =
self.personalizeBtnBanner.dataset.openModal;
self.modalBtnBoolean = true;
} else {
if (!self.personalizeBtnBanner.dataset.closeModal) {
throw new Error("Cannot find attribute data-close-modal");
}
self.personalizeBtnBanner.innerHTML =
self.personalizeBtnBanner.dataset.closeModal;
self.modalBtnBoolean = false;
}
});
this.setListenerOnChange();
const cookie = this.getLDCWebCookie("ldcwebcn-init");
if (cookie === undefined) {
throw Error("Ldcweb cookie is not set");
}
const test = cookie.split(",");
test.forEach((elm) => {
const test = elm.split("=");
if (test[1] === "true") {
this.config[test[0]].script();
} else {
if (this.config[test[0]].fallback != null) {
this.config[test[0]].fallback();
}
}
});
this.bannerBtn.addEventListener("click", (e: MouseEvent) => {
self.ldcwebBannerDetails.classList.toggle(
"ldcweb-banner-details-open"
);
self.bannerBtn.classList.toggle("ldcweb-banner-btn-details-p-open");
if (!self.bannerBtn.dataset.open || !self.bannerBtn.dataset.close) {
throw new Error(
"Cannot find attribute data-open or data-close"
);
}
if (
!self.ldcwebBannerParaP.dataset.open ||
!self.ldcwebBannerParaP.dataset.close
) {
throw new Error(
"Cannot find attribute data-open or data-close"
);
}
if (self.bannerBtnTextBoolean) {
self.bannerBtn.innerHTML = self.bannerBtn.dataset.close;
self.ldcwebBannerParaP.innerHTML =
self.ldcwebBannerParaP.dataset.close;
self.ldcwebBannerDetails.style.height = "0px";
self.bannerBtnTextBoolean = false;
} else {
self.bannerBtn.innerHTML = self.bannerBtn.dataset.open;
self.ldcwebBannerParaP.innerHTML =
self.ldcwebBannerParaP.dataset.open;
self.ldcwebBannerDetails.style.height =
self.ldcwebBannerDetails.children[0].clientHeight + "px";
self.bannerBtnTextBoolean = true;
}
});
/**
* Show the default vue of the cookies modal
*/
const resetVue = function (e: { preventDefault: () => void }) {
e.preventDefault();
self.bannerContainer.classList.toggle("ldcweb-cn-banner-open");
if (
self.bannerContainer.classList.contains("ldcweb-cn-banner-open")
) {
self.ldcwebBannerContent.classList.remove("visibility");
self.ldcwebBannerDetails.classList.remove("visibility");
self.ldcwebBannerBtnDetails.classList.remove("visibility");
self.modalContainer.classList.add("visibility");
if (!self.personalizeBtnBanner.dataset.closeModal) {
throw new Error("Cannot find attribut data-close-modal");
}
self.personalizeBtnBanner.innerHTML =
self.personalizeBtnBanner.dataset.closeModal;
self.modalBtnBoolean = false;
}
}.bind(this);
this.ldcwebBtn.addEventListener("click", resetVue);
}
/**
* Set the cookies list in the modal
*/
setCookieList() {
const self = this;
this.cookiesList.innerHTML = "";
for (const [key, value] of Object.entries(this.config)) {
const cookie = document.createElement("li");
const childItem = this.template.children.item(
0
) as HTMLDivElement | null;
if (childItem === null) {
throw new Error("Cannot find child item");
}
cookie.append(childItem.cloneNode(true));
const name = cookie.querySelector(
"span.ldcweb-cn-name"
) as HTMLSpanElement;
const description = cookie.querySelector(
"span.ldcweb-cn-description"
) as HTMLSpanElement;
const link = cookie.querySelector(
"a.ldcweb-cn-link"
) as HTMLButtonElement;
const acceptInput = cookie.querySelector(
".accept > input"
) as HTMLInputElement;
const denyInput = cookie.querySelector(
".deny > input"
) as HTMLInputElement;
const acceptLabel = cookie.querySelector(
".accept > label"
) as HTMLLabelElement;
const denyLabel = cookie.querySelector(
".deny > label"
) as HTMLLabelElement;
name.textContent = value.name;
description.textContent = value.description;
link.textContent = value.labelLink;
link.setAttribute("href", value.link);
acceptInput.id = key + "1";
acceptInput.name = key;
acceptInput.dataset.name = key;
acceptLabel.htmlFor = key + "1";
denyInput.id = key + "2";
denyInput.name = key;
denyInput.dataset.name = key;
denyLabel.htmlFor = key + "2";
acceptInput.addEventListener("click", () => {
acceptLabel.classList.add("active");
denyLabel.classList.remove("active");
self.addCookie(key, value);
});
denyInput.addEventListener("click", () => {
acceptLabel.classList.remove("active");
denyLabel.classList.add("active");
self.removeCookie(key, value);
});
this.cookiesList.append(cookie);
const cookiesSite = this.getLDCWebCookie("ldcwebcn-init");
if (cookiesSite === undefined) {
throw Error("Ldcweb cookie is not set");
}
const cookiesArray = cookiesSite.split(",");
for (const cookieEl of cookiesArray) {
const name = cookieEl.slice(0, cookieEl.indexOf("="));
const status = cookieEl.slice(cookieEl.indexOf("=") + 1);
if (name === key) {
acceptLabel.classList.remove("active");
denyLabel.classList.remove("active");
switch (status) {
case "true":
acceptLabel.classList.add("active");
break;
case "false":
denyLabel.classList.add("active");
break;
}
}
}
}
this.setListenerOnChange();
}
/**
* Add a specific cookie and
* change his status to true
*
* @param key
* @param value
*/
addCookie(key: string, value: LdcwebCnOptions) {
if (value.script) {
value.script();
}
this.changeStatus(key, "true");
}
/**
* Remove a specific cookie and
* change his status to false
*
* @param key
* @param value
*/
removeCookie(key: string, value: LdcwebCnOptions) {
for (const cookieName of value.cookies) {
this.deleteBrowserCookie(cookieName, "/", "." + location.host);
}
const cookieName = document.getElementById(key);
if (cookieName) {
cookieName.remove();
}
if (value.fallback) {
value.fallback();
}
this.changeStatus(key, "false");
}
/**
* Add events for each cookie buttons
* Activate or Deactivate a specific cookie
*/
setListenerOnChange() {
const self = this;
this.changeBtn = document.getElementsByClassName(
"ldcweb-cn-change"
) as HTMLCollectionOf<HTMLElement>;
for (const item of this.changeBtn) {
this.addEvent(item, "click", () => {
if (!item.dataset.name) {
throw new Error("Dataset is missing required elements");
}
const status = item.dataset.status as
| LdcwebCookieStatus
| undefined;
if (!status || !(status in LdcwebCookieStatus)) {
throw new Error("Dataset is missing required elements");
}
self.changeStatus(item.dataset.name, status);
});
}
}
/**
* Change the status of a cookie
*
* @param name
* @param status
*/
changeStatus(name: string, status: LdcwebCookieStatusString) {
/** Contains array of string like youtube=true etc */
const newCookie: string[] = [];
const cookie = this.getLDCWebCookie("ldcwebcn-init");
if (cookie === undefined) {
throw Error("Ldcweb cookie is not set");
}
/** specificCookieString contains youtube=true like */
cookie.split(",").forEach((specificCookieString) => {
/** Contanins cookie name 0 and cookie value 1 */
const test = specificCookieString.split("=");
// Check this cookie is the one to update
if (test[0] === name) {
newCookie.push(name + "=" + status);
if (status === "false") {
// * Iterer sur chque cookie possible de la config
this.config[test[0]].cookies.forEach(
(cookieNametoRemove) => {
const cookies =
this.getLDCWebCookie(cookieNametoRemove);
// * Si le navigateur possede le cookie
if (cookies !== undefined) {
// * Suppression du cookie et de sa version precedé dun point
document.cookie =
cookieNametoRemove +
"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=" +
document.domain +
"; path=/";
document.cookie =
cookieNametoRemove +
"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=." +
document.domain +
"; path=/";
}
}
);
}
} else {
newCookie.push(specificCookieString);
}
});
this.saveLDCWebCookie(newCookie.join(","));
}
/**
* Set an older expire parameter to a specific cookie
*
* @param name
* @param path
* @param domain
*/
deleteBrowserCookie(name: string, path: string, domain: string) {
if (this.getLDCWebCookie(name)) {
document.cookie =
name +
"=" +
(path ? ";path=" + path : "") +
(domain ? ";domain=" + domain : "") +
";expires=Thu, 01 Jan 1970 00:00:01 GMT";
}
}
/**
* Get the Ldcweb cookie
*
* @param name
* @returns A string like analytics=true,youtube=true or undefined
*/
getLDCWebCookie(name: string) {
const matches = document.cookie.match(
new RegExp(
"(?:^|; )" +
name.replace(/([.$?*|{}()[\]\\/+^])/g, "\\$1") +
"=([^;]*)"
)
);
return matches ? decodeURIComponent(matches[1]) : undefined;
}
/**
* Add event on a specific element
*
* @param element
* @param evnt
* @param funct
* @returns
*/
addEvent(element: HTMLElement, evnt: string, funct: () => void) {
return element.addEventListener(evnt, funct, false);
}
/**
* Save cookie content on web browser
*
* @param content
*/
saveLDCWebCookie(content: string) {
const date = new Date();
const newDate = new Date(date.setMonth(date.getMonth() + 13));
document.cookie =
"ldcwebcn-init=" +
content +
"; expires=" +
newDate.toUTCString() +
"; path=/;";
}
/**
* Open the cookies modal
*/
openModal() {
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
this.ldcwebBannerContent.classList.add("visibility");
this.ldcwebBannerDetails.classList.add("visibility");
this.ldcwebBannerBtnDetails.classList.add("visibility");
this.modalContainer.classList.remove("visibility");
this.personalizeBtnBanner.innerHTML =
this.personalizeBtnBanner.dataset?.closeModal ?? "PERSONNALISER";
this.modalBtnBoolean = true;
// Scroll to the top of the cookies list
this.modalDetails.scrollTop = 0;
this.setCookieList();
}
}