Really easy field validation with Prototype
Saturday, January 6, 2007I wanted a robust javascript validation library that was simple to implement and didn't require me do any extra work other than creating the form. My favourite idea for a method of doing this is to utilise the field elements' class attribute to indicate what sort of field it is and hence any validation requirements. There are a few javascript libraries that implement that idea like wForms, but, since I'm currently hell-bent on re-writing all my javascript using Prototype, I thought I'd see how difficult or easy it would be to roll my own. Turns out that this is just the sort of thing that is easy with Prototype. Here's what I came up with.
Do not be alarmed! The library has moved here.
100 Comments
Does the script check to see if a validated fields is within a hidden element and therefore not trigger?
A
"So here it is in it's first usable, albeit basic, form."
Not yet ;)
It does now!
<a href="http://www.matsblog.com/stories/1897119/">realy great work!</a> (because i can't use trackback here :)
Great script.
By adding a couple of lines to the script I've added 'blur' capabilities to this script, so that the validation can also be run when a field loses focus.
I added the following few lines of code to the Validation.initialize method:
Form.getElements(this.form).each(function(input) {
Event.observe(input, 'blur', function(ev) { $V(Event.element(ev).id) });
});
Seems to work a treat!
Thanks Mike, looks great! I might add it and make it optional.
You rock!
Great. Does it work with other fields ?(SELECT, TEXTAREA...)
Hi Benoit (8), it simply tests the value returned by the prototype $F(element) function. So the simple answer is yes, it does all those.
It's a pitty that this very same form, doesn't use such a nice script.
Come on! You can show it off a little bit!
when you have time, would you please add a basic US/Canadian phone number validation for format 123-456-7890??
beyond this, thank you very much for working on this, standard validations like this should be included in all the good javascript libraries!!
thank you, :) tom
I'm into it.
One day I'd like to tie this into SmartyValidator (for those of us still coding in PHP w/ SMARTY templates). Until then; this is going in the bookmarks.
Good work
~ Brice
One thing that is seriously lacking is server side validation, that's kinda the whole point of AJAX form validation isnt it? To avoid page refreshes with XMLHTTPRequest. Other than that, great implementation!
have you heard of TMT validator. It is a much cleaner way of dealing with validation. google it.
Hmm... looks very similar to my solution.
http://software.jonandnic.com/jsObjects
Check out jsUI-Textbox, which reads extended attributes of form-field elements to validate types...
I like it.
Very cool. I've created something very similar, but instead of validation it does keypress masking (ie: class="mask-alphaNumeric")
One thing you might consider, rather than using a constructor like "new Validation('form-id')", you could simply add a className to the form itself, ala [form class="Validate" ...]
Or, i suppose it would be possible to skip that step altogether, and just parse every form for validate-* classNames, and invoke the constructor as required.
Neat stuff!
look great.
just spotted a small typo:
dd/mm/yyy should be dd/mm/yyyy
This is really nice. I am going to write support for this into Zoop Framework, a PHP framework that already has excellent validation, but could use a cleaner javascript implementation. I will let you know when it is done. To work with Zoop we would need a few more validation types which I can add and share back.
Prototype.js - or the way you are using it - leaks memory in Firefox.
Install this:
https://addons.mozilla.org/firefox/2490/
Run dexagogo's code, and see for yourself
Prototype.js - or your use of it - leaks memory in Firefox. Install this:
https://addons.mozilla.org/firefox/2490/
then run this dexagogo demo and see for yourself!
The e-mail validator doesn't work properly; it doesn't support international addresses[EDITED OUT] That's a valid e-mail address, but it doesn't work in the demo.
Great article. Thanks.
I am trying to impement this technique but can not get it to work with IE. My example: http://klevo.yweb.sk/forms/1/
Any suggestions?
Problem is, I already have validations defined in my Rails models, and I Don't want to Repeat Myself by having validation code in the views.
10 points to the first developer who makes this work *without* explicitly adding extra code to the views.
Arrrrg, I got dugg.
Anyways, Joe (13), yeah it's nothing to do with AJAX, just a little javascript validation library. JS validation is good because it saves a trip to the server for basic problems.
But,Server side validation is a must for many reasons, not the least of which is security. If the user-agent does not execute javascript, your only fall back is server-side validation.
JS validation is a nice little extra and as such the easier you can implement it the better.
Thanks for the typo warning Analdesia (18)!
Brice (12) and Supernerd (19) glad you can find it useful. Let me know how you get on.
an0n (21), thanks for the heads up.
Klevo (23) probably something to do with window.onload=function() {
Nifty("div#form1", "big");
}
use the prototype Event.observe for that too and see how you go.
Sorry, Daniel Schierbeck (22), the email address borked the page... yeah yeah I know... It'll be fixed.
Why are you using the class attribute for specifying validation requirements? That means you won't be able to use the class attribute for styling text boxes or just the text inside. The alt attribute would be better as browsers don't do anything with it but is accessible.
Have you ever heard of fValidate? A greate validation kit but not supported any more. It would be nice if some Javascript guru would pick up where the original programmer left off.
Hi Alex (29), what's stopping you from using it for both? I use the class 'required' for validation but also in the CSS in the demo. That's what gives required fields the blue border. You can also add your own CSS class name to the class attribute and the validation library will ignore it. for example:
class="required big-red-box"
Nice script. How about functionality for "at least X characters" or "no more than X characters" or combination of both? Addition of phone number validation would be cool too!
Thx,
Mike
If I submit '-1' for the donation amount in the demo it passes the validation. Does that mean you owe me money? ;-)
Glann (32), yes it does! Congratulations! To claim your nomintated dollar amount please post your bank account details and home address!
i seldom post my forms using the Submit button
but calling javascript to do
document.myForm.submit();
doesnt seem to capture the event when submitted this way
I was trying wForms today! You've made a really great work here too!!!
I would like to know if there is an easy way to make the values of elements in an 'display:none' don't be submited.
Francis (34), that's because the validation library adds an event listener to the onsubmit event and it is a generally known that when calling form.submit() the browsers do not fire the onsubmit event. What you generally have to do is write a custom form submit function which fires the onsubmit and then submit functions manually.
For example: http://www.javascript-coder.com/javascript-form/javascript-form-submit.phtml
oh thanks
this bit of code did the job
<input type="submit" name="fakeSubmitButton" style="display: none"/>
instead of calling document.forms['form name'].submit(); call
document.forms['form name'].fakeSubmitButton.click();
Arrrrg, I got dugg.
Anyways, Joe (13), yeah it's nothing to do with AJAX, just a little javascript validation library. JS validation is good because it saves a trip to the server for basic problems.
But,Server side validation is a must for many reasons, not the least of which is security. If the user-agent does not execute javascript, your only fall back is server-side validation.
JS validation is a nice little extra and as such the easier you can implement it the better.
==============================================
Right, but without server side validation, wouldn't this just be an enhanced alert eyecandy? Server side validation will really improve this already great implementation :)
Forgot to mention, it can be client side for basic validations still, only those require server trips will post a request. I believe this is how wForm works too.
great script! But Im using it on a file upload....
<input type="file" name="imageupload" id="imageupload" value="" class="required" />
... and it returns the validation failed fine but when a file is attached still returns validation failed... Any ideas?
Thanks
I like it. But it had one drawback for me: The error messages are 'hard-coded' in the JS file, but I'd like them in my view (for example, if you're going multi-language).
So I hacked a bit, and Now you can (but you don't need to) add a element to your HTML code with the proper id (the same the automatically generated element uses), hide it per CSS and if the validation test failed, it will be displayed. And it falls back to generation if you don't have an element.
---
Code:
[before if(typeof Effect == 'undefined') {]
var advice = $(id);
if(advice == undefined)
{
advice = document.createElement('div');
this.parentNode.insertBefore(advice, this.nextSibling);
advice.className = 'validation-advice';
advice.id = id;
advice.appendChild(document.createTextNode(v.error));
};
Dom G (40), the script only tests the value returned from the $F function in Prototype. Looking at it now, it does not support input elements of type file. It'll return blank every time.
Sidney (41), that's a great idea!
I was trying to validate a name field and it always failed regardless of whether I used alpha or alphanum.
The name was: Scott O'Neil
The apostrophe was making it fail, but so was the space between the first and last names.
I guess I'll just mark it as 'required'.
Anyway, thought it was something that should be in your comments.
Keep up the awesome work :)
Thanks Derek (43), I'll look into it. I have a healthy to-do list now, after all these comments!
This is great work!
I'm using prototype and fValidate in my projects - whilst fValidate is great, the code is a bit bulky, however there are some things it can do over and above this -
1) checkbox / radio validation - validates single/multiple selections and displays errors at the end of the group
2) 'equalto' as a validation type - great for checking for email address typo's
Whilst evaluating this code, I wrote a couple of extra validaton types that might be useful to others:
['validate-ukpost', 'Please enter a UK postcode.', function(v) {
return Validation.get('IsEmpty').test(v) || /^[A-Za-z]{1,2}[\d]{1,2}([A-Za-z])?\s?[\d][A-Za-z]{2}$/.test(v)
}],
['validate-ukphone', 'Please enter a UK postcode.', function(v) {
// pattern from http://www.regexlib.com/REDetails.aspx?regexp_id=589
return Validation.get('IsEmpty').test(v) || /^(((\+44\s?\d{4}|\(?0\d{4}\)?)(\s?\d{3}\s?\d{3}|\s?\d{5}))|((\+44\s?\d{3}|\(?0\d{3}\)?)(\s?\d{3}\s?\d{4}|\s?\d{3}\s?\d{3}))|((\+44\s?\d{2}|\(?0\d{2}\)?)(\s?\d{4}\s?\d{4})|\s?\d{3}\s?\d{4}))(\s?\#(\d{4}|\d{3}))?$/.test(v)
}]
Thanks Phil (45), that's awsome. Points 1 and 2 are great and should be added, I agree.
Thanks for your validator patterns. One point my preference is to make validator keys have the country codes last like: 'validate-phone-uk'. I just like the neatness of a bunch of 'validate-phone-XX' patterns for internationalisation.
Very nice script and came in extremely handy, thanks!
It would be really great if the library did a focus() on the first field that fails. The reason being that on very long forms, the user is left with no indication of what happened if a field at the top of page fails, and they pressed submit at the bottom.
Awesome script! I could see myself using it for all the forms I build.
One caveat I did notice is with <select> boxes. Consider the following <select> box:
<select id="test" name="test" class="required">
<option value="">Please Select..</option>
<option value="val1">Value 1</option>
<option value="val2">Value 2</option>
</select>
If submitted with the blank value, $F() will for some reason return the value "Please Select..". a bug? feature? who knows.
As a workaround, I created my own validation for select boxes, "validate-select".
First off, brilliant idea that works very effectively. I would like to be able to submit the form via AJAX, but that requires me to intercept the submit request, but that then stops the validation occuring. Any idea how I can get it so that on submit it does:
1) Validation
2) Custom function
3) Cancel submission event
I suppose this is really a prototype question, how to add an additional function to an event.
John (43), You wish has been granted!
Grant (44), great! That's exactly how I intended the library to be used.
Daniel (45), Event.observe() allows you to do that.
Good,but it is difficult to show i18n error message in this schema,because the error message is included in the javascript file,if the implementation can separate the message text from the javascript file,it will be better,i think
..And if anyone is wondering what the validate-select function looks like:
Validation.add('validate-select', 'This is a required field.', function(v) {
return ((v != "none") && (v != null) && (v.length != 0));
});
sorry,i am wrong,i18n can be easily got..
Hi. This is really really great work. Just yesterday we were discussing building something similar to use with random projects here at work. You've saved a lot of headache and done it about 23 times cleaner than I could have.
Thank you so much.
How do I call some more javascript after validation? (like if I want to submit the form via AJAX if it's valid)
It would be nice if you could call a static Validation.validateForm('form-id') so that you could call it inside of your own onsubmit, from your example it looks like i'd have to call Valiation.validate('field-id') for each field..
Of course, I didn't look at the code, so slap me if I'm wrong!!! :)
Hi daryn, if you assign the object instance to a variable you can call the validate function manually.
i.e. var valid = new Validation('form');
then call If(valid.validate()) {} whenever you like.
Nicely done, Andrew.
One minor tip on your numeric validation (validate-number) on the demo page - it accepts the space character as a valid number. The Javascript isNaN function is to blame; it thinks the space character is a number - not sure why.
Hey,
Great script, i just need to know a couple of things though, where abouts does it tell it to stop and carry on submitting them form? As i'd like to modify it so when you submit it, it uses
returns something like "Form Submitted" or something like that?
Basically the question i asked should be, what does your script use to stop and start the form submission?
Hi Rob, thanks for the isNaN tip.
Hi Sam Again, It uses the Event.observe() function from Prototype to add an event listener to the form's onsubmit event. Then, if validation fails, it cancels the event.
This is a great library, but I have two questions:
1) It's possible put two elements for a class? e.g: class="required validate-email"
2) How I can validate if two fields have the same content? Use in form for password validation
Regards
Hi ReynierPM, 1) yep, see the demo, 2) You'll need to write your own valildator.
Hi, very very nice, worked on it all the morning at work.
I'm from france so we use éïù, - in names etc...
I can't find a good validation for this cases, how can i modify validate-alpha regex ([a-zA-Z]+$) to add support of accentued letters and "-" in names for form (eg: what's your name : ? Vincent voyé-georges (yes it can happend)
I think people outside france will be very happy too because we're not the ones to use accentued letters AND especially "-" wich you must use too in your names.
THANK YOU
Hey,
Its sam again from (58) :P
Ok i understand where if validation fails it uses Event.stop(ev);.
I see how to set validation rules, is there anyway to get it, so when they submit it checks a mysql database for an existing username/email or whatever and then returns, "User already exists" etc? I am fluent in php, im presuming that would help :P Please contact me on msn/email, i would love if you could help me :D samcleaver.beaver [a':'t] gmail.com.
Hi Andrew, relating to my earlier post (45) I've had a go at writing a validator for "equalto".
I have a strong suspicion there is a better way to approach this problem, but this sort-of works for me.
Hopefully my attempt can inspire some better programmers out there than me ;-)
['validate-equalto', 'Please ensure these values are equal', function(v) {
// won't work properly with {immediate : true}
var elmEqualto = document.getElementsByClassName('validate-equalto');
return ($F(elmEqualto[0].id) != $F(elmEqualto[1].id)) ? false:true;
}]
Keep up the great work.
Phill
Great stuff....
I have a prob though. It seems that I have to add an "id" element to every input field I have. Is there a reason why? Can you make it so it doesn't have to do that?
Any particular reason not to extend the test callback from (v) to (v,elem) [by switching !v.test($F(this)) to !v.test($F(this),this)) in Validation.test]?
It could be useful for allowing more application-specific validation rules which want to look at, say, the element id, or whatnot...
Hi wouaren, yep internationalisation is something I'd like to tackle. But in regular expressions it looks like the only option is to use unicode escapes. For example [\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff]
is the set of all the Latin-1 character codes that you mention in your comment. I used a set generator from here:
http://www.codeproject.com/dotnet/UnicodeCharCatHelper.asp
very handy tool!
Sam, AJAX validation is something I'll tackle soon.
Thanks Phil! I'm working on making validaiton like that easier.
Nate, yep I can make it so it doesn't have to do that.
Issac, look for the next release.
Andrew your great.. :D
I used it as below:
[snip]then,i find something which may be improved on:
1. if i press submit button directly,the required tooltips while appear below <input type="checkbox">,not appear below <textarea>.
it seem the framework don't support <textarea>.
2.if i fill <textarea> and <checkbox>,then press submit button,the radio input check will work,but it can't show required tooltips.
3.i suggest it may be better if your framework can use form item's title attribute as required tooltips .because i'm a chinese,and required work on Chinese tooltips.
allthougn i can modify your framework source code by my own.
however,thanks for create this wonderful frame,wish it be great better,and you !
Sorry, It's not my day. I hope you can delete that last one:
['validate-url', 'Please enter a valid URL.', function (v) {
return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\//i.test(v)}]
Hello,
Thank you for your work. As mention, the only seen drawback are the "hard" coded error messages. Here is a small diff on your current JS to allow you to use the title elemement of the form as an error message.
Regards,
xav
-------------------------------------------
# diff -Naur validation.js validation.js.1
--- validation.js 2006-05-18 13:45:29.000000000 +0200
+++ validation.js.1 2006-05-30 20:27:34.000000000 +0200
@@ -74,7 +74,12 @@
var advice = Validation.getAdvice(name, this.id);
if(typeof advice == 'undefined') {
advice = document.createElement('div');
+ // title
+ if(this.title) {
+ advice.appendChild(document.createTextNode(this.title));
+ } else {
advice.appendChild(document.createTextNode(v.error));
+ }
advice.className = 'validation-advice';
advice.id = 'advice-' + name + '-' + this.id;
advice.style.display = 'none';
Hi xav, the current version does include the 'custom advice' feature where you can put your error advice within any element on the page.
Thanks for the code, using the element's title has been mentioned before too and you've provided the code to do it!
Ain't open source grand :)
hi, thnx for the very handy and cool validation frameworks. but i noticed the 'validate-date-au' cannot determine leapyears.
so i suggest u to change the date validator some thing like following:
['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {
if(Validation.get('IsEmpty').test(v)) return true;
var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
if(! regex.test(v)) return false;
var d = new Date(v.replace(regex, '$2/$1/$3'));
return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) )
&& (parseInt(RegExp.$1, 10) == d.getDate())
&& (parseInt(RegExp.$3, 10) == d.getFullYear()
);
}]
thanks.. keep up nice works.
validate phone numbers:
339-4248
339-42-48
339 42 48
339 4248
3394248
(095) #phone#
(095)#phone#
+7 (095) #phone#
+7 (095)#phone#
+7(095) #phone#
+7(095)#phone#
['validate-phone', 'Please enter a valid phone number. For example (123) 456-789', function(v) {
return Validation.get('IsEmpty').test(v) || /^(\+\d)*\s*(\(\d{3}\)\s*)*\d{3}(-{0,1}|\s{0,1})\d{2}(-{0,1}|\s{0,1})\d{2}$/.test(v);
}],
Excellent work, but hows about validating select box's and radio buttons? If only to see if they're empty or not..
Hi everybody
I have played around the validation code is uses a semilar aproch
Well I dont think it’s perferct yet
known issue:
suppose we put 2 validation conditions if one is true the input is then valide even the second condition is false
please take a look at the script let me think what do you think about it and how we can improve it together.
you can see a demo and download the script at http://www.tus.com.tn/area51/lab/vf/vf.htm
you can host it here if you want since it’s my company’s site
Hello,
I'm style playing with your well done simple form validation script.
I noticed that on Konqueror (the linux geek browser) the script is not working. I figured out that the following line is causing problems :
this.parentNode.insertBefore(advice, this.nextSibling);
Konqueror seems not to handle this.
Using the "new Insertion.After" method instead is fixing the problme with Konqueror and has no consequence on other browsers.
This change required some minors changes on the "test" function. Don't hesitate to contact me for full code.
Regards,
xav
Great work, thanks!
@ #65, Phil:
Hi, i have one cuestion. How do you make your "equal-to" validation work? I don't get how you pass the name of the field you want to validate against.
Something else only. "email@example.com " doesn't validate. You should trim spaces in every string.
BTW, I hope someone comes up with an equalto validation. I've tried to do it myself but my js knowledge is soooooo limited...
Hello,
Great Job.
Here is a patch that does the following:
In your initial work, ids are mandatory, I removed this by modifying getAdvice and taking the hypthesis that the advice is always next to the checked node and that the node has the class validation-advice.
I also changed some functions to make the code work with prototype 1.4
I finally removed the addition/removal of validation-passed class
I also encountered some problems with the code type of XXXX == 'undefined', that I replaced with XXXX == undefined
Here is the patch.
Philippe.
Index: validation.js
===================================================================
RCS file: /PMD/CVSRepository/fwk-3/webapp/fwk/js/fwk/validation/validation.js,v
retrieving revision 1.1
diff -u -r1.1 validation.js
--- validation.js 6 Jun 2006 20:52:31 -0000 1.1
+++ validation.js 6 Jun 2006 21:00:38 -0000
@@ -22,23 +22,34 @@
}
}
-var Validation = Class.create();
+Validation = Class.create();
Validation.prototype = {
initialize : function(form, options){
- this.options = Object.extend({
- stopOnFirst : false,
- immediate : false,
- focusOnError : true
- }, options || {});
+ this.setOptions(options);
this.form = $(form);
- Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
- if(this.options.immediate) {
- Form.getElements(this.form).each(function(input) { // Thanks Mike!
- Event.observe(input, 'blur', function(ev) { Validation.validate(Event.element(ev).id) });
+ if(this.options.validateOnSubmit)
+ {
+ Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
+ }
+ if(this.options.immediate)
+ {
+ Form.getElements(this.form).each(function(input)
+ {
+ Event.observe(input, 'blur', function(ev) { Validation.validate(Event.element(ev)) });
});
}
},
+ setOptions : function(options)
+ {
+ this.options =
+ {
+ stopOnFirst : false,
+ immediate : false,
+ validateOnSubmit : false,
+ focusOnError : true
+ }.extend(options || {});
+ },
onSubmit : function(ev){
if(!this.validate()) {
Event.stop(ev);
@@ -63,7 +74,7 @@
validate : function(elm, index, options){ // index is here only because we use this function in Enumerations
var options = Object.extend({}, options || {}); // options still under development and here as a placeholder only
elm = $(elm);
- var cn = elm.classNames();
+ var cn = Element.classNames(elm);
return result = cn.all(Validation.test.bind(elm));
},
test : function(name) {
@@ -71,59 +82,69 @@
var prop = '__advice'+name.camelize();
if(Validation.isVisible(this) && !v.test($F(this))) {
if(!this[prop]) {
- var advice = Validation.getAdvice(name, this.id);
- if(typeof advice == 'undefined') {
+ var advice = Validation.getAdvice(name, this.id, this);
+ if(advice == undefined) {
advice = document.createElement('div');
advice.appendChild(document.createTextNode(v.error));
advice.className = 'validation-advice';
- advice.id = 'advice-' + name + '-' + this.id;
- advice.style.display = 'none';
+ // We make the Validation work even if id is not defined
+ if(this.id != null)
+ {
+ advice.id = 'advice-' + name + '-' + this.id;
+ }
+ //advice.style.display = 'none';
this.parentNode.insertBefore(advice, this.nextSibling);
}
- if(typeof Effect == 'undefined') {
+ if(Effect == undefined) {
advice.style.display = 'block';
} else {
new Effect.Appear(advice.id, {duration : 1 });
}
}
+
this[prop] = true;
- this.removeClassName('validation-passed');
- this.addClassName('validation-failed');
+ //Element.removeClassName(this,'validation-passed');
+ Element.addClassName(this,'validation-failed');
return false;
} else {
- var advice = Validation.getAdvice(name, this.id);
- if(typeof advice != 'undefined') advice.hide();
- this[prop] = '';
- this.removeClassName('validation-failed');
- this.addClassName('validation-passed');
+ var advice = Validation.getAdvice(name, this.id, this);
+ if(advice != undefined)
+ {
+ Element.hide(advice);
+ }
+ this[prop] = false;
+ Element.removeClassName(this, 'validation-failed');
+ //Element.addClassName(this,'validation-passed');
return true;
}
},
isVisible : function(elm) {
while(elm.tagName != 'BODY') {
- if(!$(elm).visible()) return false;
+ if(!Element.visible(elm)) return false;
elm = elm.parentNode;
}
return true;
},
- getAdvice : function(name, id) {
+ getAdvice : function(name, id, elm) {
var advice = Try.these(
+ // We make the Validation work even if id is not defined
+ function(){ if(Element.classNames(elm.nextSibling).toString().indexOf('validation-advice')>=0) return elm.nextSibling; },
function(){ return $('advice-' + name + '-' + id) },
function(){ return $('advice-' + id) }
);
return advice;
},
reset : function(elm) {
- var cn = elm.classNames();
+ var cn = Element.classNames(elm);
cn.each(function(value) {
var prop = '__advice'+value.camelize();
if(elm[prop]) {
var advice = Validation.getAdvice(value, elm.id);
- advice.hide();
+ Element.hide(advice);
elm[prop] = '';
}
- elm.removeClassName('validation-failed');
- elm.removeClassName('validation-passed');
+ Element.removeClassName(elm, 'validation-failed');
+ //Element.removeClassName(elm, 'validation-passed');
});
},
add : function(className, error, test, options) {
To: Philippe Mouawad
Nice work.
Could I download not only the diff?
It would be great if it works with 1.4, too.
Thank you!
Great stuff Andrew!
Im trying to modify Phil(65) script so that it can be used to validate a date range (starting and ending date) so that the end date is more recent than the starting date.
I then decided to hold off on the date validation until i could get the field comparison to work properly using Phil's(65) code as he posted it...
Like Santiago(81), I cannot get it to work;
the fields validate as being equal even when they are not.
Any idears?!?
OK... how do we validate the form fields as we exit the individual fields. (Rather than just waiting to validate the whole form?)
I would like to ask is it possible to handle checking which it will depends on the value input for another fields. That is if the 'NAME' field of the form input, then all elements in the form are required, otherwise they are optional. Thanks!
It seems like there should be ability to check the fields as you go rather than just on a form submit. (Which I mentioned above, but this way you can answer two posts at the same time.)
Also, it also seems like we should be able to use callbacks to trigger other functions upon failures (or success). This would be key to allowing selective actions for good data to do things like ajax calls. (One senario would be sending the whole form on a successful validation. Another would be to validate the values of a field and upon certain conditions it would trigger a function for things like populating a select box via ajax.) This is a validation triggered event, and it is a good way to do things.
For anyone interested in a date validation for MMDDYY format, I have modified the stock validate-date code. I am by no means a javascript/ajax programmer, so this is by no means a brain buster, just thought someone may find it useful.
---------------------------------------------
['validate-date', 'Please use this date format: mmddyy. For example 031706 for March 17, 2006.', function(v) {
if(!Validation.get('IsEmpty').test(v)) {
var upper = 31;
if(/^(\d{2})(\d{2})(\d{2})$/.test(v)) { // mmddyy /^(\d{2})\/(\d{2})\/(\d{2})$/ <-- original regexp w/ slashes
if(RegExp.$1 == '02') upper = 29;
if((RegExp.$1 <= 12) && (RegExp.$2 <= upper)) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return true;
}
}],
John and SoSensible, from teh article above:
"You can also pass the option {immediate : true} to enable field valiation when leaving each field. That is on the onblur event for all the form elements."
Any ideas as to how radio/checkbox groups can be validated so that if 1 or more is selected in a given group, pass validation...else, spit back an error message?
Just wondering if it can be done with the TITLE tag where each element in your "group" would be checked to see what group they were a part of by naming them as such: TITLE="group1[contact]"
A fantastic AJAX script implements this sort of method is Lightbox2.0 by Lokesh Dhakar
http://www.huddletogether.com/projects/lightbox2/
His script implements the same idea using the rel="" attribute within <img> tags to group images together.
Just an idea.
Hi Evan (85) and Santiago (81),
Sorry for the inconvenience, the equalto validation as posted doesn't work, so try this replacement:
['validate-equalto', 'Please ensure these values are equal', function(v) {
var elmEqualto = $$("input.validate-equalto");
return (elmEqualto[0].value) === (elmEqualto[1].value);
}]
Looks like there are a few of us needing an equalto validator, I hope Andrew has time to work on this ;-) Be warned, my attempt to solve this is a hack, but if you *have* to use it, here's an explanation. I couldn't find a way of passing both the values I needed to the validation function. So two form elements are given the class 'validate-equalto'. Then the line...
var elmEqualto = $$("input.validate-equalto");;
... grabs an array of the elements on the page with the classname 'validate-equalto'. The values of the 2 elements are then compared on the next line and a true/false response generated.
This approach makes a the assumption that there are only 2 elements on the page with the 'validate-equalto' classname, for instance 'email' and 'repeat-email'. If you try to run two equalto comparisons on the same page only the first will be validated. Also it is inefficient as the validation is called on each input element with a 'validate-equalto' classname.
Hope this answers your queries, regards,
Phill
Hi,
Thanks for the great script. I thought I'd post a rule I've been using - it forces that 'at least 1' field is not empty (or in the case of a checkbox, checked). The only problem so far is that you can only have 1 'group' of these on a page, though I havn't needed any more than that so far.
This validation routine was made really easy by prototype's $F and getElementsByClassName function!
Validation.add('validate-at-least-one', 'At least one field must be complete.', function (v) {
var fields = getElementsByClassName('validate-at-least-one');
fields.each( function(field){
if ($F(field)) return(true);
});
return false;
});
Thanks Phil, looks good. I will give it a go; fortunately I don't have a need to match two sets of fields, so your workaround is just dandy.
This is another question regarding #61
It seems like the demo is not validation both elements (class="required validate-email"). The validate-email element works great by itself but combined with required, it doesn't. Does anyone know why? Thanks
(96) it seems as though the problem was introduced in version 1.5, because i still have a copy of 1.4 that works with multiple validations. if anyone knows why it quit working, this should be addressed. thanks.
I experience the problem with version 1.5 too.
This error happens when form fields contain multiple class names.
This is because the 'return' statement is missing in cn.all() cycle. Hence it will always return false and skip calling other then the first validators in the list.
Here's working modification of Validation.validate function:
==================================
validate : function(elm, options){
options = Object.extend({
useTitle : false
}, options || {});
elm = $(elm);
var cn = elm.classNames();
return result = cn.all(function(value) {
return Validation._testClassName(value,elm,options.useTitle);
});
},
===================================
Oops, I'm an idiot.
nice work atany... btw, i still haven't found a good phone number checker, so i wrote one. i wanted something flexible enough to accept more than just (555) 555-5555 because quite frankly we shouldn't make the user try over and over to get the format right, if anything we should take what they give us if it's close and then format it the way we want. so here's my contribution:
['validate-phone', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
}]
it will accept any of the following formats:
555-555-5555
555 555 5555
(555)555-5555
(555)555 5555
(555) 555-5555
(555) 555 5555
or i suppose any combination like the ones above. basically i was interested in just getting an area code and a 7 digit number from the user... the format doesn't matter to me, because we can always format it before using it or storing it. any ideas or suggestions let me know as this is my first reg exp!
how would I go about adding a function for checking validate-checkboxes I'm unsure how I would add this function to this library, great work aswell this is one of the most clean validation checks I've seen its a blessing
Thanks for the great work keep it up.
Hi, i added password length verification :
//var $V = Validation.validate;
//var $VG = Validation.get;
//var $VA = Validation.add;
Validation.add('IsEmpty', '', function(v) {
return ((v == null) || (v.length == 0) || /^\s+$/.test(v));
});
Validation.add('IsShort', '', function(v) {
return ((v == null) || (v.length < 6) || /^\s+$/.test(v));
});
Validation.addAllThese([
['required', 'Ce champ ne peut être vide.', function(v) {
return !Validation.get('IsEmpty').test(v);
}],
['validate-mdp', 'Votre mot de passe est trop court', function(v) {
return !Validation.get('IsShort').test(v);
}],
if you dont know where to add this, mail me ;)