jquery.validate plugin - how to trim values before form validation

JqueryJquery Validate

Jquery Problem Overview


I'm using the excellent jquery.validation plugin by Jörn Zaefferer and I was wondering whether there's a easy way to automatically trim form elements before they are validated?

The following is a cut down but working example of a form which validates a email address:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"
           type="text/javascript"></script>
    <script src="http://ajax.microsoft.com/ajax/jquery.validate/1.5.5/jquery.validate.js" 
           type="text/javascript"></script>
    <script type="text/javascript">
        $().ready(function() {
          $("#commentForm").validate({
            rules: {
                email: {
                    required: true,
                    email: true
                }
            }
          });
        });
    </script>
</head>
<body>

  <form class="cmxform" id="commentForm" method="get" action="">
     <label for="cemail">E-Mail:</label><input id="cemail" name="email"
      class="required email" />
     <input class="submit" type="submit" value="Submit"/>
  </form>

</body>
</html>

The problem is that some users are getting confused because they accidently enter some whitespace in their email address, e.g. "[email protected] ". And the form won't submit and has a error message: "Please enter a valid email address.". Non-techy users don't know how to spot whitespace and may just quit the site rather than try to work out what they've done wrong.

Anyway, I was hoping I could chain "jQuery.trim(value)" before the validation so the whitespace is removed and the validation error never occurs?

I could use addMethod to build my own email validation function. But I'm sure there's a more elegant solution?

Jquery Solutions


Solution 1 - Jquery

I did this with success.

Instead of:

Email: { required: true, email: true }

I did this:

Email: {
    required: {
        depends:function(){
            $(this).val($.trim($(this).val()));
            return true;
        }
    },
    email: true
}

Solution 2 - Jquery

This code works for me. I haven't used it much so there may be bugs.

It wraps each method and trims the first element which is value.

(function ($) {

    $.each($.validator.methods, function (key, value) {
        $.validator.methods[key] = function () {           
            if(arguments.length > 0) {
                arguments[0] = $.trim(arguments[0]);
            }

            return value.apply(this, arguments);
        };
    });
} (jQuery));

if you're using select2 and validation at the same time, I recommend to put el.val($.trim(el.val())); inside an IF like this: if(el.prop('type') != 'select-multiple'){el.val($.trim(el.val()));}. That way, your jquery validation will behave as expected, and it will let you select multiple items.

Solution 3 - Jquery

Since I want this behavior on all my forms by default I decided to modify the jquery.validate.js file. I applied the following change to onfocusout method:

Original:

onfocusout: function (element, event) {
	if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) {
		this.element(element);
	}
}

To:

onfocusout: function (element, event) {
	if (element.tagName === "TEXTAREA" || (element.tagName === "INPUT" && element.type !== "password")) {
		element.value = $.trim(element.value);
	}
	if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) {
		this.element(element);
	}
}

I do want to allow spaces at the begging and end of password.

autoTrim could be added as a property to options.

Solution 4 - Jquery

I like the approach by xuser (https://stackoverflow.com/a/10406573/80002), however, I do not like messing with the plugin source code.

So, I suggest doing this instead:

 function injectTrim(handler) {
  return function (element, event) {
    if (element.tagName === "TEXTAREA" || (element.tagName === "INPUT" 
                                       && element.type !== "password")) {
      element.value = $.trim(element.value);
    }
    return handler.call(this, element, event);
  };
 }


 $("form").validate({
    onfocusout: injectTrim($.validator.defaults.onfocusout)
 });

Solution 5 - Jquery

When downloading validator.js, there is a file called additional-methods.js that contains the method "nowhitespace" and "lettersonly" that will strip out any white space in a field.

rules: {
  user_name: {
    required: true,
    minlength: 3,
    nowhitespace: true
  }
}

Solution 6 - Jquery

Add a new jQuery validator method requiredNotBlank. Then apply that function to your elements rather than the default required function. This solution doesn't change the original validator source code, nor does it modify the default required function, nor does it modify the element's value directly.

// jQuery Validator method for required not blank.
$.validator.addMethod('requiredNotBlank', function(value, element) {
	return $.validator.methods.required.call(this, $.trim(value), element);
}, $.validator.messages.required);

// ...
$('#requiredNotBlankField').rules('add', 'requiredNotBlank');

Solution 7 - Jquery

For reference, until I find a more elegant solution, I'm using addMethod as follows:

// Extend email validation method so that it ignores whitespace
jQuery.validator.addMethod("emailButAllowTrailingWhitespace", function(value, element) {
    return (this.optional(element) || jQuery.validator.methods.email.call(this, jQuery.trim(value), element));
}, "Please enter a valid email");

$().ready(function() {
    $("#commentForm").validate({
        rules: {
            cemail: {
                required: true,
                emailButAllowTrailingWhitespace: true
            }
        }
    });
});

Note: this doesn't actually strip the whitespace from the field, it only ignores it. So you need to ensure you perform trim on the server-side before inserting in the DB.

Solution 8 - Jquery

Starting from jQuery Validation plugin version 1.15 a normalizer function is supported. The normalizer can transform the value of an element before validation.

Note that the result of the normalizer is only used for validation. If you would like to update the value of the element you must do so explicitly.

$("#form").validate({
    rules: {
        email: {
            required: true,
            email: true,
            // Optionally disable validation on every key press
            onkeyup: false,
            normalizer: function(value) {
                // Update the value of the element
                this.value = $.trim(value);
                // Use the trimmed value for validation
                return this.value;
            }
        }
    }
});

Solution 9 - Jquery

Pulled the regex from the jquery validator. Just override their email validation.

$.validator.addMethod("email", function(value, element) {
value = value.trim();
return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
}, "Please enter a valid email.");

Solution 10 - Jquery

This is what works for me:

$(':input').change(function() {
    $(this).val($(this).val().trim());
});

Solution 11 - Jquery

Could you not bind the trim to a blur event? Something like...

$("#cemail").blur(function(){
$(this).val(jQuery.trim($(this).val());
});

Solution 12 - Jquery

Use normalizer, Please check below example

<script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/additional-methods.min.js"></script>
<script>
  $("#myform").validate({
    rules: {
      field: {
        required: true,
        normalizer: function(value) {
          // Trim the value of the `field` element before
          // validating. this trims only the value passed
          // to the attached validators, not the value of
          // the element itself.
          return $.trim(value);
        }
      }
    }
  });
</script>

Solution 13 - Jquery

I've found that the majority of these are not quite what is needed.

Using the following only fires on form change rather than on key down allowing you to still check on key stroke for the rest of the validation.

It's not as tidy as including it within the plugin, but it's an acceptable compromise.

$('body').on 'change', 'form input[type=text], form input[type=email]',  ->
    $(@).val $.trim($(@).val())

Solution 14 - Jquery

In jquery validation you will find the below code:

required: function( value, element, param ) {

		// Check if dependency is met
		if ( !this.depend( param, element ) ) {
			return "dependency-mismatch";
		}
		if ( element.nodeName.toLowerCase() === "select" ) {

			// Could be an array for select-multiple or a string, both are fine this way
			var val = $( element ).val();
			return val && val.length > 0;
		}
		if ( this.checkable( element ) ) {
			return this.getLength( value, element ) > 0;
		}
		return value.length > 0;
	}

Change the value.length to $.trim(value).length

Solution 15 - Jquery

You can run code before the form is checked like this:

var origCheckForm = $.validator.prototype.checkForm;
$.validator.prototype.checkForm = function() {
    $(this.currentForm).find('.CodeMirror').each(function() {
        if(this.CodeMirror && this.CodeMirror.save) {
            this.CodeMirror.save();
        }
    });

    return origCheckForm.apply(this, arguments);
};

I've used it to save all my CodeMirror instances back to their corresponding texareas. You could use it to trim values instead if you want.

Solution 16 - Jquery

Why not do this?

Validation is occurring after the keyup event. On keyup replace textbox value with its trimmed value (or use a regex to remove any space):

$("#user_name").on("keyup", function(){
    $("#user_name").val($.trim($("#user_name").val()));
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomView Question on Stackoverflow
Solution 1 - JqueryMDPView Answer on Stackoverflow
Solution 2 - JqueryhwiechersView Answer on Stackoverflow
Solution 3 - JquerytmorellView Answer on Stackoverflow
Solution 4 - JquerymarkView Answer on Stackoverflow
Solution 5 - JqueryjeremyzilarView Answer on Stackoverflow
Solution 6 - JquerysevencardzView Answer on Stackoverflow
Solution 7 - JqueryTomView Answer on Stackoverflow
Solution 8 - JqueryCraig WohlfeilView Answer on Stackoverflow
Solution 9 - JqueryRyanCodesView Answer on Stackoverflow
Solution 10 - Jqueryuser3830900View Answer on Stackoverflow
Solution 11 - JqueryPsytronicView Answer on Stackoverflow
Solution 12 - JquerySavooView Answer on Stackoverflow
Solution 13 - JquerylededjeView Answer on Stackoverflow
Solution 14 - JqueryAmulView Answer on Stackoverflow
Solution 15 - JquerympenView Answer on Stackoverflow
Solution 16 - JqueryAdrian P.View Answer on Stackoverflow