* Major CBI improvements

This commit is contained in:
Steven Barth 2008-03-27 23:14:01 +00:00
parent 3f1064b919
commit 077db659bb
21 changed files with 260 additions and 116 deletions

View file

@ -20,18 +20,11 @@ all: compile
dist-compile: compile dist dist-compile: compile dist
dist-source: source dist dist-source: source dist
examples-compile: compile examples
examples-source: source examples
dist: dist:
cp src/ffluci/controller/* dist/ffluci/controller/ -R cp src/ffluci/controller/* dist/ffluci/controller/ -R
cp src/ffluci/i18n/* dist/ffluci/i18n/ cp src/ffluci/i18n/* dist/ffluci/i18n/
cp src/ffluci/view/* dist/ffluci/view/ -R cp src/ffluci/view/* dist/ffluci/view/ -R
cp src/ffluci/model/cbi/* dist/ffluci/model/cbi/ -R cp src/ffluci/model/cbi/* dist/ffluci/model/cbi/ -R
examples:
cp examples/* dist/ -R
compile: compile:
mkdir -p $(DIRECTORIES) mkdir -p $(DIRECTORIES)

View file

@ -4,13 +4,13 @@ config core main
config public contact config public contact
option nickname - option nickname
option name - option name
option mail - option mail
option phone - option phone
option location - option location
option geo - option geo
option note - option note
config event uci_oncommit config event uci_oncommit

View file

@ -179,27 +179,31 @@ code {
margin-top: 1em; margin-top: 1em;
} }
.cbi-section-create { .cbi-section-remove {
margin-bottom: 3em; text-align: right;
} }
.cbi-value-title { .cbi-value-title {
line-height: 1.75em; line-height: 1.75em;
width: 15em;
font-weight: bold;
} }
.cbi-value-field { .cbi-value-field {
margin-left: 10em; text-align: left;
text-align: center;
line-height: 1.75em; line-height: 1.75em;
} }
.cbi-value-field input, .cbi-value-field select, .cbi-optionals select, .cbi-optionals input { .cbi-value-field input, .cbi-value-field select,
.cbi-optionals select, .cbi-optionals input,
.cbi-section-remove input, .cbi-section-create input {
font-size: 0.8em; font-size: 0.8em;
} }
.cbi-value-description { .cbi-value-description {
font-style: italic; font-style: italic;
font-size: 0.8em; font-size: 0.8em;
margin-bottom: 0.5em;
} }
.cbi-form-separator { .cbi-form-separator {
@ -211,6 +215,7 @@ code {
background: #f7f7f7; background: #f7f7f7;
border: 1px solid #d7d7d7; border: 1px solid #d7d7d7;
overflow: auto; overflow: auto;
margn-bottom: 0%;
} }
.cbi-section-node h3 { .cbi-section-node h3 {
@ -220,10 +225,12 @@ code {
.cbi-error { .cbi-error {
color: red; color: red;
font-weight: bold; font-weight: bold;
font-size: 0.8em;
margin-bottom: 0.75em;
} }
.cbi-optionals { .cbi-optionals {
margin-top: 2em; margin-top: 1em;
} }
.cbi-optionals option { .cbi-optionals option {

36
contrib/media/cbi.js Normal file
View file

@ -0,0 +1,36 @@
var cbi_d = {};
function cbi_d_add(field, target, value) {
if (!cbi_d[target]) {
cbi_d[target] = {};
}
if (!cbi_d[target][value]) {
cbi_d[target][value] = [];
}
cbi_d[target][value].push(field);
}
function cbi_d_update(target) {
if (!cbi_d[target]) {
return;
}
for (var x in cbi_d[target]) {
for (var i=0; i<cbi_d[target][x].length; i++) {
document.getElementById(cbi_d[target][x][i]).style.display = "none";
}
}
var t = document.getElementById(target);
if (t && t.value && cbi_d[target][t.value]) {
for (var i=0; i<cbi_d[target][t.value].length; i++) {
document.getElementById(cbi_d[target][t.value][i]).style.display = "block";
}
}
}
function cbi_d_init() {
for (var x in cbi_d) {
cbi_d_update(x);
}
}

View file

@ -35,6 +35,7 @@ define Package/ffluci/install
$(INSTALL_DIR) $(1)/usr/lib/lua $(INSTALL_DIR) $(1)/usr/lib/lua
$(INSTALL_DIR) $(1)/www/cgi-bin $(INSTALL_DIR) $(1)/www/cgi-bin
$(INSTALL_DIR) $(1)/www/ffluci $(INSTALL_DIR) $(1)/www/ffluci
$(INSTALL_DIR) $(1)/etc/config
$(CP) $(PKG_BUILD_DIR)/dist/* $(1)/usr/lib/lua/ -R $(CP) $(PKG_BUILD_DIR)/dist/* $(1)/usr/lib/lua/ -R
$(CP) $(PKG_BUILD_DIR)/contrib/media $(1)/www/ffluci/ -R $(CP) $(PKG_BUILD_DIR)/contrib/media $(1)/www/ffluci/ -R
$(INSTALL_BIN) $(PKG_BUILD_DIR)/contrib/ffluci $(1)/www/cgi-bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/contrib/ffluci $(1)/www/cgi-bin

View file

@ -218,7 +218,6 @@ function AbstractSection.parse_optionals(self, section)
for k,v in ipairs(self.children) do for k,v in ipairs(self.children) do
if v.optional and not v:cfgvalue(section) then if v.optional and not v:cfgvalue(section) then
if field == v.option then if field == v.option then
self.map:set(section, field, v.default)
field = nil field = nil
else else
table.insert(self.optionals[section], v) table.insert(self.optionals[section], v)
@ -328,18 +327,30 @@ end
TypedSection - A (set of) configuration section(s) defined by the type TypedSection - A (set of) configuration section(s) defined by the type
addremove: Defines whether the user can add/remove sections of this type addremove: Defines whether the user can add/remove sections of this type
anonymous: Allow creating anonymous sections anonymous: Allow creating anonymous sections
valid: a list of names or a validation function for creating sections validate: a validation function returning nil if the section is invalid
scope: a list of names or a validation function for editing sections
]]-- ]]--
TypedSection = class(AbstractSection) TypedSection = class(AbstractSection)
function TypedSection.__init__(self, ...) function TypedSection.__init__(self, ...)
AbstractSection.__init__(self, ...) AbstractSection.__init__(self, ...)
self.template = "cbi/tsection" self.template = "cbi/tsection"
self.deps = {}
self.excludes = {}
self.anonymous = false self.anonymous = false
self.valid = nil end
self.scope = nil
-- Return all matching UCI sections for this TypedSection
function TypedSection.cfgsections(self)
local sections = {}
for k, v in pairs(self.map:get()) do
if v[".type"] == self.sectiontype then
if self:checkscope(k) then
sections[k] = v
end
end
end
return sections
end end
-- Creates a new section of this type with the given name (or anonymous) -- Creates a new section of this type with the given name (or anonymous)
@ -357,6 +368,16 @@ function TypedSection.create(self, name)
end end
end end
-- Limits scope to sections that have certain option => value pairs
function TypedSection.depends(self, option, value)
table.insert(self.deps, {option=option, value=value})
end
-- Excludes several sections by name
function TypedSection.exclude(self, field)
self.excludes[field] = true
end
function TypedSection.parse(self) function TypedSection.parse(self)
if self.addremove then if self.addremove then
-- Create -- Create
@ -368,10 +389,17 @@ function TypedSection.parse(self)
end end
else else
if name then if name then
name = ffluci.util.validate(name, self.valid) -- Ignore if it already exists
if self:cfgvalue(name) then
name = nil;
end
name = self:checkscope(name)
if not name then if not name then
self.err_invalid = true self.err_invalid = true
end end
if name and name:len() > 0 then if name and name:len() > 0 then
self:create(name) self:create(name)
end end
@ -383,7 +411,7 @@ function TypedSection.parse(self)
name = ffluci.http.formvalue(crval) name = ffluci.http.formvalue(crval)
if type(name) == "table" then if type(name) == "table" then
for k,v in pairs(name) do for k,v in pairs(name) do
if ffluci.util.validate(k, self.valid) then if self:cfgvalue(k) and self:checkscope(k) then
self:remove(k) self:remove(k)
end end
end end
@ -404,20 +432,37 @@ function TypedSection.render_children(self, section)
end end
end end
-- Return all matching UCI sections for this TypedSection -- Verifies scope of sections
function TypedSection.cfgsections(self) function TypedSection.checkscope(self, section)
local sections = {} -- Check if we are not excluded
for k, v in pairs(self.map:get()) do if self.excludes[section] then
if v[".type"] == self.sectiontype then return nil
if ffluci.util.validate(k, self.scope) then end
sections[k] = v
-- Check if at least one dependency is met
if #self.deps > 0 and self:cfgvalue(section) then
local stat = false
for k, v in ipairs(self.deps) do
if self:cfgvalue(section)[v.option] == v.value then
stat = true
end end
end end
if not stat then
return nil
end
end end
return sections
return self:validate(section)
end end
-- Dummy validate function
function TypedSection.validate(self, section)
return section
end
--[[ --[[
AbstractValue - An abstract Value Type AbstractValue - An abstract Value Type
@ -437,14 +482,25 @@ function AbstractValue.__init__(self, map, option, ...)
self.map = map self.map = map
self.config = map.config self.config = map.config
self.tag_invalid = {} self.tag_invalid = {}
self.deps = {}
self.valid = nil self.rmempty = false
self.depends = nil self.default = nil
self.default = " "
self.size = nil self.size = nil
self.optional = false self.optional = false
end end
-- Add a dependencie to another section field
function AbstractValue.depends(self, field, value)
table.insert(self.deps, {field=field, value=value})
end
-- Return whether this object should be created
function AbstractValue.formcreated(self, section)
local key = "cbi.opt."..self.config.."."..section
return (ffluci.http.formvalue(key) == self.option)
end
-- Returns the formvalue for this object -- Returns the formvalue for this object
function AbstractValue.formvalue(self, section) function AbstractValue.formvalue(self, section)
local key = "cbid."..self.map.config.."."..section.."."..self.option local key = "cbid."..self.map.config.."."..section.."."..self.option
@ -453,12 +509,8 @@ end
function AbstractValue.parse(self, section) function AbstractValue.parse(self, section)
local fvalue = self:formvalue(section) local fvalue = self:formvalue(section)
if fvalue == "" then
fvalue = nil
end
if fvalue and fvalue ~= "" then -- If we have a form value, write it to UCI
if fvalue then -- If we have a form value, validate it and write it to UCI
fvalue = self:validate(fvalue) fvalue = self:validate(fvalue)
if not fvalue then if not fvalue then
self.tag_invalid[section] = true self.tag_invalid[section] = true
@ -469,16 +521,14 @@ function AbstractValue.parse(self, section)
elseif ffluci.http.formvalue("cbi.submit") then -- Unset the UCI or error elseif ffluci.http.formvalue("cbi.submit") then -- Unset the UCI or error
if self.rmempty or self.optional then if self.rmempty or self.optional then
self:remove(section) self:remove(section)
else
self.tag_invalid[section] = true
end end
end end
end end
-- Render if this value exists or if it is mandatory -- Render if this value exists or if it is mandatory
function AbstractValue.render(self, section) function AbstractValue.render(self, s)
if not self.optional or self:cfgvalue(section) then if not self.optional or self:cfgvalue(s) or self:formcreated(s) then
ffluci.template.render(self.template, {self=self, section=section}) ffluci.template.render(self.template, {self=self, section=s})
end end
end end
@ -488,8 +538,8 @@ function AbstractValue.cfgvalue(self, section)
end end
-- Validate the form value -- Validate the form value
function AbstractValue.validate(self, val) function AbstractValue.validate(self, value)
return ffluci.util.validate(val, self.valid) return value
end end
-- Write to UCI -- Write to UCI
@ -529,7 +579,7 @@ function Value.validate(self, val)
val = nil val = nil
end end
return ffluci.util.validate(val, self.valid, self.isnumber, self.isinteger) return ffluci.util.validate(val, self.isnumber, self.isinteger)
end end
@ -585,7 +635,7 @@ function ListValue.__init__(self, ...)
self.widget = "select" self.widget = "select"
end end
function ListValue.add_value(self, key, val) function ListValue.value(self, key, val)
val = val or key val = val or key
table.insert(self.keylist, tostring(key)) table.insert(self.keylist, tostring(key))
table.insert(self.vallist, tostring(val)) table.insert(self.vallist, tostring(val))
@ -618,7 +668,7 @@ function MultiValue.__init__(self, ...)
self.delimiter = " " self.delimiter = " "
end end
function MultiValue.add_value(self, key, val) function MultiValue.value(self, key, val)
val = val or key val = val or key
table.insert(self.keylist, tostring(key)) table.insert(self.keylist, tostring(key))
table.insert(self.vallist, tostring(val)) table.insert(self.vallist, tostring(val))

View file

@ -5,6 +5,7 @@ menu = {
order = 20, order = 20,
entries = { entries = {
{action = "vlan", descr = "VLAN"}, {action = "vlan", descr = "VLAN"},
{action = "ifaces", descr = "Schnittstellen"} {action = "ifaces", descr = "Schnittstellen"},
{action = "ptp", descr = "PPPoE / PPTP"},
} }
} }

View file

@ -10,7 +10,7 @@ function action_apply()
-- Collect files to be applied -- Collect files to be applied
for i, line in ipairs(ffluci.util.split(changes)) do for i, line in ipairs(ffluci.util.split(changes)) do
local r = line:match("^[^.]+") local r = line:match("^-?([^.]+)")
if r then if r then
apply[r] = true apply[r] = true
end end
@ -41,7 +41,7 @@ function action_revert()
-- Collect files to be reverted -- Collect files to be reverted
for i, line in ipairs(ffluci.util.split(changes)) do for i, line in ipairs(ffluci.util.split(changes)) do
local r = line:match("^[^.]+") local r = line:match("^-?([^.]+)")
if r then if r then
revert[r] = true revert[r] = true
end end

View file

@ -1,15 +1,32 @@
-- ToDo: Translate, Add descriptions and help texts
m = Map("network", "Schnittstellen") m = Map("network", "Schnittstellen")
s = m:section(TypedSection, "interface") s = m:section(TypedSection, "interface")
s.addremove = true s.addremove = true
s:exclude("loopback")
s:depends("proto", "static")
s:depends("proto", "dhcp")
p = s:option(ListValue, "proto", "Protokoll") p = s:option(ListValue, "proto", "Protokoll")
p:add_value("static", "statisch") p:value("static", "statisch")
p:add_value("dhcp", "DHCP") p:value("dhcp", "DHCP")
s:option(Value, "ipaddr", "IP-Adresse").optional = 1
s:option(Value, "netmask", "Netzmaske").optional = 1 s:option(Value, "ifname", "Schnittstelle")
s:option(Value, "gateway", "Gateway").optional = 1
s:option(Value, "dns", "DNS").optional = 1 s:option(Value, "ipaddr", "IP-Adresse")
s:option(Value, "mtu", "MTU").optional = 1
s:option(Value, "netmask", "Netzmaske"):depends("proto", "static")
gw = s:option(Value, "gateway", "Gateway")
gw:depends("proto", "static")
gw.rmempty = true
dns = s:option(Value, "dns", "DNS-Server")
dns:depends("proto", "static")
dns.optional = true
mtu = s:option(Value, "mtu", "MTU")
mtu.optional = true
mtu.isinteger = true
return m return m

View file

@ -0,0 +1,31 @@
-- ToDo: Translate, Add descriptions and help texts
m = Map("network", "Punkt-zu-Punkt Verbindungen")
s = m:section(TypedSection, "interface")
s.addremove = true
s:depends("proto", "pppoe")
s:depends("proto", "pptp")
p = s:option(ListValue, "proto", "Protokoll")
p:value("pppoe", "PPPoE")
p:value("pptp", "PPTP")
p.default = "pppoe"
s:option(Value, "ifname", "Schnittstelle")
s:option(Value, "username", "Benutzername")
s:option(Value, "password", "Passwort")
s:option(Value, "keepalive", "Keep-Alive").optional = true
s:option(Value, "demand", "Dial on Demand (idle time)").optional = true
srv = s:option(Value, "server", "PPTP-Server")
srv:depends("proto", "pptp")
srv.optional = true
mtu = s:option(Value, "mtu", "MTU")
mtu.optional = true
mtu.isinteger = true
return m

View file

@ -1,12 +1,10 @@
-- ToDo: Autodetect things, maybe use MultiValue instead, Translate, Add descriptions
m = Map("network", "VLAN", "Konfguriert den Switch des Routers.") m = Map("network", "VLAN", "Konfguriert den Switch des Routers.")
s = m:section(TypedSection, "switch") s = m:section(TypedSection, "switch")
-- ToDo: Autodetect things, maybe use MultiValue instead
for i = 0, 15 do for i = 0, 15 do
local c = s:option(Value, "vlan"..i, "vlan"..i) s:option(Value, "vlan"..i, "vlan"..i).optional = true
c.default = "5"
c.optional = true
end end
return m return m

View file

@ -7,6 +7,9 @@ is comparable to the syntax of the uci application
Any return value of false or nil can be interpreted as an error Any return value of false or nil can be interpreted as an error
ToDo: Reimplement in Lua
FileId: FileId:
$Id$ $Id$

View file

@ -203,7 +203,7 @@ end
-- Validates a variable -- Validates a variable
function validate(value, valid, cast_number, cast_int) function validate(value, cast_number, cast_int)
if cast_number or cast_int then if cast_number or cast_int then
value = tonumber(value) value = tonumber(value)
end end
@ -212,15 +212,6 @@ function validate(value, valid, cast_number, cast_int)
value = nil value = nil
end end
if type(valid) == "function" then
value = valid(value)
elseif type(valid) == "table" then
if not contains(valid, value) then
value = nil
end
end
return value return value
end end

View file

@ -1,4 +1,5 @@
<input type="submit" value="<%:save Speichern%>" /> <input type="submit" value="<%:save Speichern%>" />
<input type="reset" value="<%:reset Zurücksetzen%>" /> <input type="reset" value="<%:reset Zurücksetzen%>" />
<script type="text/javascript">cbi_d_init();</script>
</form> </form>
<%+footer%> <%+footer%>

View file

@ -1,10 +1,11 @@
<div class="cbi-value"> <div class="cbi-value" id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<div class="left"> <div class="cbi-value-title left"><%=self.title%></div>
<div class="cbi-value-title"><%=self.title%></div>
<div class="cbi-value-description"><%=self.description%></div>
</div>
<div class="cbi-value-field"> <div class="cbi-value-field">
<input type="checkbox" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" /> <input onchange="cbi_d_update(this.id)" type="checkbox" id="cbid.<%=self.config.."."..section.."."..self.option%>" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self:cfgvalue(section) == self.enabled then %> checked="checked"<% end %> value="1" />
<div class="cbi-value-description inline"><%=self.description%></div>
</div> </div>
<div class="clear"></div> </div>
</div> <% if #self.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>

View file

@ -1,4 +1,5 @@
<%+header%> <%+header%>
<form method="post" action="<%=os.getenv("REQUEST_URI")%>"> <form method="post" action="<%=os.getenv("REQUEST_URI")%>">
<script type="text/javascript" src="<%=media%>/cbi.js"></script>
<input type="hidden" name="cbi.submit" value="1" /> <input type="hidden" name="cbi.submit" value="1" />
<input type="submit" value="<%:cbi_save Speichern%>" class="hidden" /> <input type="submit" value="<%:cbi_save Speichern%>" class="hidden" />

View file

@ -1,9 +1,8 @@
<div class="cbi-value"> <div class="cbi-value" id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<div class="cbi-value-title left"><%=self.title%></div> <div class="cbi-value-title left"><%=self.title%></div>
<div class="cbi-value-description right"><%=self.description%></div>
<div class="cbi-value-field"> <div class="cbi-value-field">
<% if self.widget == "select" then %> <% if self.widget == "select" then %>
<select name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self.size then %> size="<%=self.size%>"<% end %>> <select onchange="cbi_d_update(this.id)" id="cbid.<%=self.config.."."..section.."."..self.option%>" name="cbid.<%=self.config.."."..section.."."..self.option%>"<% if self.size then %> size="<%=self.size%>"<% end %>>
<%for i, key in pairs(self.keylist) do%> <%for i, key in pairs(self.keylist) do%>
<option<% if self:cfgvalue(section) == key then %> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%></option> <option<% if self:cfgvalue(section) == key then %> selected="selected"<% end %> value="<%=key%>"><%=self.vallist[i]%></option>
<% end %> <% end %>
@ -16,6 +15,10 @@
<% if c == self.size then c = 0 %><br /> <% if c == self.size then c = 0 %><br />
<% end end %> <% end end %>
<% end %> <% end %>
<div class="cbi-value-description inline"><%=self.description%></div>
</div> </div>
<div class="clear"></div> </div>
</div> <% if #self.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>

View file

@ -1,11 +1,8 @@
<% <%
local v = self:valuelist(section) local v = self:valuelist(section)
%> %>
<div class="cbi-value"> <div class="cbi-value" id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<div class="left"> <div class="cbi-value-title left"><%=self.title%></div>
<div class="cbi-value-title"><%=self.title%></div>
<div class="cbi-value-description"><%=self.description%></div>
</div>
<div class="cbi-value-field"> <div class="cbi-value-field">
<% if self.widget == "select" then %> <% if self.widget == "select" then %>
<select multiple="multiple" name="cbid.<%=self.config.."."..section.."."..self.option%>[]"<% if self.size then %> size="<%=self.size%>"<% end %>> <select multiple="multiple" name="cbid.<%=self.config.."."..section.."."..self.option%>[]"<% if self.size then %> size="<%=self.size%>"<% end %>>
@ -21,6 +18,10 @@ local v = self:valuelist(section)
<% if c == self.size then c = 0 %><br /> <% if c == self.size then c = 0 %><br />
<% end end %> <% end end %>
<% end %> <% end %>
<div class="cbi-value-description inline"><%=self.description%></div>
</div> </div>
<div class="clear"></div> </div>
</div> <% if #self.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>

View file

@ -2,27 +2,30 @@
<div class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>"> <div class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>">
<h2><%=self.title%></h2> <h2><%=self.title%></h2>
<div class="cbi-section-descr"><%=self.description%></div> <div class="cbi-section-descr"><%=self.description%></div>
<% if self.addremove then %><div class="cbi-section-remove">
<input type="submit" name="cbi.rns.<%=self.config%>.<%=self.section%>" value="<%:cbi_del Eintrag entfernen%>" />
</div><% end %>
<fieldset class="cbi-section-node"> <fieldset class="cbi-section-node">
<% self:render_children(self.section) %> <% self:render_children(self.section) %>
<% if #self.optionals[self.section] > 0 or self.dynamic then %> <% if #self.optionals[self.section] > 0 or self.dynamic then %>
<div class="cbi-optionals"> <div class="cbi-optionals">
<input type="submit" value="<%:cbi_addopt Feld hinzufügen%>" />
<% if self.dynamic then %> <% if self.dynamic then %>
<input type="text" name="cbi.opt.<%=self.config%>.<%=self.section%>" /> <input type="text" name="cbi.opt.<%=self.config%>.<%=self.section%>" />
<% else %> <% else %>
<select name="cbi.opt.<%=self.config%>.<%=self.section%>"> <select name="cbi.opt.<%=self.config%>.<%=self.section%>">
<option><%:cbi_selopt *** Zusätzliche Parameter ***%></option> <option><%:cbi_selopt *** Zusätzliche Parameter ***%></option>
<% for key, val in pairs(self.optionals[self.section]) do %> <% for key, val in pairs(self.optionals[self.section]) do %>
<option value="<%=val.option%>"><%=val.title%></option> <option id="cbi-<%=self.config.."-"..self.section.."-"..val.option%>" value="<%=val.option%>"><%=val.title%></option>
<% if #val.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(val.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..self.section.."-"..val.option%>", "cbid.<%=self.config.."."..self.section.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>
<% end %> <% end %>
</select> </select>
<% end %> <% end %>
<input type="submit" value="<%:cbi_addopt Feld hinzufügen%>" />
</div> </div>
<% end %> <% end %>
<br />
<% if self.addremove then %>
<input type="submit" name="cbi.rns.<%=self.config%>.<%=self.section%>" value="<%:cbi_del Eintrag entfernen%>" />
<% end %>
</fieldset> </fieldset>
</div> </div>
<% elseif self.addremove then %> <% elseif self.addremove then %>

View file

@ -2,8 +2,11 @@
<h2><%=self.title%></h2> <h2><%=self.title%></h2>
<div class="cbi-section-descr"><%=self.description%></div> <div class="cbi-section-descr"><%=self.description%></div>
<% for k, v in pairs(self:cfgsections()) do%> <% for k, v in pairs(self:cfgsections()) do%>
<fieldset class="cbi-section-node" id="cbi-<%=self.config%>-<%=k%>"> <% if self.addremove then %><div class="cbi-section-remove right">
<input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" value="<%:cbi_del Eintrag entfernen%>" />
</div><% end %>
<% if not self.anonymous then %><h3><%=k%></h3><% end %> <% if not self.anonymous then %><h3><%=k%></h3><% end %>
<fieldset class="cbi-section-node" id="cbi-<%=self.config%>-<%=k%>">
<% self:render_children(k) %> <% self:render_children(k) %>
<% if #self.optionals[k] > 0 or self.dynamic then %> <% if #self.optionals[k] > 0 or self.dynamic then %>
<div class="cbi-optionals"> <div class="cbi-optionals">
@ -11,19 +14,19 @@
<input type="text" name="cbi.opt.<%=self.config%>.<%=k%>" /> <input type="text" name="cbi.opt.<%=self.config%>.<%=k%>" />
<% else %> <% else %>
<select name="cbi.opt.<%=self.config%>.<%=k%>"> <select name="cbi.opt.<%=self.config%>.<%=k%>">
<option><%:cbi_selopt *** Zusätzliche Parameter ***%></option> <option><%:cbi_addopt -- Feld --%></option>
<% for key, val in pairs(self.optionals[k]) do %> <% for key, val in pairs(self.optionals[k]) do %>
<option value="<%=val.option%>"><%=val.title%></option> <option id="cbi-<%=self.config.."-"..k.."-"..val.option%>" value="<%=val.option%>"><%=val.title%></option>
<% if #val.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(val.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..k.."-"..val.option%>", "cbid.<%=self.config.."."..k.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>
<% end %> <% end %>
</select> </select>
<% end %> <% end %>
<input type="submit" value="<%:cbi_addopt Feld hinzufügen%>" /> <input type="submit" value="<%:add hinzufügen%>" />
</div> </div>
<% end %> <% end %>
<br />
<% if self.addremove then %>
<input type="submit" name="cbi.rts.<%=self.config%>.<%=k%>" value="<%:cbi_del Eintrag entfernen%>" />
<% end %>
</fieldset> </fieldset>
<br /> <br />
<% end %> <% end %>

View file

@ -1,9 +1,12 @@
<div class="cbi-value"> <div class="cbi-value clear" id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<div class="cbi-value-title left"><%=self.title%></div> <div class="cbi-value-title left"><%=self.title%></div>
<div class="cbi-value-description right"><%=self.description%></div>
<div class="cbi-value-field"> <div class="cbi-value-field">
<input type="text" <% if self.size then %>size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:cfgvalue(section) or "")%>" /> <input type="text" onchange="cbi_d_update(this.id)" <% if self.size then %>size="<%=self.size%>" <% end %><% if self.maxlength then %>maxlength="<%=self.maxlength%>" <% end %>name="cbid.<%=self.config.."."..section.."."..self.option%>" value="<%=(self:cfgvalue(section) or "")%>" />
<div class="cbi-value-description inline"><%=self.description%></div>
</div> </div>
<div class="clear"></div>
<% if self.tag_invalid[section] then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %> <% if self.tag_invalid[section] then %><div class="cbi-error"><%:cbi_invalid Fehler: Ungültige Eingabe%></div><% end %>
</div> </div>
<% if #self.deps > 0 then %><script type="text/javascript">
<% for j, d in ipairs(self.deps) do %>cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option%>", "cbid.<%=self.config.."."..section.."."..d.field%>", "<%=d.value%>");
<% end %>
</script><% end %>