<button onclick="openDialog('dialog1', this, 'close')" id="dialog-label">
Open Dialog
</button>
<div role="dialog" id="dialog1" aria-labelledby="dialog1_label" aria-modal="true" class="lightbox-overlay">
<button class="lightbox-overlay__close" id="close">
<div class="visually-hidden">Close dialog</div>
</button>
<div>The content of the overlay goes here</div>
</div>
No notes defined.
/* No context defined. */
const attemptFocus = element => {
try {
element.focus();
} catch (e) {
console.log(e);
}
return document.activeElement === element;
};
export class Dialog {
constructor({ dialogId, focusAfterClosed, focusFirst, closeCallBack }) {
this.dialogNode = document.getElementById(dialogId);
this.closeCallBack = closeCallBack;
this.dialogId = dialogId;
if (this.dialogNode === null) {
throw new Error(`No element found with id="${dialogId}".`);
}
const validRoles = ['dialog', 'alertdialog'];
const isDialog = (this.dialogNode.getAttribute('role') || '')
.trim()
.split(/\s+/g)
.some(token => validRoles.some(role => token === role));
if (!isDialog) {
throw new Error(
'Dialog() requires a DOM element with ARIA role of dialog or alertdialog.'
);
}
if (typeof focusAfterClosed === 'string') {
this.focusAfterClosed = document.getElementById(focusAfterClosed);
} else if (typeof focusAfterClosed === 'object') {
this.focusAfterClosed = focusAfterClosed;
} else {
throw new Error(
'the focusAfterClosed parameter is required for the aria.Dialog constructor.'
);
}
this.dialogNode.classList.add('lightbox-overlay--active');
document.body.style.overflow = 'hidden';
if (typeof focusFirst === 'string') {
this.focusFirst = document.getElementById(focusFirst);
} else if (typeof focusFirst === 'object') {
this.focusFirst = focusFirst;
} else {
this.focusFirst = null;
}
if (this.focusFirst) {
this.focusFirst.focus();
}
this.lastFocus = document.activeElement;
this.addEventListeners();
}
focusFirstDescendant(element) {
for (let i = 0; i < element.childNodes.length; i++) {
const child = element.childNodes[i];
if (attemptFocus(child) || this.focusFirstDescendant(child)) {
return true;
}
}
return false;
}
trapFocus(event) {
if (this.dialogNode.contains(event.target)) {
this.lastFocus = event.target;
} else {
this.focusFirstDescendant(this.dialogNode);
this.lastFocus = document.activeElement;
}
}
destroy() {
const videoDialog = document.querySelector('#generated-video-dialog');
const vimeoDialog = document.querySelector('#generated-vimeo-video-dialog');
// added conditon to fix search popup close event trigger while video lighbox close
if (
this.dialogId === 'efl-search-mechanic-dialog' &&
((videoDialog &&
videoDialog.classList.contains('lightbox-overlay--active')) ||
(vimeoDialog &&
vimeoDialog.classList.contains('lightbox-overlay--active')))
) {
return;
}
this.removeListeners();
this.dialogNode.classList.remove('lightbox-overlay--active');
document.body.style.overflow = 'initial';
this.focusAfterClosed.focus();
if (this.closeCallBack) {
this.closeCallBack();
}
}
// EVENT LISTENERS
handleEscape(event) {
if (event.key !== 'Escape') {
return;
}
this.destroy();
}
handleClick({ target }) {
// We are only interested in clicks on the outer dialog, or the close button
if (
!target.classList.contains('lightbox-overlay__close') &&
target.getAttribute('role') !== 'dialog'
) {
return;
}
this.destroy();
}
removeListeners() {
document.removeEventListener('focus', this.trapFocus, true);
document.removeEventListener('keydown', this.handleEscape, true);
document.removeEventListener('click', this.handleClick, true);
}
addEventListeners() {
document.addEventListener('click', event => this.handleClick(event));
document.addEventListener('keydown', event => this.handleEscape(event));
document.addEventListener('focus', event => this.trapFocus(event));
}
}
export default () => {
window.openDialog = (
dialogId,
focusAfterClosed,
focusFirst,
closeCallBack
) => {
return new Dialog({
dialogId,
focusAfterClosed,
focusFirst,
closeCallBack,
});
};
};
.lightbox-overlay {
align-items: center;
background-color: rgba($black, 0.8);
bottom: 0;
display: none;
justify-content: center;
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: 200;
&--active {
display: flex;
}
&__close {
align-items: center;
background: none;
border: 0;
border-radius: 50%;
display: inline-block;
height: 3.8rem;
justify-content: center;
width: 3.8rem;
position: absolute;
top: -4.5rem;
right: -7px;
z-index: 1;
cursor: pointer;
outline: none;
&::before {
content: '';
background: url('./assets/images/lightbox-close.svg') no-repeat center
center;
background-size: contain;
width: 3.4rem;
height: 3.4rem;
display: inline-block;
position: relative;
left: -10px;
}
&:hover {
&::before {
background: url('./assets/images/lightbox-close-blue.svg') no-repeat
center center;
background-size: contain;
width: 3.4rem;
height: 3.4rem;
}
}
}
.video {
position: relative;
width: calc(100%);
&--is-playing {
width: 100%;
.lightbox-overlay__close {
display: none;
}
}
&__poster {
&::before {
content: '';
background: linear-gradient(
180deg,
rgba(var(--brand-primary-rgb), 0) 0%,
rgba(var(--brand-primary-rgb), 1) 100%
);
border-radius: 4px 4px 0 0;
transform: rotate(180deg);
height: 153px;
width: 100%;
display: block;
position: absolute;
}
.play-button {
position: absolute;
left: calc(50% - 36px);
top: calc(50% - 36px);
font-size: 0;
cursor: pointer;
&::before {
content: '';
background: url('./assets/images/play-button.svg') no-repeat center
center;
width: 71px;
height: 71px;
display: inline-block;
}
}
}
&__player-wrap iframe {
width: 100%;
height: 56.25vw;
}
&__player-wrap .vimeo-video-player {
width: 100%;
height: 100%;
}
&__player-wrap img {
object-fit: cover;
width: 100%;
height: 100%;
display: none;
}
@media screen and (max-width: $mq-medium) and (orientation: landscape) {
&__player-wrap iframe {
height: 34rem;
}
}
@media screen and (min-width: $mq-medium) {
min-width: 576px;
width: 50vw;
height: 28.15vw;
min-height: 32.4rem;
&--is-playing {
width: 80rem;
}
&__player-wrap {
width: 100%;
height: 100%;
}
&__player-wrap iframe {
width: 100%;
height: 100%;
}
}
@media screen and (min-width: $mq-large) {
max-width: 128rem;
}
}
}
<button onclick="openDialog('dialog1', this, 'close')" id="dialog-label">
Open Dialog
</button>
<div role="dialog" id="dialog1" aria-labelledby="dialog1_label" aria-modal="true" class="lightbox-overlay">
<button class="lightbox-overlay__close" id="close">
<div class="visually-hidden">Close dialog</div>
</button>
<div>The content of the overlay goes here</div>
</div>