summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-04-01 16:09:41 +0200
committerJo-Philipp Wich <jo@mein.io>2019-07-07 15:36:24 +0200
commit9c7eb1decd82344e22a10e6f5ac36b463d2149f5 (patch)
treea79b11f65288a7bc5d1c7a32a5f95ea57a1e57a3 /modules/luci-base
parent808b9f36eb60cf4717cbf28b163d7ad2faa7f157 (diff)
luci-base: switch from server side to client side widget markup
Do not render standard widgets like checkboxes, select boxes, text input fields etc. on the server side anymore but utilize the ui.js primitives instead. This avoids logic duplication between server side cbi templates and JS widgets in the future. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-base')
-rw-r--r--modules/luci-base/luasrc/cbi.lua12
-rw-r--r--modules/luci-base/luasrc/view/cbi/dropdown.htm69
-rw-r--r--modules/luci-base/luasrc/view/cbi/dynlist.htm21
-rw-r--r--modules/luci-base/luasrc/view/cbi/fvalue.htm18
-rw-r--r--modules/luci-base/luasrc/view/cbi/lvalue.htm53
-rw-r--r--modules/luci-base/luasrc/view/cbi/mvalue.htm55
-rw-r--r--modules/luci-base/luasrc/view/cbi/value.htm57
7 files changed, 108 insertions, 177 deletions
diff --git a/modules/luci-base/luasrc/cbi.lua b/modules/luci-base/luasrc/cbi.lua
index 971830fe81..450e413916 100644
--- a/modules/luci-base/luasrc/cbi.lua
+++ b/modules/luci-base/luasrc/cbi.lua
@@ -1347,6 +1347,18 @@ function AbstractValue.deplist2json(self, section, deplist)
return util.serialize_json(deps)
end
+-- Serialize choices
+function AbstractValue.choices(self)
+ if type(self.keylist) == "table" and #self.keylist > 0 then
+ local i, k, v = nil, nil, {}
+ for i, k in ipairs(self.keylist) do
+ v[k] = self.vallist[i] or k
+ end
+ return v
+ end
+ return nil
+end
+
-- Generates the unique CBID
function AbstractValue.cbid(self, section)
return "cbid."..self.map.config.."."..section.."."..self.option
diff --git a/modules/luci-base/luasrc/view/cbi/dropdown.htm b/modules/luci-base/luasrc/view/cbi/dropdown.htm
index 6f4b89905b..40bd8e9536 100644
--- a/modules/luci-base/luasrc/view/cbi/dropdown.htm
+++ b/modules/luci-base/luasrc/view/cbi/dropdown.htm
@@ -1,54 +1,19 @@
<%+cbi/valueheader%>
-
-<%-
- local selected = { }
-
- if self.multiple then
- local val
- for val in luci.util.imatch(self:cfgvalue(section)) do
- selected[val] = true
- end
- else
- selected[self:cfgvalue(section)] = true
- end
-
- if not next(selected) and self.default then
- selected[self.default] = true
- end
--%>
-
-<div class="cbi-dropdown"<%=
- attr("name", cbid) ..
- attr("display-items", self.display or self.size or 3) ..
- attr("dropdown-items", self.dropdown or self.display or self.size or 5) ..
- attr("placeholder", self.placeholder or translate("-- please select --")) ..
- ifattr(self.multiple, "multiple", "multiple") ..
- ifattr(self.optional or self.rmempty, "optional", "optional")
-%>>
- <ul>
- <% local i, key; for i, key in pairs(self.keylist) do %>
- <li<%=
- attr("data-index", i) ..
- attr("data-depends", self:deplist2json(section, self.deplist[i])) ..
- attr("data-value", key) ..
- ifattr(selected[key], "selected", "selected")
- %>>
- <%=pcdata(self.vallist[i])%>
- </li>
- <% end %>
- <% if self.custom then %>
- <li>
- <input type="password" style="display:none" />
- <input class="create-item-input" type="text"<%=
- attr("placeholder", self.custom ~= true and
- self.custom or
- (self.multiple and
- translate("Enter custom values") or
- translate("Enter custom value")))
- %> />
- </li>
- <% end %>
- </ul>
-</div>
-
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Dropdown", self:cfgvalue(section), self:choices(), {
+ id = cbid,
+ name = cbid,
+ sort = self.keylist,
+ multi = self.multiple,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ readonly = self.readonly,
+ maxlength = self.maxlength,
+ placeholder = self.placeholder,
+ display_items = self.display or self.size or 3,
+ dropdown_items = self.dropdown or self.display or self.size or 5,
+ custom_placeholder = self.custom or
+ (self.multiple and translate("Enter custom values") or translate("Enter custom value"))
+ }
+}))%>></div>
<%+cbi/valuefooter%>
diff --git a/modules/luci-base/luasrc/view/cbi/dynlist.htm b/modules/luci-base/luasrc/view/cbi/dynlist.htm
index fa7dbdb418..d50328d79f 100644
--- a/modules/luci-base/luasrc/view/cbi/dynlist.htm
+++ b/modules/luci-base/luasrc/view/cbi/dynlist.htm
@@ -1,13 +1,12 @@
<%+cbi/valueheader%>
-<div<%=
- attr("data-prefix", cbid) ..
- attr("data-browser-path", self.default_path) ..
- attr("data-dynlist", luci.util.serialize_json({
- self.keylist, self.vallist,
- self.datatype, self.optional or self.rmempty
- })) ..
- attr("data-values", luci.util.serialize_json(self:cfgvalue(section))) ..
- ifattr(self.size, "data-size", self.size) ..
- ifattr(self.placeholder, "data-placeholder", self.placeholder)
-%>></div>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "DynamicList", self:cfgvalue(section), self:choices(), {
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ placeholder = self.placeholder
+ }
+}))%>></div>
<%+cbi/valuefooter%>
diff --git a/modules/luci-base/luasrc/view/cbi/fvalue.htm b/modules/luci-base/luasrc/view/cbi/fvalue.htm
index 197d03cf31..7f975b95e1 100644
--- a/modules/luci-base/luasrc/view/cbi/fvalue.htm
+++ b/modules/luci-base/luasrc/view/cbi/fvalue.htm
@@ -1,10 +1,12 @@
<%+cbi/valueheader%>
- <input type="hidden" value="1"<%=
- attr("name", "cbi.cbe." .. self.config .. "." .. section .. "." .. self.option)
- %> />
- <input class="cbi-input-checkbox" data-update="click change" type="checkbox"<%=
- attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) ..
- ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked")
- %> />
- <label<%= attr("for", cbid)%>></label>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Checkbox", self:cfgvalue(section) or self.default, {
+ id = cbid,
+ name = cbid,
+ readonly = self.readonly,
+ hiddenname = "cbi.cbe." .. self.config .. "." .. section .. "." .. self.option,
+ value_enabled = self.enabled or 1,
+ value_disabled = self.disabled or 0
+ }
+}))%>></div>
<%+cbi/valuefooter%>
diff --git a/modules/luci-base/luasrc/view/cbi/lvalue.htm b/modules/luci-base/luasrc/view/cbi/lvalue.htm
index 34d02eeca0..e076488356 100644
--- a/modules/luci-base/luasrc/view/cbi/lvalue.htm
+++ b/modules/luci-base/luasrc/view/cbi/lvalue.htm
@@ -1,43 +1,14 @@
-<%
- local i, key
- local br = self.orientation == "horizontal" and '&#160;' or '<br />'
-%>
-
<%+cbi/valueheader%>
-<% if self.widget == "select" then %>
- <select class="cbi-input-select" data-update="change"<%=
- attr("id", cbid) ..
- attr("name", cbid) ..
- ifattr(self.size, "size")
- %>>
- <% for i, key in pairs(self.keylist) do -%>
- <option<%=
- attr("id", cbid.."-"..key) ..
- attr("value", key) ..
- attr("data-index", i) ..
- attr("data-depends", self:deplist2json(section, self.deplist[i])) ..
- ifattr(tostring(self:cfgvalue(section) or self.default) == key, "selected", "selected")
- %>><%=pcdata(self.vallist[i])%></option>
- <%- end %>
- </select>
-<% elseif self.widget == "radio" then %>
- <div>
- <% for i, key in pairs(self.keylist) do %>
- <label<%=
- attr("data-index", i) ..
- attr("data-depends", self:deplist2json(section, self.deplist[i]))
- %>>
- <input class="cbi-input-radio" data-update="click change" type="radio"<%=
- attr("id", cbid.."-"..key) ..
- attr("name", cbid) ..
- attr("value", key) ..
- ifattr((self:cfgvalue(section) or self.default) == key, "checked", "checked")
- %> />
- <label<%= attr("for", cbid.."-"..key)%>></label>
- <%=pcdata(self.vallist[i])%>
- </label>
- <% if i == self.size then write(br) end %>
- <% end %>
- </div>
-<% end %>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Select", self:cfgvalue(section), self:choices(), {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ widget = self.widget,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ placeholder = self.placeholder
+ }
+}))%>></div>
<%+cbi/valuefooter%>
diff --git a/modules/luci-base/luasrc/view/cbi/mvalue.htm b/modules/luci-base/luasrc/view/cbi/mvalue.htm
index db17450d27..4974a4ed28 100644
--- a/modules/luci-base/luasrc/view/cbi/mvalue.htm
+++ b/modules/luci-base/luasrc/view/cbi/mvalue.htm
@@ -1,43 +1,16 @@
-<%
- local i, key
- local v = self:valuelist(section) or {}
--%>
-
<%+cbi/valueheader%>
-<% if self.widget == "select" then %>
- <select class="cbi-input-select" multiple="multiple" data-update="click change"<%=
- attr("id", cbid) ..
- attr("name", cbid) ..
- ifattr(self.size, "size")
- %>>
- <% for i, key in pairs(self.keylist) do -%>
- <option<%=
- attr("id", cbid.."-"..key) ..
- attr("value", key) ..
- attr("data-index", i) ..
- attr("data-depends", self:deplist2json(section, self.deplist[i])) ..
- ifattr(luci.util.contains(v, key), "selected", "selected")
- %>><%=pcdata(self.vallist[i])%></option>
- <%- end %>
- </select>
-<% elseif self.widget == "checkbox" then %>
- <div>
- <% for i, key in pairs(self.keylist) do %>
- <label<%=
- attr("data-index", i) ..
- attr("data-depends", self:deplist2json(section, self.deplist[i]))
- %>>
- <input class="cbi-input-checkbox" type="checkbox" data-update="click change"<%=
- attr("id", cbid.."-"..key) ..
- attr("name", cbid) ..
- attr("value", key) ..
- ifattr(luci.util.contains(v, key), "checked", "checked")
- %> />
- <label<%= attr("for", cbid.."-"..key)%>></label>
- <%=pcdata(self.vallist[i])%>
- </label>
- <% if self.size and (i % self.size) == 0 then write('<br />') end %>
- <% end %>
- </div>
-<% end %>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Select", self:cfgvalues(section), self:choices(), {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ multi = true,
+ widget = self.widget,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ readonly = self.readonly,
+ placeholder = self.placeholder
+ }
+}))%>></div>
<%+cbi/valuefooter%>
diff --git a/modules/luci-base/luasrc/view/cbi/value.htm b/modules/luci-base/luasrc/view/cbi/value.htm
index 144853fd9f..6060310b19 100644
--- a/modules/luci-base/luasrc/view/cbi/value.htm
+++ b/modules/luci-base/luasrc/view/cbi/value.htm
@@ -1,26 +1,35 @@
<%+cbi/valueheader%>
- <%- if self.password then -%>
- <input type="password" style="position:absolute; left:-100000px" aria-hidden="true" tabindex="-1"<%=
- attr("name", "password." .. cbid)
- %> />
- <%- end -%>
- <input data-update="change"<%=
- attr("id", cbid) ..
- attr("name", cbid) ..
- attr("type", self.password and "password" or "text") ..
- attr("class", self.password and "cbi-input-password" or "cbi-input-text") ..
- attr("value", self:cfgvalue(section) or self.default) ..
- ifattr(self.password, "autocomplete", "new-password") ..
- ifattr(self.size, "size") ..
- ifattr(self.placeholder, "placeholder") ..
- ifattr(self.readonly, "readonly") ..
- ifattr(self.maxlength, "maxlength") ..
- ifattr(self.datatype, "data-type", self.datatype) ..
- ifattr(self.datatype, "data-optional", self.optional or self.rmempty) ..
- ifattr(self.combobox_manual, "data-manual", self.combobox_manual) ..
- ifattr(#self.keylist > 0, "data-choices", { self.keylist, self.vallist })
- %> />
- <%- if self.password then -%>
- <button class="cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" aria-label="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'; event.preventDefault()">∗</button>
- <% end %>
+
+<% local choices = self:choices()
+ if choices then %>
+ <div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Combobox", self:cfgvalue(section) or self.default, choices, {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ readonly = self.readonly,
+ maxlength = self.maxlength,
+ placeholder = self.placeholder,
+ custom_placeholder = self.combobox_manual
+ }
+ }))%>></div>
+<% else %>
+ <div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Textfield", self:cfgvalue(section) or self.default, {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ datatype = self.datatype,
+ optional = self.optional or self.rmempty,
+ password = self.password,
+ readonly = self.readonly,
+ maxlength = self.maxlength,
+ placeholder = self.placeholder
+ }
+ }))%>></div>
+<% end %>
+
<%+cbi/valuefooter%>