J'utilise l'excellent jquery.validation plugin de Jörn Zaefferer et je me demandais s'il existait un moyen facile de supprimer automatiquement les éléments de formulaire avant leur validation.
Voici un exemple simplifié mais pratique de formulaire qui valide une adresse électronique:
<!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>
Le problème est que certains utilisateurs deviennent confus parce qu’ils ont accidentellement saisi des espaces dans leur adresse électronique, par exemple. "[email protected]". Et le formulaire ne sera pas envoyé et comportera un message d'erreur: "Veuillez entrer une adresse électronique valide.". Les utilisateurs non avertis ne savent pas comment repérer les espaces et peuvent simplement quitter le site plutôt que d'essayer de déterminer ce qu'ils ont mal fait.
Quoi qu'il en soit, j'espérais pouvoir enchaîner "jQuery.trim(value)
" avant la validation afin que l'espace Soit éliminé et que l'erreur de validation ne se produise jamais?
Je pourrais utiliser addMethod pour créer ma propre fonction de validation de courrier électronique. Mais je suis sûr qu'il existe une solution plus élégante?
Je l'ai fait avec succès.
Au lieu de:
Email: { required: true, email: true }
J'ai fait ça:
Email: {
required: {
depends:function(){
$(this).val($.trim($(this).val()));
return true;
}
},
email: true
}
Ce code fonctionne pour moi. Je ne l'ai pas beaucoup utilisé, il y a peut-être des bugs.
Il enveloppe chaque méthode et coupe le premier élément qui est 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));
si vous utilisez select2 et la validation en même temps, je vous recommande de placer el.val($.trim(el.val()));
dans un IF comme ceci: if(el.prop('type') != 'select-multiple'){el.val($.trim(el.val()));}
. Ainsi, votre validation jquery se comportera comme prévu et vous permettra de sélectionner plusieurs éléments.
Puisque je veux ce comportement sur tous mes formulaires par défaut, j'ai décidé de modifier le fichier jquery.validate.js . J'ai appliqué la modification suivante à la méthode onfocusout:
Original:
onfocusout: function (element, event) {
if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) {
this.element(element);
}
}
À:
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);
}
}
Je veux autoriser des espaces au début et à la fin du mot de passe.
autoTrim pourrait être ajouté en tant que propriété aux options.
J'aime l'approche de xuser ( https://stackoverflow.com/a/10406573/80002 ), cependant, je n'aime pas jouer avec le code source du plugin.
Donc, je suggère de faire ceci à la place:
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)
});
Lors du téléchargement de validator.js, il existe un fichier appelé additional-methods.js qui contient la méthode "nowhitespace" et "lettersonly" qui supprimera tout espace blanc dans un champ.
rules: {
user_name: {
required: true,
minlength: 3,
nowhitespace: true
}
}
Pour référence, jusqu'à ce que je trouve une solution plus élégante, j'utilise addMethod comme suit:
// 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
}
}
});
});
Remarque: ceci ne supprime pas les espaces du champ, mais les ignore. Vous devez donc vous assurer que vous exécutez trim
côté serveur avant de l'insérer dans la base de données.
Ajoutez une nouvelle méthode de validation jQuery requiredNotBlank
. Appliquez ensuite cette fonction à vos éléments plutôt qu'à la fonction required
par défaut. Cette solution ne modifie pas le code source du validateur d'origine, ne modifie pas non plus la fonction required
par défaut, ni ne modifie directement la valeur de l'élément.
// 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');
C'est ce qui fonctionne pour moi:
$(':input').change(function() {
$(this).val($(this).val().trim());
});
Tiré la regex du validateur JQuery. Il suffit de remplacer leur validation de courrier électronique.
$.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.");
Ne pourriez-vous pas lier le recadrage à un événement de flou? Quelque chose comme...
$ ("# cemail"). blur (function () { $ (this) .val (jQuery.trim ($ (this) .val ()); });
J'ai constaté que la majorité d'entre eux ne correspond pas tout à fait à ce qu'il faut.
L'utilisation de ce qui suit se déclenche uniquement lors du changement de formulaire plutôt que lorsque vous appuyez sur une touche, ce qui vous permet de toujours vérifier la course de touche pour le reste de la validation.
Ce n'est pas aussi bien que de l'inclure dans le plugin, mais c'est un compromis acceptable.
$('body').on 'change', 'form input[type=text], form input[type=email]', ->
$(@).val $.trim($(@).val())
À partir du plugin jQuery Validation version 1.15, une fonction normalisation est prise en charge. Le normalisateur peut transformer la valeur d'un élément avant la validation.
Notez que le résultat du normalisateur n'est utilisé que pour la validation. Si vous souhaitez mettre à jour la valeur de l'élément, vous devez le faire explicitement.
$("#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;
}
}
}
});
Dans la validation JQuery, vous trouverez le code ci-dessous:
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;
}
Changez la valeur.length en $ .trim (valeur) .length
Vous pouvez exécuter le code avant que le formulaire ne soit vérifié comme ceci:
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);
};
Je l'ai utilisé pour sauvegarder toutes mes instances CodeMirror dans leurs texareas correspondantes. Vous pouvez l'utiliser pour réduire les valeurs si vous le souhaitez.
Pourquoi ne pas faire ça?
La validation a lieu après l'événement keyup. Sur keyup, remplacez la valeur textbox par sa valeur ajustée (ou utilisez une expression rationnelle pour supprimer tout espace):
$("#user_name").on("keyup", function(){
$("#user_name").val($.trim($("#user_name").val()));
});