Skip to content

Commit 43a6a01

Browse files
committed
Core: Added normalizer
The user can change the value of an element before validating the element in question. The new value will be then used by the associated methods instead of the `real one`. Closes #1602
1 parent e5e346e commit 43a6a01

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

src/core.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,22 @@ $.extend( $.validator, {
627627
val = this.elementValue( element ),
628628
result, method, rule;
629629

630+
// If a normalizer is defined for this element, then
631+
// call it to retreive the changed value instead
632+
// of using the real one.
633+
// Note that `this` in the normalizer is `element`.
634+
if ( typeof rules.normalizer === "function" ) {
635+
val = rules.normalizer.call( element, val );
636+
637+
if ( typeof val !== "string" ) {
638+
throw new TypeError( "The normalizer should return a string value." );
639+
}
640+
641+
// Delete the normalizer from rules to avoid treating
642+
// it as a pre-defined method.
643+
delete rules.normalizer;
644+
}
645+
630646
for ( method in rules ) {
631647
rule = { method: method, parameters: rules[ method ] };
632648
try {
@@ -861,7 +877,7 @@ $.extend( $.validator, {
861877
// meta-characters that should be escaped in order to be used with JQuery
862878
// as a literal part of a name/id or any selector.
863879
escapeCssMeta: function( string ) {
864-
return string.replace( /(!|"|#|\$|%|&|'|\(|\)|\*|\+|,|\.|\/|:|;|<|=|>|\?|@|\[|\\|\]|\^|`|\{|\||\}|~)/g, "\\$1");
880+
return string.replace( /([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1" );
865881
},
866882

867883
idOrName: function( element ) {
@@ -1104,7 +1120,7 @@ $.extend( $.validator, {
11041120

11051121
// evaluate parameters
11061122
$.each( rules, function( rule, parameter ) {
1107-
rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
1123+
rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter;
11081124
} );
11091125

11101126
// clean number parameters

test/.jshintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"stop": false,
3636
"test": false,
3737
"TestHelpers": true,
38+
"throws": false,
3839
"JSHINT": false
3940
}
4041
}

test/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ <h2 id="qunit-userAgent"></h2>
7171
<label id="errorFirstnamec" for="firstnamec" class="error">error for firstname</label>
7272
<input title="buga" name="lastname" id="lastnamec">
7373
<input name="username" id="usernamec">
74+
<input id="urlc" type="text" name="urlc">
7475
</form>
7576
<form id="userForm">
7677
<input type="text" data-rule-required="true" name="username" id="username">
@@ -378,7 +379,7 @@ <h3></h3>
378379
</form>
379380
<form id="testForm21">
380381
<label for="testForm21!#$%&'()*+,./:;<=>?@[\]^`{|}~">Input text</label>
381-
<input type="text" name="testForm21!#$%&'()*+,./:;<=>?@[\]^`{|}~\" id="testForm21!#$%&'()*+,./:;<=>?@[\]^`{|}~" required minlength="15">
382+
<input type="text" name="testForm21!#$%&'()*+,./:;<=>?@[\]^`{|}~" id="testForm21!#$%&'()*+,./:;<=>?@[\]^`{|}~" required minlength="15">
382383
</form>
383384
</div>
384385
</body>

test/rules.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,91 @@ test( "rules(), rangelength attribute as array", function() {
305305
rangelength: [ 2, 3 ]
306306
} );
307307
} );
308+
309+
test( "rules(), normalizer", function() {
310+
var username = $( "#usernamec" ),
311+
urlc = $( "#urlc" ),
312+
lastname = $( "#lastnamec" ),
313+
v;
314+
315+
username.val( "\t\t \r" );
316+
urlc.val( "" );
317+
318+
v = $( "#testForm1clean" ).validate( {
319+
rules: {
320+
username: {
321+
required: true,
322+
// Using the normalizer to trim the value of the element
323+
// before validating it.
324+
normalizer: function( value ) {
325+
equal( this, username[ 0 ], "`this` in the normalizer should be the username element." );
326+
327+
// Trim the value of the input
328+
return $.trim( value );
329+
}
330+
},
331+
urlc: {
332+
required: true,
333+
url: true,
334+
// Using the normalizer to append https:// if it's not
335+
// present on the input value
336+
normalizer: function( value ) {
337+
equal( this, urlc[ 0 ], "`this` in the normalizer should be the urlc element." );
338+
339+
var url = value;
340+
341+
// Check if it doesn't start with http:// or https:// or ftp://
342+
if ( url && url.substr( 0, 7 ) !== "http://" &&
343+
url.substr( 0, 8 ) !== "https://" &&
344+
url.substr( 0, 6 ) !== "ftp://" ) {
345+
// then prefix with http:// or even https://
346+
url = "https://" + url;
347+
}
348+
349+
// Return the new url
350+
return url;
351+
}
352+
},
353+
lastname: {
354+
required: true,
355+
// Using the normalizer to trim the value of the element
356+
// before validating it.
357+
normalizer: function( value ) {
358+
equal( this, lastname[ 0 ], "`this` in the normalizer should be the lastname element." );
359+
360+
// Return null in order to make sure a exception is thrown
361+
// when normalizer returns a non string value.
362+
value = null;
363+
364+
return value;
365+
}
366+
}
367+
}
368+
} );
369+
370+
// Validate only the username and the url elements.
371+
username.valid();
372+
equal( v.invalidElements()[ 0 ], username[ 0 ], "The username should be invalid" );
373+
374+
urlc.valid();
375+
equal( v.invalidElements()[ 0 ], urlc[ 0 ], "The url should be invalid" );
376+
377+
equal( v.numberOfInvalids(), 2, "There is two invalid elements" );
378+
379+
username.val( "something" );
380+
urlc.val( "google.com" );
381+
382+
username.trigger( "keyup" );
383+
urlc.trigger( "keyup" );
384+
385+
equal( v.numberOfInvalids(), 0, "All elements are valid" );
386+
equal( v.size(), 0, "All elements are valid" );
387+
equal( v.isValidElement( urlc[ 0 ] ), true, "The url element should be valid" );
388+
389+
// Validate the lastname element, which will throw an exception
390+
throws( function() {
391+
v.check( lastname[ 0 ] );
392+
}, function( err ) {
393+
return err.name === "TypeError" && err.message === "The normalizer should return a string value.";
394+
}, "This should throw a TypeError exception." );
395+
} );

0 commit comments

Comments
 (0)