6

I want to create a For loop for a series of 'click' events on my page. I'm creating a timetable where clicking on a Day button will display the events assigned to that day in a div box.
HTML

<div class="cwt-buttons">
<a id="cwt-button1">Monday</a>
<a id="cwt-button2">Tuesday</a>
<a id="cwt-button3">Wednesday</a>
<a id="cwt-button4">Thursday</a>
<a id="cwt-button5">Friday</a>
<a id="cwt-button6">Saturday</a>
<a id="cwt-button7">Sunday</a>
</div>

<div id="cwt-timetable">
<div class="current">Housework</div>
<div class="cwt-Day1">Kickboxing</div>
<div class="cwt-Day2">Homework</div>
<div class="cwt-Day3">Yoga</div>
<div class="cwt-Day4">Eating</div>
<div class="cwt-Day5">Fasting</div>
<div class="cwt-Day6">Running</div>
<div class="cwt-Day7">Funeral</div>
</div>

JS

$(function() {
    for ( var i = 1; i < 8; i++ ) {
        var clickedButton = $("#cwt-button"+i);
        $(clickedButton).click(function() {
        var currentDay = $('#cwt-timetable div.current');
        var selectedDay = $('#cwt-timetable div.cwt-Day'+i);
        currentDay.removeClass('current').addClass('previous');
        (selectedDay).css({ opacity: 0.0 }).addClass('current').animate({ opacity: 1.0 }, 1000,
        function() {
            currentDay.removeClass('previous');
        });     
    })
    }
});

The JavaScript works fine when I have the exact value in e.g. "#cwt-button1"
It just doesn't work when I concatenate the 'i' counter in the loop.

Can anyone see where I'm going wrong? Or am I do something JavaScript can't handle?

4
  • 1
    You shouldn't have to do this. Just use $('cwt-buttons a').click(...) and make your event handler generic enough to work for any link. Commented Sep 16, 2013 at 2:41
  • 1
    You're also using $(...) twice; effectively you're writing $($('#cwt-button1')), which isn't a problem, just unnecessary. Commented Sep 16, 2013 at 2:42
  • try this: var clickedButton = "#cwt-button"+i;, just a guess. Commented Sep 16, 2013 at 2:53
  • Hey guys, removing the $() in the variable results in an error, only reason I'm doing it that way. Commented Sep 16, 2013 at 3:16

1 Answer 1

2

This is just the same old issue that gets asked multiple times a day. All your functions created in the loop are created in the same variable scope, so they share the same i variable.

To scope a variable you need a function invocation. jQuery's $.each() is a handy way to do this:

$(function () { // -----------v-----scoped to the function
    $.each(Array(7), function(i) {
        var clickedButton = $('#cwt-button' + (++i));

        $(clickedButton).click(function () {
            var currentDay = $('#cwt-timetable div.current');

            // --------using scoped `i`------------------------v
            var selectedDay = $('#cwt-timetable div.cwt-Day' + i);
            currentDay.removeClass('current').addClass('previous');
            (selectedDay).css({
                opacity: 0.0
            }).addClass('current').animate({
                opacity: 1.0
            }, 1000, function () {
                currentDay.removeClass('previous');
            });
        });
    });
});
Sign up to request clarification or add additional context in comments.

9 Comments

that is an ugly hack. each was not meant to do this. use an anon function instead
@mkoryak: That's silly. First, I am using an anonymous function. Second, this is precisely the benefit of using a functional style iterator. It's not a hack. It's being used exactly as intended.
you arent iterating over the array you created, you are using it as a hacky way to get the each to work. i should have said, create an anon function inside the for loop and call it a day
@mkoryak: What defines the number of iterations isn't relevant. What we need is a scoped variable, which is what the function invocation provides.
@mkoryak: If you're referring to an IIFE, that's a less efficient way to do it since a new function object is created for every iteration of the loop. This way, only one function is created. It's also a less cryptic syntax than the IIFE, which confuses many people, especially when inlined in a loop.
|

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.