Dynamic function names

Is it possible to call a function where part of the name is a string that can change?

In this code I’m checking if elements with a certain class name exist in the form. If they do I want to validate it.

my function name will be ValJs.validate_ + ValJs.inputClassNames[i] + ();

is this possible?


validateForm: function(e){

        for(i = 0, ii = ValJs.inputClassNames.length; i < ii; i++){

            // check if ValJs.inputClassNames[i] is in the form
            if($('.' + ValJs.inputClassNames[i], this).length > 0){
                // a form element with class name [i] was found in the form, go validate all of them
                ValJs.validate_ + ValJs.inputClassNames[i] + ();
                //ValJs.validate_notEmpty();
            }
        }

    }

With square bracket notation, yes.

ValJs’validate_’ + ValJs.inputClassNames[i]

Oh snap! it worked, thanks!

related to my validation, i have the below code where i find elements with jQuery, then try to loop over them with a for loop but it doesn’t seem to be working. is that not possible?


        var inputs = $('.notEmpty');

        for(i = 0, ii = inputs.length; i < ii; i++){
            alert(inputs.attr('id'));
        }

Hi there,

This will work:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unbenanntes Dokument</title>
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
  </head>
  
  <body>
    <div class="notEmpty" id="one">One</div>
    <div class="notEmpty" id="two">Two</div>
    <div class="notEmpty" id="three">Three</div>
    
    <script>
      // the jQuery way
      $(".notEmpty").each(function(){
        console.log($(this).attr("id"));
      });
      
      // Pure JS  
      var inputs = document.getElementsByClassName("notEmpty");
      for(var i = 0, ii = inputs.length; i < ii; i++){
        console.log(inputs[i].id);
      }  
      
      // Bit of both
      $(".notEmpty").each(function(){
        console.log(this.id);
      });
    </script>
  </body>
</html>

Here you can see the jQuery way vs the pure JS way.

I would personally opt for the third version, as I like the jQuery syntax, but creating a jQuery object and the using its attr() method for obtaining an element ID is inefficient and unnecessary. Just use the element’s id property, which works in all browsers.

One notable difference between the two methods (apart from speed) is if the element has no id, then this.id will return a blank string while $(this).attr("id") will return undefined.

Regarding speed, if you’re feeling bored, look here: http://jsperf.com/el-attr-id-vs-el-id/2

2 questions:

ok, so my example just isn’t possible? you can’t do a pure js for loop over a jQuery collection?

also, I’ve been away from js for a while, but, is document.getElementsByClassName new? I thought a learnable course i watched said it didn’t exist so they used a custom getElementsByClassName.

Not like you’re trying to do. This:

var inputs = $('.notEmpty');

will, AFAIK, return a jQuery object known as a “wrapped set,” which is an array-like structure that contains all the selected DOM elements. This means that this:

console.log(inputs[0]);

outputs:

<div class="notEmpty" id="one">One</div>

which doesn’t have a .attr() method, as it is a DOM element, not a jQuery object.

To make your script work like you want, you have to do this:

var inputs = $('.notEmpty');
for(i = 0, ii = inputs.length; i < ii; i++){
 console.log($(inputs[i]).attr('id'));
}

which turns each element of the wrapped set into a jQuery object, or this:

var inputs = $('.notEmpty');
for(i = 0, ii = inputs.length; i < ii; i++){
  console.log(inputs[i].id);
}

which references the DOM element’s native id attribute.

It’s newish, but supported in all major browsers.
See here: https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName
And here: https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName#Browser_compatibility

HTH

makes total sense, thanks