From 70706cf388f8ac100778831e9ef9d7b1eb74c752 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 25 Oct 2010 17:04:03 +0000 Subject: [PATCH] libs/web: rework DynamicList widget --- libs/web/htdocs/luci-static/resources/cbi.js | 185 ++++++++++++++++-- libs/web/luasrc/cbi.lua | 45 +++-- libs/web/luasrc/view/cbi/dynlist.htm | 47 ++--- libs/web/luasrc/view/cbi/full_valuefooter.htm | 2 +- 4 files changed, 222 insertions(+), 57 deletions(-) diff --git a/libs/web/htdocs/luci-static/resources/cbi.js b/libs/web/htdocs/luci-static/resources/cbi.js index 74a257673..d5355f904 100644 --- a/libs/web/htdocs/luci-static/resources/cbi.js +++ b/libs/web/htdocs/luci-static/resources/cbi.js @@ -265,22 +265,19 @@ function cbi_d_update() { } function cbi_bind(obj, type, callback, mode) { - if (typeof mode == "undefined") { - mode = false; - } if (!obj.addEventListener) { - ieCallback = function(){ - var e = window.event; - if (!e.target && e.srcElement) { - e.target = e.srcElement; - }; - e.target['_eCB' + type + callback] = callback; - e.target['_eCB' + type + callback](e); - e.target['_eCB' + type + callback] = null; - }; - obj.attachEvent('on' + type, ieCallback); + obj.attachEvent('on' + type, + function(){ + var e = window.event; + + if (!e.target && e.srcElement) + e.target = e.srcElement; + + return !!callback(e); + } + ); } else { - obj.addEventListener(type, callback, mode); + obj.addEventListener(type, callback, !!mode); } return obj; } @@ -345,7 +342,9 @@ function cbi_combobox(id, values, def, man) { obj.focus(); } else { obj.value = sel.options[sel.selectedIndex].value; - sel.className = (!obj.validate || obj.validate()) + + var vld = obj.getAttribute("cbi_validate"); + sel.className = (!vld || vld()) ? 'cbi-input-select' : 'cbi-input-select cbi-input-invalid'; } @@ -375,6 +374,152 @@ function cbi_filebrowser(id, url, defpath) { browser.focus(); } +function cbi_dynlist_init(name) +{ + function cbi_dynlist_renumber(e) + { + var count = 1; + var childs = e.parentNode.childNodes; + + for( var i = 0; i < childs.length; i++ ) + if( childs[i].name == name ) + childs[i].id = name + '.' + (count++); + + e.focus(); + } + + function cbi_dynlist_keypress(ev) + { + ev = ev ? ev : window.event; + + var se = ev.target ? ev.target : ev.srcElement; + + if (se.nodeType == 3) + se = se.parentNode; + + switch (ev.keyCode) + { + /* backspace, delete */ + case 8: + case 46: + if (se.value.length == 0) + { + if (ev.preventDefault) + ev.preventDefault(); + + return false; + } + + return true; + + /* enter, arrow up, arrow down */ + case 13: + case 38: + case 40: + if (ev.preventDefault) + ev.preventDefault(); + + return false; + } + + return true; + } + + function cbi_dynlist_keydown(ev) + { + ev = ev ? ev : window.event; + + var se = ev.target ? ev.target : ev.srcElement; + + if (se.nodeType == 3) + se = se.parentNode; + + var prev = se.previousSibling; + while (prev && prev.name != name) + prev = prev.previousSibling; + + var next = se.nextSibling; + while (next && next.name != name) + next = next.nextSibling; + + switch (ev.keyCode) + { + /* backspace, delete */ + case 8: + case 46: + var jump = (ev.keyCode == 8) + ? (prev || next) : (next || prev); + + if (se.value.length == 0 && jump) + { + se.parentNode.removeChild(se.nextSibling); + se.parentNode.removeChild(se); + + cbi_dynlist_renumber(jump); + + if (ev.preventDefault) + ev.preventDefault(); + + return false; + } + + break; + + /* enter */ + case 13: + var n = document.createElement('input'); + n.name = se.name; + n.type = se.type; + + cbi_bind(n, 'keydown', cbi_dynlist_keydown); + cbi_bind(n, 'keypress', cbi_dynlist_keypress); + + if (next) + { + se.parentNode.insertBefore(n, next); + se.parentNode.insertBefore(document.createElement('br'), next); + } + else + { + se.parentNode.appendChild(n); + se.parentNode.appendChild(document.createElement('br')); + } + + var dt = se.getAttribute('cbi_datatype'); + var op = se.getAttribute('cbi_optional') == 'true'; + + if (dt) + cbi_validate_field(n, op, dt); + + cbi_dynlist_renumber(n); + break; + + /* arrow up */ + case 38: + if (prev) + prev.focus(); + + break; + + /* arrow down */ + case 40: + if (next) + next.focus(); + + break; + } + + return true; + } + + var inputs = document.getElementsByName(name); + for( var i = 0; i < inputs.length; i++ ) + { + cbi_bind(inputs[i], 'keydown', cbi_dynlist_keydown); + cbi_bind(inputs[i], 'keypress', cbi_dynlist_keypress); + } +} + //Hijacks the CBI form to send via XHR (requires Prototype) function cbi_hijack_forms(layer, win, fail, load) { var forms = layer.getElementsByTagName('form'); @@ -484,7 +629,7 @@ function cbi_validate_reset(form) function cbi_validate_field(cbid, optional, type) { - var field = document.getElementById(cbid); + var field = (typeof cbid == "string") ? document.getElementById(cbid) : cbid; var vldcb = cbi_validators[type]; if( field && vldcb ) @@ -513,7 +658,13 @@ function cbi_validate_field(cbid, optional, type) field.form.cbi_validators = [ ]; field.form.cbi_validators.push(validator); - field.onblur = field.onkeyup = field.validate = validator; + + cbi_bind(field, "blur", validator); + cbi_bind(field, "keyup", validator); + + field.setAttribute("cbi_validate", validator); + field.setAttribute("cbi_datatype", type); + field.setAttribute("cbi_optional", (!!optional).toString()); validator(); } diff --git a/libs/web/luasrc/cbi.lua b/libs/web/luasrc/cbi.lua index 5fa992dee..17ca18c94 100644 --- a/libs/web/luasrc/cbi.lua +++ b/libs/web/luasrc/cbi.lua @@ -1641,25 +1641,48 @@ function DynamicList.value(self, key, val) table.insert(self.vallist, tostring(val)) end -function DynamicList.write(self, ...) - self.map.proceed = true - return AbstractValue.write(self, ...) +function DynamicList.write(self, section, value) + if self.cast == "string" and type(value) == "table" then + value = table.concat(value, " ") + elseif self.cast == "table" and type(value) == "string" then + local x, t = { } + for x in value:gmatch("%S+") do + t[#t+1] = x + end + value = t + end + + return AbstractValue.write(self, section, value) +end + +function DynamicList.cfgvalue(self, section) + local value = AbstractValue.cfgvalue(self, section) + + if type(value) == "string" then + local x + local t = { } + for x in value:gmatch("%S+") do + t[#t+1] = x + end + value = t + end + + return value end function DynamicList.formvalue(self, section) local value = AbstractValue.formvalue(self, section) - value = (type(value) == "table") and value or {value} - local valid = {} - for i, v in ipairs(value) do - if v and #v > 0 - and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i) - and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then - table.insert(valid, v) + if type(value) == "string" then + local x + local t = { } + for x in value:gmatch("%S+") do + t[#t+1] = x end + value = t end - return valid + return value end diff --git a/libs/web/luasrc/view/cbi/dynlist.htm b/libs/web/luasrc/view/cbi/dynlist.htm index 826e2e698..9ca753473 100644 --- a/libs/web/luasrc/view/cbi/dynlist.htm +++ b/libs/web/luasrc/view/cbi/dynlist.htm @@ -13,40 +13,31 @@ $Id$ -%> <%+cbi/valueheader%> +
<% local vals = self:cfgvalue(section) or {} for i=1, #vals + 1 do local val = vals[i] %> - /> - <% if i <= #vals then %> - " alt="<%:Delete%>" title="<%:Delete%>" src="<%=resource%>/cbi/remove.gif" /> - <% else %> - " alt="<%:Add%>" title="<%:Add%>" src="<%=resource%>/cbi/add.gif" /> - <% end %> + />
+<% end %> +
+ + cbi_combobox_init('<%=cbid .. "." .. i%>', { + <%- for i, k in ipairs(self.keylist) do -%> + <%-=string.format("%q", k) .. ":" .. string.format("%q", self.vallist[i])-%> + <%-if i<#self.keylist then-%>,<%-end-%> + <%- end -%> + }, '<%- if not self.rmempty and not self.optional then -%> + <%-:cbi_select-%> + <%- end -%>', '<%: -- custom -- %>'); <% end -%> -<% if i <= #vals then %>
-<% end end %> -<% if self.datatype then -%> - + <% for i=1, #vals + 1 do -%> + cbi_validate_field('<%=cbid%>.<%=i%>', <%=tostring(self.optional == true or i > #vals)%>, '<%=self.datatype%>'); + <%- end %> <% end -%> + <%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/full_valuefooter.htm b/libs/web/luasrc/view/cbi/full_valuefooter.htm index c069b7f92..18b2f2d76 100644 --- a/libs/web/luasrc/view/cbi/full_valuefooter.htm +++ b/libs/web/luasrc/view/cbi/full_valuefooter.htm @@ -14,7 +14,7 @@ $Id$ -%> <% if self.description and #self.description > 0 then -%> - <% if not luci.util.instanceof( self, luci.cbi.Flag ) or self.orientation == "horizontal" then -%> + <% if not luci.util.instanceof(self, luci.cbi.DynamicList) and (not luci.util.instanceof(self, luci.cbi.Flag) or self.orientation == "horizontal") then -%>
<%- end %>
-- 2.25.1