0

this is my fiddle, which I am building on from this example.

And now I have this fiddle where it uses an array to draw 1 chart per each element in the array

arr = ["https://dl.dropboxusercontent.com/u/49714666/data.tsv", "https://dl.dropboxusercontent.com/u/49714666/data2.tsv"]

for (this_file in arr) {

  d3.tsv(arr[this_file], type, function(error, data) {
    if (error) throw error;

    //draw chart code 

    //add a graph title
    svg.append("text")
      .attr("x", (width / 2))
      .attr("y", 0 - (margin.top / 2))
      .attr("text-anchor", "middle")
      .style("font-size", "12px")
      //.style("text-decoration", "underline")  
      .text(arr[this_file] + " - 1");


  });

}

But the way this works is that each chart title gets the name from the 2nd name in the array. What I want is the 1st elment name to be the title of chart 1 and the 2nd element to be the title of chart 2... How can this be done? Or do I have a slight misunderstanding here?

My current workaround is to use a var=ii to get this to work. here is the fiddle but I am just wondering is there a better way, or maybe I need to rewrite it?

HattrickNZ
  • 4,373
  • 15
  • 54
  • 98
  • `this_file`, when used within `function(error, data)`, is always set to the value it was the last time your loop executed (i.e. the value of the last element in the array). This is a general javascript issue — not specific to d3. [See this post](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). – meetamit Jun 22 '16 at 22:56
  • tks, so is that my code is faulty or is my work around the best I can do here? – HattrickNZ Jun 22 '16 at 23:29

1 Answers1

1

Avoid your workaround! Having a global-ish variable ii modified as a side effect of a render action (the ii++ bit) is unclear and can backfire big time. Try this:

var arr = ["https://dl.dropboxusercontent.com/u/49714666/data.tsv", "https://dl.dropboxusercontent.com/u/49714666/data2.tsv"]

for (var this_file in arr) {
  // "createDataHandler" is declared below
  d3.tsv(arr[this_file], type, createDataHandler(arr[this_file]));
}

// This is a function that returns a function. This way, the returned, inner function
// is already scoped to the appropriate "instance of this_file".
// The returned function becomes the "data loaded" handler of d3.tsv
function createDataHandler(fileUrl) {
  // This bit will be executed once per fileUrl (aka this_file)
  // Note how when it executes, the tsv hasn't even began yet loading.
  console.log("Create handler for " + fileUrl);

  return function(error, data) {
    // This bit executes once the TSV associated with each fileUrl (aka this_file)
    // is loaded.

    if (error) throw error;

    //draw chart code 

    //add a graph title
    svg.append("text")
      .attr("x", (width / 2))
      .attr("y", 0 - (margin.top / 2))
      .attr("text-anchor", "middle")
      .style("font-size", "12px")

      // instead of this:
      //.text(arr[this_file] + " - 1");

      // you get to use fileUrl:
      .text(fileUrl + " - 1");
  }
}
meetamit
  • 24,727
  • 9
  • 57
  • 68
  • tks, but this is close [fiddle here](https://jsfiddle.net/HattrickNZ/ygmkvreb/18/) the 2nd chart drawn the title is written on top which does not look right. can this be fixed? – HattrickNZ Jun 23 '16 at 00:04
  • correction that was my mistake, I was duplicating writing to the chart title. here is the updated [fiddle](https://jsfiddle.net/HattrickNZ/ygmkvreb/19/) – HattrickNZ Jun 23 '16 at 02:08
  • 1
    @HattrickNZ sorry, but can you rephrase your question? I'm not sure what you're asking. – meetamit Jun 23 '16 at 15:24
  • don't worry you were right with your first answer. my fiddles should hopefully show this. – HattrickNZ Jun 23 '16 at 21:08