Na potrzeby projektu próbuję stworzyć tandem walidatorów - jeden po stronie serwera w php, drugi po stronie klienta w JS 'podpinany' o ile to tylko możliwe.
Deklaracja pól do walidacji i sposobu ich sprawdzania ma się znajdować jedynie po stronie serwera, do klienta wysyłana jako doklejony kod JSON.
Klasa będzie oczywiście rozwijana, to co w tej chwili prezentuję można potraktować jako pre-alpha

Sposób użycia w kodzie HTML:
<ul id="MyFormErrors"> </ul> <form id="MyForm"> <input name="field1" /> <input name="field2" /> </form> <script language="javascript"> new Validator('MyForm', 'MyFormErrors', { field1: { errorMsg: 'Podaj prawidłową wartość liczbową (10-100)', validator: name: 'checkInt', params: { min: 10, max: 60 } } }, field2: { errorMsg: 'Podaj prawidlowy kod pocztowy', validator: { name: 'preg', params: { regexp: /^[0-9]{2}-[0-9]{3}$/ } } } }); </script>
Kod klasy Validator:
Kod
Validator = Class.create();
Validator.prototype = {
initialize: function(form, errors, fields) {
this.form = $(form);
this.errors = $(errors);
this.fields = fields;
$H(fields).each(function(field) {
this.attach(field.key);
field.value.error = null;
}.bind(this));
},
attach: function(name, event) {
node = this.form.firstChild;
while(node) {
if(node.name == name)
Event.observe(node, 'change', this.validate.bind(this), true);
node = node.nextSibling;
}
},
validate: function(e) {
obj = Event.element(e);
field = this.fields[obj.name];
if(!this[field.validator.name](obj.value, field.validator.params)) {
if(field.error == null) {
obj.addClassName('error');
li = document.createElement('li');
li.appendChild(document.createTextNode(field.errorMsg));
this.errors.appendChild(li);
field.error = li;
}
} else if(field.error != null) {
obj.removeClassName('error');
field.error.parentNode.removeChild(field.error);
field.error = null;
}
return true;
},
preg: function(field, data) {
return (field.match(data.regexp) != null);
},
checkInt: function(field, data) {
return (!isNaN(parseInt(field)) && (data.min != undefined || field >= data.min) && (data.max != undefined || field <= data.max));
},
checkFloat: function(field, data) {
return (!isNaN(parseInt(field)) && (data.min != undefined || field >= data.min) && (data.max != undefined || field <= data.max));
}
}
Validator.prototype = {
initialize: function(form, errors, fields) {
this.form = $(form);
this.errors = $(errors);
this.fields = fields;
$H(fields).each(function(field) {
this.attach(field.key);
field.value.error = null;
}.bind(this));
},
attach: function(name, event) {
node = this.form.firstChild;
while(node) {
if(node.name == name)
Event.observe(node, 'change', this.validate.bind(this), true);
node = node.nextSibling;
}
},
validate: function(e) {
obj = Event.element(e);
field = this.fields[obj.name];
if(!this[field.validator.name](obj.value, field.validator.params)) {
if(field.error == null) {
obj.addClassName('error');
li = document.createElement('li');
li.appendChild(document.createTextNode(field.errorMsg));
this.errors.appendChild(li);
field.error = li;
}
} else if(field.error != null) {
obj.removeClassName('error');
field.error.parentNode.removeChild(field.error);
field.error = null;
}
return true;
},
preg: function(field, data) {
return (field.match(data.regexp) != null);
},
checkInt: function(field, data) {
return (!isNaN(parseInt(field)) && (data.min != undefined || field >= data.min) && (data.max != undefined || field <= data.max));
},
checkFloat: function(field, data) {
return (!isNaN(parseInt(field)) && (data.min != undefined || field >= data.min) && (data.max != undefined || field <= data.max));
}
}