libs/cbi: implement realtime client side input validation for Value and DynamicList...
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 26 Apr 2010 21:42:10 +0000 (21:42 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 26 Apr 2010 21:42:10 +0000 (21:42 +0000)
libs/cbi/htdocs/luci-static/resources/cbi.js
libs/cbi/luasrc/view/cbi/header.htm
libs/cbi/luasrc/view/cbi/value.htm

index 3840456ca4bcace6d5fdff1b6e6c42f958ead12d..7cdca642d24241f46cdea8a0979b332e8ff1f72f 100644 (file)
@@ -304,6 +304,9 @@ function cbi_combobox(id, values, def, man) {
        var sel = document.createElement("select");
        sel.id = selid;
        sel.className = 'cbi-input-select';
+       if (obj.className && obj.className.match(/cbi-input-invalid/)) {
+               sel.className += ' cbi-input-invalid';
+       }
        if (obj.nextSibling) {
                obj.parentNode.insertBefore(sel, obj.nextSibling);
        } else {
@@ -351,6 +354,8 @@ function cbi_combobox(id, values, def, man) {
                        obj.focus();
                } else {
                        obj.value = sel.options[sel.selectedIndex].value;
+                       sel.className = (!obj.validate || obj.validate())
+                               ? 'cbi-input-select' : 'cbi-input-select cbi-input-invalid';
                }
 
                try {
@@ -447,43 +452,63 @@ function cbi_t_update() {
 }
 
 
-function cbi_validate_disable_form(form, onoff)
+function cbi_validate_form(form, errmsg)
 {
-       for( var i = 0; i < form.elements.length; i++ )
+       if( form.cbi_validators )
        {
-               if( form.elements[i].type == 'submit' )
+               for( var i = 0; i < form.cbi_validators.length; i++ )
                {
-                       form.elements[i].disabled = onoff;
-                       break;
+                       var validator = form.cbi_validators[i];
+                       if( !validator() && errmsg )
+                       {
+                               alert(errmsg);
+                               return false;
+                       }
                }
        }
+
+       return true;
 }
 
-function cbi_validate_field(type, optional, field)
+function cbi_validate_reset(form)
 {
-       field.className = field.className.replace(/ cbi-input-invalid/g, '');
+       window.setTimeout(
+               function() { cbi_validate_form(form, null) }, 100
+       );
+
+       return true;
+}
 
+function cbi_validate_field(cbid, optional, type)
+{
+       var field = document.getElementById(cbid);
        var vldcb = cbi_validators[type];
-       if( vldcb )
-       {
-               var value = (field.options) ? field.options[field.options.selectedIndex].value : field.value;
 
-               if( ((value.length == 0) && optional) || vldcb(value) )
-               {
-                       // OK
-                       cbi_validate_disable_form(field.form, false);
-               }
-               else
-               {
-                       // Invalid
-                       field.className += ' cbi-input-invalid';
-                       cbi_validate_disable_form(field.form, true);
-               }
-       }
-       else
+       if( field && vldcb )
        {
-               // OK
-               cbi_validate_disable_form(field.form, false);
+               var validator = function(reset)
+               {
+                       field.className = field.className.replace(/ cbi-input-invalid/g, '');
+
+                       // validate value
+                       var value = (field.options) ? field.options[field.options.selectedIndex].value : field.value;
+                       if( !(((value.length == 0) && optional) || vldcb(value)) )
+                       {
+                               // invalid
+                               field.className += ' cbi-input-invalid';
+                               return false;
+                       }
+
+                       return true;
+               };
+
+               if( ! field.form.cbi_validators )
+                       field.form.cbi_validators = [ ];
+
+               field.form.cbi_validators.push(validator);
+               field.onblur = field.onkeyup = field.validate = validator;
+
+               validator();
        }
 }
 
index bece16bb2a8fbeeb55f6b4508cacbe13f51a5680..fd1ab8bd1a4d4069d82d5371b2e65c5568145923 100644 (file)
@@ -1,7 +1,7 @@
 <%#
 LuCI - Lua Configuration Interface
 Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+Copyright 2008-2010 Jo-Philipp Wich <xm@subsignal.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@ $Id$
 -%>
 
 <%+header%>
-<form method="post" name="cbi" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
+<form method="post" name="cbi" action="<%=REQUEST_URI%>" enctype="multipart/form-data" onreset="return cbi_validate_reset(this)" onsubmit="return cbi_validate_form(this, '<%:Some fields are invalid, cannot save values!%>')">
        <div>
                <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
                <input type="hidden" name="cbi.submit" value="1" />
index 8bdebd902ffe320ca6ecbac6ba27247e40eef121..a7b49de7ff9fa5e5a737ff3f109427e3a00b8b58 100644 (file)
@@ -1,7 +1,7 @@
 <%#
 LuCI - Lua Configuration Interface
 Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+Copyright 2008-2010 Jo-Philipp Wich <xm@subsignal.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -15,8 +15,9 @@ $Id$
 <%+cbi/valueheader%>
        <input type="<%=self.password and 'password" class="cbi-input-password' or 'text" class="cbi-input-text' %>" onchange="cbi_d_update(this.id)"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self:cfgvalue(section) or self.default) .. ifattr(self.size, "size")%> />
        <% if self.password then %><img src="<%=resource%>/cbi/reload.gif" style="vertical-align:middle" title="<%:Reveal/hide password%>" onclick="var e = document.getElementById('<%=cbid%>'); e.type = (e.type=='password') ? 'text' : 'password';" /><% end %>
-       <% if #self.keylist > 0 then -%>
+       <% if #self.keylist > 0 or self.datatype then -%>
        <script type="text/javascript">
+               <% if #self.keylist > 0 then -%>
                cbi_combobox_init('<%=cbid%>', {
                <%-
                        for i, k in ipairs(self.keylist) do
@@ -34,6 +35,10 @@ $Id$
                <%- else -%>
                        <%-: -- custom -- -%>
                <%- end -%>');
+               <%- end %>
+               <% if self.datatype then -%>
+               cbi_validate_field('<%=cbid%>', <%=tostring(self.optional == true)%>, '<%=self.datatype%>');
+               <%- end %>
        </script>
        <% end -%>
 <%+cbi/valuefooter%>