Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery: Calling a Function Dynamically

I have attached a onClick event handle to a tag. On click, I wanted to pick-up an attribute -- let's say, fn; and I want to call the function mentioned as the attribute value.

The following code does not work

<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
    <script language="JavaScript">
        var Test = Test? Test : new Object();
        $(document).ready(function(){
            Test.main();
        })
        Test.sub = function(){
            alert('called');
        }
        Test.main = function(){
            $('.caller').click(function(e){
                e.preventDefault();
                var fn = $(this).attr('fn');
                alert('calling: '+fn);
                return fn();
            });
        }
    </script>
</head>
<body>
    <a class="caller" fn="Test.sub" href="#">test call</a>
</body>
</html>

My questions are

  • Is it possible?
  • What am I doing wrong?
  • What could be right approach to solve this issue?

Thanks
Nishant

like image 392
Nishant Avatar asked Dec 13 '22 17:12

Nishant


1 Answers

Is it possible?

Yes. If you change your link to just have sub:

<a class="caller" fn="sub" href="#">test call</a>

Then this works:

$('.caller').click(function(e){
    e.preventDefault();
    var fn = $(this).attr('fn');
    alert('calling: '+fn);
    return Test[fn]();
});

The value you retrieve is a string. You can index into an object's properties using a string if you like using bracketed notation ([]), so all of these are equivalent:

Test.sub();
Test['sub']();
var fn = 'sub';
Test[fn]();

What am I doing wrong?

You were nearly there. You had "Test.sub" in a string, but as it was a string, not a function, you couldn't call it. It would be like doing this:

"Test.sub"();

....which obviously isn't quite doing what you want. :-)

What could be right approach to solve this issue?

In technical terms, the above solves the problem. Part of me worries about having the actual function name in an attribute and wants to say "have a lookup table instead", but your Test object basically is the lookup table, so...

Side note: In this situation, you may see people using eval. Usually that's because they didn't realize you could index into an object with bracketed notation. eval is best avoided.


Off-topic #1: Your attribute, fn, is invalid (invalid = won't validate). In HTML4 and earlier, all custom attributes were invalid, although every desktop browser I've ever seen allows them (browsers let us get away with lots of things). As of HTML5, the demand for this feature was heard and we can have valid custom attributes, but they must start with data- so the validator knows they're custom. So if validation is part of your workflow (and it's usually a good idea), you might go with data-fn="sub" rather than simply fn="sub". More here.


Off-topic #2: If you want to save some typing, use {} rather than new Object(). E.g.:

var Test = Test? Test : {};

And if you want to save even more, use the curiously-powerful || operator:

var Test = Test || {};
like image 63
T.J. Crowder Avatar answered Dec 30 '22 22:12

T.J. Crowder