luci-base: refactor cbi dependency handling code

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
This commit is contained in:
Jo-Philipp Wich 2016-01-18 17:05:36 +01:00
parent be8dba57a9
commit b50471787f
8 changed files with 43 additions and 105 deletions

View file

@ -344,7 +344,7 @@ var cbi_validators = {
{
return (this.match(/^[0-9\*#!\.]+$/) != null);
},
'timehhmmss': function()
'timehhmmss': function()
{
return (this.match(/^[0-6][0-9]:[0-6][0-9]:[0-6][0-9]$/) != null);
},
@ -388,12 +388,12 @@ var cbi_validators = {
};
function cbi_d_add(field, dep, next) {
var obj = document.getElementById(field);
function cbi_d_add(field, dep, index) {
var obj = (typeof(field) === 'string') ? document.getElementById(field) : field;
if (obj) {
var entry
for (var i=0; i<cbi_d.length; i++) {
if (cbi_d[i].id == field) {
if (cbi_d[i].id == obj.id) {
entry = cbi_d[i];
break;
}
@ -401,10 +401,10 @@ function cbi_d_add(field, dep, next) {
if (!entry) {
entry = {
"node": obj,
"id": field,
"id": obj.id,
"parent": obj.parentNode.id,
"next": next,
"deps": []
"deps": [],
"index": index
};
cbi_d.unshift(entry);
}
@ -467,19 +467,27 @@ function cbi_d_update() {
var state = false;
for (var i=0; i<cbi_d.length; i++) {
var entry = cbi_d[i];
var next = document.getElementById(entry.next)
var node = document.getElementById(entry.id)
var parent = document.getElementById(entry.parent)
var node = document.getElementById(entry.id);
var parent = document.getElementById(entry.parent);
if (node && node.parentNode && !cbi_d_check(entry.deps)) {
node.parentNode.removeChild(node);
state = true;
} else if ((!node || !node.parentNode) && cbi_d_check(entry.deps)) {
var next = undefined;
for (next = parent.firstChild; next; next = next.nextSibling) {
if (next.getAttribute && parseInt(next.getAttribute('data-index'), 10) > entry.index) {
break;
}
}
if (!next) {
parent.appendChild(entry.node);
} else {
next.parentNode.insertBefore(entry.node, next);
parent.insertBefore(entry.node, next);
}
state = true;
}
}
@ -494,6 +502,21 @@ function cbi_d_update() {
}
}
function cbi_init() {
var nodes = document.querySelectorAll('[data-depends]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var deps = JSON.parse(node.getAttribute('data-depends'));
if (deps.length > 0) {
for (var alt = 0; alt < deps.length; alt++) {
cbi_d_add(node, deps[alt], i);
}
}
}
cbi_d_update();
}
function cbi_bind(obj, type, callback, mode) {
if (!obj.addEventListener) {
obj.attachEvent('on' + type,
@ -871,27 +894,6 @@ function cbi_dynlist_init(name, respath, datatype, optional, url, defpath, choic
cbi_dynlist_redraw(NaN, -1, -1);
}
//Hijacks the CBI form to send via XHR (requires Prototype)
function cbi_hijack_forms(layer, win, fail, load) {
var forms = layer.getElementsByTagName('form');
for (var i=0; i<forms.length; i++) {
$(forms[i]).observe('submit', function(event) {
// Prevent the form from also submitting the regular way
event.stop();
// Submit via XHR
event.element().request({
onSuccess: win,
onFailure: fail
});
if (load) {
load();
}
});
}
}
function cbi_t_add(section, tab) {
var t = document.getElementById('tab.' + section + '.' + tab);

View file

@ -1,20 +1,2 @@
</div>
<div id="cbip-<%=self.config.."-"..section.."-"..self.option%>"></div>
</td>
<% 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..d.add%>", {
<%-
for k,v in pairs(d.deps) do
-%>
<%-=string.format('"cbid.%s.%s.%s"', self.config, section, k) .. ":" .. string.format("%q", v)-%>
<%-if next(d.deps, k) then-%>,<%-end-%>
<%-
end
-%>
}, "cbip-<%=self.config.."-"..section.."-"..self.option%>");
<%- end %>
</script>
<%- end %>

View file

@ -1,2 +1,2 @@
<td class="cbi-value-field<% if self.error and self.error[section] then %> cbi-value-error<% end %>">
<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>">

View file

@ -19,7 +19,7 @@
<input class="cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
<% end %>
<script type="text/javascript">cbi_d_update();</script>
<script type="text/javascript">cbi_init();</script>
</div>
<%- end -%>
</form>

View file

@ -11,49 +11,3 @@
</div>
<%- end -%>
</div>
<% if #self.deps > 0 or #self.subdeps > 0 then -%>
<script type="text/javascript" id="cbip-<%=self.config.."-"..section.."-"..self.option%>">
<% for j, d in ipairs(self.subdeps) do -%>
cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option..d.add%>", {
<%-
for k,v in pairs(d.deps) do
local depk
if k:find("!", 1, true) then
depk = string.format('"%s"', k)
elseif k:find(".", 1, true) then
depk = string.format('"cbid.%s"', k)
else
depk = string.format('"cbid.%s.%s.%s"', self.config, section, k)
end
-%>
<%-= depk .. ":" .. string.format("%q", v)-%>
<%-if next(d.deps, k) then-%>,<%-end-%>
<%-
end
-%>
}, "cbip-<%=self.config.."-"..section.."-"..self.option..d.add%>");
<%- end %>
<% for j, d in ipairs(self.deps) do -%>
cbi_d_add("cbi-<%=self.config.."-"..section.."-"..self.option..d.add%>", {
<%-
for k,v in pairs(d.deps) do
local depk
if k:find("!", 1, true) then
depk = string.format('"%s"', k)
elseif k:find(".", 1, true) then
depk = string.format('"cbid.%s"', k)
else
depk = string.format('"cbid.%s.%s.%s"', self.config, section, k)
end
-%>
<%-= depk .. ":" .. string.format("%q", v)-%>
<%-if next(d.deps, k) then-%>,<%-end-%>
<%-
end
-%>
}, "cbip-<%=self.config.."-"..section.."-"..self.option..d.add%>");
<%- end %>
</script>
<%- end %>

View file

@ -1,4 +1,4 @@
<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 %>" id="cbi-<%=self.config.."-"..section.."-"..self.option%>">
<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 %>" 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 -%>

View file

@ -2,7 +2,7 @@
<% if self.widget == "select" then %>
<select class="cbi-input-select" onchange="cbi_d_update(this.id)"<%= attr("id", cbid) .. attr("name", cbid) .. ifattr(self.size, "size") %>>
<% for i, key in pairs(self.keylist) do -%>
<option id="cbi-<%=self.config.."-"..section.."-"..self.option.."-"..key%>"<%= attr("value", key) .. ifattr(tostring(self:cfgvalue(section) or self.default) == key, "selected", "selected") %>><%=striptags(self.vallist[i])%></option>
<option id="cbi-<%=self.config.."-"..section.."-"..self.option.."-"..key%>"<%= attr("value", key) .. ifattr(tostring(self:cfgvalue(section) or self.default) == key, "selected", "selected") .. attr("data-index", i) .. attr("data-depends", self:deplist2json(section, self.deplist[i])) %>><%=striptags(self.vallist[i])%></option>
<%- end %>
</select>
<% elseif self.widget == "radio" then
@ -10,8 +10,8 @@
for i, key in pairs(self.keylist) do
c = c + 1
%>
<input class="cbi-input-radio" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="radio"<%= attr("id", cbid..c) .. attr("name", cbid) .. attr("value", key) .. ifattr((self:cfgvalue(section) or self.default) == key, "checked", "checked") %> />
<label<%= attr("for", cbid..c) %>><%=self.vallist[i]%></label>
<input class="cbi-input-radio" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="radio"<%= attr("id", cbid.."-"..key) .. attr("name", cbid) .. attr("value", key) .. ifattr((self:cfgvalue(section) or self.default) == key, "checked", "checked") .. attr("data-index", i) .. attr("data-depends", self:deplist2json(section, self.deplist[i])) %> />
<label<%= attr("for", cbid.."-"..key) %>><%=self.vallist[i]%></label>
<% if c == self.size then c = 0 %><% if self.orientation == "horizontal" then %>&#160;<% else %><br /><% end %>
<% end end %>
<% end %>

View file

@ -3,7 +3,7 @@
<% if self.widget == "select" then %>
<select class="cbi-input-select" multiple="multiple" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)"<%= attr("name", cbid) .. ifattr(self.size, "size") %>>
<% for i, key in pairs(self.keylist) do -%>
<option<%= attr("value", key) .. ifattr(luci.util.contains(v, key), "selected", "selected") %>><%=striptags(self.vallist[i])%></option>
<option<%= attr("id", cbid.."-"..key) .. attr("value", key) .. ifattr(luci.util.contains(v, key), "selected", "selected") .. attr("data-index", i) .. attr("data-depends", self:deplist2json(section, self.deplist[i])) %>><%=striptags(self.vallist[i])%></option>
<%- end %>
</select>
<% elseif self.widget == "checkbox" then
@ -11,8 +11,8 @@
for i, key in pairs(self.keylist) do
c = c + 1
%>
<input class="cbi-input-checkbox" type="checkbox" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)"<%= attr("id", cbid..c) .. attr("name", cbid) .. attr("value", key) .. ifattr(luci.util.contains(v, key), "checked", "checked") %> />
<label<%= attr("for", cbid..c) %>><%=self.vallist[i]%></label><% if not self.oneline then %><br /><% else %> <% end %>
<input class="cbi-input-checkbox" type="checkbox" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)"<%= attr("id", cbid.."-"..key) .. attr("name", cbid) .. attr("value", key) .. ifattr(luci.util.contains(v, key), "checked", "checked") .. attr("data-index", i) .. attr("data-depends", self:deplist2json(section, self.deplist[i])) %> />
<label<%= attr("for", cbid.."-"..key) %>><%=self.vallist[i]%></label><br />
<% if c == self.size then c = 0 %><br />
<% end end %>
<% end %>