79 lines
2.1 KiB
JavaScript
79 lines
2.1 KiB
JavaScript
/**
|
|
* Base class for modals.
|
|
*/
|
|
export class BaseModal extends HTMLElement {
|
|
|
|
constructor() {
|
|
super();
|
|
|
|
this.attached = false;
|
|
this.pendingLayoutAfterResize = false;
|
|
|
|
// Modal can return a result via a promise.
|
|
const self = this;
|
|
this.result = new Promise((resolve, reject) => {
|
|
self.resolve = resolve;
|
|
self.reject = reject;
|
|
});
|
|
|
|
// Create event handlers for instance.
|
|
this.handlerResize = this.onResize.bind(this);
|
|
window.addEventListener('resize', this.handlerResize);
|
|
this.handlerKeyDown = this.onKeyDown.bind(this);
|
|
this.addEventListener('keydown', this.handlerKeyDown);
|
|
|
|
// Allows the modal element to recieve focus.
|
|
this.classList.add('liebs-picker-modal');
|
|
this.setAttribute('tabindex', '0');
|
|
}
|
|
|
|
// Invoked when the window is resized.
|
|
onResize() {
|
|
// Recalculate the layout when the window resizes, but throttle the
|
|
// rate at which it gets called.
|
|
const self = this;
|
|
if (!self.pendingLayoutAfterResize) {
|
|
self.pendingLayoutAfterResize = true;
|
|
setTimeout(async () => {
|
|
await self.layout();
|
|
self.pendingLayoutAfterResize = false;
|
|
}, 200);
|
|
}
|
|
}
|
|
|
|
// Update the modal layout.
|
|
async layout() { }
|
|
|
|
// Attach the modal to the DOM.
|
|
async attach() {
|
|
if (!this.attached) {
|
|
this.classList.add('first-layout');
|
|
document.body.appendChild(this);
|
|
this.attached = true;
|
|
this.layout();
|
|
|
|
// Delay focus until modal is attached to DOM.
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
this.focus();
|
|
resolve();
|
|
}, 0);
|
|
})
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
// Detach the modal from the DOM.
|
|
detach() {
|
|
if (this.attached) {
|
|
document.body.removeChild(this);
|
|
this.attached = false;
|
|
}
|
|
}
|
|
|
|
// Handle keydown in the modal.
|
|
onKeyDown() { }
|
|
|
|
}
|