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); 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); 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) { function cbi_d_add(field, dep, index) {
var obj = document.getElementById(field); var obj = (typeof(field) === 'string') ? document.getElementById(field) : field;
if (obj) { if (obj) {
var entry var entry
for (var i=0; i<cbi_d.length; i++) { 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]; entry = cbi_d[i];
break; break;
} }
@ -401,10 +401,10 @@ function cbi_d_add(field, dep, next) {
if (!entry) { if (!entry) {
entry = { entry = {
"node": obj, "node": obj,
"id": field, "id": obj.id,
"parent": obj.parentNode.id, "parent": obj.parentNode.id,
"next": next, "deps": [],
"deps": [] "index": index
}; };
cbi_d.unshift(entry); cbi_d.unshift(entry);
} }
@ -467,19 +467,27 @@ function cbi_d_update() {
var state = false; var state = false;
for (var i=0; i<cbi_d.length; i++) { for (var i=0; i<cbi_d.length; i++) {
var entry = cbi_d[i]; var entry = cbi_d[i];
var next = document.getElementById(entry.next) var node = document.getElementById(entry.id);
var node = document.getElementById(entry.id) var parent = document.getElementById(entry.parent);
var parent = document.getElementById(entry.parent)
if (node && node.parentNode && !cbi_d_check(entry.deps)) { if (node && node.parentNode && !cbi_d_check(entry.deps)) {
node.parentNode.removeChild(node); node.parentNode.removeChild(node);
state = true; state = true;
} else if ((!node || !node.parentNode) && cbi_d_check(entry.deps)) { } 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) { if (!next) {
parent.appendChild(entry.node); parent.appendChild(entry.node);
} else { } else {
next.parentNode.insertBefore(entry.node, next); parent.insertBefore(entry.node, next);
} }
state = true; 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) { function cbi_bind(obj, type, callback, mode) {
if (!obj.addEventListener) { if (!obj.addEventListener) {
obj.attachEvent('on' + type, 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); 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) { function cbi_t_add(section, tab) {
var t = document.getElementById('tab.' + section + '.' + tab); var t = document.getElementById('tab.' + section + '.' + tab);

View file

@ -1,20 +1,2 @@
</div> </div>
<div id="cbip-<%=self.config.."-"..section.."-"..self.option%>"></div>
</td> </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 %>"> <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%>'" /> <input class="cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
<% end %> <% end %>
<script type="text/javascript">cbi_d_update();</script> <script type="text/javascript">cbi_init();</script>
</div> </div>
<%- end -%> <%- end -%>
</form> </form>

View file

@ -11,49 +11,3 @@
</div> </div>
<%- end -%> <%- end -%>
</div> </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 -%> <%- if self.title and #self.title > 0 then -%>
<label class="cbi-value-title"<%= attr("for", cbid) %>> <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 -%> <%- 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 %> <% 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") %>> <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 -%> <% 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 %> <%- end %>
</select> </select>
<% elseif self.widget == "radio" then <% elseif self.widget == "radio" then
@ -10,8 +10,8 @@
for i, key in pairs(self.keylist) do for i, key in pairs(self.keylist) do
c = c + 1 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") %> /> <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..c) %>><%=self.vallist[i]%></label> <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 %> <% if c == self.size then c = 0 %><% if self.orientation == "horizontal" then %>&#160;<% else %><br /><% end %>
<% end end %> <% end end %>
<% end %> <% end %>

View file

@ -3,7 +3,7 @@
<% if self.widget == "select" then %> <% 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") %>> <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 -%> <% 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 %> <%- end %>
</select> </select>
<% elseif self.widget == "checkbox" then <% elseif self.widget == "checkbox" then
@ -11,8 +11,8 @@
for i, key in pairs(self.keylist) do for i, key in pairs(self.keylist) do
c = c + 1 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") %> /> <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..c) %>><%=self.vallist[i]%></label><% if not self.oneline then %><br /><% else %> <% end %> <label<%= attr("for", cbid.."-"..key) %>><%=self.vallist[i]%></label><br />
<% if c == self.size then c = 0 %><br /> <% if c == self.size then c = 0 %><br />
<% end end %> <% end end %>
<% end %> <% end %>