luci-base: form.js: implement readonly property for forms and options
authorJo-Philipp Wich <jo@mein.io>
Mon, 13 Apr 2020 14:53:10 +0000 (16:53 +0200)
committerJo-Philipp Wich <jo@mein.io>
Tue, 14 Apr 2020 15:08:36 +0000 (17:08 +0200)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/htdocs/luci-static/resources/form.js

index 5c324acc2e0a662ebe6aba6b6704c4a238bfe437..3d9b18efa5dcb1ca8ebd1f4ea67750c9d13d47cd 100644 (file)
@@ -360,9 +360,20 @@ var CBIMap = CBIAbstractElement.extend(/** @lends LuCI.form.Map.prototype */ {
 
                this.config = config;
                this.parsechain = [ config ];
+               this.readonly = false;
                this.data = uci;
        },
 
+       /**
+        * Toggle readonly state of the form.
+        *
+        * If set to `true`, the Map instance is marked readonly and any form
+        * option elements added to it will inherit the readonly state.
+        *
+        * @name LuCI.form.Map.prototype#readonly
+        * @type boolean
+        */
+
        /**
         * Find all DOM nodes within this Map which match the given search
         * parameters. This function is essentially a convenience wrapper around
@@ -1308,6 +1319,19 @@ var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractVa
         * @default null
         */
 
+       /**
+        * Make option element readonly.
+        *
+        * This property defaults to the readonly state of the parent form element.
+        * When set to `true`, the underlying widget is rendered in disabled state,
+        * means its contents cannot be changed and the widget cannot be interacted
+        * with.
+        *
+        * @name LuCI.form.AbstractValue.prototype#readonly
+        * @type boolean
+        * @default false
+        */
+
        /**
         * Override the cell width of a table or grid section child option.
         *
@@ -1960,13 +1984,15 @@ var CBITypedSection = CBIAbstractSection.extend(/** @lends LuCI.form.TypedSectio
                        createEl.appendChild(E('button', {
                                'class': 'cbi-button cbi-button-add',
                                'title': btn_title || _('Add'),
-                               'click': ui.createHandlerFn(this, 'handleAdd')
+                               'click': ui.createHandlerFn(this, 'handleAdd'),
+                               'disabled': this.map.readonly || null
                        }, [ btn_title || _('Add') ]));
                }
                else {
                        var nameEl = E('input', {
                                'type': 'text',
-                               'class': 'cbi-section-create-name'
+                               'class': 'cbi-section-create-name',
+                               'disabled': this.map.readonly || null
                        });
 
                        dom.append(createEl, [
@@ -1981,7 +2007,8 @@ var CBITypedSection = CBIAbstractSection.extend(/** @lends LuCI.form.TypedSectio
                                                        return;
 
                                                return this.handleAdd(ev, nameEl.value);
-                                       })
+                                       }),
+                                       'disabled': this.map.readonly || null
                                })
                        ]);
 
@@ -2024,7 +2051,8 @@ var CBITypedSection = CBIAbstractSection.extend(/** @lends LuCI.form.TypedSectio
                                                        'class': 'cbi-button',
                                                        'name': 'cbi.rts.%s.%s'.format(config_name, cfgsections[i]),
                                                        'data-section-id': cfgsections[i],
-                                                       'click': ui.createHandlerFn(this, 'handleRemove', cfgsections[i])
+                                                       'click': ui.createHandlerFn(this, 'handleRemove', cfgsections[i]),
+                                                       'disabled': this.map.readonly || null
                                                }, [ _('Delete') ])));
                        }
 
@@ -2400,7 +2428,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
                                E('div', {
                                        'title': _('Drag to reorder'),
                                        'class': 'btn cbi-button drag-handle center',
-                                       'style': 'cursor:move'
+                                       'style': 'cursor:move',
+                                       'disabled': this.map.readonly || null
                                }, '☰')
                        ]);
                }
@@ -2441,7 +2470,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
                                E('button', {
                                        'title': btn_title || _('Delete'),
                                        'class': 'cbi-button cbi-button-remove',
-                                       'click': ui.createHandlerFn(this, 'handleRemove', section_id)
+                                       'click': ui.createHandlerFn(this, 'handleRemove', section_id),
+                                       'disabled': this.map.readonly || null
                                }, [ btn_title || _('Delete') ])
                        );
                }
@@ -2592,6 +2622,7 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
                    s = m.section(CBINamedSection, section_id, this.sectiontype);
 
                m.parent = parent;
+               m.readonly = parent.readonly;
 
                s.tabs = this.tabs;
                s.tab_names = this.tab_names;
@@ -2639,7 +2670,8 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
                                        }, [ _('Dismiss') ]), ' ',
                                        E('button', {
                                                'class': 'cbi-button cbi-button-positive important',
-                                               'click': ui.createHandlerFn(this, 'handleModalSave', m)
+                                               'click': ui.createHandlerFn(this, 'handleModalSave', m),
+                                               'disabled': m.readonly || null
                                        }, [ _('Save') ])
                                ])
                        ], 'cbi-modal');
@@ -2926,7 +2958,8 @@ var CBINamedSection = CBIAbstractSection.extend(/** @lends LuCI.form.NamedSectio
                                        E('div', { 'class': 'cbi-section-remove right' },
                                                E('button', {
                                                        'class': 'cbi-button',
-                                                       'click': ui.createHandlerFn(this, 'handleRemove')
+                                                       'click': ui.createHandlerFn(this, 'handleRemove'),
+                                                       'disabled': this.map.readonly || null
                                                }, [ _('Delete') ])));
                        }
 
@@ -2941,7 +2974,8 @@ var CBINamedSection = CBIAbstractSection.extend(/** @lends LuCI.form.NamedSectio
                        sectionEl.appendChild(
                                E('button', {
                                        'class': 'cbi-button cbi-button-add',
-                                       'click': ui.createHandlerFn(this, 'handleAdd')
+                                       'click': ui.createHandlerFn(this, 'handleAdd'),
+                                       'disabled': this.map.readonly || null
                                }, [ _('Add') ]));
                }
 
@@ -3135,7 +3169,8 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ {
                                optional: this.optional || this.rmempty,
                                datatype: this.datatype,
                                select_placeholder: this.placeholder || placeholder,
-                               validate: L.bind(this.validate, this, section_id)
+                               validate: L.bind(this.validate, this, section_id),
+                               disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                        });
                }
                else {
@@ -3145,7 +3180,8 @@ var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ {
                                optional: this.optional || this.rmempty,
                                datatype: this.datatype,
                                placeholder: this.placeholder,
-                               validate: L.bind(this.validate, this, section_id)
+                               validate: L.bind(this.validate, this, section_id),
+                               disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                        });
                }
 
@@ -3200,7 +3236,8 @@ var CBIDynamicList = CBIValue.extend(/** @lends LuCI.form.DynamicList.prototype
                        optional: this.optional || this.rmempty,
                        datatype: this.datatype,
                        placeholder: this.placeholder,
-                       validate: L.bind(this.validate, this, section_id)
+                       validate: L.bind(this.validate, this, section_id),
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return widget.render();
@@ -3265,7 +3302,8 @@ var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ {
                        sort: this.keylist,
                        optional: this.optional,
                        placeholder: this.placeholder,
-                       validate: L.bind(this.validate, this, section_id)
+                       validate: L.bind(this.validate, this, section_id),
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return widget.render();
@@ -3336,7 +3374,8 @@ var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
                        id: this.cbid(section_id),
                        value_enabled: this.enabled,
                        value_disabled: this.disabled,
-                       validate: L.bind(this.validate, this, section_id)
+                       validate: L.bind(this.validate, this, section_id),
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return widget.render();
@@ -3464,7 +3503,8 @@ var CBIMultiValue = CBIDynamicList.extend(/** @lends LuCI.form.MultiValue.protot
                        select_placeholder: this.placeholder,
                        display_items: this.display_size || this.size || 3,
                        dropdown_items: this.dropdown_size || this.size || -1,
-                       validate: L.bind(this.validate, this, section_id)
+                       validate: L.bind(this.validate, this, section_id),
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return widget.render();
@@ -3556,7 +3596,8 @@ var CBITextValue = CBIValue.extend(/** @lends LuCI.form.TextValue.prototype */ {
                        cols: this.cols,
                        rows: this.rows,
                        wrap: this.wrap,
-                       validate: L.bind(this.validate, this, section_id)
+                       validate: L.bind(this.validate, this, section_id),
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return widget.render();
@@ -3626,7 +3667,7 @@ var CBIDummyValue = CBIValue.extend(/** @lends LuCI.form.DummyValue.prototype */
                    hiddenEl = new ui.Hiddenfield(value, { id: this.cbid(section_id) }),
                    outputEl = E('div');
 
-               if (this.href)
+               if (this.href && !((this.readonly != null) ? this.readonly : this.map.readonly))
                        outputEl.appendChild(E('a', { 'href': this.href }));
 
                dom.append(outputEl.lastChild || outputEl,
@@ -3747,7 +3788,8 @@ var CBIButtonValue = CBIValue.extend(/** @lends LuCI.form.ButtonValue.prototype
 
                                                ev.currentTarget.parentNode.nextElementSibling.value = value;
                                                return this.map.save();
-                                       }, section_id)
+                                       }, section_id),
+                                       'disabled': ((this.readonly != null) ? this.readonly : this.map.readonly) || null
                                }, [ btn_title ])
                        ]);
                else
@@ -3922,7 +3964,8 @@ var CBIFileUpload = CBIValue.extend(/** @lends LuCI.form.FileUpload.prototype */
                        show_hidden: this.show_hidden,
                        enable_upload: this.enable_upload,
                        enable_remove: this.enable_remove,
-                       root_directory: this.root_directory
+                       root_directory: this.root_directory,
+                       disabled: (this.readonly != null) ? this.readonly : this.map.readonly
                });
 
                return browserEl.render();