luci-base: refactor cbi dependency handling code
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 18 Jan 2016 16:05:36 +0000 (17:05 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 18 Jan 2016 16:05:36 +0000 (17:05 +0100)
Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
modules/luci-base/htdocs/luci-static/resources/cbi.js
modules/luci-base/luasrc/view/cbi/cell_valuefooter.htm
modules/luci-base/luasrc/view/cbi/cell_valueheader.htm
modules/luci-base/luasrc/view/cbi/footer.htm
modules/luci-base/luasrc/view/cbi/full_valuefooter.htm
modules/luci-base/luasrc/view/cbi/full_valueheader.htm
modules/luci-base/luasrc/view/cbi/lvalue.htm
modules/luci-base/luasrc/view/cbi/mvalue.htm

index dd8d7b8..81cc657 100644 (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);
index 220ebd4..786ee43 100644 (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 %>
index 9e2e145..9c9c218 100644 (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))%>">
index 115250a..42bf98b 100644 (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>
index 4876fbc..f780936 100644 (file)
        </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 %>
index aaf0854..10a5543 100644 (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 -%>
index 8cc086d..9210ae5 100644 (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 %>
index 5d09261..9118a22 100644 (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 %>