javascript addEventListener is not working

I’m writing a simple chrome extension that lists all the open tabs, I have this code on it

function changeTab(tabID){
  chrome.tabs.update(tabID,{active:false})
}

chrome.windows.getCurrent({populate: true},function (window){
  list = document.getElementById('open-tabs');
  for (var i = 0; i < window.tabs.length; i++)
  {
    var li = document.createElement('li');
    var element = document.createElement('a');
    element.setAttribute('href','#');
    element.innerHTML = window.tabs[i].title;
    element.addEventListener("click",function(){
      changeTab(window.tabs[i].id);
    },false);
    li.appendChild(element);
    list.appendChild(li);
  }
});

It lists the open tabs, but doesn’t seem to add the onClick event, when I checked the chrome console I get this

  • Match pattern for all Google search pages
  • Get text (not url) from address bar in Google Chrome
  • How does the Google Hangouts extension create the panel window?
  • Why does my very simple Chrome extension work on Mac but not PC?
  • How to download file in google chrome extension without opening a new tab
  • Chrome 27: New Tab Page extension can't steal focus from Omnibox
  • chrome console

    Why is not adding the event correctly?

    –edit–
    Adding the html if it helps

    <!doctype html>
    <html>
    <head>
        <title>Count Me</title>
        <link rel="stylesheet" href="popup.css" type="text/css">
        <script src="popup.js"></script>
    </head>
    <body>
        <div id="main">
            <ul id="open-tabs"></ul>
        </div>
    </body>
    </html>
    

    Edit2

    I tried using the sugestion given on an answer using the .bind(this,i) but still doesn’t work, I added console.log() to see what’s happening, and it seems it’s not going inside the addEventListener heres the code with the log calls:

    function changeTab(tabID){
      chrome.tabs.update(tabID,{active:false})
    }
    
    chrome.windows.getCurrent({populate: true},function (window){
      list = document.getElementById('open-tabs');
      for (var i = 0; i < window.tabs.length; i++)
      {
        var li = document.createElement('li');
        var element = document.createElement('a');
        element.setAttribute('href','#');
        element.innerHTML = window.tabs[i].title;
        console.log('before');
        console.log(window.tabs[i].id);
        element.addEventListener("click",function(iVal){
          console.log('inside');
          changeTab(window.tabs[iVal].id);
        }.bind(this,i),false);
        console.log('after');
        console.log(window.tabs[i].id);
        li.appendChild(element);
        list.appendChild(li);
      }
    });
    

    As you can see I have a Before and After console.log() as well as inside the addEventListener and it doesn’t seem to call anything inside the addEventListener as you can see here:

    chrome console

    It’s calling the console.log inside the addEventListener but still isn’t working

    chrome console 3

  • Chrome extension code vs Content scripts vs Injected scripts
  • Keydown Which Not Working Chrome Extension
  • Using page's angular JS in chrome extension
  • How should I securely store passwords and use http auth in a chrome extension
  • Chrome extension: load different content scripts
  • Chrome's webstore server reject an extension with “Error : The manifest must define a version.”
  • 2 Solutions collect form web for “javascript addEventListener is not working”

    Your function callback is happening in a context that does not recognize i..
    You can bind the i value to function and by that make it work:

    element.addEventListener("click",function(iVal){
          changeTab(window.tabs[iVal].id);
        }.bind(this,i),false);
    

    Try adding a closure around the function

    (function(num) {
        element.addEventListener("click",function(){
           changeTab(window.tabs[num].id);
        },false);
    })(i)
    

    The event will be executed a later stage when you click the element. So when the for loop is completed, i always points to last iterated value.

    So enclosing it in an anonymous function creates a closure around the variable which will be available at the time the click event occurs.