Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block youtube video's if cookies are not set #390

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 73 additions & 88 deletions tailoff/js/components/videoToggle.component.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,111 @@
import { DOMHelper } from "../utils/domHelper";
import { Ajax } from '../utils/ajax';
import { Cookies } from '../utils/cookies';

export class VideoToggleComponent {
constructor() {
const triggers = document.querySelectorAll("button[data-s-video-toggle]");
const triggers = document.querySelectorAll('button[data-s-video-toggle]');
Array.from(triggers).forEach((trigger, index) => {
new VideoToggle(trigger as HTMLButtonElement, index);
});

const consent = Cookies.getCookie('__cookie_consent');
if (consent !== 'true' && consent !== '2') {
window.addEventListener('cookie-closed', () => {
const newConsent = Cookies.getCookie('__cookie_consent');
if (newConsent === 'true' || newConsent === '2') {
triggers.forEach((trigger: HTMLButtonElement) => {
trigger.disabled = false;
});
const videoBlockers = document.querySelectorAll('[data-video-consent-blocker]');
Array.from(videoBlockers).forEach((blocker: HTMLElement) => {
blocker.remove();
});
}
});
}
}
}

class VideoToggle {
private options = {
url: "",
url: '',
container: null,
aspectRatio: "auto",
aspectRatio: 'auto',
hideTrigger: true,
showCloseButton: true,
hideClass: "hidden",
toggleContent: "close",
hideClass: 'hidden',
toggleContent: 'close',
};

private trigger: HTMLButtonElement;
private videoContent: HTMLDivElement;
private videoIFrame: HTMLIFrameElement;
private videoCloseButton: HTMLButtonElement;
private videoOpen = false;
private openContent = "";
private openContent = '';

constructor(trigger: HTMLButtonElement, index: number = 0) {
this.trigger = trigger;
this.options.url = trigger.getAttribute("data-s-video-toggle") as string;
this.options.container = trigger.hasAttribute(
"data-s-video-toggle-container"
)
? document.querySelector(
trigger.getAttribute("data-s-video-toggle-container")
)
this.options.url = trigger.getAttribute('data-s-video-toggle') as string;
this.options.container = trigger.hasAttribute('data-s-video-toggle-container')
? document.querySelector(trigger.getAttribute('data-s-video-toggle-container'))
: trigger.parentElement;

this.options.aspectRatio = trigger.hasAttribute(
"data-s-video-toggle-aspect-ratio"
)
? (trigger.getAttribute("data-s-video-toggle-aspect-ratio") as string)
this.options.aspectRatio = trigger.hasAttribute('data-s-video-toggle-aspect-ratio')
? (trigger.getAttribute('data-s-video-toggle-aspect-ratio') as string)
: this.options.aspectRatio;

this.options.showCloseButton = trigger.hasAttribute(
"data-s-video-toggle-show-close-button"
)
? (trigger.getAttribute(
"data-s-video-toggle-show-close-button"
) as string) === "true"
this.options.showCloseButton = trigger.hasAttribute('data-s-video-toggle-show-close-button')
? (trigger.getAttribute('data-s-video-toggle-show-close-button') as string) === 'true'
: this.options.showCloseButton;

this.options.hideTrigger = trigger.hasAttribute(
"data-s-video-toggle-hide-trigger"
)
? (trigger.getAttribute("data-s-video-toggle-hide-trigger") as string) ===
"true"
this.options.hideTrigger = trigger.hasAttribute('data-s-video-toggle-hide-trigger')
? (trigger.getAttribute('data-s-video-toggle-hide-trigger') as string) === 'true'
: this.options.hideTrigger;

this.options.hideClass = trigger.hasAttribute(
"data-s-video-toggle-hide-class"
)
? (trigger.getAttribute("data-s-video-toggle-hide-class") as string)
this.options.hideClass = trigger.hasAttribute('data-s-video-toggle-hide-class')
? (trigger.getAttribute('data-s-video-toggle-hide-class') as string)
: this.options.hideClass;

this.options.toggleContent = trigger.hasAttribute(
"data-s-video-toggle-toggle-content"
)
? (trigger.getAttribute("data-s-video-toggle-toggle-content") as string)
this.options.toggleContent = trigger.hasAttribute('data-s-video-toggle-toggle-content')
? (trigger.getAttribute('data-s-video-toggle-toggle-content') as string)
: this.options.toggleContent;

this.videoContent = document.createElement("div");
this.videoContent.classList.add("video-toggle__content");
this.videoContent = document.createElement('div');
this.videoContent.classList.add('video-toggle__content');
this.videoContent.classList.add(this.options.hideClass);
this.videoContent.id = "videoToggleContent" + index;
this.videoContent.id = 'videoToggleContent' + index;

this.videoIFrame = document.createElement("iframe");
this.videoIFrame.classList.add("video-toggle__iframe");
this.videoIFrame.setAttribute("title", "Video embed");
this.videoIFrame = document.createElement('iframe');
this.videoIFrame.classList.add('video-toggle__iframe');
this.videoIFrame.setAttribute('title', 'Video embed');
this.videoIFrame.setAttribute(
"allow",
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
'allow',
'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'
);
this.videoIFrame.setAttribute("allowfullscreen", "");
this.videoIFrame.setAttribute("width", "100%");
this.videoIFrame.setAttribute("height", "100%");
this.videoIFrame.setAttribute('allowfullscreen', '');
this.videoIFrame.setAttribute('width', '100%');
this.videoIFrame.setAttribute('height', '100%');

this.videoContent.appendChild(this.videoIFrame);

this.options.container.appendChild(this.videoContent);
this.options.container.classList.add("video-toggle__container");
this.options.container.classList.add('video-toggle__container');

if (this.options.showCloseButton) {
this.videoCloseButton = document.createElement("button");
this.videoCloseButton.classList.add("video-toggle__close");
this.videoCloseButton = document.createElement('button');
this.videoCloseButton.classList.add('video-toggle__close');
this.videoCloseButton.classList.add(this.options.hideClass);
this.videoCloseButton.setAttribute("aria-label", "Close video");
this.videoCloseButton.setAttribute("title", "Close video");
this.videoCloseButton.addEventListener(
"click",
this.closeVideo.bind(this)
);
this.videoCloseButton.setAttribute('aria-label', 'Close video');
this.videoCloseButton.setAttribute('title', 'Close video');
this.videoCloseButton.addEventListener('click', this.closeVideo.bind(this));
this.options.container.appendChild(this.videoCloseButton);
}

trigger.setAttribute("aria-expanded", "false");
trigger.setAttribute("aria-controls", "videoToggleContent" + index);
trigger.setAttribute('aria-expanded', 'false');
trigger.setAttribute('aria-controls', 'videoToggleContent' + index);

trigger.addEventListener("click", this.toggleVideo.bind(this));
trigger.addEventListener('click', this.toggleVideo.bind(this));
}

private toggleVideo(e: Event) {
Expand All @@ -120,15 +117,9 @@ class VideoToggle {
}

private clearVideoContainer() {
const videocloseButtons = this.options.container.querySelectorAll(
".video-toggle__close"
);
const videoContentBlocks = this.options.container.querySelectorAll(
".video-toggle__content"
);
const videoIframes = this.options.container.querySelectorAll(
".video-toggle__iframe"
);
const videocloseButtons = this.options.container.querySelectorAll('.video-toggle__close');
const videoContentBlocks = this.options.container.querySelectorAll('.video-toggle__content');
const videoIframes = this.options.container.querySelectorAll('.video-toggle__iframe');

Array.from(videocloseButtons).forEach((button: HTMLElement) => {
button.classList.add(this.options.hideClass);
Expand All @@ -137,15 +128,15 @@ class VideoToggle {
block.classList.add(this.options.hideClass);
});
Array.from(videoIframes).forEach((iframe: HTMLIFrameElement) => {
iframe.setAttribute("src", "");
iframe.setAttribute('src', '');
});
}

private openVideo(e: Event) {
this.clearVideoContainer();
this.trigger.setAttribute("aria-expanded", "true");
this.trigger.setAttribute('aria-expanded', 'true');
this.videoContent.classList.remove(this.options.hideClass);
this.videoIFrame.setAttribute("src", this.options.url + "?autoplay=1");
this.videoIFrame.setAttribute('src', this.options.url + '?autoplay=1');
if (this.options.showCloseButton) {
this.videoCloseButton.classList.remove(this.options.hideClass);
}
Expand All @@ -155,25 +146,23 @@ class VideoToggle {
this.openContent = this.trigger.innerHTML;
this.trigger.innerHTML = this.options.toggleContent;
}
if (this.options.aspectRatio !== "auto") {
const aspectRatio = this.options.aspectRatio.split(":");
if (this.options.aspectRatio !== 'auto') {
const aspectRatio = this.options.aspectRatio.split(':');
const width = parseInt(aspectRatio[0]);
const height = parseInt(aspectRatio[1]);
const newHeight = (this.options.container.offsetWidth * height) / width;
this.options.container.style.height = newHeight + "px";
this.options.container.style.height = newHeight + 'px';
}

this.videoOpen = true;

document.dispatchEvent(
new CustomEvent("s:video:open", { detail: this.videoContent })
);
document.dispatchEvent(new CustomEvent('s:video:open', { detail: this.videoContent }));
}

private closeVideo(e: Event) {
this.trigger.setAttribute("aria-expanded", "false");
this.trigger.setAttribute('aria-expanded', 'false');
this.videoContent.classList.add(this.options.hideClass);
this.videoIFrame.setAttribute("src", "");
this.videoIFrame.setAttribute('src', '');
if (this.options.showCloseButton) {
this.videoCloseButton.classList.add(this.options.hideClass);
}
Expand All @@ -182,19 +171,15 @@ class VideoToggle {
} else {
this.trigger.innerHTML = this.openContent;
}
if (this.options.aspectRatio !== "auto") {
this.options.container.style.height = "";
if (this.options.aspectRatio !== 'auto') {
this.options.container.style.height = '';
}

this.videoOpen = false;

document.dispatchEvent(
new CustomEvent("s:video:close", { detail: this.videoContent })
);
document.dispatchEvent(new CustomEvent('s:video:close', { detail: this.videoContent }));

const containerToggleButton = this.options.container.querySelector(
"[data-s-video-toggle]"
);
const containerToggleButton = this.options.container.querySelector('[data-s-video-toggle]');

if (containerToggleButton) {
containerToggleButton.classList.remove(this.options.hideClass);
Expand Down
18 changes: 15 additions & 3 deletions templates/_site/_snippet/_content/_blocks/_textVideo.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
<div class="flex flex-wrap -mx-4 {{ inverseClass }}">
<div class="w-full px-4 md:w-1/2">
{% if block.video|length %}
{% set consent = craft.app.request.rawCookies.value('__cookie_consent') %}

{% set embed = craft.videoparser.parse(block.video) %}
{% if embed %}
<figure class="block">
<div class="relative bg-center bg-cover bg-black/50 bg-blend-multiply aspect-video js-bg-target" id="video-{{block.id}}">
<div class="relative bg-center bg-cover bg-black/50 bg-blend-multiply before:aspect-video before:block before:w-full js-bg-target" id="video-{{block.id}}">
{% set image = block.placeholderImage.collect().first() %}
{% if image %}
{% set optimizedImage = image.optimizedTextImage %}
Expand Down Expand Up @@ -36,11 +37,22 @@
<button type="button" class="absolute inset-0"
data-s-video-toggle="{{embed.embedSrc}}"
data-s-video-toggle-container="#video-{{block.id}}"
data-s-video-toggle-show-close-button="false">
<span class="absolute flex items-center px-4 py-2 text-white -translate-x-1/2 -translate-y-1/2 rounded bg-primary-dark top-1/2 left-1/2">
data-s-video-toggle-show-close-button="false"
{% if consent != "true" and consent != "2" %}disabled{% endif %}>
<span class="absolute flex items-center px-4 py-2 text-white -translate-x-1/2 -translate-y-1/2 rounded bg-primary top-1/2 left-1/2">
{{ icon('play-arrow', { class: 'mr-2 text-xl' }) }} {{ 'Play video'|t }}
</span>
</button>
{% if consent != "true" and consent != "2" %}
<div class="relative z-10 w-full h-full -mt-[56.25%] lg:mt-0 max-w-full p-6 overflow-auto bg-white border-black lg:absolute border-1 lg:-translate-x-1/2 lg:-translate-y-1/2 lg:top-1/2 lg:left-1/2 lg:w-max lg:h-auto" data-video-consent-blocker>
<h2 class="text-xl font-bold">{{ 'Cookie consent required'|t }}</h2>
<p class="mt-2">{{ 'This video can only be viewed after accepting cookies'|t }}</p>
<div class="flex flex-wrap items-center w-full gap-2 mt-4 md:gap-6">
<button type="button" class=" btn btn--primary js-cookie-settings">{{ 'Accept cookies'|t }}</button>
<a href="{{block.video}}" class="underline hover:no-underline" target="_blank">{{ "Or view this video on "|t}}{{embed.type}}</a>
</div>
</div>
{% endif %}
</div>
{% if block.videoCaption|length %}
<figcaption class="mt-2 text-sm text-editor">
Expand Down
18 changes: 15 additions & 3 deletions templates/_site/_snippet/_content/_blocks/_video.twig
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{% if block.video|length %}
<figure class="block w-full mx-auto md:w-2/3">
{% set embed = craft.videoparser.parse(block.video) %}
{% set consent = craft.app.request.rawCookies.value('__cookie_consent') %}

{% if embed %}
<div class="relative bg-center bg-cover aspect-video bg-black/50 bg-blend-multiply js-bg-target" id="video-{{block.id}}">
<div class="relative bg-center bg-cover bg-black/50 bg-blend-multiply before:aspect-video before:block before:w-full js-bg-target" id="video-{{block.id}}">
{% set image = block.placeholderImage.collect().first() %}
{% if image %}
{% set optimizedImage = image.optimizedTextImage %}
Expand Down Expand Up @@ -32,11 +33,22 @@
<button type="button" class="absolute inset-0"
data-s-video-toggle="{{embed.embedSrc}}"
data-s-video-toggle-container="#video-{{block.id}}"
data-s-video-toggle-show-close-button="false">
<span class="absolute flex items-center px-4 py-2 text-white -translate-x-1/2 -translate-y-1/2 rounded bg-primary-dark top-1/2 left-1/2">
data-s-video-toggle-show-close-button="false"
{% if consent != "true" and consent != "2" %}disabled{% endif %}>
<span class="absolute flex items-center px-4 py-2 text-white -translate-x-1/2 -translate-y-1/2 rounded bg-primary top-1/2 left-1/2">
{{ icon('play-arrow', { class: 'mr-2 text-xl' }) }} {{ 'Play video'|t }}
</span>
</button>
{% if consent != "true" and consent != "2" %}
<div class="relative z-10 w-full h-full -mt-[56.25%] sm:mt-0 p-6 bg-white border-1 border-black sm:-translate-x-1/2 sm:-translate-y-1/2 sm:absolute sm:top-1/2 sm:left-1/2 sm:w-max sm:h-auto" data-video-consent-blocker>
<h2 class="text-xl font-bold">{{ 'Cookie consent required'|t }}</h2>
<p class="mt-2">{{ 'This video can only be viewed after accepting cookies'|t }}</p>
<div class="flex flex-wrap items-center w-full gap-2 mt-4 sm:gap-6">
<button type="button" class=" btn btn--primary js-cookie-settings">{{ 'Accept cookies'|t }}</button>
<a href="{{block.video}}" class="underline hover:no-underline" target="_blank">{{ "Or view this video on "|t}}{{embed.type}}</a>
</div>
</div>
{% endif %}
</div>
{% endif %}

Expand Down