0

I am trying to create a list so that when the LI element is clicked, a specific div is displayed. I want to read the id of the div and other properties from a dictionary. So, the dictionary looks like this:

var ifSrc = {"welcome":"welcome.html",
          "proceduresAndComputers":"../proceduresAndComputers/index.html",
          "someId":"../someSourceFileForAnIFrame"}

and the function to form those LI elements

function createMenu(){
    var listy = document.getElementById("sidebar");
    for(var key in ifSrc){
        var elem = document.createElement('li');
        elem.innerHTML = key;
        elem.className = "unselected";
        elem.addEventListener("click",function(){openDiv(this,key);},false);
        listy.appendChild(elem);
    }
    listy.firstElementChild.className="selected";
}

So, the Menu (UL with LI elements) looks ok, but no matter which LI I click on, the openDiv function passes the right value for this, but same value for key. In particular, it passes the last value for key in the ifSrc dictionary. However, the innerHTML of each elem (which is set to key) appears fine. I checked the documentation for addEventListener and I couldn't find much.

Why is this happening? Any insights?

fiacobelli
  • 1,960
  • 5
  • 24
  • 31

1 Answers1

0

Just make sure that you're capturing the correct key value (with a closure, in my example below). The way you have it now, key is always a reference to the same value in all of the click events. You can copy the current value of key for each click event by doing this:

    elem.addEventListener("click", (function(k) {
        return function() { 
            openDiv(this, k);
        }
    })(key), false);

Demo - jsfiddle.net

For reference -- check out "The Infamous Loop Problem" as explained here.

Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
  • So javascript won't evaluate key when I loop through the keys of the dictionary, but at runtime, when the eventListener is called? Is that why I want to add a closure? If that is the case, why didn't I get all the LI items saying the same thing? Any good pointers where I can read about this? – fiacobelli Aug 23 '13 at 18:04
  • The problem was with your inner function. Each function you were assigning as a click event had a reference to the same `key` variable. By using a closure you capture the *current* value of `key` and pass *that* into your click handler. See my edit, by the way, I changed it a bit to make it more obvious what's happening. – Cᴏʀʏ Aug 23 '13 at 18:10
  • Thanks, that link to the infamous loop helped, as well as the section "closure in loops: a common mistake" here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures – fiacobelli Aug 23 '13 at 18:10
  • You're welcome. There's also [this SO post](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) that has a ton of discussion and examples on the matter. – Cᴏʀʏ Aug 23 '13 at 18:11