diff --git a/src/core/js/form_elements.js b/src/core/js/form_elements.js index 18e75033f18cbe03799c75ede7d4894375dcce7e..7662f6a224471d33f21b92a7271d37481938a966 100644 --- a/src/core/js/form_elements.js +++ b/src/core/js/form_elements.js @@ -85,13 +85,15 @@ var form_elements = new function () { * The configuration for double, integer, date input elements. * * There are specializations of this configuration object. See - * {@link ReferenceDropDownConfig} + * {@link ReferenceDropDownConfig}, {@link RangeFieldConfig}. * * @typedef {object} FieldConfig + * * @property {string} name * @property {string} type * @property {string} label * @see {@link ReferenceDropDownConfig} + * @see {@link RangeFieldConfig} */ this.version = "0.1"; @@ -117,7 +119,7 @@ var form_elements = new function () { this.get_cache_value = function (field) { var ret = $(field) .find(":input") - .val() + .val(); if (!ret) { return null; } else { @@ -297,6 +299,14 @@ var form_elements = new function () { return form_elements._make_option(entity_id, desc); } + /** + * Return an `option` element for a `select`. + * + * @param {string} value - the actual value of the option element. + * @param {string} label - the string which is shown for this option in the + * drop-down menu of the select input. + * @return {HTMLElement} + */ this._make_option = function (value, label) { const opt_str = '<option value="' + value + '">' + label + "</option>"; @@ -350,6 +360,16 @@ var form_elements = new function () { return ret[0]; } + /** + * Return a new select element. + * + * This function is mainly used by other factory functions, e.g. {@link + * make_reference_select} and {@link make_select_input}. + * + * @param {boolean} multiple - the `multiple` attribute of the select element. + * @param {string} name - the name of the select element. + * @return {HTMLElement} + */ this._make_select = function (multiple, name) { const ret = $(`<select class="selectpicker form-control" name="${name}" title="Nothing selected"/>`); if (typeof name !== "undefined") { @@ -409,10 +429,23 @@ var form_elements = new function () { return result; } + /** + * Call a server-side script with the content a the given form and + * return the results. + * + * Note that the form should be one generated by this form_elements + * module. Otherwise it cannot be guaranteed that the form will be + * serialized (to json) correctly. + * + * @param {string} script - the path of the script + * @param {HTMLElements} form - a form generated by this module. + * @return {ScriptingResult} the results of the call. + */ this._run_script = async function (script, form) { const form_objects = form_elements.form_to_object(form[0]); const json_str = JSON.stringify(form_objects[0]); + // append non-file form fields to the request const params = { "-p0": { "filename": "form.json", @@ -422,6 +455,7 @@ var form_elements = new function () { } }; + // append files to the request const files = form_objects[1]; for (let i = 0; i < files.length; i++) { params[`file_${i}`] = { @@ -446,7 +480,8 @@ var form_elements = new function () { */ /** - * Bla, TODO + * Convert the reponse of a server-side scripting call into a {@link + * ScriptingResult} object. * * @param {XMLDocument} result * @return {ScriptingResult} @@ -598,9 +633,20 @@ var form_elements = new function () { } /** - * generate a java script object representation of a form + * Generate a java script object representation of a form and extract the + * files from the form. + * + * The property names (aka keys) are the names of the form fields and + * subforms. The values are single strings or arrays of strings. If the + * field was had a file-type input, the value is a string identifying the + * file blob which belongs to this key. * - * @function + * Subforms lead to nested objects of the same structure. + * + * @param {HTMLElement} form - a form generated by this module. + * @return {object[]} - an array of length 2. The first element is an + * object representing the fields of the form. The second contains a + * list of file blobs resulting from file inputs in the form. */ this.form_to_object = function (form) { this.logger.trace("entity form_to_json", form); @@ -635,12 +681,15 @@ var form_elements = new function () { var fileList = child.files; if (fileList.length > 0) { for (let i = 0; i < fileList.length; i++) { + // generate an identifyer for the file(s) of this input value = name + "_" + fileList[i].name; if (typeof data[name] === "undefined") { + // first and possibly only value data[name] = value } else if (Array.isArray(data[name])) { data[name].push(value); } else { + // there is a value present yet - convert to array. data[name] = [data[name], value] } files.push({ @@ -693,6 +742,16 @@ var form_elements = new function () { } /** + * Return a new form field (or a subform). + * + * This function is intended to be called by make_form and recursively by + * other make_* functions which create subforms or other deeper structured + * form fields. + * + * This function also configures the caching, whether a form field is + * 'required' or not, and the help for each field. + * + * @param {FieldConfig} config - the configuration of the form field * @return {HTMLElement} */ this.make_form_field = function (config) { @@ -834,6 +893,17 @@ var form_elements = new function () { } /** + * @typedef {object} SubFormConfig + * + * @augments FieldConfig + * @property {FieldConfig[]} fields - array of fields. The order is the + * order in which they appear in the resulting subform. + */ + + /** + * Return a new subform. + * + * @param {SubFormConfig} config - the configuration of the subform. * @return {HTMLElement} */ this.make_subform = function (config) { @@ -1159,11 +1229,24 @@ var form_elements = new function () { } /** + * @typedef {object} RangeFieldConfig + * + * @augments FieldConfig + * @property {FieldConfig} from - the start point of the range. This is + * usually an integer or double input field. + * @property {FieldConfig] to - the end point of the range. This is + * usually an integer or a double input field. + */ + + /** + * Return a new form field representing a range of numbers. + * + * @param {RangeFieldConfig} config * @return {HTMLElement} */ this.make_range_input = function (config) { - // TODO + // TODO // 1. wrapp both inputs to separate it from the label into a container // 2. make two rows for each input // 3. make inline-block for all included elements @@ -1218,6 +1301,9 @@ var form_elements = new function () { } /** + * Return a new date field. + * + * @param {FieldConfig} config * @return {HTMLElement} */ this.make_date_input = function (config) { @@ -1225,6 +1311,9 @@ var form_elements = new function () { } /** + * Return a new text field. + * + * @param {FieldConfig} config * @return {HTMLElement} */ this.make_text_input = function (config) { @@ -1237,7 +1326,7 @@ var form_elements = new function () { * * `config.type` is set to "number" and overrides any other type. * - * @param {form_elements.input_config} config. + * @param {FieldConfig} config. * @returns {HTMLElement} a double form field. */ this.make_double_input = function (config) { @@ -1255,7 +1344,7 @@ var form_elements = new function () { * * `config.type` is set to "number" and overrides any other type. * - * @param {form_elements.input_config} config. + * @param {FieldConfig} config. * @returns {HTMLElement} an integer form field. */ this.make_integer_input = function (config) { @@ -1271,6 +1360,18 @@ var form_elements = new function () { } /** + * @typedef {object} FileFieldConfig + * + * @augments FieldConfig + * @property {boolean} [multiple=false] - whether to accept multiple files. + * @property {string} [accept] - a comma separated list of file extensions + * which are accepted (exclusively). + */ + + /** + * Return a new form field for a file upload. + * + * @param {FileFieldConfig} config - configuration for this form field. * @return {HTMLElement} */ this.make_file_input = function (config) { @@ -1290,10 +1391,26 @@ var form_elements = new function () { return ret; } + /** + * @typedef {object} SelectOptionConfig + * + * @property {string} value - the value of the select option. + * @property {string} [label] - a visible representation (think: + * description) of the value of the select option. defaults to the + * value itself. + */ + + /** + * @typedef {object} SelectFieldConfig + * + * @augments {FieldConfig} + * @property {SelectOptionConfig} - options + */ + /** * Return a select field. * - * @param {form_elements.input_config} config + * @param {SelectFieldConfig} config * @returns {HTMLElement} a select field. */ this.make_select_input = function (config) {