javaScript form validation with multiple forms - javascript

I have two forms on different pages of my website, however I want to re-use the javaScript validation. So for example:
function notnull() {
var firstName = document.forms["newsletter"]["firstName"].value;
if (firstName === null || firstName === "") {
inlineMsg('firstName', 'You must enter your name.', 3000000);
return false;
} else {
return true;
}
}
This code is only good for my newsletter form (e.g. document.forms["newsletter"]["firstName"].value) but I want to use it for my "contact" form too.
Can I build the variables up dynamically like document.forms[][].value?

You can change your notnull function to accept 2 parameters
function notnull(formType,fieldName){
var fieldName = document.forms[formType][fieldName].value;
if(fieldName === null || fieldName === "") {
inlineMsg(fieldName, 'You must enter your '+fieldName,3000000);
return false;
} else
return true;
}
something along that line. I'm unsure what your inlineMsg does. You can also alternatively pass in the error friendly name for your error message into the function.
I'm sure there are better approach of handling the above, but looking at your code only, that's what I would suggest.

Related

How to style Validation checking before "save"

This is just a best practice question that I have run into and can't find the answer for. Any input is welcome! (Backed up responses with data/research would be amazing)
Example Save Button
When my save button is pressed, I want to do some validation, name (must be first and last), age (must be from 0 - 125), email (valid email address) and if these are all true, I want to "save" the user (to a db or wherever doesn't matter)
Right now my functions are set up
// Global error handler for example
var errors = {};
// Save Button Function
saveButton = function(dataModel) {
var valid = true;
valid = validateName(valid, dataModel.name);
valid = validateAge(valid, dataModel.age, 'extraParam');
valid = validateEmail(valid, dataModel.email, 'secondParam', 'thirdParam');
valid = (dataModel.red) ? validateRedUser(valid, dataModel) : valid;
if (valid) {
// Save user to database
}
else {
// alert to user an error has occured
// user errors object to respond with the errors
}
}
I feel like passing around the valid state to each sub validation function is not the best approach to a problem like this. It works, but can it be improved?
Edit: A sub-validation function would look something like:
validateName = function(valid, dataModel.name) {
if (!dataModel.name) {
valid = false;
// access global error handler to save error
errors.name = 'error in the name';
}
return valid;
}
Taking your sample function added the valid state condition check.
validateName = function(valid, dataModel.name) {
if (!dataModel.name && valid) {
valid = false;
// access global error handler to save error
errors.name = 'error in the name';
}
return valid;
}

CRM: Javascript to Check Email Validation and Prevent Saving if not Valid

On CRM 2013 on-premise, I'm working to write a javascript that checks for email validation. The field can contain a list of email address, however if the email is not valid, it will not let the users save the form.
I got the splitting and validating to work fine now.
However I continue to have problems to prevent users from saving the form.
On the OnChange, I check the box on the "Pass execution context as first parameter"
I user the preventDefault() function as suggested by an MSDN article however I keep getting error message "Unable to get property 'preventDefault' of undefined or null reference".
Any idea is appreciated. Here's my code:
function EmailTest(EmailField)
{
var Email = /^([a-zA-Z0-9_.-])+#([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+/;
if(Email.test(EmailField))
{
return true;
}
else
{
return false;
}
}
function CheckEmailString(context)
{
try
{
var EmailString = context.getEventSource().getValue();
if (EmailString != null)
{
var separator = [" ", ",", ";", "|"];
var EmailArray = EmailString.split(separator);
var Flag = true;
for(var i = 0;i < EmailArray.length;i++)
{
if(!EmailTest(EmailArray[i]))
{
Flag = false;
break;
}
}
if(Flag != true)
{
alert("The list of emails entered contain invalid email format. Please re-enter");
context.getEventArgs().preventDefault();
}
}
}
catch(err)
{
alert(err.message);
}
}
you get the error
Unable to get property 'preventDefault' of undefined or null reference
because the getEventArgs is available only when you are inside the save event, it's not available inside onchange event.
You should add the validation check also inside the save event if you want to stop the save.
Could I suggest you might try updating it to the full version of the method ie
Xrm.Page.context.getEventArgs.preventDefault().
I understand when working in CRM you have to reference use the full names in order for your function to see the prevent default method.
Hopefully that helps but if not good luck in seeking a solution

JQuery/AJAX form validation with nested testing...elegant solution?

I'm performing form validation using JQuery/AJAX. When an entry is missing or malformed, I want to send a message via alert() and return the user to the form with all fields as they were so the user can edit them and try submitting the form again. I also don't want the user to get a series of alert() boxes for each field that is malformed, but rather the first field that is discovered to be malformed should issue an alert() box; upon clicking the alert() box, the user may then return to editing the form. If there are 6 malformed fields, I don't want a series of 6 consecutive alert() boxes, but rather just the first one discovered by the routine to be errant and a return to the form (eventually the user will get them all right).
I have utilized a method that works, although it's not elegant and rather tedious to edit and error-prone...it's like a series of Russian dolls, where the first error prevents the successive routines from being run. When there are 5 fields or fields that require multiple kinds of integrity checking, the number of nested IF-ELSE statements increases exponentially, and for forms where I'm passing data via GET to a PHP file, like this:
$.get('admin_email_length_check.php', { new_email: $('#new_email').val(), max_email_length: max_email_length }, function(data) {
if (data != 0) {
alert(data);
} else {
...it has to be closed out with:
}
});
...not just a simple:
}
But here's a short routine for a 2 field validation. I set allow_submit to FALSE and prevent submission until all integrity checks are passed, at which point allow_submit becomes TRUE and I dynamically re-submit the form; this means that the integrity check (and its e.preventDefault();) will be bypassed entirely and the form will then be processed. Again, it works, but the kind of IF-ELSE structures I need to construct for forms with many fields that require many types of form validation requires extremely LONG structures with carefully edited closing braces (or braces + parentheses + ;, etc.) Is there a shorter or more elegant way to do this?:
var allow_submit = false;
$('#change_password_form').on('submit', function(e) {
if (!allow_submit) {
e.preventDefault();
// First ensure that at least one of the fields has a value:
if (($('#new_password').val() == '') && ($('#retype_password').val() == '')) {
alert("Nothing specified in either of the 'Change Password' fields.\n\nAdd data and re-submit.\n");
} else {
// Ensure both fields are filled:
if (($('#new_password').val() == '') || ($('#retype_password').val() == '')) {
alert("When changing your password, both the 'New Password' and the 'Retype Password' fields must be filled.\n\nPlease supply new, matching passwords in both fields and re-submit.\n");
} else {
// Do the two fields match?
if ($('#new_password').val() != $('#retype_password').val()) {
alert("New Password fields do not match.\n\nPlease edit password fields and re-submit.\n");
} else {
allow_submit = true;
$('#change_password_form').submit();
}
}
}
}
});
I have two suggestions:
Use early return statements to de-nest your code a bit.
Whenever you have too much conditional logic, try to use a data structure instead. See this quote by Linus Torvalds.
Here is my attempt:
$('#change_password_form').on('submit', function(e) {
var data = collect_data();
if (!data_is_valid(data)) {
e.preventDefault();
} else {
// Submit.
}
});
function collect_data() {
return {
passwords {
new_: $('#new_password').val(),
retyped: $('#retype_password').val()
},
...
};
}
function data_is_valid(data) {
if (!password_is_valid(data.passwords)) {
return false;
}
...
return true;
}
function password_is_valid(passwords) {
for (var i = 0; i < password_validators.length; i++) {
var validator = password_validators[i];
if (!validator.fails(passwords)) {
alert(validator.message);
return false;
}
}
return true;
}
var password_validators = [
{
fails: function(passwords) {
return passwords.new_ === '' && passwords.retyped === '';
},
message: 'No password provided'
},
{
fails: function(passwords) {
return passwords.new_ !== .passwordsretyped;
},
message: 'Passwords do not match'
},
...
];

Javascript: Validation alerts

what i need to do is the following:
Alert 'empty field' if name OR email is empty
Alert 'bad email' if email does not contain a #
Alert 'success' if both name and email is filled in correctly
function test10(email, name){
if(email=="") {
alert("empty field");}
else if(email.indexOf("#")<0){
alert("bad email");}
if(name=="") {
alert("empty field");}
}
This is what i've come up with so far, i want to keep it as simple as possible. Now how would i in this same vein make it say "success" when both are filled in? I need to do it purely in javascript.
It's probably worth mentioning that i'm very new to javascript so keep the insults to yourselves if you think this is stupid, i'm just trying to learn here.
Try this:
function test10(email, name){
// The || is a boolean "OR" , so if (email equals "") OR (name equals "")
// then alert the failure reason.
if(email=="" || name == "") {
alert("empty field");
return false;
}
if(email.indexOf("#") == -1){
alert("bad email");
return false;
}
//Conditions are met.
alert("Succes!");
return true;
}
This works exactly as you specified.
Try this
function test10(email, name){
if(email=="" || name=="") {
alert("empty field");}
else if(email.indexOf("#")<0){
alert("bad email");}
else{
alert("success");}
}
Either you put a final else clause at the end of your function and alert the success message from there, or you could return from the function whenever you hit an error, making sure to stop the function from continue running when it run into an invalid input. You could then have an alert at the end of the function that says success, since you will never get to that point as longs as you still have errors in the input.
Something like this:
function test10(email, name){
if (email === "" || name === "") {
alert("empty field");
return false;
}
if(email.indexOf("#")<0){
alert("bad email");
return false;
}
// If we get here, the input is all good!
alert("success");
return true;
}
Like this you will only alert the user about one error at a time, giving her time to fix that error, instead of throwing up three alerts after each other, if non of your rules are met.
Returning false/true from the function has the benefit that the function then can be used to stop a form submission if the input is invalid.
Alternative validation method
With HTML5, data form validation was introduced, providing a native option for validation using attributes like required and pattern. Browsers can also perform validation on email input if you use the new <input type="email">
More extensive reading on this is available at MDN.
Just add a return statement in each of the wrong cases
function test10(email, name)
{
if(email=="") {
alert("empty field");
return false;
}
if(email.indexOf("#")<0){
alert("bad email");
return false;
}
if(name=="") {
alert("empty field");
return false;
}
alert("success");
return true;
}
Note: you need to add in the form event onsubmit="return test10(email,name);"

Fixing a delayed callback causing false errors in jQuery Validation w/ jQuery Mobile in PhoneGap

So here's my problem.
I'm currently working on a PhoneGap application using jQuery Mobile and the Validation jQuery plugin for form validation.
I'm trying to set up a custom rule so that it will check to see if a name is already in the database, and if so, prevent the form from being submitted until the user chooses a name that is unique.
The problem is one that I've encountered before but have not yet managed to properly solve. When I call the method that executes the SQL select statement, the success callback does not get completed until after the validator has already completed and thrown false. This means that if a user enters a unique name, it will display an error, but if the user forces it to re-validate the fields, it will then be valid because the success callback had, in the meantime, completed.
Here's the relevant code:
var nameUnique;
jQuery.validator.addMethod("nameIsUnique", function(value, element) {
checkNameSQL();
return this.optional(element) || nameUnique;
}, "This name is already in use. Please choose another.");
$('#createForm').validate({
rules: {
createName: {
required: true,
nameIsUnique: true
},
createDescription: {
required: true
}
},
//snip//
});
function checkNameSQL()
{
var name = document.forms['createForm'].elements['createName'].value;
if (!(name == null || name == ""))
{
dbShell.transaction(function(tx) {
tx.executeSql("SELECT STATEMENT",[name],function(tx,results){if(results.rows.length==0){nameUnique = true;}},errorHandler)
},errorHandler);
}
}
I've simplified it where it makes sense, cutting out code not relevant to the question. As you can see, I call the method to check if the name exists, but before the success callback function triggers to set nameUnique to true, it's being returned by the validator, causing a false error.
How should I change my code to prevent this from occurring? What general programming practices should I follow to circumvent similar problems in the future? Thanks!
You can return pending as a value from the addMethod() besides true and false which can be used to delay the validation. For more info you can check the source of validation library.
Try this way:
$.validator.addMethod("nameIsUnique", function(value, element) {
var validator = this;
var previous = this.previousValue(element);
checkNameSQL(value, function(status) {
var valid = status === true;
if (valid) {
var submitted = validator.formSubmitted;
validator.prepareElement(element);
validator.formSubmitted = submitted;
validator.successList.push(element);
validator.showErrors();
} else {
var errors = {};
var message = status || validator.defaultMessage(element, "remote");
errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
validator.showErrors(errors);
}
previous.valid = valid;
validator.stopRequest(element, valid);
});
return "pending";
}, "This name is already in use. Please choose another.");
function checkNameSQL(name, callback) {
if (!(name == null || name == "")) {
dbShell.transaction(function(tx) {
tx.executeSql("SELECT STATEMENT", [name], function(tx, results) {
if (results.rows.length == 0) {
nameUnique = true;
callback(true);
}else{
callback(false);
}
}, errorHandler)
}, errorHandler);
}
}
For demo check this fiddle - http://jsfiddle.net/dhavaln/GqsVt/

Categories