Sandrina Pereira Sandrina Pereira - 1 month ago 14
jQuery Question

How can I reduce / join multiple similar event handlers

I want to reduce my repetitive code used to validate inputs values.
For that I'm using:


  • a class associated to the input

  • condition to validate the input value

  • event handler



First I declare the classes I'm using:

var inputNotNull = '.js-mandatory-notnull',
input2Words = '.js-mandatory-2words',
inputNumb = '.js-mandatory-numb';


Then I create an event handler for each class and each of them has the same pattern: Call the function
validateInput(event, thisInput, itsCondition)


$(document).on('keyup change focusout', inputNotNull, function(e){
var $xthis = $(this),
condition = $xthis.val().length>0;
validateInput(e, $xthis, condition);
});


$(document).on('keyup change focusout', input2Words, function(e){
var $xthis = $(this),
condition = $xthis.val().match(/^[A-Za-zÀ-ú]+ [A-Za-zÀ-ú]+/i);
validateInput(e, $xthis, condition);
});

$(document).on('keyup change focusout', inputNumb, function(e){
var $xthis = $(this),
condition = this.value.match(/^(?=.*\d)\d*[\.\,]?\d*$/);
validateInput(e, $xthis, condition);
});


I was wondering how could I reduce this code. I mean the part
$(document).on('keyup change focusout', xxx, function(e){


In this example I only show 3 classes, but on my full code I have > 20 different classes.

Is it possible to do something similar to "key:value" ("input:condition") and I would end up writing something like this:

var validations = {
'.js-mandatory-notnull' : length > 0,
'.js-mandatory-2words' : match(/^[A-Za-zÀ-ú]+ [A-Za-zÀ-ú]+/i),
'.js-mandatory-numb' : match(/^(?=.*\d)\d*[\.\,]?\d*$/),
}


And then somehow treat this object to reproduce the event handlers I wrote initially.

P.S. In this example I'm talking about validations, but I would like to apply this knowledge into another repetitive code scenarios.

Thank you :)

Answer

You can use functions for those validations:

var validations = {
    '.js-mandatory-notnull': function(val) {
        return val.length > 0;
    },
    '.js-mandatory-2words': function(val) {
        return val.match(/^[A-Za-zÀ-ú]+ [A-Za-zÀ-ú]+/i);
    },
    '.js-mandatory-numb': function(val) {
        return val.match(/^(?=.*\d)\d*[\.\,]?\d*$/);
    }
}

And then install those via a loop:

$.each(validations, function(selector, validate) {
    $(document).on('keyup change focusout', selector, function(e){
        validateInput(e, $(this), validate(this.value));
    });
});