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

152 lines
5.0 KiB
JavaScript

"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.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @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;
})();