0
\$\begingroup\$

A while ago I've written a custom validation method for .validate(). It is a local validation plugin, with some limited validation.

I was required to write a validation method with the following requirements:

  • Must accept a custom string.
  • Must allow a maximum value.
  • Must allow a minimum value.
  • Has to allow to have dynamic values on the string.
  • Must validate using a regular expression.
  • Must allow numbers in the Portuguese and English formats.

At the time, it was quite a challenge and I was happy with the result, but the code is BAD. It works, but it is so hacky and kludged it hurts my soul.

(function(){
    var __c_number_between=new String('');

        __c_number_between.valueOf=function(){
                return 'The value must be between __MIN__ and __MAX__'
                    .replace(/__MIN__/g,this.min)
                    .replace(/__MAX__/g,this.max);
            };
        __c_number_between.toString=function(){return this.valueOf();};

    $.validator.addMethod('c_number_between',
        function(d,i,o){
            var num=d.replace(/\./g,'').replace(',','.')/1;
            __c_number_between.min=o.min;
            __c_number_between.max=o.max;
            return o.max>=num&&num>=o.min;
        },__c_number_between);
})();

Yes, that is the code. It fulfills all my needs, but relies on a really bad behaviour in Javascript, which is that objects are passed as a reference. It also relies on Javascript being executed linearly, instead of having multiple threads, which is REALLY bad!

How can I re-write this in a clean and decent way?


Also, worth noticing is that this is a cross-posting from StackOverflow, on the following question: jQuery .validation plugin: help cleaning aditional method

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

jQuery.validator.format()

jQuery.validator has a format method

This allows you to replace the String you created entirely.

However, this would require you to replace your 'o' parameter object with an array ( [min,max] ).

$.validator.addMethod('c_number_between',
    function(d,i,o){
        var num=d.replace(/\./g,'').replace(',','.')/1,
            // min/max assigns for context readability (optional)
            min = o[0],
            max = o[1];
        return max>=num&&num>=min;
    },$.validator.format('The value must be between {0} and {1}'));

Update:

While the docs say:

The default message to display for this method. Can be a function created by ''jQuery.validator.format(value)''. When undefined, an existing message is used (handy for localization), otherwise the field-specific messages have to be defined.

Any function that returns a string can be used so boom:

$.validator.addMethod('c_number_between',
    function(d,i,o){
        var num=d.replace(/\./g,'').replace(',','.')/1,
        return 0.max>=num&&num>=0.min;
    },function(params){return 'The value must be between {0} and {1}'.replace('{0}',params.min).replace('{1}',params.max);});
\$\endgroup\$
3
  • \$\begingroup\$ Actually, it is o.max and o.min, instead of o[0] and o[1]. But other than that... WOW! I had no idea about that method. It really is a lifesaver! Thank you a lot! Now, I have a few validations to fix. Once again, thank you \$\endgroup\$ Aug 5, 2015 at 18:01
  • \$\begingroup\$ To use $.validator.format the o parameter has to be an array (as far as i know) so {min:y,max: x} is now [x,y]... aleast in how i interpreted your code \$\endgroup\$
    – Shaun H
    Aug 5, 2015 at 18:05
  • \$\begingroup\$ That would be a bad surprise. It isn't feasable to change everything. I have at least 100 instances of that validation. But that is a problem outside the scope of your review, and something I didn't mention. Therefore, you deserved the reputation. I will look into some way to hammer this screw on my steel bar. \$\endgroup\$ Aug 5, 2015 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.