summaryrefslogtreecommitdiffhomepage
path: root/libs/web
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2010-10-25 17:04:03 +0000
committerJo-Philipp Wich <jow@openwrt.org>2010-10-25 17:04:03 +0000
commit70706cf388f8ac100778831e9ef9d7b1eb74c752 (patch)
tree096cada604879e8806762a050fd176b9b592f24c /libs/web
parenteecec8b0f2a2cd86827115c1479de974ece00850 (diff)
libs/web: rework DynamicList widget
Diffstat (limited to 'libs/web')
-rw-r--r--libs/web/htdocs/luci-static/resources/cbi.js185
-rw-r--r--libs/web/luasrc/cbi.lua45
-rw-r--r--libs/web/luasrc/view/cbi/dynlist.htm47
-rw-r--r--libs/web/luasrc/view/cbi/full_valuefooter.htm2
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 74a2576736..d5355f904b 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 5fa992dee8..17ca18c941 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 826e2e698e..9ca7534738 100644
--- a/libs/web/luasrc/view/cbi/dynlist.htm
+++ b/libs/web/luasrc/view/cbi/dynlist.htm
@@ -13,40 +13,31 @@ $Id$
-%>
<%+cbi/valueheader%>
+<div>
<%
local vals = self:cfgvalue(section) or {}
for i=1, #vals + 1 do
local val = vals[i]
%>
- <input class="cbi-input-text" value="<%=pcdata(val)%>" onchange="cbi_d_update(this.id)" type="text"<%= attr("id", cbid .. "." .. i) .. attr("name", cbid) .. ifattr(self.size, "size")%> />
- <% if i <= #vals then %>
- <input class="cbi-input-image" type="image" value="<%:Delete%>" name="cbi.rle.<%=section .. "." .. self.option .. "." .. i%>" alt="<%:Delete%>" title="<%:Delete%>" src="<%=resource%>/cbi/remove.gif" />
- <% else %>
- <input class="cbi-input-image" type="image" value="<%:Add%>" name="cbi.ale.<%=section .. "." .. self.option%>" alt="<%:Add%>" title="<%:Add%>" src="<%=resource%>/cbi/add.gif" />
- <% end %>
+ <input class="cbi-input-text" value="<%=pcdata(val)%>" onchange="cbi_d_update(this.id)" type="text"<%= attr("id", cbid .. "." .. i) .. attr("name", cbid) .. ifattr(self.size, "size")%> /><br />
+<% end %>
+</div>
+<script type="text/javascript">
+cbi_dynlist_init('<%=cbid%>');
+<% if self.datatype then -%>
<% if #self.keylist > 0 then -%>
- <script type="text/javascript">
- 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 -- %>');
- </script>
+ 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 %><br />
-<% end end %>
-<% if self.datatype then -%>
- <script type="text/javascript">
- <% for i=1, #vals + 1 do -%>
- cbi_validate_field('<%=cbid%>.<%=i%>', <%=tostring(self.optional == true or i > #vals)%>, '<%=self.datatype%>');
- <%- end %>
- </script>
+ <% for i=1, #vals + 1 do -%>
+ cbi_validate_field('<%=cbid%>.<%=i%>', <%=tostring(self.optional == true or i > #vals)%>, '<%=self.datatype%>');
+ <%- end %>
<% end -%>
+</script>
<%+cbi/valuefooter%>
diff --git a/libs/web/luasrc/view/cbi/full_valuefooter.htm b/libs/web/luasrc/view/cbi/full_valuefooter.htm
index c069b7f92c..18b2f2d76e 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 -%>
<br />
<%- end %>
<div class="cbi-value-description">