Dan G. Switzer, II
unread,Mar 1, 2011, 11:33:22 AM3/1/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to ValidateThis
I'm just in the process of evaluating ValidateThis and I've noticed
some real inefficiencies with the jQuery code that's generated.
For each validation method you end up generating code that looks like:
if ($(":input[name='UserName']",$form_frmMain).length) {
$(":input[name='UserName']",$form_frmMain).rules("add", { required :
true, messages: {required: "The Email Address is required."} });
}
This has several issues:
1) Doing lookup via the CSS selector ":input[name=UserName]" is pretty
expensive (especially in older browsers that don't support
document.querySelectorAll().) Because this selector is slow, it's
important to minimize the times you call this selector.
The if() check is actually completely unnecessary in this context. It
actually adds nothing, but performance overhead. If the jQuery object
doesn't then the rules() method won't do anything. So take the if()
statement out completely.
All you need is:
$(":input[name='UserName']",$form_frmMain).rules("add", { required :
true, messages: {required: "The Email Address is required."} });
2) Every time you create a new jQuery object, there's overhead
involved. That means with code like:
if ($(":input[name='UserName']",$form_frmMain).length) {
$(":input[name='UserName']",$form_frmMain).rules("add", { required :
true, messages: {required: "The Email Address is required."} });
}
if ($(":input[name='UserName']",$form_frmMain).length) {
$(":input[name='UserName']",$form_frmMain).rules('add',{"email":
"true","messages":{"email":"Hey, buddy, you call that an Email
Address?"}});
}
You end up creating 4 instances of the exact same object. So, not only
are you creating expensive operations on the selector, you're also
creating jQuery object which have overhead.
The best solution is to either cache all your objects or chain your
methods together.
Unfortunately, the $o.rules("add", {}) call isn't chainable, however
you could create a small plug-in that is:
$.fn.addRule = function (rules){
this.rules("add", rules);
return this;
}
Now you could do:
$(":input[name='UserName']",$form_frmMain)
.addRules({ required : true, messages: {required: "The Email Address
is required."} })
.addRules({"email": "true","messages":{"email":"Hey, buddy, you call
that an Email Address?"}})
;
The benefit here is now you only create a single instance of the
jQuery object which fixes both issues #1 and #2.
However, what might be even a better solution is initiate a cache of
all the jQuery objects you might need in your validation. The benefit
here is that you could use the cached objects instead of the selectors
to speed up code in the validation methods.
Something like this:
// create a cache
function createCache(fields, context){
var cache = {};
for( var i=0; i < fields.length; i++ ) cache[fields[i]] = $
(":input[name='" + fields[i] + "']", context);
return cache;
}
// create all the jQuery objects
var fields = createCache(["UserName", "UserPass", "VerifyPassword",
"UserGroupId"], $form_frmMain);
Now you could do:
fields["VerifyPassword"].rules('add',{"equalTo":
fields["UserPass"],"messages":{"equalTo":"The Verify Password must be
the same as The Password."}});
Instead of:
$(":input[name='VerifyPassword']",$form_frmMain).rules('add',
{"equalTo": ":input[name='UserPass']","messages":{"equalTo":"The
Verify Password must be the same as The Password."}});
Now I haven't looked at the CF code to see how easy/hard these changes
are to make to the framework, but the changes will:
1) Reduce the amount of client-side code being generated
2) Speed up the code
NOTE: The performance issue you gain may be negligible on small forms,
but if you have really large forms you're definitely notice a
difference--especially on older browsers.