title: D3.js binding nested data
body: <p>I'm really new to coding, and also to asking questions about coding. So let me know if my explanation is overly complex, or if you need more context on anything, etc.</p>
  
  <p>I am creating an interactive map of migration flows on the Mediterranean Sea. The flows show origin and destination regions of the migrant flows, as well as the total number of migrants, for Italy and Greece. Flows should be displayed in a Sankey diagram like manner. Because I am displaying the flows on a map and not in a diagram fashion, I am not using D3’s Sankey plugin, but creating my own paths.</p>
  
  <p><a href="https://i.stack.imgur.com/6r1SJ.png" rel="nofollow noreferrer">My flow map, as of now (curved flows are on top of each other, should line up next to each other)</a></p>
  
  <p>For generating my flows I have four points: </p>
  
  <ul>
  <li>2 points for the straight middle part of the flow (country total)</li>
  <li>1 point each for the curved outer parts (origin and destination region), using the two points of the straight middle part as starting points</li>
  </ul>
  
  <p>The straight middle and both curved outer parts are each generated independently from their own data source. Flow lines are updated by changing the data source and calling the function again. The flow lines are generated using the SVG path mini-language. In order for the curved outer parts of the flows to show correctly, I need them to be lined up next to each other. To line them up correctly, I need to shift their starting points. The distance of the shift for each path element is determined by the width of the path elements before it. So, grouping by country, each path element <em>i</em> needs to know the sum of the width of the elements <em>0-i</em> in the same group.</p>
  
  <ul>
  <li>After grouping my data with d3.nest(), which would allow me to iterate over each group, I am not able to bind the data correctly to the path elements</li>
  <li>I also can't figure out a loop function that adds up values for all elements 0-i. Any help here? (Sorry if this is kind of unrelated to the issue of binding nested data)</li>
  </ul>
  
  <p>Here is a working function for the curved paths, working for unnested data:</p>
  
  <pre><code>    function lineFlow(data, flowSubGroup, flowDir) {
              var flowSelect = svg.select(".flowGroup").select(flowSubGroup).selectAll("path");
              var flow = flowSelect.data(data);
              var flowDirection = flowDir;
              flow.enter()
              .append("path").append("title");
              flow
              .attr("stroke", "purple")
              .attr("stroke-linecap", "butt")
              .attr("fill", "none")
              .attr("opacity", 0.75)
              .transition()
                  .duration(transitionDur)
                  .ease(d3.easeCubic)
              .attr("d", function(d) {
                  var
                      slope = (d.cy2-d.cy1)/(d.cx2-d.cx1),
                      dist = (Math.sqrt(Math.pow((d.rx2-d.rx1),2)+Math.pow((d.ry2-d.ry1),2)))*0.5,
                      ctrlx = d.rx1 + Math.sqrt((Math.pow(dist,2))/(1+Math.pow(slope,2)))*flowDirection,
                      ctrly = slope*(ctrlx-d.rx1)+d.ry1;
                  return "M"+d.rx1+","+d.ry1+"Q"+ctrlx+","+ctrly+","+d.rx2+","+d.ry2})
              .attr("stroke-width", function(d) {return (d.totalmig)/flowScale});
              flowSelect
                  .select("title")
                  .text(function(d) {
                       return d.region + "\n"
                       + "Number of migrants: " + addSpaces(d.totalmig)});
          };
  </code></pre>
  
  <p>I tried adapting the code to work with data grouped by country:</p>
  
  <pre><code>    function lineFlowNested(data, flowSubGroup, flowDir) {
              var g=svg.select(".flowGroup").select(flowSubGroup).append("g").data(data).enter();
              var gflowSelect=g.selectAll("path");
              var gflow=gflowSelect.data (function(d) {return d.values});
              gflow.enter()
              .append("path");
              gflow.attr("stroke", "purple")
              .attr("stroke-linecap", "butt")
              .attr("fill", "none")
              .attr("opacity", 0.75)
              // .transition()
                  // .duration(transitionDur)
                  // .ease(d3.easeCubic)
              .attr("d", function(d) {
                  var
                      slope = (d.cy2-d.cy1)/(d.cx2-d.cx1),
                      dist = (Math.sqrt(Math.pow((d.rx2-d.rx1),2)+Math.pow((d.ry2-d.ry1),2)))*0.5,
                      ctrlx = d.rx1 - Math.sqrt((Math.pow(dist,2))/(1+Math.pow(slope,2)))*flowDirection,
                      ctrly = slope*(ctrlx-d.rx1)+d.ry1;
                  return "M"+d.rx1+","+d.ry1+"Q"+ctrlx+","+ctrly+","+d.rx2+","+d.ry2})
              .attr("stroke-width", function(d) {return (d.totalmig)/flowScale});
          };
  </code></pre>
  
  <p>which isn't working. What am I doing wrong? Thanks for any hints!</p>