"use strict"; import {Fieldset, Div, Form, UL} from "../Utils/HTMLDSL.ecma.js"; /** * @class FormsComponent * @constructor * @param {!AnP} anp * @return {void} * @access private * @static */ export const FormsComponent = (function(){ /** * @callback form_submit_callback * @param {!HTMLElement} form * @param {!Event} event * @return {any|null|void} */ /** * @constructs FormsComponent * @param {!AnP} anp * @return {void} * @access private * @static */ const FormsComponent = function(anp){ /** @type {FormsComponent} */ const self = this; /** * @returns {void} * @access private */ const constructor = () => { setTimeout(() => { anp.components.forms = self; anp.components.form = self.build; }, 0); }; /** * @param {string} name * @param {!(Object.|Array.)} inputs * @return {Array.} * @access public */ this.build = (name, inputs) => { /** @type {form_submit_callback|null} */ const submit = Common.get_value("submit", inputs, null); return Form({ data_name : name, method : Common.get_value("method", inputs, "post"), action : Common.get_value("action", inputs, "#"), ...(submit ? {on_submit : submit} : {}) }, [ Fieldset({class : "form"}, [ anp.components.i18n(name, "legend"), anp.components.i18n(name + "_description", "p"), Div({class : "form-fields"}, Common.get_value("structure", inputs, []).map(([type, name, ...inputs], i) => { /** @type {string} */ let id = anp.unique_keys.create(true), /** @type {number} */ l = inputs.length - 1; if(!Check.is_dictionary(inputs[l])){ inputs.push({}); l ++; }; inputs[l].id = id; return Div({ data_field : name, data_i : i }, [ Label({ for : id, data_i18n : name, data_i18n_without : true, title : anp.components.i18n(name, "label") }, [ anp.components.i18n(name), anp.components.i18n(name + "_description"), ]), Span({class : "value"}, [ anp.components[type](name, ...inputs) ]), UL({class : "errors"}) ]); })), UL({class : "global-errors"}), Div({class : "buttons"}, Common.get_value(["actions", "buttons"], inputs, []).concat( anp.components.button(Common.get_value("submit_reset", inputs, "reset"), "reset"), submit ? anp.components.button(Common.get_value("submit_name", inputs, "submit"), "submit") : null )) ]) ]); }; this.get = item => { if(item) while(item.tagName.toLowerCase() != "form" && (item = item.parentElement)); return item; }; this.get_values = form => [...self.get(form).querySelectorAll("[name]")].reduce((values, field) => { let name = field.getAttribute("name"); const is_array = self.is_array(field), tag = field.tagName.toLowerCase(), type = field.getAttribute("type").toLowerCase().trim(); if(is_array){ (values[name = name.slice(0, -2)] = values[name] || []).push(self.get_value(field)); }else values[name] = self.get_value(field); return values; }, {}); this.is_array = input => input.getAttribute("name").endsWith("[]"); this.get_value = input => { switch(input.tagName.toLowerCase()){ case "select": return input.multiple ? [...input.options].filter(option => option.selected).map(option => option.value) : input.value; }; switch(input.getAttribute("type")){ case "checkbox": case "radio": return self.is_array(input) ? input.checked ? input.value : null : input.checked; case "number": return parseFloat(input.value) || 0; }; return input.value; }; constructor(); }; return FormsComponent; })();