diff --git a/src/components/modal.js b/src/components/modal.js index f6518fa..14f673f 100644 --- a/src/components/modal.js +++ b/src/components/modal.js @@ -18,8 +18,12 @@ import { /** * Create a new HTML Dialog + * + * @param {Object} config */ -export const DialogContructor = (() => { +export function DialogContructor ( + config = {} +) { const initCfg = { state: {}, slugs: {}, @@ -43,362 +47,351 @@ export const DialogContructor = (() => { status: DIALOG_STATUS.NOT_LOADING, } - /** - * Create a new HTML Dialog - * - * @param {Object} config - */ - const dl = function DialogModal( - config = {} - ) { - config = { - ...initCfg, - ...config, - } + config = { + ...initCfg, + ...config, + } - this.eventHandlers = [] + this.eventHandlers = [] - this.state = createSignal({ - ...initialState, - ...config.state, - }) + this.state = createSignal({ + ...initialState, + ...config.state, + }) - this.slugs = { - dialog: toSlug(this.state.value.name, this.state.value.id), - form: toSlug(this.state.value.id, this.state.value.name), - ...config.slugs, - } + this.slugs = { + dialog: toSlug(this.state.value.name, this.state.value.id), + form: toSlug(this.state.value.id, this.state.value.name), + ...config.slugs, + } - this.appElement = document.body + this.appElement = document.body - this.elements = { - ...config.elements, - } + this.elements = { + ...config.elements, + } - this.markup = {} - - effect(() => { - this.markup.header = html` -
- ${this.state.value.name} - ${ - this.state.value.closeTxt && html`` - } -
- ` - this.markup.footer = html` - - ` - }) + this.markup = {} - this.markup.fields = html` - - - -

Some instructions

+ effect(() => { + this.markup.header = html` +
+ ${this.state.value.name} + ${ + this.state.value.closeTxt && html`` + } +
` - - this.markup.content = () => html` - ${this.markup.header} - -
- ${this.markup.fields} - -
-
- - ${this.markup.footer} + this.markup.footer = html` + ` + }) + + this.markup.fields = html` + + + +

Some instructions

+ ` + + this.markup.content = () => html` + ${this.markup.header} + +
+ ${this.markup.fields} + +
+
+ + ${this.markup.footer} + ` + + this.markup = { + ...this.markup, + ...config.markup, + } - this.markup = { - ...this.markup, - ...config.markup, - } - - this.events = { - input: event => { - }, - change: event => { - }, - blur: event => { - // event.preventDefault() - if ( - event?.target?.validity?.patternMismatch && - event?.target?.type !== 'checkbox' - ) { - event.preventDefault() - let label = event.target?.previousElementSibling?.textContent?.trim() - if (label) { - event.target.setCustomValidity(`Invalid ${label}`) - } - } else { - event.target.setCustomValidity('') - } - event.target.reportValidity() - }, - focusout: event => { - // event.preventDefault() - }, - focusin: event => { - // event.preventDefault() - }, - drop: event => { - event.preventDefault() - }, - dragover: event => { - event.preventDefault() - }, - dragend: event => { - event.preventDefault() - }, - dragleave: event => { - event.preventDefault() - }, - render: ( - state, - ) => { - }, - show: ( - state, - ) => { - // focus first input - this.elements.form.querySelector( - 'input' - )?.focus() - }, - close: ( - resolve = res=>{}, - reject = res=>{}, - ) => async event => { + this.events = { + input: event => { + }, + change: event => { + }, + blur: event => { + // event.preventDefault() + if ( + event?.target?.validity?.patternMismatch && + event?.target?.type !== 'checkbox' + ) { event.preventDefault() - removeAllListeners.bind(this) - - this.state.value.status = DIALOG_STATUS.NOT_LOADING - this.elements.dialog?.querySelector('progress')?.remove() - - if (this.elements.dialog.returnValue !== 'cancel') { - resolve(this.elements.dialog.returnValue) - } else { - resolve('cancel') + let label = event.target?.previousElementSibling?.textContent?.trim() + if (label) { + event.target.setCustomValidity(`Invalid ${label}`) } + } else { + event.target.setCustomValidity('') + } + event.target.reportValidity() + }, + focusout: event => { + // event.preventDefault() + }, + focusin: event => { + // event.preventDefault() + }, + drop: event => { + event.preventDefault() + }, + dragover: event => { + event.preventDefault() + }, + dragend: event => { + event.preventDefault() + }, + dragleave: event => { + event.preventDefault() + }, + render: ( + state, + ) => { + }, + show: ( + state, + ) => { + // focus first input + this.elements.form.querySelector( + 'input' + )?.focus() + }, + close: ( + resolve = res=>{}, + reject = res=>{}, + ) => async event => { + event.preventDefault() + removeAllListeners.bind(this) + + this.state.value.status = DIALOG_STATUS.NOT_LOADING + this.elements.dialog?.querySelector('progress')?.remove() + + if (this.elements.dialog.returnValue !== 'cancel') { + resolve(this.elements.dialog.returnValue) + } else { + resolve('cancel') + } - setTimeout(t => { - this.state.value.rendered = null - event?.target?.remove() - }, this.state.value.delay) - }, - submit: event => { - event.preventDefault() + setTimeout(t => { + this.state.value.rendered = null + event?.target?.remove() + }, this.state.value.delay) + }, + submit: event => { + event.preventDefault() + + let fde = formDataEntries(event) + + this.elements.dialog.returnValue = String(fde.intent) + + this.elements.dialog.close(String(fde.intent)) + }, + reset: event => { + event.preventDefault() + this.elements.form?.removeEventListener( + 'close', + this.events.reset + ) + this.elements.dialog.close('cancel') + }, + click: event => { + if (event.target === this.elements.dialog) { + this.elements.dialog.close('cancel') + } + }, + } - let fde = formDataEntries(event) + const dialogElement = document.createElement('dialog') + const formElement = document.createElement('form') + const progressElement = document.createElement('progress') - this.elements.dialog.returnValue = String(fde.intent) + this.elements.dialog = dialogElement + this.elements.form = formElement + this.elements.progress = progressElement - this.elements.dialog.close(String(fde.intent)) - }, - reset: event => { - event.preventDefault() - this.elements.form?.removeEventListener( - 'close', - this.events.reset - ) - this.elements.dialog.close('cancel') - }, - click: event => { - if (event.target === this.elements.dialog) { - this.elements.dialog.close('cancel') - } - }, - } + this.element = this.elements.dialog - const dialogElement = document.createElement('dialog') - const formElement = document.createElement('form') - const progressElement = document.createElement('progress') + progressElement.classList.add('pending') - this.elements.dialog = dialogElement - this.elements.form = formElement - this.elements.progress = progressElement + dialogElement.innerHTML = `` + dialogElement.id = this.slugs.dialog + if (this.state.value.responsive) { + dialogElement.classList.add('responsive') + } + dialogElement.classList.add(...(this.state.value.placement.split(' '))) - this.element = this.elements.dialog + formElement.name = `${this.slugs.form}` + formElement.method = 'dialog' + formElement.innerHTML = this.markup.content() - progressElement.classList.add('pending') + dialogElement.insertAdjacentElement( + 'afterbegin', + formElement + ) - dialogElement.innerHTML = `` - dialogElement.id = this.slugs.dialog - if (this.state.value.responsive) { - dialogElement.classList.add('responsive') - } - dialogElement.classList.add(...(this.state.value.placement.split(' '))) - - formElement.name = `${this.slugs.form}` - formElement.method = 'dialog' - formElement.innerHTML = this.markup.content() - - dialogElement.insertAdjacentElement( - 'afterbegin', - formElement - ) - - /** - * Show the dialog - * @function - */ - this.show = (callback, el = this.appElement) => new Promise((resolve, reject) => { - removeAllListeners.call(this) - addListeners.call(this, resolve, reject) - console.log('modal.js dialog show', this.elements.dialog) - - this.render({ - el, - position: 'afterend' - }) - - this.elements.dialog.show() - this.events.show?.(this) - callback?.() + /** + * Show the dialog + * @function + */ + this.show = (callback, el = this.appElement) => new Promise((resolve, reject) => { + removeAllListeners.call(this) + addListeners.call(this, resolve, reject) + console.log('modal.js dialog show', this.elements.dialog) + + this.render({ + el, + position: 'afterend' }) - /** - * Show the Modal form of the dialog - * @function - */ - this.showModal = (callback, el = this.appElement) => new Promise((resolve, reject) => { - removeAllListeners.call(this) - addListeners.call(this, resolve, reject) - console.log('modal.js dialog showModal', this, this.elements.dialog) - - this.render({ - el, - // cfg: config, - position: 'afterend' - }) - - this.elements.dialog.showModal() - this.events.show?.(this) - callback?.() + this.elements.dialog.show() + this.events.show?.(this) + callback?.() + }) + + /** + * Show the Modal form of the dialog + * @function + */ + this.showModal = (callback, el = this.appElement) => new Promise((resolve, reject) => { + removeAllListeners.call(this) + addListeners.call(this, resolve, reject) + console.log('modal.js dialog showModal', this, this.elements.dialog) + + this.render({ + el, + // cfg: config, + position: 'afterend' }) - /** - * Close the dialog - * @function - */ - this.close = returnVal => this.elements.dialog.close(returnVal) - - /** - * Update the config of the dialog - * @function - */ - this.updateConfig = (config = {}) => { - console.log('Dialog updateConfig TOP', config) - - for (let param in config) { - if ('value' in this[param]) { - this[param].value = { - ...this[param].value, - ...(config[param] || {}), - } - } else { - this[param] = { - ...this[param], - ...(config[param] || {}), - } - } - } + this.elements.dialog.showModal() + this.events.show?.(this) + callback?.() + }) - console.log('Dialog updateConfig BOT', this) - } + /** + * Close the dialog + * @function + */ + this.close = returnVal => this.elements.dialog.close(returnVal) - /** - * Trigger the rendering of the dialog - * @function - */ - this.render = ({ - cfg = {}, - position = 'afterend', - el = this.appElement, - }) => { - console.log('dialog render', this, dl) - - if (el !== this.appElement) { - this.appElement = el + /** + * Update the config of the dialog + * @function + */ + this.updateConfig = (config = {}) => { + console.log('Dialog updateConfig TOP', config) + + for (let param in config) { + if ('value' in this[param]) { + this[param].value = { + ...this[param].value, + ...(config[param] || {}), + } + } else { + this[param] = { + ...this[param], + ...(config[param] || {}), + } } + } - this.updateConfig(cfg) + console.log('Dialog updateConfig BOT', this) + } - console.log('DIALOG elements', this, this.elements) + /** + * Trigger the rendering of the dialog + * @function + */ + this.render = ({ + cfg = {}, + position = 'afterend', + el = this.appElement, + }) => { + console.log('dialog render', this) + + if (el !== this.appElement) { + this.appElement = el + } - this.elements.dialog.id = this.slugs.dialog - this.elements.form.name = this.slugs.form - this.elements.form.innerHTML = this.markup.content() + this.updateConfig(cfg) - console.log('DIALOG RENDER STATE', this.state.value, cfg) + console.log('DIALOG elements', this, this.elements) - console.log('DIALOG RENDER', position, this.slugs.dialog) + this.elements.dialog.id = this.slugs.dialog + this.elements.form.name = this.slugs.form + this.elements.form.innerHTML = this.markup.content() - if ( - this.state.value.status === DIALOG_STATUS.LOADING - ) { - this.elements.form.insertAdjacentElement( - 'beforebegin', - this.elements.progress, - ) - } + console.log('DIALOG RENDER STATE', this.state.value, cfg) - if ( - this.state.value.status === DIALOG_STATUS.SUCCESS || - this.state.value.status === DIALOG_STATUS.ERROR - ) { - this.elements.dialog.querySelector('progress')?.remove() - } + console.log('DIALOG RENDER', position, this.slugs.dialog) - if (!this.state.value.rendered) { - console.log('!this.state.rendered el', el, this.appElement, this.elements.dialog) - // @ts-ignore - el?.insertAdjacentElement(position, this.elements.dialog) - this.state.value.rendered = this.elements.dialog + if ( + this.state.value.status === DIALOG_STATUS.LOADING + ) { + this.elements.form.insertAdjacentElement( + 'beforebegin', + this.elements.progress, + ) + } - this.elements.dialog.addEventListener( - 'close', - this.events.close - ) - } + if ( + this.state.value.status === DIALOG_STATUS.SUCCESS || + this.state.value.status === DIALOG_STATUS.ERROR + ) { + this.elements.dialog.querySelector('progress')?.remove() + } - this.events.render(this.state) + if (!this.state.value.rendered) { + console.log('!this.state.rendered el', el, this.appElement, this.elements.dialog) + // @ts-ignore + el?.insertAdjacentElement(position, this.elements.dialog) + this.state.value.rendered = this.elements.dialog - return this + this.elements.dialog.addEventListener( + 'close', + this.events.close + ) } - } - return dl -})(); + this.events.render(this.state) + + return this + } +} export default DialogContructor