589 lines
21 KiB
TypeScript
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();
|
|
}
|
|
}
|