1

I have this scenario:

<html>
<head>
<script type="text/javascript" src="jquery-1.4.4.js"></script>
<script type="text/javascript">
var actions = {
    'view' : function(){alert("view");},
    'history': function(){alert("history");},
    'renewal': function(){alert("renewal");}
}
for(var action in actions){
    $('.' + action).live('click', function(e){
        e.preventDefault();
        if(actions[action])
            actions[action]();
    });
}
</script>
</head>
<body>
    <a class="view" href="#">view</a>
    <a class="history" href="#">history</a>
    <a class="renewal" href="#">renewal</a>
</body>
</html>

I think a closure is created, since clicking a link always alerts "renewal" and I am not able to fix it.

3
  • 3
    This basic question must account for about 10% of all JavaScript questions here :-) Commented Feb 24, 2011 at 15:50
  • Are you referring to "closure" as some sort of error? Because it isn't. Commented Feb 24, 2011 at 15:51
  • possible duplicate of Javascript closure inside loops - simple practical example Commented Jan 17, 2013 at 17:52

4 Answers 4

2

Why dont you try using the classname in the click event?

I'm no jQuery expert, but something like this:

$('.' + action).live('click', function(e)
{
 e.preventDefault();
 if(actions[this.className])
   actions[this.className]();
});
Sign up to request clarification or add additional context in comments.

Comments

2

It is indeed. You can replace

for(var action in actions){
    $('.' + action).live('click', function(e){
        e.preventDefault();
        if(actions[action])
            actions[action]();
    });
}

with

for(var action in actions){
    $('.' + action).live('click', function(e){
        e.preventDefault();
        var currentAction = $(e.target).attr('class');
        if(actions[currentAction])
            actions[currentAction]();
    });
}

By the way, the problem is not that there is a closure. Indeed, if there was not a closure, the value of the variable action would not be rembered at all! The problem is that all the functions in the loop refer to the same variable action, that at the end of the loop will have the value renewal.

Comments

0

There are better ways of doing this, but to make your solution work:

for(var action in actions){
    (function(myAction){
        $('.' + myAction).live('click', function(e){
            e.preventDefault();
            if(actions[myAction])
                actions[myAction]();
        });
    })(action);
}

You are going to find out that live is not going to cancel the default action, You are going to want to use delegate

Comments

0

That's not what happens. Instead, your event handler function references the action variable, which will always have the value 'renewal', since that 's the last item in the list after the loop is done. The best way to go about it is to replace the loop with something like that:

for(var action in actions) {
    $('.' + action).live('click', function(e){
        e.preventDefault();
        var action = $(e.currentTarget).attr('class');
        if(actions[action]) actions[action]();
   });
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.