AnP/Public/ecma/Components/FormsComponent.ecma.js
2026-07-14 07:28:07 +02:00

172 lines
5.8 KiB
JavaScript

"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
import {Fieldset, Div, Form, UL, Label, Span} 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 {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @access public
*/
this.build = inputs => {
/** @type {form_submit_callback|null} */
const submit = Common.get_value("submit", inputs, null),
/** @type {string} */
name = Common.get_value("name", inputs),
/** @type {string|null} */
view = Common.get_value("view", inputs, null);
return Form({
class : "form-component",
data_name : name,
...(view ? {data_view : view} : {}),
method : Common.get_value("method", inputs, "post"),
action : Common.get_value("action", inputs, "#"),
on_submit : (item, event) => {
event.preventDefault();
anp.execute(submit, {
item : item,
event : event
});
return false;
}
}, [
Fieldset({class : "form"}, [
anp.components.i18n(name, "legend"),
anp.components.i18n(name + "_description", "p"),
Div({class : "form-fields"}, Common.get_value("structure", inputs, []).map(([name, type, ...inputs], i) => {
/** @type {string} */
let id = anp.unique_keys.get(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.i18n.get(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_cancel", inputs, "cancel"), (item, event) => {
anp.routes.back();
}),
anp.components.button(Common.get_value("submit_reset", inputs, "clean"), "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;
})();