1

Got a problem here and i've been pulling my hair last few days...

I'm making a sort of language filter function for a website and it's a menu where you click a language and it filters out the rest of them. Since i got lots of different languages i figured it would be best to loop everything instead of making like 15 pieces of the same code.

Here's my code:

// >>> Language click effects
    for(langClickNum = 1; langClickNum < langList.length; langClickNum++) {

        $('#lang'+langList[langClickNum]).click(function() {
            if (!langSelect[langClickNum]) {

                clrSearch();
                clrLang();
                langHide();

                $('#lang'+langList[langClickNum]).addClass('langCheck');
                $('.itemLang'+langList[langClickNum]).show();
                langSelect[langClickNum] = true;
            }
            else {
                clrLang();
                langShow();
            }
        });

    }

As you can see inside the click function I want to pick indexes from different arrays using the loop counters number. But since the script inside the click function dosent run unless I click it, it won't catch the correct array number. Instead it picks the last array number for each language i click. I'm very aware of what problem is but I have no idea how to solve it. Please help me out there!

If I give it numbers not looping it it works just fine, like this:

$('#lang'+langList[1]).click(function() {
        if (!langSelect[1]) {

            clrSearch();
            clrLang();
            langHide();

            $('#lang'+langList[1]).addClass('langCheck');
            $('.itemLang'+langList[1]).show();
            langSelect[1] = true;
        }
        else {
            clrLang();
            langShow();
        }
});

I hope you can see my problem.

1
  • you could consider using JSfiddle to demo this type of problem Commented Sep 30, 2012 at 18:49

3 Answers 3

1

I had faced a similar problem few months back. You go about doing like this:

$('#lang'+langList[langClickNum]).click(function(langClickNum) {
    return function() {
        if (!langSelect[langClickNum]) {

            clrSearch();
            clrLang();
            langHide();

            $('#lang'+langList[langClickNum]).addClass('langCheck');
            $('.itemLang'+langList[langClickNum]).show();
            langSelect[langClickNum] = true;
        }
        else {
            clrLang();
            langShow();
        }
    }
});

The reason is that all the click handler functions share the same closure environment and hence the variable langClickNum will be the same for all of them. If you need langClickNum to be different for each of them, you need to make pass it to the function which will essentially create a copy of langClickNum for that function's closure. Not sure if I explained it perfectly...

Sign up to request clarification or add additional context in comments.

2 Comments

I added the return function() but that didn't work either. Now i get no response at all from the click function.
Have tried putting a breakpoint inside the function in Firebug and checking the value of langClickNum?
0

The problem is related to the concept of JS variable scoping/closure.

The value of langClickNum iterates ok when you are binding the 'click' handler, but when the click handler is executed, the 'langClickNum' is already equal to langList.length.

you could do something like:

for(x = 1; x < langList.length; x++) {      
    (function(){
        var langClickNum = x;   
        $('#lang'+langList[langClickNum]).click(function() {//... rest of your code}
    })();
}

Here, the value of langClickNum will be as you expected, because of the function scoping in JS.

see for more information: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope

1 Comment

This worked fine! Thanks for the example and the explanation!
0

Rather than using a for loop, simply iterate through the lang objects in the DOM using a counter.

<script type="text/javascript">
    jQuery(document).ready(function () {
        var _LangList = ['lang1', 'lang2', 'lang3', 'lang4', 'lang5'];
        var _iCurrLangIndex = 0;
        var _iIndex = 0;
        jQuery.each(jQuery('#lang_list').children(), function () {
            var _oCurrLangObj = jQuery(this).click(function () {
                var __iThisItemsIndex = parseInt(jQuery(this).attr('data-lang-index'));
                // Code Here
            }).attr('data-lang-index', _iIndex++);
        });
    });
</script>

<div id="lang_list">
    <div id="lang0"></div>
    <div id="lang1"></div>
    <div id="lang2"></div>
    <div id="lang3"></div>
    <div id="lang4"></div>
</div>

Also for selecting a value, I would simply use 1 global Index var (_iCurrLangIndex) for managing which is used and make it 0-based if possible.

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.