Skip to content

Commit

Permalink
added tests for Validate.Custom displayMessageWhenEmpty option, did s…
Browse files Browse the repository at this point in the history
…ome refactoring, and moved the check for the displayMessageWhenEmpty to validateElement rather than in th loop of doValidations

git-svn-id: svn://livevalidation.com/livevalidation/trunk@61 c130c166-013a-0410-90be-eade3a03707a
  • Loading branch information
alechill committed Sep 9, 2008
1 parent e32a882 commit 1f56a72
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 65 deletions.
62 changes: 32 additions & 30 deletions src/livevalidation_prototype.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ LiveValidation.prototype = {
* @var optionsObj {Object} - general options, see below for details
*
* optionsObj properties:
* validMessage {String} - the message to show when the field passes validation
* validMessage {String} - the message to show when the field passes validation (set to '' or false to not insert any message)
* (DEFAULT: "Thankyou!")
* beforeValidation {Function} - function to execute directly before validation is performed
* (DEFAULT: function(){})
Expand Down Expand Up @@ -177,7 +177,7 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Object} - the LiveValidation object itself so that calls can be chained
* @return {Object} - the LiveValidation object itself so that calls can be chained
*/
add: function(validationFunction, validationParamsObj){
this.validations.push( { type: validationFunction, params: validationParamsObj || {} } );
Expand All @@ -189,7 +189,7 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Object} - the LiveValidation object itself so that calls can be chained
* @return {Object} - the LiveValidation object itself so that calls can be chained
*/
remove: function(validationFunction, validationParamsObj){
this.validations = this.validations.reject(function(v){
Expand Down Expand Up @@ -230,23 +230,23 @@ LiveValidation.prototype = {
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
*/
getElementType: function(){
var nn = this.element.nodeName;
var nt = this.element.type;
var nn = this.element.nodeName.toUpperCase();
var nt = this.element.type.toUpperCase();
switch(true){
case (nn.toUpperCase() == 'TEXTAREA'):
case (nn == 'TEXTAREA'):
return LiveValidation.TEXTAREA;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'TEXT'):
case (nn == 'INPUT' && nt == 'TEXT'):
return LiveValidation.TEXT;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'PASSWORD'):
case (nn == 'INPUT' && nt == 'PASSWORD'):
return LiveValidation.PASSWORD;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'CHECKBOX'):
case (nn == 'INPUT' && nt == 'CHECKBOX'):
return LiveValidation.CHECKBOX;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'FILE'):
case (nn == 'INPUT' && nt == 'FILE'):
return LiveValidation.FILE;
case (nn.toUpperCase() == 'SELECT'):
case (nn == 'SELECT'):
return LiveValidation.SELECT;
case (nn.toUpperCase() == 'INPUT'):
throw new Error('LiveValidation::getElementType - Cannot use LiveValidation on an ' + nt + ' input!');
case (nn == 'INPUT'):
throw new Error('LiveValidation::getElementType - Cannot use LiveValidation on an ' + nt.toLowerCase() + ' input!');
default:
throw new Error('LiveValidation::getElementType - Element must be an input, select, or textarea - ' + nn.toLowerCase() + ' was given!');
}
Expand All @@ -257,23 +257,12 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Boolean} - whether the all the validations passed or if one failed
* @return {Boolean} - whether the all the validations passed or if one failed
*/
doValidations: function(){
this.validationFailed = false;
for(var i = 0, len = this.validations.length; i < len; ++i){
var v = this.validations[i];
switch(v.type){
case Validate.Presence:
case Validate.Confirmation:
case Validate.Acceptance:
this.displayMessageWhenEmpty = true;
break;
case Validate.Custom:
if(v.params.displayMessageWhenEmpty) this.displayMessageWhenEmpty = true;
break;
}
this.validationFailed = !this.validateElement(v.type, v.params);
this.validationFailed = !this.validateElement(this.validations[i].type, this.validations[i].params);
if(this.validationFailed) return false;
}
this.message = this.validMessage;
Expand All @@ -285,14 +274,27 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Boolean} - whether the validation has passed or failed
* @return {Boolean} - whether the validation has passed or failed
*/
validateElement: function(validationFunction, validationParamsObj){
// check whether we should display the message when empty
switch(validationFunction){
case Validate.Presence:
case Validate.Confirmation:
case Validate.Acceptance:
this.displayMessageWhenEmpty = true;
break;
case Validate.Custom:
if(validationParamsObj.displayMessageWhenEmpty) this.displayMessageWhenEmpty = true;
break;
}
// select and checkbox elements values are handled differently
var value = (this.elementType == LiveValidation.SELECT) ? this.element.options[this.element.selectedIndex].value : this.element.value;
if(validationFunction == Validate.Acceptance){
if(this.elementType != LiveValidation.CHECKBOX) throw new Error('LiveValidation::validateElement - Element to validate acceptance must be a checkbox!');
value = this.element.checked;
}
// now validate
var isValid = true;
try{
validationFunction(value, validationParamsObj);
Expand All @@ -314,7 +316,7 @@ LiveValidation.prototype = {
/**
* makes it do the all the validations and fires off the various callbacks
*
* @return {Boolean} - whether the all the validations passed or if one failed
* @return {Boolean} - whether the all the validations passed or if one failed
*/
validate: function(){
if(!this.element.disabled){
Expand Down Expand Up @@ -368,7 +370,7 @@ LiveValidation.prototype = {
/**
* makes a span containg the passed or failed message
*
* @return {HTMLSpanObject} - a span element with the message in it
* @return {HTMLSpanObject} - a span element with the message in it
*/
createMessageSpan: function(){
var span = document.createElement('span');
Expand All @@ -384,7 +386,7 @@ LiveValidation.prototype = {
*/
insertMessage: function(elementToInsert){
this.removeMessage();
if(!this.validationFailed && !this.validMessage) return; // dont insert anything if vaalidMesssage has been set to false
if(!this.validationFailed && !this.validMessage) return; // dont insert anything if validMesssage has been set to false or empty string
if( (this.displayMessageWhenEmpty && (this.elementType == LiveValidation.CHECKBOX || this.element.value == '')) || this.element.value != '' ){
var className = this.validationFailed ? this.invalidClass : this.validClass;
$(elementToInsert).addClassName( this.messageClass + ' ' + className );
Expand Down
68 changes: 35 additions & 33 deletions src/livevalidation_standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@
* @var optionsObj {Object} - general options, see below for details
*
* optionsObj properties:
* validMessage {String} - the message to show when the field passes validation
* validMessage {String} - the message to show when the field passes validation (set to '' or false to not insert any message)
* (DEFAULT: "Thankyou!")
* onValid {Function} - function to execute when field passes validation
* (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); } )
* onInvalid {Function} - function to execute when field fails validation
* (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); })
* beforeValidation {Function} - function to execute directly before validation is performed
* (DEFAULT: function(){})
* afterValidation {Function} - function to execute directly after validation is performed
* (DEFAULT: function(){})
* beforeValid {Function} - function to execute directly before the onValid function is executed
* (DEFAULT: function(){})
* onValid {Function} - function to execute when field passes validation
* (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); } )
* afterValid {Function} - function to execute directly after the onValid function is executed
* (DEFAULT: function(){})
* beforeInvalid {Function} - function to execute directly before the onInvalid function is executed
* (DEFAULT: function(){})
* onInvalid {Function} - function to execute when field fails validation
* (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); })
* aterInvalid {Function} - function to execute directly after the onInvalid function is executed
* (DEFAULT: function(){})
* insertAfterWhatNode {Int} - position to insert default message
Expand Down Expand Up @@ -187,7 +187,7 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Object} - the LiveValidation object itself so that calls can be chained
* @return {Object} - the LiveValidation object itself so that calls can be chained
*/
remove: function(validationFunction, validationParamsObj){
var victimless = [];
Expand Down Expand Up @@ -233,23 +233,23 @@ LiveValidation.prototype = {
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
*/
getElementType: function(){
var nn = this.element.nodeName;
var nt = this.element.type;
var nn = this.element.nodeName.toUpperCase();
var nt = this.element.type.toUpperCase();
switch(true){
case (nn.toUpperCase() == 'TEXTAREA'):
case (nn == 'TEXTAREA'):
return LiveValidation.TEXTAREA;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'TEXT'):
case (nn == 'INPUT' && nt == 'TEXT'):
return LiveValidation.TEXT;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'PASSWORD'):
case (nn == 'INPUT' && nt == 'PASSWORD'):
return LiveValidation.PASSWORD;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'CHECKBOX'):
case (nn == 'INPUT' && nt == 'CHECKBOX'):
return LiveValidation.CHECKBOX;
case (nn.toUpperCase() == 'INPUT' && nt.toUpperCase() == 'FILE'):
case (nn == 'INPUT' && nt == 'FILE'):
return LiveValidation.FILE;
case (nn.toUpperCase() == 'SELECT'):
case (nn == 'SELECT'):
return LiveValidation.SELECT;
case (nn.toUpperCase() == 'INPUT'):
throw new Error('LiveValidation::getElementType - Cannot use LiveValidation on an ' + nt + ' input!');
case (nn == 'INPUT'):
throw new Error('LiveValidation::getElementType - Cannot use LiveValidation on an ' + nt.toLowerCase() + ' input!');
default:
throw new Error('LiveValidation::getElementType - Element must be an input, select, or textarea - ' + nn.toLowerCase() + ' was given!');
}
Expand All @@ -260,23 +260,12 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Boolean} - whether the all the validations passed or if one failed
* @return {Boolean} - whether the all the validations passed or if one failed
*/
doValidations: function(){
this.validationFailed = false;
for(var i = 0, len = this.validations.length; i < len; ++i){
var v = this.validations[i];
switch(v.type){
case Validate.Presence:
case Validate.Confirmation:
case Validate.Acceptance:
this.displayMessageWhenEmpty = true;
break;
case Validate.Custom:
if(v.params.displayMessageWhenEmpty) this.displayMessageWhenEmpty = true;
break;
}
this.validationFailed = !this.validateElement(v.type, v.params);
this.validationFailed = !this.validateElement(this.validations[i].type, this.validations[i].params);
if(this.validationFailed) return false;
}
this.message = this.validMessage;
Expand All @@ -288,14 +277,27 @@ LiveValidation.prototype = {
*
* @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
* @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
* @return {Boolean} - whether the validation has passed or failed
* @return {Boolean} - whether the validation has passed or failed
*/
validateElement: function(validationFunction, validationParamsObj){
var value = (this.elementType == LiveValidation.SELECT) ? this.element.options[this.element.selectedIndex].value : this.element.value;
// check whether we should display the message when empty
switch(validationFunction){
case Validate.Presence:
case Validate.Confirmation:
case Validate.Acceptance:
this.displayMessageWhenEmpty = true;
break;
case Validate.Custom:
if(validationParamsObj.displayMessageWhenEmpty) this.displayMessageWhenEmpty = true;
break;
}
// select and checkbox elements values are handled differently
var value = (this.elementType == LiveValidation.SELECT) ? this.element.options[this.element.selectedIndex].value : this.element.value;
if(validationFunction == Validate.Acceptance){
if(this.elementType != LiveValidation.CHECKBOX) throw new Error('LiveValidation::validateElement - Element to validate acceptance must be a checkbox!');
value = this.element.checked;
}
// now validate
var isValid = true;
try{
validationFunction(value, validationParamsObj);
Expand All @@ -317,7 +319,7 @@ LiveValidation.prototype = {
/**
* makes it do the all the validations and fires off the various callbacks
*
* @return {Boolean} - whether the all the validations passed or if one failed
* @return {Boolean} - whether the all the validations passed or if one failed
*/
validate: function(){
if(!this.element.disabled){
Expand Down Expand Up @@ -387,7 +389,7 @@ LiveValidation.prototype = {
*/
insertMessage: function(elementToInsert){
this.removeMessage();
if(!this.validationFailed && !this.validMessage) return; // dont insert anything if vaalidMesssage has been set to false
if(!this.validationFailed && !this.validMessage) return; // dont insert anything if vaalidMesssage has been set to false or empty string
if( (this.displayMessageWhenEmpty
&& (this.elementType == LiveValidation.CHECKBOX || this.element.value == ''))
|| this.element.value != '' ){
Expand Down
8 changes: 7 additions & 1 deletion src/tests_prototype_version.js
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,13 @@ function runTests(){
// test that it will fail if should fail and has a value in the field
subjects.lv.element.value = 'howdy';
assertEqual(false, subjects.lv.validateElement(Validate.Format, { pattern: /hello/i}), "Validation should fail and return false for a non-empty field with an invalid value with Validate.Format only");
}},
//test that if you pass a Validate.Custom without displayMessageWhenEmpty option, then it will not run the validation (and so return true)
subjects.lv.element.value = '';
var areYouFrench = function(value, argsObj){ return value == 'oui'; }
assert(subjects.lv.validateElement(Validate.Custom, { against: areYouFrench }), "Validation should not fail (as it should not be run) for an empty field with a Custom validation when it has not been given displayMessageWhenEmpty option");
//test that if you pass a Validate.Custom with displayMessageWhenEmpty option, then it will run the validation (we will pass it one that will fail)
assertEqual(false, subjects.lv.validateElement(Validate.Custom, { against: areYouFrench, displayMessageWhenEmpty: true }), "Validation should fail and return false for an empty field with a Custom validation set up to fail on empty when it has been given displayMessageWhenEmpty option");
}},

testDoValidations: function(){ with(this){
subjects.lv.add(Validate.Presence);
Expand Down
8 changes: 7 additions & 1 deletion src/tests_standalone_version.js
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,13 @@ function runTests(){
// test that it will fail if should fail and has a value in the field
subjects.lv.element.value = 'howdy';
assertEqual(false, subjects.lv.validateElement(Validate.Format, { pattern: /hello/i}), "Validation should fail and return false for a non-empty field with an invalid value with Validate.Format only");
}},
//test that if you pass a Validate.Custom without displayMessageWhenEmpty option, then it will not run the validation (and so return true)
subjects.lv.element.value = '';
var areYouFrench = function(value, argsObj){ return value == 'oui'; }
assert(subjects.lv.validateElement(Validate.Custom, { against: areYouFrench }), "Validation should not fail (as it should not be run) for an empty field with a Custom validation when it has not been given displayMessageWhenEmpty option");
//test that if you pass a Validate.Custom with displayMessageWhenEmpty option, then it will run the validation (we will pass it one that will fail)
assertEqual(false, subjects.lv.validateElement(Validate.Custom, { against: areYouFrench, displayMessageWhenEmpty: true }), "Validation should fail and return false for an empty field with a Custom validation set up to fail on empty when it has been given displayMessageWhenEmpty option");
}},

testDoValidations: function(){ with(this){
subjects.lv.add(Validate.Presence);
Expand Down

0 comments on commit 1f56a72

Please sign in to comment.