2
function add(obj) {
    for (var i = 0; i < obj.length; i++) {
        var elements = Object.keys(obj[i]);
        var host = obj[i].host;
        for (var key in obj[i]) {
            if (key === "host")
                continue;
            else {
                $("#table").append('<tr id=' + key + host.replace(/\./g, "") + '><th>' + key + '</th><td>' + host + '</td></tr>');
                var id = key + host.replace(/\./g, "");
                for (var j = 0; j < obj[i][key].length; j++) {
                    var cellId = id + Object.keys(timeList[j]).toString().split(" ").join("-").replace(/:/g,"-");
                    var list = obj[i][key][j];
                    var flag = aggregateTags(list);
                    if (flag == "OKAY")
                    $("#" + id).append('<td><img id ='+cellId+' src="/static/img/dashboard_green.gif" style="padding-top: 20px"></td>');
                    else if (flag == "WARNING")
                    $("#" + id).append('<td><img id ='+cellId+' src ="/static/img/dashboard_yellow.gif" style="padding-top: 20px"></td>');
                    else
                    $("#" + id).append('<td><img id ='+cellId+' src ="/static/img/dashboard_red.gif" style="padding-top: 20px"></td>');
                    $("#"+cellId).click(function(){ console.log(" i clicked on " +this.id);show(list)});
                }
            }
        }
    }
}

This function basically adds rows in a table dynamically. Each row was j cells. The problem with my $("#"+cellId).click function is that on clicking any cell , the results displayed are that of the last cell in that row. This is because , the "list" I have passed as an argument to the show function is always corresponding to the last cell of that row.

Basically : if these are the 4 lists corresponding to every cell for a given row :

list [{"host":"example.com","metric":"PENDING_COUNT","value":{"15-10-2014 19:30_0":1},"tags":"","alert":"OKAY"}]
 list [{"host":"example.com","metric":"PENDING_COUNT","value":{"15-10-2014 19:25_0":1},"tags":"","alert":"OKAY"}]
 list [{"host":"example.com","metric":"PENDING_COUNT","value":{"15-10-2014 19:20_0":1},"tags":"","alert":"OKAY"}]
 list [{"host":"example.com","metric":"PENDING_COUNT","value":{"15-10-2014 19:15_0":1},"tags":"","alert":"OKAY"}] 

The only list getting passed to the show() function [ no matter which cell of that row is clicked ] is the last 'list' .

i.e :

list [{"host":"example.com","metric":"PENDING_COUNT","value":{"15-10-2014 19:15_0":1},"tags":"","alert":"OKAY"}] 

Can someone tell me how to fix this problem?

Thanks in advance!

Gary
  • 13,303
  • 18
  • 49
  • 71
joanOfArc
  • 467
  • 1
  • 6
  • 16

1 Answers1

4

You need to wrap your click handler in a closure and pass in list.

(function(list){
    $("#"+cellId).click(function(){ console.log(" i clicked on " +this.id);show(list)});
})(list);

This makes a locally scoped list to prevent all iterations from using the same list. Without a closure, all of the click handlers are seeing the same list, because they are picking it up from the higher scope.

MrCode
  • 63,975
  • 10
  • 90
  • 112
  • Thanks this works!You saved my day!Do not have enough reputation to vote up though! But (function(list){})(list) does what exactly? I am a little unfamiliar with this structure – joanOfArc Oct 16 '14 at 06:27
  • 2
    It defines a function, then immediately executes it (known as an IEFE or IIFE). The reason is functions create a new scope, which we need. In the first line, the function defines a parameter (argument) `list`, then on the last line, we pass the list from the loop in as that argument. Because that's a new scope, nothing can overwrite the local list. More info on closures http://stackoverflow.com/questions/111102/how-do-javascript-closures-work – MrCode Oct 16 '14 at 06:30