From 683bc54fd9bfc22c900dc0cdfcd660d61da253ef Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 6 Aug 2020 17:58:47 +0200 Subject: docs: update js api docs Signed-off-by: Jo-Philipp Wich --- docs/jsapi/form.js.html | 386 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 359 insertions(+), 27 deletions(-) (limited to 'docs/jsapi/form.js.html') diff --git a/docs/jsapi/form.js.html b/docs/jsapi/form.js.html index f266a1c27c..a3c8a15480 100644 --- a/docs/jsapi/form.js.html +++ b/docs/jsapi/form.js.html @@ -292,8 +292,16 @@
  • cfgsections
  • +
  • cfgvalue
  • +
  • filter
  • +
  • formvalue
  • + +
  • getOption
  • + +
  • getUIElement
  • +
  • load
  • option
  • @@ -333,6 +341,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • readonly
  • @@ -423,6 +433,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -513,6 +525,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -599,6 +613,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -693,6 +709,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -783,6 +801,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -873,6 +893,8 @@
  • modaltitle
  • +
  • nodescriptions
  • +
  • parentoption
  • rowcolors
  • @@ -900,8 +922,16 @@
  • append
  • +
  • cfgvalue
  • +
  • filter
  • +
  • formvalue
  • + +
  • getOption
  • + +
  • getUIElement
  • +
  • load
  • option
  • @@ -939,6 +969,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -1071,8 +1103,12 @@ Members +
  • orientation
  • +
  • size
  • +
  • widget
  • +
  • datatype
  • default
  • @@ -1081,6 +1117,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -1225,6 +1263,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -1324,8 +1364,16 @@
  • cfgsections
  • +
  • cfgvalue
  • +
  • filter
  • +
  • formvalue
  • + +
  • getOption
  • + +
  • getUIElement
  • +
  • load
  • option
  • @@ -1367,6 +1415,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -1457,6 +1507,8 @@
  • modaltitle
  • +
  • nodescriptions
  • +
  • rowcolors
  • sectiontitle
  • @@ -1492,8 +1544,16 @@
  • append
  • +
  • cfgvalue
  • +
  • filter
  • +
  • formvalue
  • + +
  • getOption
  • + +
  • getUIElement
  • +
  • load
  • option
  • @@ -1539,6 +1599,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • password
  • @@ -1642,8 +1704,16 @@
  • cfgsections
  • +
  • cfgvalue
  • +
  • filter
  • +
  • formvalue
  • + +
  • getOption
  • + +
  • getUIElement
  • +
  • load
  • option
  • @@ -1687,6 +1757,8 @@
  • modalonly
  • +
  • onchange
  • +
  • optional
  • readonly
  • @@ -2520,6 +2592,8 @@
  • getLocalData
  • +
  • getToken
  • +
  • setLocalData
  • @@ -2670,6 +2744,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -2678,6 +2754,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -2748,6 +2826,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isChecked
  • isValid
  • @@ -2758,6 +2838,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -2798,12 +2880,16 @@
  • closeAllDropdowns
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • triggerValidation
  • @@ -2842,12 +2928,16 @@
  • closeAllDropdowns
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • triggerValidation
  • @@ -2888,6 +2978,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -2896,6 +2988,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -2936,6 +3030,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -2944,6 +3040,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -2980,6 +3078,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -2988,6 +3088,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -3020,6 +3122,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -3028,6 +3132,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -3098,6 +3204,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -3106,6 +3214,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -3170,6 +3280,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -3178,6 +3290,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -3214,6 +3328,8 @@
  • getValue
  • +
  • isChanged
  • +
  • isValid
  • registerEvents
  • @@ -3222,6 +3338,8 @@
  • setChangeEvents
  • +
  • setPlaceholder
  • +
  • setUpdateEvents
  • setValue
  • @@ -3345,17 +3463,7 @@ var CBIJSONConfig = baseclass.extend({ if (!data.hasOwnProperty(sectiontype)) continue; - if (L.isObject(data[sectiontype])) { - this.data[sectiontype] = Object.assign(data[sectiontype], { - '.anonymous': false, - '.name': sectiontype, - '.type': sectiontype - }); - - section_ids.push(sectiontype); - num_sections++; - } - else if (Array.isArray(data[sectiontype])) { + if (Array.isArray(data[sectiontype])) { for (var i = 0, index = 0; i < data[sectiontype].length; i++) { var item = data[sectiontype][i], anonymous, name; @@ -3383,6 +3491,16 @@ var CBIJSONConfig = baseclass.extend({ }); } } + else if (L.isObject(data[sectiontype])) { + this.data[sectiontype] = Object.assign(data[sectiontype], { + '.anonymous': false, + '.name': sectiontype, + '.type': sectiontype + }); + + section_ids.push(sectiontype); + num_sections++; + } } section_ids.sort(L.bind(function(a, b) { @@ -3849,12 +3967,15 @@ var CBIMap = CBIAbstractElement.extend(/** @lends LuCI.form.Map.prototype */ { * an error. */ load: function() { - var doCheckACL = (!(this instanceof CBIJSONMap) && this.readonly == null); + var doCheckACL = (!(this instanceof CBIJSONMap) && this.readonly == null), + loadTasks = [ doCheckACL ? callSessionAccess('uci', this.config, 'write') : true ], + configs = this.parsechain || [ this.config ]; - return Promise.all([ - doCheckACL ? callSessionAccess('uci', this.config, 'write') : true, - this.data.load(this.parsechain || [ this.config ]) - ]).then(L.bind(function(res) { + loadTasks.push.apply(loadTasks, configs.map(L.bind(function(config, i) { + return i ? L.resolveDefault(this.data.load(config)) : this.data.load(config); + }, this))); + + return Promise.all(loadTasks).then(L.bind(function(res) { if (res[0] === false) this.readonly = true; @@ -3918,7 +4039,7 @@ var CBIMap = CBIAbstractElement.extend(/** @lends LuCI.form.Map.prototype */ { E('p', {}, [ _('An error occurred while saving the form:') ]), E('p', {}, [ E('em', { 'style': 'white-space:pre' }, [ e.message ]) ]), E('div', { 'class': 'right' }, [ - E('button', { 'click': ui.hideModal }, [ _('Dismiss') ]) + E('button', { 'class': 'btn', 'click': ui.hideModal }, [ _('Dismiss') ]) ]) ]); } @@ -4369,6 +4490,138 @@ var CBIAbstractSection = CBIAbstractElement.extend(/** @lends LuCI.form.Abstract return obj; }, + /** + * Query underlying option configuration values. + * + * This function is sensitive to the amount of arguments passed to it; + * if only one argument is specified, the configuration values of all + * options within this section are returned as dictionary. + * + * If both the section ID and an option name are supplied, this function + * returns the configuration value of the specified option only. + * + * @param {string} section_id + * The configuration section ID + * + * @param {string} [option] + * The name of the option to query + * + * @returns {null|string|string[]|Object<string, null|string|string[]>} + * Returns either a dictionary of option names and their corresponding + * configuration values or just a single configuration value, depending + * on the amount of passed arguments. + */ + cfgvalue: function(section_id, option) { + var rv = (arguments.length == 1) ? {} : null; + + for (var i = 0, o; (o = this.children[i]) != null; i++) + if (rv) + rv[o.option] = o.cfgvalue(section_id); + else if (o.option == option) + return o.cfgvalue(section_id); + + return rv; + }, + + /** + * Query underlying option widget input values. + * + * This function is sensitive to the amount of arguments passed to it; + * if only one argument is specified, the widget input values of all + * options within this section are returned as dictionary. + * + * If both the section ID and an option name are supplied, this function + * returns the widget input value of the specified option only. + * + * @param {string} section_id + * The configuration section ID + * + * @param {string} [option] + * The name of the option to query + * + * @returns {null|string|string[]|Object<string, null|string|string[]>} + * Returns either a dictionary of option names and their corresponding + * widget input values or just a single widget input value, depending + * on the amount of passed arguments. + */ + formvalue: function(section_id, option) { + var rv = (arguments.length == 1) ? {} : null; + + for (var i = 0, o; (o = this.children[i]) != null; i++) { + var func = this.map.root ? this.children[i].formvalue : this.children[i].cfgvalue; + + if (rv) + rv[o.option] = func.call(o, section_id); + else if (o.option == option) + return func.call(o, section_id); + } + + return rv; + }, + + /** + * Obtain underlying option LuCI.ui widget instances. + * + * This function is sensitive to the amount of arguments passed to it; + * if only one argument is specified, the LuCI.ui widget instances of all + * options within this section are returned as dictionary. + * + * If both the section ID and an option name are supplied, this function + * returns the LuCI.ui widget instance value of the specified option only. + * + * @param {string} section_id + * The configuration section ID + * + * @param {string} [option] + * The name of the option to query + * + * @returns {null|LuCI.ui.AbstractElement|Object<string, null|LuCI.ui.AbstractElement>} + * Returns either a dictionary of option names and their corresponding + * widget input values or just a single widget input value, depending + * on the amount of passed arguments. + */ + getUIElement: function(section_id, option) { + var rv = (arguments.length == 1) ? {} : null; + + for (var i = 0, o; (o = this.children[i]) != null; i++) + if (rv) + rv[o.option] = o.getUIElement(section_id); + else if (o.option == option) + return o.getUIElement(section_id); + + return rv; + }, + + /** + * Obtain underlying option objects. + * + * This function is sensitive to the amount of arguments passed to it; + * if no option name is specified, all options within this section are + * returned as dictionary. + * + * If an option name is supplied, this function returns the matching + * LuCI.form.AbstractValue instance only. + * + * @param {string} [option] + * The name of the option object to obtain + * + * @returns {null|LuCI.form.AbstractValue|Object<string, LuCI.form.AbstractValue>} + * Returns either a dictionary of option names and their corresponding + * option instance objects or just a single object instance value, + * depending on the amount of passed arguments. + */ + getOption: function(option) { + var rv = (arguments.length == 0) ? {} : null; + + for (var i = 0, o; (o = this.children[i]) != null; i++) + if (rv) + rv[o.option] = o; + else if (o.option == option) + return o; + + return rv; + }, + /** @private */ renderUCISection: function(section_id) { var renderTasks = []; @@ -4447,6 +4700,9 @@ var CBIAbstractSection = CBIAbstractElement.extend(/** @lends LuCI.form.Abstract var isEqual = function(x, y) { + if (typeof(y) == 'object' && y instanceof RegExp) + return (x == null) ? false : y.test(x); + if (x != null && y != null && typeof(x) != typeof(y)) return false; @@ -4686,6 +4942,21 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa * @default null */ + /** + * Register a custom value change handler. + * + * If this property is set to a function value, the function is invoked + * whenever the value of the underlying UI input element is changing. + * + * The invoked handler function will receive the DOM click element as + * first and the underlying configuration section ID as well as the input + * value as second and third argument respectively. + * + * @name LuCI.form.AbstractValue.prototype#onchange + * @type function + * @default null + */ + /** * Add a dependency contraint to the option. * @@ -4743,6 +5014,10 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa * Equivalent to the previous example. * </li> * <li> + * <code>opt.depends({ foo: /test/ })</code><br> + * Require the value of `foo` to match the regular expression `/test/`. + * </li> + * <li> * <code>opt.depends({ foo: "test", bar: "qrx" })</code><br> * Require the value of `foo` to be `test` and the value of `bar` to be * `qrx`. @@ -4764,11 +5039,11 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa * </li> * </ul> * - * @param {string|Object<string, string|boolean>} optionname_or_depends + * @param {string|Object<string, string|RegExp>} optionname_or_depends * The name of the option to depend on or an object describing multiple * dependencies which must be satified (a logical "and" expression). * - * @param {string} optionvalue + * @param {string} optionvalue|RegExp * When invoked with a plain option name as first argument, this parameter * specifies the expected value. In case an object is passed as first * argument, this parameter is ignored. @@ -5092,6 +5367,10 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa if (field && field.classList.contains('hidden') == active) { field.classList[active ? 'remove' : 'add']('hidden'); + + if (dom.matches(field.parentNode, '.td.cbi-value-field')) + field.parentNode.classList[active ? 'remove' : 'add']('inactive'); + return true; } @@ -5583,6 +5862,16 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p * @default false */ + /** + * If set to `true`, the header row with the options descriptions will + * not be displayed. By default, descriptions row is automatically displayed + * when at least one option has a description. + * + * @name LuCI.form.TableSection.prototype#nodescriptions + * @type boolean + * @default false + */ + /** * The `TableSection` implementation does not support option tabbing, so * its implementation of `tab()` will always throw an exception when @@ -5720,7 +6009,7 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p trEls.appendChild(trEl); } - if (has_descriptions) { + if (has_descriptions && !this.nodescriptions) { var trEl = E('div', { 'class': 'tr cbi-section-table-descr ' + anon_class }); @@ -5739,7 +6028,7 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p (typeof(opt.width) == 'number') ? opt.width+'px' : opt.width; } - if (this.sortable || this.extedit || this.addremove || has_more) + if (this.sortable || this.extedit || this.addremove || has_more || has_action) trEl.appendChild(E('div', { 'class': 'th cbi-section-table-cell cbi-section-actions' })); @@ -5915,7 +6204,7 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p /** @private */ handleModalSave: function(modalMap, ev) { - return modalMap.save() + return modalMap.save(null, true) .then(L.bind(this.map.load, this.map)) .then(L.bind(this.map.reset, this.map)) .then(ui.hideModal) @@ -6414,6 +6703,20 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ { .then(this.renderFrame.bind(this, section_id, in_table, option_index)); }, + /** @private */ + handleValueChange: function(section_id, state, ev) { + if (typeof(this.onchange) != 'function') + return; + + var value = this.formvalue(section_id); + + if (isEqual(value, state.previousValue)) + return; + + state.previousValue = value; + this.onchange.call(this, ev, section_id, value); + }, + /** @private */ renderFrame: function(section_id, in_table, option_index, nodes) { var config_name = this.uciconfig || this.section.uciconfig || this.map.config, @@ -6483,6 +6786,9 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ { if (depend_list && depend_list.length) optionEl.classList.add('hidden'); + optionEl.addEventListener('widget-change', + L.bind(this.handleValueChange, this, section_id, {})); + optionEl.addEventListener('widget-change', L.bind(this.map.checkDepends, this.map)); @@ -6620,6 +6926,7 @@ var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ { __init__: function() { this.super('__init__', arguments); this.widget = 'select'; + this.orientation = 'horizontal'; this.deplist = []; }, @@ -6631,6 +6938,29 @@ var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ { * @default null */ + /** + * Set the type of the underlying form controls. + * + * May be one of `select` or `radio`. If set to `select`, an HTML + * select element is rendered, otherwise a collection of `radio` + * elements is used. + * + * @name LuCI.form.ListValue.prototype#widget + * @type string + * @default select + */ + + /** + * Set the orientation of the underlying radio or checkbox elements. + * + * May be one of `horizontal` or `vertical`. Only applies to non-select + * widget types. + * + * @name LuCI.form.ListValue.prototype#orientation + * @type string + * @default horizontal + */ + /** @private */ renderWidget: function(section_id, option_index, cfgvalue) { var choices = this.transformChoices(); @@ -6638,7 +6968,9 @@ var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ { id: this.cbid(section_id), size: this.size, sort: this.keylist, + widget: this.widget, optional: this.optional, + orientation: this.orientation, placeholder: this.placeholder, validate: L.bind(this.validate, this, section_id), disabled: (this.readonly != null) ? this.readonly : this.map.readonly @@ -7372,22 +7704,22 @@ var CBISectionValue = CBIValue.extend(/** @lends LuCI.form.SectionValue.prototyp /** @override */ load: function(section_id) { - return this.subsection.load(); + return this.subsection.load(section_id); }, /** @override */ parse: function(section_id) { - return this.subsection.parse(); + return this.subsection.parse(section_id); }, /** @private */ renderWidget: function(section_id, option_index, cfgvalue) { - return this.subsection.render(); + return this.subsection.render(section_id); }, /** @private */ checkDepends: function(section_id) { - this.subsection.checkDepends(); + this.subsection.checkDepends(section_id); return CBIValue.prototype.checkDepends.apply(this, [ section_id ]); }, @@ -7512,7 +7844,7 @@ return baseclass.extend(/** @lends LuCI.form.prototype */ { -- cgit