AnP/Public/ecma/Components/FormsComponent.ecma.js

196 lines
6.4 KiB
JavaScript

"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.<string, any|null>|Array.<any|null>)} 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.<string, any|null>}
* @access public
*/
this.get_data = form => {
/** @type {Object.<string, any|null>} */
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;
})();