summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-compat/luasrc/view/cbi
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-11-03 20:49:31 +0100
committerJo-Philipp Wich <jo@mein.io>2019-11-03 20:49:31 +0100
commitd5dff8f9a5ca85d197cbb6037f95053bc55941e5 (patch)
treeeeb9271b96ba7b52bad777841ca4ebd452b1a2b0 /modules/luci-compat/luasrc/view/cbi
parent9e57fbb2c3f9c44cdf0a57e6fb9c1df32c84d52b (diff)
treewide: move server side CBI support to luci-compat
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-compat/luasrc/view/cbi')
-rw-r--r--modules/luci-compat/luasrc/view/cbi/browser.htm10
-rw-r--r--modules/luci-compat/luasrc/view/cbi/button.htm7
-rw-r--r--modules/luci-compat/luasrc/view/cbi/cell_valuefooter.htm2
-rw-r--r--modules/luci-compat/luasrc/view/cbi/cell_valueheader.htm12
-rw-r--r--modules/luci-compat/luasrc/view/cbi/compound.htm1
-rw-r--r--modules/luci-compat/luasrc/view/cbi/delegator.htm24
-rw-r--r--modules/luci-compat/luasrc/view/cbi/dropdown.htm19
-rw-r--r--modules/luci-compat/luasrc/view/cbi/dvalue.htm13
-rw-r--r--modules/luci-compat/luasrc/view/cbi/dynlist.htm12
-rw-r--r--modules/luci-compat/luasrc/view/cbi/error.htm19
-rw-r--r--modules/luci-compat/luasrc/view/cbi/footer.htm41
-rw-r--r--modules/luci-compat/luasrc/view/cbi/full_valuefooter.htm12
-rw-r--r--modules/luci-compat/luasrc/view/cbi/full_valueheader.htm9
-rw-r--r--modules/luci-compat/luasrc/view/cbi/fvalue.htm12
-rw-r--r--modules/luci-compat/luasrc/view/cbi/header.htm18
-rw-r--r--modules/luci-compat/luasrc/view/cbi/ipaddr.htm27
-rw-r--r--modules/luci-compat/luasrc/view/cbi/lvalue.htm14
-rw-r--r--modules/luci-compat/luasrc/view/cbi/map.htm40
-rw-r--r--modules/luci-compat/luasrc/view/cbi/mvalue.htm24
-rw-r--r--modules/luci-compat/luasrc/view/cbi/nsection.htm29
-rw-r--r--modules/luci-compat/luasrc/view/cbi/nullsection.htm37
-rw-r--r--modules/luci-compat/luasrc/view/cbi/simpleform.htm77
-rw-r--r--modules/luci-compat/luasrc/view/cbi/tabcontainer.htm14
-rw-r--r--modules/luci-compat/luasrc/view/cbi/tblsection.htm203
-rw-r--r--modules/luci-compat/luasrc/view/cbi/tsection.htm52
-rw-r--r--modules/luci-compat/luasrc/view/cbi/tvalue.htm5
-rw-r--r--modules/luci-compat/luasrc/view/cbi/ucisection.htm56
-rw-r--r--modules/luci-compat/luasrc/view/cbi/upload.htm14
-rw-r--r--modules/luci-compat/luasrc/view/cbi/value.htm35
-rw-r--r--modules/luci-compat/luasrc/view/cbi/valuefooter.htm1
-rw-r--r--modules/luci-compat/luasrc/view/cbi/valueheader.htm1
-rw-r--r--modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm173
32 files changed, 1013 insertions, 0 deletions
diff --git a/modules/luci-compat/luasrc/view/cbi/browser.htm b/modules/luci-compat/luasrc/view/cbi/browser.htm
new file mode 100644
index 0000000000..eb47ffafe6
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/browser.htm
@@ -0,0 +1,10 @@
+<%+cbi/valueheader%>
+
+<input class="cbi-input-text" type="text"<%=
+ attr("id", cbid) ..
+ attr("name", cbid) ..
+ attr("value", self:cfgvalue(section) or self.default) ..
+ attr("data-browser", self.default_path or "")
+%> />
+
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/button.htm b/modules/luci-compat/luasrc/view/cbi/button.htm
new file mode 100644
index 0000000000..6ccba58f23
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/button.htm
@@ -0,0 +1,7 @@
+<%+cbi/valueheader%>
+ <% if self:cfgvalue(section) ~= false then %>
+ <input class="cbi-button cbi-button-<%=self.inputstyle or "button" %>" type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> />
+ <% else %>
+ -
+ <% end %>
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/cell_valuefooter.htm b/modules/luci-compat/luasrc/view/cbi/cell_valuefooter.htm
new file mode 100644
index 0000000000..bdd6bc9687
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/cell_valuefooter.htm
@@ -0,0 +1,2 @@
+</div>
+</div>
diff --git a/modules/luci-compat/luasrc/view/cbi/cell_valueheader.htm b/modules/luci-compat/luasrc/view/cbi/cell_valueheader.htm
new file mode 100644
index 0000000000..4b70957543
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/cell_valueheader.htm
@@ -0,0 +1,12 @@
+<%-
+ local title = luci.util.trim(striptags(self.title))
+ local descr = luci.util.trim(striptags(self.description))
+ local ftype = self.typename or (self.template and self.template:gsub("^.+/", ""))
+-%>
+<div class="td cbi-value-field<% if self.error and self.error[section] then %> cbi-value-error<% end %><% if self.password then %> nowrap<% end %>"<%=
+ attr("data-name", self.option) ..
+ ifattr(ftype and #ftype > 0, "data-type", ftype) ..
+ ifattr(title and #title > 0, "data-title", title, true) ..
+ ifattr(descr and #descr > 0, "data-description", descr, true)
+%>>
+<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>">
diff --git a/modules/luci-compat/luasrc/view/cbi/compound.htm b/modules/luci-compat/luasrc/view/cbi/compound.htm
new file mode 100644
index 0000000000..12d02bb1d8
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/compound.htm
@@ -0,0 +1 @@
+<%- self:render_children() %>
diff --git a/modules/luci-compat/luasrc/view/cbi/delegator.htm b/modules/luci-compat/luasrc/view/cbi/delegator.htm
new file mode 100644
index 0000000000..4fd19265d8
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/delegator.htm
@@ -0,0 +1,24 @@
+<%- self.active:render() %>
+ <div class="cbi-page-actions">
+ <input type="hidden" name="cbi.delg.current" value="<%=self.current%>" />
+<% for _, x in ipairs(self.chain) do %>
+ <input type="hidden" name="cbi.delg.path" value="<%=x%>" />
+<% end %>
+<% if not self.disallow_pageactions then %>
+<% if self.allow_finish and not self:get_next(self.current) then %>
+ <input class="cbi-button cbi-button-finish" type="submit" value="<%:Finish%>" />
+<% elseif self:get_next(self.current) then %>
+ <input class="cbi-button cbi-button-next" type="submit" value="<%:Next »%>" />
+<% end %>
+<% if self.allow_cancel then %>
+ <input class="cbi-button cbi-button-cancel" type="submit" name="cbi.cancel" value="<%:Cancel%>" />
+<% end %>
+<% if self.allow_reset then %>
+ <input class="cbi-button cbi-button-reset" type="reset" value="<%:Reset%>" />
+<% end %>
+<% if self.allow_back and self:get_prev(self.current) then %>
+ <input class="cbi-button cbi-button-back" type="submit" name="cbi.delg.back" value="<%:« Back%>" />
+<% end %>
+<% end %>
+ <script type="text/javascript">cbi_d_update();</script>
+ </div>
diff --git a/modules/luci-compat/luasrc/view/cbi/dropdown.htm b/modules/luci-compat/luasrc/view/cbi/dropdown.htm
new file mode 100644
index 0000000000..927ecf2396
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/dropdown.htm
@@ -0,0 +1,19 @@
+<%+cbi/valueheader%>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Dropdown", self:cfgvalue(section) or self.default, self:choices(), {
+ id = cbid,
+ name = cbid,
+ sort = self.keylist,
+ multiple = 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-compat/luasrc/view/cbi/dvalue.htm b/modules/luci-compat/luasrc/view/cbi/dvalue.htm
new file mode 100644
index 0000000000..78e6f323d7
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/dvalue.htm
@@ -0,0 +1,13 @@
+<%+cbi/valueheader%>
+<% if self.href then %><a href="<%=self.href%>"><% end -%>
+ <%
+ local val = self:cfgvalue(section) or self.default or ""
+ if not self.rawhtml then
+ write(pcdata(val))
+ else
+ write(val)
+ end
+ %>
+<%- if self.href then %></a><%end%>
+<input type="hidden" id="<%=cbid%>" value="<%=pcdata(self:cfgvalue(section) or self.default or "")%>" />
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/dynlist.htm b/modules/luci-compat/luasrc/view/cbi/dynlist.htm
new file mode 100644
index 0000000000..2a3da67ff9
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/dynlist.htm
@@ -0,0 +1,12 @@
+<%+cbi/valueheader%>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "DynamicList", self:cfgvalue(section) or self.default, 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-compat/luasrc/view/cbi/error.htm b/modules/luci-compat/luasrc/view/cbi/error.htm
new file mode 100644
index 0000000000..75ec1082aa
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/error.htm
@@ -0,0 +1,19 @@
+<div class="cbi-map" id="cbi-<%=self.config%>">
+ <% if self.title and #self.title > 0 then %><h2 name="content"><%=self.title%></h2><% end %>
+ <% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %>
+
+ <p class="alert-message danger">
+ <%: The configuration file could not be loaded due to the following error: %><br />
+ <code><%=pcdata(self.error)%></code>
+ </p>
+
+ <textarea name="cbi.source" style="width:100%; margin-bottom:1em" rows="<%=math.max(self.source:cmatch("\n"), 10)%>"><%=pcdata(self.source)%></textarea>
+
+ <p class="alert-message">
+ <%: Edit the raw configuration data above to fix any error and hit "Save" to reload the page. %>
+ </p>
+
+ <div class="cbi-page-actions">
+ <input class="cbi-button cbi-button-apply" type="submit" name="cbi.save" value="<%:Save%>" />
+ </div>
+</div>
diff --git a/modules/luci-compat/luasrc/view/cbi/footer.htm b/modules/luci-compat/luasrc/view/cbi/footer.htm
new file mode 100644
index 0000000000..ed632202ce
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/footer.htm
@@ -0,0 +1,41 @@
+<%
+ local display_back = (redirect and not flow.hidebackbtn)
+ local display_skip = (flow.skip)
+ local display_apply = (not autoapply and not flow.hideapplybtn)
+ local display_save = (not flow.hidesavebtn)
+ local display_reset = (not flow.hideresetbtn)
+
+ if pageaction and
+ (display_back or display_skip or display_apply or display_save or display_reset)
+ then
+ %><div class="cbi-page-actions"><%
+
+ if display_back then
+ %><input class="cbi-button cbi-button-link" type="button" value="<%:Back to Overview%>" onclick="location.href='<%=pcdata(redirect)%>'" /> <%
+ end
+
+ if display_skip then
+ %><input class="cbi-button cbi-button-skip" type="button" value="<%:Skip%>" onclick="cbi_submit(this, 'cbi.skip')" /> <%
+ end
+
+ if display_apply then
+ %><input class="cbi-button cbi-button-apply" type="button" value="<%:Save & Apply%>" onclick="cbi_submit(this, 'cbi.apply')" /> <%
+ end
+
+ if display_save then
+ %><input class="cbi-button cbi-button-save" type="submit" value="<%:Save%>" /> <%
+ end
+
+ if display_reset then
+ %><input class="cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" /> <%
+ end
+
+ %></div><%
+ end
+%>
+
+</form>
+
+<script type="text/javascript">cbi_init();</script>
+
+<%+footer%>
diff --git a/modules/luci-compat/luasrc/view/cbi/full_valuefooter.htm b/modules/luci-compat/luasrc/view/cbi/full_valuefooter.htm
new file mode 100644
index 0000000000..d4ad093efa
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/full_valuefooter.htm
@@ -0,0 +1,12 @@
+ <% if self.description and #self.description > 0 then -%>
+ <% if not luci.util.instanceof(self, luci.cbi.DynamicList) and (not luci.util.instanceof(self, luci.cbi.Flag) or self.orientation == "horizontal") then -%>
+ <br />
+ <%- end %>
+ <div class="cbi-value-description">
+ <%=self.description%>
+ </div>
+ <%- end %>
+ <%- if self.title and #self.title > 0 then -%>
+ </div>
+ <%- end -%>
+</div>
diff --git a/modules/luci-compat/luasrc/view/cbi/full_valueheader.htm b/modules/luci-compat/luasrc/view/cbi/full_valueheader.htm
new file mode 100644
index 0000000000..1d9ebeba94
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/full_valueheader.htm
@@ -0,0 +1,9 @@
+<div class="cbi-value<% if self.error and self.error[section] then %> cbi-value-error<% end %><% if self.last_child then %> cbi-value-last<% end %><% if self.password then %> nowrap<% end %>" id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>">
+ <%- if self.title and #self.title > 0 then -%>
+ <label class="cbi-value-title"<%= attr("for", cbid) %>>
+ <%- if self.titleref then -%><a title="<%=self.titledesc or translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=self.titleref%>"><%- end -%>
+ <%-=self.title-%>
+ <%- if self.titleref then -%></a><%- end -%>
+ </label>
+ <div class="cbi-value-field">
+ <%- end -%>
diff --git a/modules/luci-compat/luasrc/view/cbi/fvalue.htm b/modules/luci-compat/luasrc/view/cbi/fvalue.htm
new file mode 100644
index 0000000000..7f975b95e1
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/fvalue.htm
@@ -0,0 +1,12 @@
+<%+cbi/valueheader%>
+<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-compat/luasrc/view/cbi/header.htm b/modules/luci-compat/luasrc/view/cbi/header.htm
new file mode 100644
index 0000000000..821fa3efae
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/header.htm
@@ -0,0 +1,18 @@
+<%+header%>
+<form method="post" name="cbi" action="<%=REQUEST_URI%>" enctype="multipart/form-data" onreset="return cbi_validate_reset(this)" onsubmit="return cbi_validate_form(this, '<%:Some fields are invalid, cannot save values!%>')"<%=
+ attr("data-strings", luci.util.serialize_json({
+ label = {
+ choose = translate('-- Please choose --'),
+ custom = translate('-- custom --'),
+ },
+ path = {
+ resource = resource,
+ browser = url("admin/filebrowser")
+ }
+ }))
+%>>
+ <div>
+ <input type="hidden" name="token" value="<%=token%>" />
+ <input type="hidden" name="cbi.submit" value="1" />
+ <input type="submit" value="<%:Save%>" class="hidden" />
+ </div>
diff --git a/modules/luci-compat/luasrc/view/cbi/ipaddr.htm b/modules/luci-compat/luasrc/view/cbi/ipaddr.htm
new file mode 100644
index 0000000000..1c924e1544
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/ipaddr.htm
@@ -0,0 +1,27 @@
+<%+cbi/valueheader%>
+ <script type="text/javascript">
+ function switchToCIDRList(ev) {
+ var input = ev.target.previousElementSibling,
+ usecidr = document.getElementById(input.id + '_usecidr');
+
+ ev.preventDefault();
+
+ usecidr.value = '1';
+ cbi_d_update();
+ }
+ </script>
+ <input data-update="change"<%=
+ attr("id", cbid) ..
+ attr("name", cbid) ..
+ attr("type", "text") ..
+ attr("class", "cbi-input-text") ..
+ attr("value", self:cfgvalue(section) or self.default) ..
+ ifattr(self.size, "size") ..
+ ifattr(self.placeholder, "placeholder") ..
+ 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 })
+ %> /><!--
+ --><button class="cbi-button cbi-button-neutral" title="<%:Switch to CIDR list notation%>" aria-label="<%:Switch to CIDR list notation%>" onclick="switchToCIDRList(event)">…</button>
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/lvalue.htm b/modules/luci-compat/luasrc/view/cbi/lvalue.htm
new file mode 100644
index 0000000000..28141472f4
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/lvalue.htm
@@ -0,0 +1,14 @@
+<%+cbi/valueheader%>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Select", self:cfgvalue(section) or self.default, self:choices(), {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ widget = self.widget,
+ datatype = self.datatype,
+ optional = self.optional,
+ placeholder = self.placeholder
+ }
+}))%>></div>
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/map.htm b/modules/luci-compat/luasrc/view/cbi/map.htm
new file mode 100644
index 0000000000..cda4d3530c
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/map.htm
@@ -0,0 +1,40 @@
+<%- if firstmap and messages then local msg; for _, msg in ipairs(messages) do -%>
+ <div class="alert-message warning"><%=pcdata(msg)%></div>
+<%- end end -%>
+
+<div class="cbi-map" id="cbi-<%=self.config%>">
+ <% if self.title and #self.title > 0 then %>
+ <h2 name="content"><%=self.title%></h2>
+ <% end %>
+ <% if self.description and #self.description > 0 then %>
+ <div class="cbi-map-descr"><%=self.description%></div>
+ <% end %>
+ <% if self.tabbed then %>
+ <div>
+ <% for i, section in ipairs(self.children) do
+ tab = section.section or section.sectiontype %>
+ <div class="cbi-tabcontainer"<%=
+ attr("id", "container.m-%s.%s" %{ self.config, tab }) ..
+ attr("data-tab", tab) ..
+ attr("data-tab-title", section.title or tab)
+ %>>
+ <% section:render() %>
+ </div>
+ <% end %>
+ </div>
+
+ <% if not self.save then -%>
+ <div class="cbi-section-error">
+ <% for _, section in ipairs(self.children) do %>
+ <% if section.error and section.error[section.section] then -%>
+ <ul><li>
+ <%:One or more invalid/required values on tab%>:&nbsp;<%=section.title or section.section or section.sectiontype%>
+ </li></ul>
+ <%- end %>
+ <% end %>
+ </div>
+ <%- end %>
+ <% else %>
+ <%- self:render_children() %>
+ <% end %>
+</div>
diff --git a/modules/luci-compat/luasrc/view/cbi/mvalue.htm b/modules/luci-compat/luasrc/view/cbi/mvalue.htm
new file mode 100644
index 0000000000..1f4f4dbcc6
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/mvalue.htm
@@ -0,0 +1,24 @@
+<%+cbi/valueheader%>
+<%
+ local util = require "luci.util"
+ local values = {}
+ local value
+ for value in util.imatch(self:cfgvalue(section) or self.default) do
+ values[#values+1] = value
+ end
+%>
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "Select", values, self:choices(), {
+ id = cbid,
+ name = cbid,
+ size = self.size,
+ sort = self.keylist,
+ multiple = 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-compat/luasrc/view/cbi/nsection.htm b/modules/luci-compat/luasrc/view/cbi/nsection.htm
new file mode 100644
index 0000000000..14232e3d94
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/nsection.htm
@@ -0,0 +1,29 @@
+<% if self:cfgvalue(self.section) then section = self.section %>
+ <div class="cbi-section">
+ <% if self.title and #self.title > 0 then -%>
+ <legend><%=self.title%></legend>
+ <%- end %>
+ <% if self.description and #self.description > 0 then -%>
+ <div class="cbi-section-descr"><%=self.description%></div>
+ <%- end %>
+ <% if self.addremove then -%>
+ <div class="cbi-section-remove right">
+ <input type="submit" class="cbi-button" name="cbi.rns.<%=self.config%>.<%=section%>" value="<%:Delete%>" />
+ </div>
+ <%- end %>
+ <div class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>">
+ <%+cbi/ucisection%>
+ </div>
+ </div>
+<% elseif self.addremove then %>
+ <% if self.template_addremove then include(self.template_addremove) else -%>
+ <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>">
+ <% if self.title and #self.title > 0 then -%>
+ <legend><%=self.title%></legend>
+ <%- end %>
+ <div class="cbi-section-descr"><%=self.description%></div>
+ <input type="submit" class="cbi-button cbi-button-add" name="cbi.cns.<%=self.config%>.<%=self.section%>" value="<%:Add%>" />
+ </div>
+ <%- end %>
+<% end %>
+<!-- /nsection -->
diff --git a/modules/luci-compat/luasrc/view/cbi/nullsection.htm b/modules/luci-compat/luasrc/view/cbi/nullsection.htm
new file mode 100644
index 0000000000..7230719d19
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/nullsection.htm
@@ -0,0 +1,37 @@
+<div class="cbi-section">
+ <% if self.title and #self.title > 0 then -%>
+ <legend><%=self.title%></legend>
+ <%- end %>
+ <% if self.description and #self.description > 0 then -%>
+ <div class="cbi-section-descr"><%=self.description%></div>
+ <%- end %>
+ <div class="cbi-section-node">
+ <div id="cbi-<%=self.config%>-<%=tostring(self):sub(8)%>">
+ <% self:render_children(1, scope or {}) %>
+ </div>
+ <% if self.error and self.error[1] then -%>
+ <div class="cbi-section-error">
+ <ul><% for _, e in ipairs(self.error[1]) do -%>
+ <li>
+ <%- if e == "invalid" then -%>
+ <%:One or more fields contain invalid values!%>
+ <%- elseif e == "missing" then -%>
+ <%:One or more required fields have no value!%>
+ <%- else -%>
+ <%=pcdata(e)%>
+ <%- end -%>
+ </li>
+ <%- end %></ul>
+ </div>
+ <%- end %>
+ </div>
+</div>
+<%-
+ if type(self.hidden) == "table" then
+ for k, v in pairs(self.hidden) do
+-%>
+ <input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" />
+<%-
+ end
+ end
+%>
diff --git a/modules/luci-compat/luasrc/view/cbi/simpleform.htm b/modules/luci-compat/luasrc/view/cbi/simpleform.htm
new file mode 100644
index 0000000000..3e10724ec5
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/simpleform.htm
@@ -0,0 +1,77 @@
+<%
+ if not self.embedded then
+ %><form method="post" enctype="multipart/form-data" action="<%=REQUEST_URI%>">
+ <input type="hidden" name="token" value="<%=token%>" />
+ <input type="hidden" name="cbi.submit" value="1" /><%
+ end
+
+ %><div class="cbi-map" id="cbi-<%=self.config%>"><%
+
+ if self.title and #self.title > 0 then
+ %><h2 name="content"><%=self.title%></h2><%
+ end
+
+ if self.description and #self.description > 0 then
+ %><div class="cbi-map-descr"><%=self.description%></div><%
+ end
+
+ self:render_children()
+
+ %></div><%
+
+ if self.message then
+ %><div class="alert-message notice"><%=self.message%></div><%
+ end
+
+ if self.errmessage then
+ %><div class="alert-message warning"><%=self.errmessage%></div><%
+ end
+
+ if not self.embedded then
+ if type(self.hidden) == "table" then
+ local k, v
+ for k, v in pairs(self.hidden) do
+ %><input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" /><%
+ end
+ end
+
+ local display_back = (redirect)
+ local display_cancel = (self.cancel ~= false and self.on_cancel)
+ local display_skip = (self.flow and self.flow.skip)
+ local display_submit = (self.submit ~= false)
+ local display_reset = (self.reset ~= false)
+
+ if display_back or display_cancel or display_skip or display_submit or display_reset then
+ %><div class="cbi-page-actions"><%
+
+ if display_back then
+ %><input class="cbi-button cbi-button-link" type="button" value="<%:Back to Overview%>" onclick="location.href='<%=pcdata(redirect)%>'" /> <%
+ end
+
+ if display_cancel then
+ local label = pcdata(self.cancel or translate("Cancel"))
+ %><input class="cbi-button cbi-button-link" type="button" value="<%=label%>" onclick="cbi_submit(this, 'cbi.cancel')" /> <%
+ end
+
+ if display_skip then
+ %><input class="cbi-button cbi-button-neutral" type="button" value="<%:Skip%>" onclick="cbi_submit(this, 'cbi.skip')" /> <%
+ end
+
+ if display_submit then
+ local label = pcdata(self.submit or translate("Submit"))
+ %><input class="cbi-button cbi-button-save" type="submit" value="<%=label%>" /> <%
+ end
+
+ if display_reset then
+ local label = pcdata(self.reset or translate("Reset"))
+ %><input class="cbi-button cbi-button-reset" type="reset" value="<%=label%>" /> <%
+ end
+
+ %></div><%
+ end
+
+ %></form><%
+ end
+%>
+
+<script type="text/javascript">cbi_init();</script>
diff --git a/modules/luci-compat/luasrc/view/cbi/tabcontainer.htm b/modules/luci-compat/luasrc/view/cbi/tabcontainer.htm
new file mode 100644
index 0000000000..7fcb835783
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/tabcontainer.htm
@@ -0,0 +1,14 @@
+<% for _, tab in ipairs(self.tab_names) do data = self.tabs[tab] %>
+ <div class="cbi-tabcontainer"<%=
+ attr("id", "container.%s.%s.%s" %{ self.config, section, tab }) ..
+ attr("data-tab", tab) ..
+ attr("data-tab-title", data.title) ..
+ attr("data-tab-active", tostring(tab == self.selected_tab))
+ %>>
+ <% if data.description then %>
+ <div class="cbi-tab-descr"><%=data.description%></div>
+ <% end %>
+
+ <% self:render_tab(tab, section, scope or {}) %>
+ </div>
+<% end %>
diff --git a/modules/luci-compat/luasrc/view/cbi/tblsection.htm b/modules/luci-compat/luasrc/view/cbi/tblsection.htm
new file mode 100644
index 0000000000..11c2206d8c
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/tblsection.htm
@@ -0,0 +1,203 @@
+<%-
+local rowcnt = 0
+
+function rowstyle()
+ rowcnt = rowcnt + 1
+ if rowcnt % 2 == 0 then
+ return " cbi-rowstyle-1"
+ else
+ return " cbi-rowstyle-2"
+ end
+end
+
+function width(o)
+ if o.width then
+ if type(o.width) == 'number' then
+ return ' style="width:%dpx"' % o.width
+ end
+ return ' style="width:%s"' % o.width
+ end
+ return ''
+end
+
+local has_titles = false
+local has_descriptions = false
+
+local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
+local titlename = ifattr(not self.anonymous or self.sectiontitle, "data-title", translate("Name"))
+
+local i, k
+for i, k in pairs(self.children) do
+ if not k.typename then
+ k.typename = k.template and k.template:gsub("^.+/", "") or ""
+ end
+
+ if not has_titles and k.title and #k.title > 0 then
+ has_titles = true
+ end
+
+ if not has_descriptions and k.description and #k.description > 0 then
+ has_descriptions = true
+ end
+end
+
+function render_titles()
+ if not has_titles then
+ return
+ end
+
+ %><div class="tr cbi-section-table-titles <%=anonclass%>"<%=titlename%>><%
+
+ local i, k
+ for i, k in ipairs(self.children) do
+ if not k.optional then
+ %><div class="th cbi-section-table-cell"<%=
+ width(k) .. attr('data-type', k.typename) %>><%
+
+ if k.titleref then
+ %><a title="<%=self.titledesc or translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=k.titleref%>"><%
+ end
+
+ write(k.title)
+
+ if k.titleref then
+ %></a><%
+ end
+
+ %></div><%
+ end
+ end
+
+ if self.sortable or self.extedit or self.addremove then
+ %><div class="th cbi-section-table-cell cbi-section-actions"></div><%
+ end
+
+ %></div><%
+
+ rowcnt = rowcnt + 1
+end
+
+function render_descriptions()
+ if not has_descriptions then
+ return
+ end
+
+ %><div class="tr cbi-section-table-descr <%=anonclass%>"><%
+
+ local i, k
+ for i, k in ipairs(self.children) do
+ if not k.optional then
+ %><div class="th cbi-section-table-cell"<%=
+ width(k) .. attr("data-type", k.typename) %>><%
+
+ write(k.description)
+
+ %></div><%
+ end
+ end
+
+ if self.sortable or self.extedit or self.addremove then
+ %><div class="th cbi-section-table-cell cbi-section-actions"></div><%
+ end
+
+ %></div><%
+
+ rowcnt = rowcnt + 1
+end
+
+-%>
+
+<!-- tblsection -->
+<div class="cbi-section cbi-tblsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
+ <% if self.title and #self.title > 0 then -%>
+ <h3><%=self.title%></h3>
+ <%- end %>
+ <%- if self.sortable then -%>
+ <input type="hidden" id="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" name="cbi.sts.<%=self.config%>.<%=self.sectiontype%>" value="" />
+ <%- end -%>
+ <div class="cbi-section-descr"><%=self.description%></div>
+ <div class="table cbi-section-table">
+ <%-
+ render_titles()
+ render_descriptions()
+
+ local isempty, section, i, k = true, nil, nil
+ for i, k in ipairs(self:cfgsections()) do
+ isempty = false
+ section = k
+
+ local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
+ local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname, true)
+ local colorclass = (self.extedit or self.rowcolors) and rowstyle() or ""
+ local scope = {
+ valueheader = "cbi/cell_valueheader",
+ valuefooter = "cbi/cell_valuefooter"
+ }
+ -%>
+ <div class="tr cbi-section-table-row<%=colorclass%>" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
+ <%-
+ local node
+ for k, node in ipairs(self.children) do
+ if not node.optional then
+ node:render(section, scope or {})
+ end
+ end
+ -%>
+
+ <%- if self.sortable or self.extedit or self.addremove then -%>
+ <div class="td cbi-section-table-cell nowrap cbi-section-actions">
+ <div>
+ <%- if self.sortable then -%>
+ <input class="cbi-button cbi-button-up" type="button" value="<%:Up%>" onclick="return cbi_row_swap(this, true, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move up%>" />
+ <input class="cbi-button cbi-button-down" type="button" value="<%:Down%>" onclick="return cbi_row_swap(this, false, 'cbi.sts.<%=self.config%>.<%=self.sectiontype%>')" title="<%:Move down%>" />
+ <% end; if self.extedit then -%>
+ <input class="cbi-button cbi-button-edit" type="button" value="<%:Edit%>"
+ <%- if type(self.extedit) == "string" then
+ %> onclick="location.href='<%=self.extedit:format(section)%>'"
+ <%- elseif type(self.extedit) == "function" then
+ %> onclick="location.href='<%=self:extedit(section)%>'"
+ <%- end
+ %> alt="<%:Edit%>" title="<%:Edit%>" />
+ <% end; if self.addremove then %>
+ <input class="cbi-button cbi-button-remove" type="submit" value="<%:Delete%>" onclick="this.form.cbi_state='del-section'; return true" name="cbi.rts.<%=self.config%>.<%=k%>" alt="<%:Delete%>" title="<%:Delete%>" />
+ <%- end -%>
+ </div>
+ </div>
+ <%- end -%>
+ </div>
+ <%- end -%>
+
+ <%- if isempty then -%>
+ <div class="tr cbi-section-table-row placeholder">
+ <div class="td"><em><%:This section contains no values yet%></em></div>
+ </div>
+ <%- end -%>
+ </div>
+
+ <% if self.error then %>
+ <div class="cbi-section-error">
+ <ul><% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
+ <li><%=pcdata(e):gsub("\n","<br />")%></li>
+ <%- end end %></ul>
+ </div>
+ <% end %>
+
+ <%- if self.addremove then -%>
+ <% if self.template_addremove then include(self.template_addremove) else -%>
+ <div class="cbi-section-create cbi-tblsection-create">
+ <% if self.anonymous then %>
+ <input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
+ <% else %>
+ <% if self.invalid_cts then -%>
+ <div class="cbi-section-error"><%:Invalid%></div>
+ <%- end %>
+ <div>
+ <input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname" data-optional="true" />
+ </div>
+ <input class="cbi-button cbi-button-add" type="submit" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" title="<%:Add%>" />
+ <% end %>
+ </div>
+ <%- end %>
+ <%- end -%>
+</div>
+<!-- /tblsection -->
diff --git a/modules/luci-compat/luasrc/view/cbi/tsection.htm b/modules/luci-compat/luasrc/view/cbi/tsection.htm
new file mode 100644
index 0000000000..8f3b7f0ffb
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/tsection.htm
@@ -0,0 +1,52 @@
+<div class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
+ <% if self.title and #self.title > 0 then -%>
+ <legend><%=self.title%></legend>
+ <%- end %>
+ <% if self.error_msg and #self.error_msg > 0 then -%>
+ <div class="cbi-section-error">
+ <%=self.error_msg%>
+ </div>
+ <%- end %>
+ <% if self.description and #self.description > 0 then -%>
+ <div class="cbi-section-descr"><%=self.description%></div>
+ <%- end %>
+ <% local isempty = true for i, k in ipairs(self:cfgsections()) do -%>
+ <% if self.addremove then -%>
+ <div class="cbi-section-remove right">
+ <input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" onclick="this.form.cbi_state='del-section'; return true" value="<%:Delete%>" class="cbi-button" />
+ </div>
+ <%- end %>
+
+ <%- section = k; isempty = false -%>
+
+ <% if not self.anonymous then -%>
+ <h3><%=section:upper()%></h3>
+ <%- end %>
+
+ <div class="cbi-section-node<% if self.tabs then %> cbi-section-node-tabbed<% end %>" id="cbi-<%=self.config%>-<%=section%>">
+ <%+cbi/ucisection%>
+ </div>
+ <%- end %>
+
+ <% if isempty then -%>
+ <em><%:This section contains no values yet%><br /><br /></em>
+ <%- end %>
+
+ <% if self.addremove then -%>
+ <% if self.template_addremove then include(self.template_addremove) else -%>
+ <div class="cbi-section-create">
+ <% if self.anonymous then -%>
+ <input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
+ <%- else -%>
+ <% if self.invalid_cts then -%>
+ <div class="cbi-section-error"><%:Invalid%></div>
+ <%- end %>
+ <div>
+ <input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>." name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>." data-type="uciname" data-optional="true" />
+ </div>
+ <input class="cbi-button cbi-button-add" type="submit" onclick="this.form.cbi_state='add-section'; return true" value="<%:Add%>" title="<%:Add%>" />
+ <%- end %>
+ </div>
+ <%- end %>
+ <%- end %>
+</div>
diff --git a/modules/luci-compat/luasrc/view/cbi/tvalue.htm b/modules/luci-compat/luasrc/view/cbi/tvalue.htm
new file mode 100644
index 0000000000..f3b12bd094
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/tvalue.htm
@@ -0,0 +1,5 @@
+<%+cbi/valueheader%>
+ <textarea class="cbi-input-textarea" <% if not self.size then %> style="width: 100%"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", cbid) .. attr("id", cbid) .. ifattr(self.rows, "rows") .. ifattr(self.wrap, "wrap") .. ifattr(self.readonly, "readonly") %>>
+ <%-=pcdata(self:cfgvalue(section) or self.default)-%>
+ </textarea>
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/ucisection.htm b/modules/luci-compat/luasrc/view/cbi/ucisection.htm
new file mode 100644
index 0000000000..8fa11d68f8
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/ucisection.htm
@@ -0,0 +1,56 @@
+<%-
+ if type(self.hidden) == "table" then
+ for k, v in pairs(self.hidden) do
+-%>
+ <input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" />
+<%-
+ end
+ end
+%>
+
+<% if self.tabs then %>
+ <%+cbi/tabcontainer%>
+<% else %>
+ <% self:render_children(section, scope or {}) %>
+<% end %>
+
+<% if self.error and self.error[section] then -%>
+ <div class="cbi-section-error" data-index="<%=#self.children + 1%>">
+ <ul><% for _, e in ipairs(self.error[section]) do -%>
+ <li>
+ <%- if e == "invalid" then -%>
+ <%:One or more fields contain invalid values!%>
+ <%- elseif e == "missing" then -%>
+ <%:One or more required fields have no value!%>
+ <%- else -%>
+ <%=pcdata(e)%>
+ <%- end -%>
+ </li>
+ <%- end %></ul>
+ </div>
+<%- end %>
+
+<% if self.optionals[section] and #self.optionals[section] > 0 or self.dynamic then %>
+ <div class="cbi-optionals" data-index="<%=#self.children + 1%>">
+ <%-
+ if self.dynamic then
+ local keys, vals, name, opt = { }, { }
+ for name, opt in pairs(self.optionals[section]) do
+ keys[#keys+1] = name
+ vals[#vals+1] = opt.title
+ end
+ -%>
+ <input type="text" id="cbi.opt.<%=self.config%>.<%=section%>" name="cbi.opt.<%=self.config%>.<%=section%>" data-type="uciname" data-optional="true"<%=
+ ifattr(#keys > 0, "data-choices", luci.util.json_encode({keys, vals}))
+ %> />
+ <%- else -%>
+ <select id="cbi.opt.<%=self.config%>.<%=section%>" name="cbi.opt.<%=self.config%>.<%=section%>" data-optionals="true">
+ <option><%: -- Additional Field -- %></option>
+ <% for key, val in pairs(self.optionals[section]) do -%>
+ <option id="cbi-<%=self.config.."-"..section.."-"..val.option%>" value="<%=val.option%>" data-index="<%=val.index%>" data-depends="<%=pcdata(val:deplist2json(section))%>"><%=striptags(val.title)%></option>
+ <%- end %>
+ </select>
+ <%- end -%>
+ <input type="submit" class="cbi-button cbi-button-fieldadd" value="<%:Add%>" />
+ </div>
+<% end %>
diff --git a/modules/luci-compat/luasrc/view/cbi/upload.htm b/modules/luci-compat/luasrc/view/cbi/upload.htm
new file mode 100644
index 0000000000..e610495380
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/upload.htm
@@ -0,0 +1,14 @@
+<%+cbi/valueheader%>
+
+<div<%=attr("data-ui-widget", luci.util.serialize_json({
+ "FileUpload", self:cfgvalue(section) or self.default, {
+ id = cbid,
+ name = cbid,
+ show_hidden = self.show_hidden,
+ enable_remove = self.enable_remove,
+ enable_upload = self.enable_upload,
+ root_directory = "/" --self.root_directory
+ }
+}))%>></div>
+
+<%+cbi/valuefooter%>
diff --git a/modules/luci-compat/luasrc/view/cbi/value.htm b/modules/luci-compat/luasrc/view/cbi/value.htm
new file mode 100644
index 0000000000..6060310b19
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/value.htm
@@ -0,0 +1,35 @@
+<%+cbi/valueheader%>
+
+<% 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%>
diff --git a/modules/luci-compat/luasrc/view/cbi/valuefooter.htm b/modules/luci-compat/luasrc/view/cbi/valuefooter.htm
new file mode 100644
index 0000000000..805312e451
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/valuefooter.htm
@@ -0,0 +1 @@
+<% include( valuefooter or "cbi/full_valuefooter" ) %>
diff --git a/modules/luci-compat/luasrc/view/cbi/valueheader.htm b/modules/luci-compat/luasrc/view/cbi/valueheader.htm
new file mode 100644
index 0000000000..761a54aed0
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/valueheader.htm
@@ -0,0 +1 @@
+<% include( valueheader or "cbi/full_valueheader" ) %>
diff --git a/modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm b/modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm
new file mode 100644
index 0000000000..eeb1d5c5cb
--- /dev/null
+++ b/modules/luci-compat/luasrc/view/cbi/wireless_modefreq.htm
@@ -0,0 +1,173 @@
+<%+cbi/valueheader%>
+
+<script type="text/javascript">//<![CDATA[
+ var freqlist = <%= luci.http.write_json(self.iwinfo.freqlist) %>;
+ var hwmodes = <%= luci.http.write_json(self.iwinfo.hwmodelist or {}) %>;
+ var htmodes = <%= luci.http.write_json(self.iwinfo.htmodelist) %>;
+ var acs = <%= luci.http.write_json(self.hostapd_acs or 0) %>;
+
+ var channels = {
+ '11g': [
+ 'auto', 'auto', true
+ ],
+ '11a': [
+ 'auto', 'auto', true
+ ]
+ };
+
+ if (acs < 1) {
+ channels[(freqlist[freqlist.length - 1].mhz > 2484) ? '11a' : '11g'].length = 0;
+ }
+
+ for (var i = 0; i < freqlist.length; i++)
+ channels[(freqlist[i].mhz > 2484) ? '11a' : '11g'].push(
+ freqlist[i].channel,
+ '%d (%d MHz)'.format(freqlist[i].channel, freqlist[i].mhz),
+ !freqlist[i].restricted
+ );
+
+ var modes = [
+ '', 'Legacy', true,
+ 'n', 'N', hwmodes.n,
+ 'ac', 'AC', hwmodes.ac
+ ];
+
+ var htmodes = {
+ '': [
+ '', '-', true
+ ],
+ 'n': [
+ 'HT20', '20 MHz', htmodes.HT20,
+ 'HT40', '40 MHz', htmodes.HT40
+ ],
+ 'ac': [
+ 'VHT20', '20 MHz', htmodes.VHT20,
+ 'VHT40', '40 MHz', htmodes.VHT40,
+ 'VHT80', '80 MHz', htmodes.VHT80,
+ 'VHT160', '160 MHz', htmodes.VHT160
+ ]
+ };
+
+ var bands = {
+ '': [
+ '11g', '2.4 GHz', (channels['11g'].length > 3),
+ '11a', '5 GHz', (channels['11a'].length > 3)
+ ],
+ 'n': [
+ '11g', '2.4 GHz', (channels['11g'].length > 3),
+ '11a', '5 GHz', (channels['11a'].length > 3)
+ ],
+ 'ac': [
+ '11a', '5 GHz', true
+ ]
+ };
+
+ function cbi_set_values(sel, vals)
+ {
+ if (sel.vals)
+ sel.vals.selected = sel.selectedIndex;
+
+ while (sel.options[0])
+ sel.remove(0);
+
+ for (var i = 0; vals && i < vals.length; i += 3)
+ {
+ if (!vals[i+2])
+ continue;
+
+ var opt = document.createElement('option');
+ opt.value = vals[i+0];
+ opt.text = vals[i+1];
+
+ sel.add(opt);
+ }
+
+ if (!isNaN(vals.selected))
+ sel.selectedIndex = vals.selected;
+
+ sel.parentNode.style.display = (sel.options.length <= 1) ? 'none' : '';
+ sel.vals = vals;
+ }
+
+ function cbi_toggle_wifi_mode(id)
+ {
+ cbi_toggle_wifi_htmode(id);
+ cbi_toggle_wifi_band(id);
+ }
+
+ function cbi_toggle_wifi_htmode(id)
+ {
+ var mode = document.getElementById(id + '.mode');
+ var bwdt = document.getElementById(id + '.htmode');
+
+ cbi_set_values(bwdt, htmodes[mode.value]);
+ }
+
+ function cbi_toggle_wifi_band(id)
+ {
+ var mode = document.getElementById(id + '.mode');
+ var band = document.getElementById(id + '.band');
+
+ cbi_set_values(band, bands[mode.value]);
+ cbi_toggle_wifi_channel(id);
+ }
+
+ function cbi_toggle_wifi_channel(id)
+ {
+ var band = document.getElementById(id + '.band');
+ var chan = document.getElementById(id + '.channel');
+
+ cbi_set_values(chan, channels[band.value]);
+ }
+
+ function cbi_init_wifi(id)
+ {
+ var mode = document.getElementById(id + '.mode');
+ var band = document.getElementById(id + '.band');
+ var chan = document.getElementById(id + '.channel');
+ var bwdt = document.getElementById(id + '.htmode');
+
+ cbi_set_values(mode, modes);
+
+ if (/VHT20|VHT40|VHT80|VHT160/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
+ mode.value = 'ac';
+ else if (/HT20|HT40/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
+ mode.value = 'n';
+ else
+ mode.value = '';
+
+ cbi_toggle_wifi_mode(id);
+
+ if (/a/.test(<%= luci.http.write_json(self.map:get(section, "hwmode")) %>))
+ band.value = '11a';
+ else
+ band.value = '11g';
+
+ cbi_toggle_wifi_band(id);
+
+ bwdt.value = <%= luci.http.write_json(self.map:get(section, "htmode")) %>;
+ chan.value = <%= luci.http.write_json(self.map:get(section, "channel")) %>;
+ }
+//]]></script>
+
+<label style="float:left; margin-right:3px">
+ <%:Mode%><br />
+ <select style="width:auto" id="<%= cbid %>.mode" name="<%= cbid %>.mode" onchange="cbi_toggle_wifi_mode('<%= cbid %>')"></select>
+</label>
+<label style="float:left; margin-right:3px">
+ <%:Band%><br />
+ <select style="width:auto" id="<%= cbid %>.band" name="<%= cbid %>.band" onchange="cbi_toggle_wifi_band('<%= cbid %>')"></select>
+</label>
+<label style="float:left; margin-right:3px">
+ <%:Channel%><br />
+ <select style="width:auto" id="<%= cbid %>.channel" name="<%= cbid %>.channel"></select>
+</label>
+<label style="float:left; margin-right:3px">
+ <%:Width%><br />
+ <select style="width:auto" id="<%= cbid %>.htmode" name="<%= cbid %>.htmode"></select>
+</label>
+<br style="clear:left" />
+
+<script type="text/javascript">cbi_init_wifi('<%= cbid %>');</script>
+
+<%+cbi/valuefooter%>