48 lines
1.6 KiB
JavaScript
48 lines
1.6 KiB
JavaScript
class DetailsModal extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.detailsContainer = this.querySelector('details');
|
|
this.summaryToggle = this.querySelector('summary');
|
|
|
|
this.detailsContainer.addEventListener('keyup', (event) => event.code.toUpperCase() === 'ESCAPE' && this.close());
|
|
this.summaryToggle.addEventListener('click', this.onSummaryClick.bind(this));
|
|
this.querySelector('button[type="button"]').addEventListener('click', this.close.bind(this));
|
|
|
|
this.summaryToggle.setAttribute('role', 'button');
|
|
}
|
|
|
|
isOpen() {
|
|
return this.detailsContainer.hasAttribute('open');
|
|
}
|
|
|
|
onSummaryClick(event) {
|
|
event.preventDefault();
|
|
event.target.closest('details').hasAttribute('open') ? this.close() : this.open(event);
|
|
}
|
|
|
|
onBodyClick(event) {
|
|
if (!this.contains(event.target) || event.target.classList.contains('modal-overlay')) this.close(false);
|
|
}
|
|
|
|
open(event) {
|
|
this.onBodyClickEvent = this.onBodyClickEvent || this.onBodyClick.bind(this);
|
|
event.target.closest('details').setAttribute('open', true);
|
|
document.body.addEventListener('click', this.onBodyClickEvent);
|
|
document.body.classList.add('overflow-hidden');
|
|
|
|
trapFocus(
|
|
this.detailsContainer.querySelector('[tabindex="-1"]'),
|
|
this.detailsContainer.querySelector('input:not([type="hidden"])')
|
|
);
|
|
}
|
|
|
|
close(focusToggle = true) {
|
|
removeTrapFocus(focusToggle ? this.summaryToggle : null);
|
|
this.detailsContainer.removeAttribute('open');
|
|
document.body.removeEventListener('click', this.onBodyClickEvent);
|
|
document.body.classList.remove('overflow-hidden');
|
|
}
|
|
}
|
|
|
|
customElements.define('details-modal', DetailsModal);
|