"use strict"; import {Check} from "../Utils/Check.ecma.js"; import {Utils} from "../Utils/Utils.ecma.js"; import {Attributes} from "../Application/Attributes.ecma.js"; /** * @typedef {import("../Application/AnP.ecma.js").AnP} AnP */ /** * @class * @constructor * @param {!AnP} anp * @returns {void} * @access public */ export const FormsComponent = (function(){ /** * @constructs BaseComponent * @param {!AnP} anp * @returns {void} * @access private */ const FormsComponent = function(anp){ /** @type {FormsComponent} */ const self = this; /** @type {boolean} */ let started = false; /** * @returns {void} * @access private */ const constructor = () => {}; /** * @param {?anp_start_callback} callback * @returns {boolean} * @access public */ this.start = (callback = null) => { /** @type {!anp_start_callback} */ const end = ok => { Utils.execute(callback, ok); return ok; }; if(started) return end(false); return end(started = true); }; /** * @param {!(Object.|Array.)} inputs * @returns {string} * @access public */ this.build = inputs => { /** @type {string|null} */ const i18n = Utils.get_value("i18n", inputs), /** @type {string|null} */ text = Utils.get_value("text", inputs, Check.is_array(i18n) ? i18n[0] : i18n); return ["form", { class : "form", on_submit : (item, event) => false, method : "get", action : "#" }, [ ["fieldset", null, [ anp.comp.i18n_text("legend", i18n, text), anp.comp.i18n_text("p", Attributes.i18n_add_suffix(i18n, "text"), Utils.get_value("description", inputs, text)), ["div", {class : "structure"}, Utils.get_array(Utils.get_value("structure", inputs, [])).reduce((structure, item, i) => { /** @type {[string|null, boolean]} */ const [type, is_array] = ( Check.is_array(item) ? [Check.is_string(item[0]) ? item[0] : null, true] : Check.is_dictionary(item) ? [Check.is_string(item.type) ? item.type : null, false] : [null, false]), /** @type {string|null} */ name = Utils.get_value(["name", "i18n"], item), /** @type {string|null} */ i18n = Utils.get_value(["i18n", "name"], item), /** @type {string} */ id = Utils.get_value("id", item) || anp.random_chain(), /** @type {string|null} */ text = Utils.get_value("text", item); structure.push(["div", { data_field : Utils.get_value("name", item, id), data_i : i }, [ ["label", {for : id}, [ anp.comp.i18n(i18n, "span", text), anp.comp.i18n_text("span", Attributes.i18n_add_suffix(i18n, "description"), Utils.get_value("description", item, text) ) ]], ["span", {class : "input"}, anp.comp[type] ? [anp.comp[type]([item, {id : id}])] : null], ["ul", {class : "errors"}] ]]); return structure; }, [])], ["ul", {class : "errors"}], anp.comp.buttons(Utils.get_array(Utils.get_value(["buttons", "actions"], inputs, []))) ]] ]]; }; /** * @param {!(HTMLFormElement|HTMLElement)} form * @returns {Object.} * @access public */ this.get_data = form => { /** @type {Object.} */ const data = {}; (form = FormsComponent.get(form)) && form.querySelectorAll("[name]").forEach(item => { /** @type {string} */ const name_attribute = item.getAttribute("name"), /** @type {boolean} */ is_array = name_attribute.slice(-2) == "[]", /** @type {string} */ name = is_array ? name_attribute.slice(0, -2) : name_attribute; if(is_array) (data[name] || (data[name] = [])).push(self.get_value(item)); else data[name] = self.get_value(item); }); return data; }; /** * @param {!HTMLElement} item * @returns {any|null} * @access public */ this.get_value = (item) => { /** @type {string} */ const type = item.getAttribute("type"), /** @type {string} */ tag = item.tagName.toLowerCase(); return ( type == "number" ? Number(item.value) : type == "date" ? new Date(item.value) : ["radio", "checkbox"].includes(type) ? item.checked : item.value); }; constructor(); }; /** * @param {!HTMLElement} form * @returns {HTMLFormElement|null} * @access public * @static */ FormsComponent.get = form => { if(form){ /** @type {HTMLFormElement} */ const child = form.querySelector && form.querySelector("form.form"); if(child) form = child; else while(( (form.tagName && form.tagName.toLowerCase() != "form") || (form.classList && !form.classList.contains("form")) ) && (form = form.parentNode)); }; return form || null; }; return FormsComponent; })();