Using dispatch events in d3.js

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












In this Plunker (Will post all code below) I'm using d3.dispatch to handle all updates of the charts.



What I want to know is if I'm using the dispatch events properly or as it was "intended" to be used, I could not find many examples using this particular method which is why I'm unsure of whether I'm using it correctly. Or just general code review.



<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="//d3js.org/d3.v5.min.js"></script>
<style>
/* --- Global --- */
body
margin:auto;
width: 850px;
font: 10px arial;
padding: 25px;
color:#333;

/* --- Chart --- */
.grid--y path,
.grid--y text
display: none;

.grid--y line
opacity:.15;

.axis--xS path
display: none;

.grid--yS path,
.grid--yS text
display: none;

.grid--yS line
opacity:.15;


</style>
</head>
<body>

<!-- Selection Category -->
<b>Välj Uteblivande</b>

<select id="category" class="options">
<option value="AA">All</option>
<option value="1U">1 Unit</option>
</select>

<!-- Selection New dataset -->
<span style="margin-left:30px;">
<b>Choose Year</b>

<select id="year" class="options">
<option value="2017">2017</option>
<option value="2016">2016</option>
</select>
</span>

<!-- Chart -->
<div id="chart"></div>

<script>

var durations = 0,
formatValue = d3.format(".2s"),
formatPercent = d3.format(",.0f");

var teamColor = d3.scaleOrdinal()
.range(["steelblue","darkorange", "lightblue"]);

var dispatch = d3.dispatch("load", "update");

var files = ["data1.csv", "data2.csv"];

Promise.all(files.map(url => d3.csv(url))).then(function(dataSet)

// === Load all data ===

var data1 = dataSet[0];
var data2 = dataSet[1];

dispatch.call("load", this);

// === Update data ===

update();

function update()

var input = d3.select('#category')
.property('value');

var data = d3.select('#year')
.property('value') == '2017' ? data1 : data2;

data.forEach(function(d, i, columns)
for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
ttl += d[columns[i]] = +d[columns[i]];
d.total = ttl;
d.sliceTotal = d3.sum([
d["Team 1 " + input],
d["Team 2 " + input],
d["Team 3 " + input]
]);
return d;
)

dispatch.call("update", this, data, input);



// === Event handler ===

d3.selectAll(".options").on("change", function()
durations = 750;
update();
)

);

dispatch.on("load.occupation", function()

let margin = top: 35, right: 45, bottom: 35, left: 45,
width = 540 - margin.left - margin.right,
height = 420 - margin.top - margin.bottom;

let g = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");

let x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1)
.padding(0.1);

let x1 = d3.scaleBand();

let y = d3.scaleLinear()
.rangeRound([height, 0]);

let xAxis = d3.axisBottom(x0),
yAxis = d3.axisLeft(y).ticks(null, "s");
yGrid = d3.axisLeft(y).tickSize(-width);

g.append("g")
.attr("class","axis axis--x")
.attr("transform", "translate(0," + height + ")");

g.append("g")
.attr("class", "axis axis--y");

g.append("g")
.attr("class", "axis grid--y");

dispatch.on("update.occupation", function(dataInit, input)

var keys = dataInit.columns.slice(1, 4);

let copy = ;

keys.forEach(function(t)
t = t.slice(0, -2)
copy.push(t)
)

var data = dataInit.filter(function(d)
return d.State !== "ALL"
)

let sumOfTeam = d3.sum(data, d=> d3.sum(keys, key=> d[key]));

y.domain([0, d3.max(data, function(d)
return d3.max(keys, function(key)
return d.sliceTotal;
);
)
]).nice();

g.selectAll(".axis.axis--y").transition()
.duration(durations)
.call(yAxis);
g.selectAll(".axis.grid--y").transition()
.duration(durations)
.call(yGrid);

// bars
let barGroups = g.selectAll("g.layer").data(data);
barGroups.enter().append("g")
.classed('layer', true);

barGroups.exit().remove();

// bars
let barGroups2 = g.selectAll("g.layer2").data(data);
barGroups2.enter().append("g")
.classed('layer2', true);

barGroups2.exit().remove();

// xDomains
x0.domain(data.map(function(d) return d.State; ));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);

// Update axis
g.selectAll(".axis.axis--x").transition()
.duration(durations)
.call(xAxis);

g.selectAll("g.layer").transition().duration(durations)
.attr("transform", function(d, i)
return "translate(" + x0(d.State) + ",0)";
);

let bars = g.selectAll("g.layer").selectAll(".bars")
.data(function(d)
return copy.map(function(key) // Return copy
return key: key+input, value: d[key+input] ; // Add input
);
);

bars = bars
.enter()
.append("rect")
.attr("class", "bars")
.attr("fill", function(d) return teamColor(d.key); )
.attr("width", x1.bandwidth())
.attr("x", function(d) return x1(d.key); )
.merge(bars)

bars.transition().duration(durations)
.attr("y", function(d) return y(d["value"]); )
.attr("height", function(d) return height - y(d["value"]); );

bars.exit().remove();

g.selectAll("g.layer2").transition().duration(durations)
.attr("transform", function(d, i)
return "translate(" + x0(d.State) + ",0)";
);

let barsTotal = g.selectAll(".test")
.data(data, function(d)
return d.State;
);

barsTotal = barsTotal
.enter()
.append("rect")
.attr("fill", "none")
.attr("stroke","#999")
.attr("stroke-width","1px")
.attr("class","test")
.attr("width", x0.bandwidth())
.merge(barsTotal);

barsTotal.transition().duration(durations)
.attr("x", function(d)
return x0(d.State);
)
.attr("y", function(d)
return y(d.sliceTotal);
)
.attr("height", function(d)
return height - y(d.sliceTotal);
);

barsTotal.exit().remove();

);

);

dispatch.on("load.all", function()

let margin = top: 35, right: 45, bottom: 35, left: 45,
width = 150 - margin.left - margin.right,
height = 420 - margin.top - margin.bottom;

let g = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1)
.padding(0.1);

var y = d3.scaleLinear()
.rangeRound([height, 0]);

let xAxis = d3.axisBottom(x),
yAxis = d3.axisLeft(y)
.ticks(null, "s");

g.append("g")
.attr("class","axis axis--x")
.attr("transform", "translate(0," + height + ")");

g.append("g")
.attr("class", "axis axis--y");

dispatch.on("update.all", function(dataInit, input)

var keys = dataInit.columns.slice(1, 4);

var copy =

keys.forEach(function(s)
s = s.slice(0, -2)
copy.push(s)
)

let combined = ;

copy.forEach(function(t)
t = t + input
combined.push(t)
)

var data = dataInit.filter(function(d)
return d.State == "ALL"
)

y.domain([0, d3.max(data, function(d)
return d3.sum(copy, function(key)
return d[key + input];
);
)
]).nice();

g.selectAll(".axis.axis--y").transition()
.duration(durations)
.call(yAxis);

teamColor.domain(combined);

x.domain(data.map(function(d) return d.State; ));

g.selectAll(".axis.axis--x").transition()
.duration(durations)
.call(xAxis);

var stacking = d3.stack().keys(combined)(data)

let barGroups = g.selectAll("g.layer")
.data(stacking,function(d)
return d.key.split(' ')[0] + d.key.split(' ')[1]
);

barGroups
.enter()
.append("g")
.classed('layer', true);

barGroups.exit().remove();

g.selectAll("g.layer").transition().duration(durations)
.attr("fill", function(d) return teamColor(d.key); );

let bars = g.selectAll("g.layer").selectAll("rect")
.data(function(d) return d; , d => d.data.State);

bars = bars
.enter()
.append("rect")
.attr("width", x.bandwidth())
.merge(bars);

bars.transition().duration(durations)
.attr("x", function(d) return x(d.data.State); )
.attr("y", function(d) return y(d[1]); )
.attr("height", function(d) return y(d[0]) - y(d[1]); );

);

);

</script>
</body>






share|improve this question

























    up vote
    1
    down vote

    favorite












    In this Plunker (Will post all code below) I'm using d3.dispatch to handle all updates of the charts.



    What I want to know is if I'm using the dispatch events properly or as it was "intended" to be used, I could not find many examples using this particular method which is why I'm unsure of whether I'm using it correctly. Or just general code review.



    <!DOCTYPE html>
    <head>
    <meta charset="utf-8">
    <script src="//d3js.org/d3.v5.min.js"></script>
    <style>
    /* --- Global --- */
    body
    margin:auto;
    width: 850px;
    font: 10px arial;
    padding: 25px;
    color:#333;

    /* --- Chart --- */
    .grid--y path,
    .grid--y text
    display: none;

    .grid--y line
    opacity:.15;

    .axis--xS path
    display: none;

    .grid--yS path,
    .grid--yS text
    display: none;

    .grid--yS line
    opacity:.15;


    </style>
    </head>
    <body>

    <!-- Selection Category -->
    <b>Välj Uteblivande</b>

    <select id="category" class="options">
    <option value="AA">All</option>
    <option value="1U">1 Unit</option>
    </select>

    <!-- Selection New dataset -->
    <span style="margin-left:30px;">
    <b>Choose Year</b>

    <select id="year" class="options">
    <option value="2017">2017</option>
    <option value="2016">2016</option>
    </select>
    </span>

    <!-- Chart -->
    <div id="chart"></div>

    <script>

    var durations = 0,
    formatValue = d3.format(".2s"),
    formatPercent = d3.format(",.0f");

    var teamColor = d3.scaleOrdinal()
    .range(["steelblue","darkorange", "lightblue"]);

    var dispatch = d3.dispatch("load", "update");

    var files = ["data1.csv", "data2.csv"];

    Promise.all(files.map(url => d3.csv(url))).then(function(dataSet)

    // === Load all data ===

    var data1 = dataSet[0];
    var data2 = dataSet[1];

    dispatch.call("load", this);

    // === Update data ===

    update();

    function update()

    var input = d3.select('#category')
    .property('value');

    var data = d3.select('#year')
    .property('value') == '2017' ? data1 : data2;

    data.forEach(function(d, i, columns)
    for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
    ttl += d[columns[i]] = +d[columns[i]];
    d.total = ttl;
    d.sliceTotal = d3.sum([
    d["Team 1 " + input],
    d["Team 2 " + input],
    d["Team 3 " + input]
    ]);
    return d;
    )

    dispatch.call("update", this, data, input);



    // === Event handler ===

    d3.selectAll(".options").on("change", function()
    durations = 750;
    update();
    )

    );

    dispatch.on("load.occupation", function()

    let margin = top: 35, right: 45, bottom: 35, left: 45,
    width = 540 - margin.left - margin.right,
    height = 420 - margin.top - margin.bottom;

    let g = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform","translate(" + margin.left + "," + margin.top + ")");

    let x0 = d3.scaleBand()
    .rangeRound([0, width])
    .paddingInner(0.1)
    .padding(0.1);

    let x1 = d3.scaleBand();

    let y = d3.scaleLinear()
    .rangeRound([height, 0]);

    let xAxis = d3.axisBottom(x0),
    yAxis = d3.axisLeft(y).ticks(null, "s");
    yGrid = d3.axisLeft(y).tickSize(-width);

    g.append("g")
    .attr("class","axis axis--x")
    .attr("transform", "translate(0," + height + ")");

    g.append("g")
    .attr("class", "axis axis--y");

    g.append("g")
    .attr("class", "axis grid--y");

    dispatch.on("update.occupation", function(dataInit, input)

    var keys = dataInit.columns.slice(1, 4);

    let copy = ;

    keys.forEach(function(t)
    t = t.slice(0, -2)
    copy.push(t)
    )

    var data = dataInit.filter(function(d)
    return d.State !== "ALL"
    )

    let sumOfTeam = d3.sum(data, d=> d3.sum(keys, key=> d[key]));

    y.domain([0, d3.max(data, function(d)
    return d3.max(keys, function(key)
    return d.sliceTotal;
    );
    )
    ]).nice();

    g.selectAll(".axis.axis--y").transition()
    .duration(durations)
    .call(yAxis);
    g.selectAll(".axis.grid--y").transition()
    .duration(durations)
    .call(yGrid);

    // bars
    let barGroups = g.selectAll("g.layer").data(data);
    barGroups.enter().append("g")
    .classed('layer', true);

    barGroups.exit().remove();

    // bars
    let barGroups2 = g.selectAll("g.layer2").data(data);
    barGroups2.enter().append("g")
    .classed('layer2', true);

    barGroups2.exit().remove();

    // xDomains
    x0.domain(data.map(function(d) return d.State; ));
    x1.domain(keys).rangeRound([0, x0.bandwidth()]);

    // Update axis
    g.selectAll(".axis.axis--x").transition()
    .duration(durations)
    .call(xAxis);

    g.selectAll("g.layer").transition().duration(durations)
    .attr("transform", function(d, i)
    return "translate(" + x0(d.State) + ",0)";
    );

    let bars = g.selectAll("g.layer").selectAll(".bars")
    .data(function(d)
    return copy.map(function(key) // Return copy
    return key: key+input, value: d[key+input] ; // Add input
    );
    );

    bars = bars
    .enter()
    .append("rect")
    .attr("class", "bars")
    .attr("fill", function(d) return teamColor(d.key); )
    .attr("width", x1.bandwidth())
    .attr("x", function(d) return x1(d.key); )
    .merge(bars)

    bars.transition().duration(durations)
    .attr("y", function(d) return y(d["value"]); )
    .attr("height", function(d) return height - y(d["value"]); );

    bars.exit().remove();

    g.selectAll("g.layer2").transition().duration(durations)
    .attr("transform", function(d, i)
    return "translate(" + x0(d.State) + ",0)";
    );

    let barsTotal = g.selectAll(".test")
    .data(data, function(d)
    return d.State;
    );

    barsTotal = barsTotal
    .enter()
    .append("rect")
    .attr("fill", "none")
    .attr("stroke","#999")
    .attr("stroke-width","1px")
    .attr("class","test")
    .attr("width", x0.bandwidth())
    .merge(barsTotal);

    barsTotal.transition().duration(durations)
    .attr("x", function(d)
    return x0(d.State);
    )
    .attr("y", function(d)
    return y(d.sliceTotal);
    )
    .attr("height", function(d)
    return height - y(d.sliceTotal);
    );

    barsTotal.exit().remove();

    );

    );

    dispatch.on("load.all", function()

    let margin = top: 35, right: 45, bottom: 35, left: 45,
    width = 150 - margin.left - margin.right,
    height = 420 - margin.top - margin.bottom;

    let g = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform","translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scaleBand()
    .rangeRound([0, width])
    .paddingInner(0.1)
    .padding(0.1);

    var y = d3.scaleLinear()
    .rangeRound([height, 0]);

    let xAxis = d3.axisBottom(x),
    yAxis = d3.axisLeft(y)
    .ticks(null, "s");

    g.append("g")
    .attr("class","axis axis--x")
    .attr("transform", "translate(0," + height + ")");

    g.append("g")
    .attr("class", "axis axis--y");

    dispatch.on("update.all", function(dataInit, input)

    var keys = dataInit.columns.slice(1, 4);

    var copy =

    keys.forEach(function(s)
    s = s.slice(0, -2)
    copy.push(s)
    )

    let combined = ;

    copy.forEach(function(t)
    t = t + input
    combined.push(t)
    )

    var data = dataInit.filter(function(d)
    return d.State == "ALL"
    )

    y.domain([0, d3.max(data, function(d)
    return d3.sum(copy, function(key)
    return d[key + input];
    );
    )
    ]).nice();

    g.selectAll(".axis.axis--y").transition()
    .duration(durations)
    .call(yAxis);

    teamColor.domain(combined);

    x.domain(data.map(function(d) return d.State; ));

    g.selectAll(".axis.axis--x").transition()
    .duration(durations)
    .call(xAxis);

    var stacking = d3.stack().keys(combined)(data)

    let barGroups = g.selectAll("g.layer")
    .data(stacking,function(d)
    return d.key.split(' ')[0] + d.key.split(' ')[1]
    );

    barGroups
    .enter()
    .append("g")
    .classed('layer', true);

    barGroups.exit().remove();

    g.selectAll("g.layer").transition().duration(durations)
    .attr("fill", function(d) return teamColor(d.key); );

    let bars = g.selectAll("g.layer").selectAll("rect")
    .data(function(d) return d; , d => d.data.State);

    bars = bars
    .enter()
    .append("rect")
    .attr("width", x.bandwidth())
    .merge(bars);

    bars.transition().duration(durations)
    .attr("x", function(d) return x(d.data.State); )
    .attr("y", function(d) return y(d[1]); )
    .attr("height", function(d) return y(d[0]) - y(d[1]); );

    );

    );

    </script>
    </body>






    share|improve this question





















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      In this Plunker (Will post all code below) I'm using d3.dispatch to handle all updates of the charts.



      What I want to know is if I'm using the dispatch events properly or as it was "intended" to be used, I could not find many examples using this particular method which is why I'm unsure of whether I'm using it correctly. Or just general code review.



      <!DOCTYPE html>
      <head>
      <meta charset="utf-8">
      <script src="//d3js.org/d3.v5.min.js"></script>
      <style>
      /* --- Global --- */
      body
      margin:auto;
      width: 850px;
      font: 10px arial;
      padding: 25px;
      color:#333;

      /* --- Chart --- */
      .grid--y path,
      .grid--y text
      display: none;

      .grid--y line
      opacity:.15;

      .axis--xS path
      display: none;

      .grid--yS path,
      .grid--yS text
      display: none;

      .grid--yS line
      opacity:.15;


      </style>
      </head>
      <body>

      <!-- Selection Category -->
      <b>Välj Uteblivande</b>

      <select id="category" class="options">
      <option value="AA">All</option>
      <option value="1U">1 Unit</option>
      </select>

      <!-- Selection New dataset -->
      <span style="margin-left:30px;">
      <b>Choose Year</b>

      <select id="year" class="options">
      <option value="2017">2017</option>
      <option value="2016">2016</option>
      </select>
      </span>

      <!-- Chart -->
      <div id="chart"></div>

      <script>

      var durations = 0,
      formatValue = d3.format(".2s"),
      formatPercent = d3.format(",.0f");

      var teamColor = d3.scaleOrdinal()
      .range(["steelblue","darkorange", "lightblue"]);

      var dispatch = d3.dispatch("load", "update");

      var files = ["data1.csv", "data2.csv"];

      Promise.all(files.map(url => d3.csv(url))).then(function(dataSet)

      // === Load all data ===

      var data1 = dataSet[0];
      var data2 = dataSet[1];

      dispatch.call("load", this);

      // === Update data ===

      update();

      function update()

      var input = d3.select('#category')
      .property('value');

      var data = d3.select('#year')
      .property('value') == '2017' ? data1 : data2;

      data.forEach(function(d, i, columns)
      for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
      ttl += d[columns[i]] = +d[columns[i]];
      d.total = ttl;
      d.sliceTotal = d3.sum([
      d["Team 1 " + input],
      d["Team 2 " + input],
      d["Team 3 " + input]
      ]);
      return d;
      )

      dispatch.call("update", this, data, input);



      // === Event handler ===

      d3.selectAll(".options").on("change", function()
      durations = 750;
      update();
      )

      );

      dispatch.on("load.occupation", function()

      let margin = top: 35, right: 45, bottom: 35, left: 45,
      width = 540 - margin.left - margin.right,
      height = 420 - margin.top - margin.bottom;

      let g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform","translate(" + margin.left + "," + margin.top + ")");

      let x0 = d3.scaleBand()
      .rangeRound([0, width])
      .paddingInner(0.1)
      .padding(0.1);

      let x1 = d3.scaleBand();

      let y = d3.scaleLinear()
      .rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x0),
      yAxis = d3.axisLeft(y).ticks(null, "s");
      yGrid = d3.axisLeft(y).tickSize(-width);

      g.append("g")
      .attr("class","axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      g.append("g")
      .attr("class", "axis grid--y");

      dispatch.on("update.occupation", function(dataInit, input)

      var keys = dataInit.columns.slice(1, 4);

      let copy = ;

      keys.forEach(function(t)
      t = t.slice(0, -2)
      copy.push(t)
      )

      var data = dataInit.filter(function(d)
      return d.State !== "ALL"
      )

      let sumOfTeam = d3.sum(data, d=> d3.sum(keys, key=> d[key]));

      y.domain([0, d3.max(data, function(d)
      return d3.max(keys, function(key)
      return d.sliceTotal;
      );
      )
      ]).nice();

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);
      g.selectAll(".axis.grid--y").transition()
      .duration(durations)
      .call(yGrid);

      // bars
      let barGroups = g.selectAll("g.layer").data(data);
      barGroups.enter().append("g")
      .classed('layer', true);

      barGroups.exit().remove();

      // bars
      let barGroups2 = g.selectAll("g.layer2").data(data);
      barGroups2.enter().append("g")
      .classed('layer2', true);

      barGroups2.exit().remove();

      // xDomains
      x0.domain(data.map(function(d) return d.State; ));
      x1.domain(keys).rangeRound([0, x0.bandwidth()]);

      // Update axis
      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      g.selectAll("g.layer").transition().duration(durations)
      .attr("transform", function(d, i)
      return "translate(" + x0(d.State) + ",0)";
      );

      let bars = g.selectAll("g.layer").selectAll(".bars")
      .data(function(d)
      return copy.map(function(key) // Return copy
      return key: key+input, value: d[key+input] ; // Add input
      );
      );

      bars = bars
      .enter()
      .append("rect")
      .attr("class", "bars")
      .attr("fill", function(d) return teamColor(d.key); )
      .attr("width", x1.bandwidth())
      .attr("x", function(d) return x1(d.key); )
      .merge(bars)

      bars.transition().duration(durations)
      .attr("y", function(d) return y(d["value"]); )
      .attr("height", function(d) return height - y(d["value"]); );

      bars.exit().remove();

      g.selectAll("g.layer2").transition().duration(durations)
      .attr("transform", function(d, i)
      return "translate(" + x0(d.State) + ",0)";
      );

      let barsTotal = g.selectAll(".test")
      .data(data, function(d)
      return d.State;
      );

      barsTotal = barsTotal
      .enter()
      .append("rect")
      .attr("fill", "none")
      .attr("stroke","#999")
      .attr("stroke-width","1px")
      .attr("class","test")
      .attr("width", x0.bandwidth())
      .merge(barsTotal);

      barsTotal.transition().duration(durations)
      .attr("x", function(d)
      return x0(d.State);
      )
      .attr("y", function(d)
      return y(d.sliceTotal);
      )
      .attr("height", function(d)
      return height - y(d.sliceTotal);
      );

      barsTotal.exit().remove();

      );

      );

      dispatch.on("load.all", function()

      let margin = top: 35, right: 45, bottom: 35, left: 45,
      width = 150 - margin.left - margin.right,
      height = 420 - margin.top - margin.bottom;

      let g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform","translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleBand()
      .rangeRound([0, width])
      .paddingInner(0.1)
      .padding(0.1);

      var y = d3.scaleLinear()
      .rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x),
      yAxis = d3.axisLeft(y)
      .ticks(null, "s");

      g.append("g")
      .attr("class","axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      dispatch.on("update.all", function(dataInit, input)

      var keys = dataInit.columns.slice(1, 4);

      var copy =

      keys.forEach(function(s)
      s = s.slice(0, -2)
      copy.push(s)
      )

      let combined = ;

      copy.forEach(function(t)
      t = t + input
      combined.push(t)
      )

      var data = dataInit.filter(function(d)
      return d.State == "ALL"
      )

      y.domain([0, d3.max(data, function(d)
      return d3.sum(copy, function(key)
      return d[key + input];
      );
      )
      ]).nice();

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      teamColor.domain(combined);

      x.domain(data.map(function(d) return d.State; ));

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var stacking = d3.stack().keys(combined)(data)

      let barGroups = g.selectAll("g.layer")
      .data(stacking,function(d)
      return d.key.split(' ')[0] + d.key.split(' ')[1]
      );

      barGroups
      .enter()
      .append("g")
      .classed('layer', true);

      barGroups.exit().remove();

      g.selectAll("g.layer").transition().duration(durations)
      .attr("fill", function(d) return teamColor(d.key); );

      let bars = g.selectAll("g.layer").selectAll("rect")
      .data(function(d) return d; , d => d.data.State);

      bars = bars
      .enter()
      .append("rect")
      .attr("width", x.bandwidth())
      .merge(bars);

      bars.transition().duration(durations)
      .attr("x", function(d) return x(d.data.State); )
      .attr("y", function(d) return y(d[1]); )
      .attr("height", function(d) return y(d[0]) - y(d[1]); );

      );

      );

      </script>
      </body>






      share|improve this question











      In this Plunker (Will post all code below) I'm using d3.dispatch to handle all updates of the charts.



      What I want to know is if I'm using the dispatch events properly or as it was "intended" to be used, I could not find many examples using this particular method which is why I'm unsure of whether I'm using it correctly. Or just general code review.



      <!DOCTYPE html>
      <head>
      <meta charset="utf-8">
      <script src="//d3js.org/d3.v5.min.js"></script>
      <style>
      /* --- Global --- */
      body
      margin:auto;
      width: 850px;
      font: 10px arial;
      padding: 25px;
      color:#333;

      /* --- Chart --- */
      .grid--y path,
      .grid--y text
      display: none;

      .grid--y line
      opacity:.15;

      .axis--xS path
      display: none;

      .grid--yS path,
      .grid--yS text
      display: none;

      .grid--yS line
      opacity:.15;


      </style>
      </head>
      <body>

      <!-- Selection Category -->
      <b>Välj Uteblivande</b>

      <select id="category" class="options">
      <option value="AA">All</option>
      <option value="1U">1 Unit</option>
      </select>

      <!-- Selection New dataset -->
      <span style="margin-left:30px;">
      <b>Choose Year</b>

      <select id="year" class="options">
      <option value="2017">2017</option>
      <option value="2016">2016</option>
      </select>
      </span>

      <!-- Chart -->
      <div id="chart"></div>

      <script>

      var durations = 0,
      formatValue = d3.format(".2s"),
      formatPercent = d3.format(",.0f");

      var teamColor = d3.scaleOrdinal()
      .range(["steelblue","darkorange", "lightblue"]);

      var dispatch = d3.dispatch("load", "update");

      var files = ["data1.csv", "data2.csv"];

      Promise.all(files.map(url => d3.csv(url))).then(function(dataSet)

      // === Load all data ===

      var data1 = dataSet[0];
      var data2 = dataSet[1];

      dispatch.call("load", this);

      // === Update data ===

      update();

      function update()

      var input = d3.select('#category')
      .property('value');

      var data = d3.select('#year')
      .property('value') == '2017' ? data1 : data2;

      data.forEach(function(d, i, columns)
      for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
      ttl += d[columns[i]] = +d[columns[i]];
      d.total = ttl;
      d.sliceTotal = d3.sum([
      d["Team 1 " + input],
      d["Team 2 " + input],
      d["Team 3 " + input]
      ]);
      return d;
      )

      dispatch.call("update", this, data, input);



      // === Event handler ===

      d3.selectAll(".options").on("change", function()
      durations = 750;
      update();
      )

      );

      dispatch.on("load.occupation", function()

      let margin = top: 35, right: 45, bottom: 35, left: 45,
      width = 540 - margin.left - margin.right,
      height = 420 - margin.top - margin.bottom;

      let g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform","translate(" + margin.left + "," + margin.top + ")");

      let x0 = d3.scaleBand()
      .rangeRound([0, width])
      .paddingInner(0.1)
      .padding(0.1);

      let x1 = d3.scaleBand();

      let y = d3.scaleLinear()
      .rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x0),
      yAxis = d3.axisLeft(y).ticks(null, "s");
      yGrid = d3.axisLeft(y).tickSize(-width);

      g.append("g")
      .attr("class","axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      g.append("g")
      .attr("class", "axis grid--y");

      dispatch.on("update.occupation", function(dataInit, input)

      var keys = dataInit.columns.slice(1, 4);

      let copy = ;

      keys.forEach(function(t)
      t = t.slice(0, -2)
      copy.push(t)
      )

      var data = dataInit.filter(function(d)
      return d.State !== "ALL"
      )

      let sumOfTeam = d3.sum(data, d=> d3.sum(keys, key=> d[key]));

      y.domain([0, d3.max(data, function(d)
      return d3.max(keys, function(key)
      return d.sliceTotal;
      );
      )
      ]).nice();

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);
      g.selectAll(".axis.grid--y").transition()
      .duration(durations)
      .call(yGrid);

      // bars
      let barGroups = g.selectAll("g.layer").data(data);
      barGroups.enter().append("g")
      .classed('layer', true);

      barGroups.exit().remove();

      // bars
      let barGroups2 = g.selectAll("g.layer2").data(data);
      barGroups2.enter().append("g")
      .classed('layer2', true);

      barGroups2.exit().remove();

      // xDomains
      x0.domain(data.map(function(d) return d.State; ));
      x1.domain(keys).rangeRound([0, x0.bandwidth()]);

      // Update axis
      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      g.selectAll("g.layer").transition().duration(durations)
      .attr("transform", function(d, i)
      return "translate(" + x0(d.State) + ",0)";
      );

      let bars = g.selectAll("g.layer").selectAll(".bars")
      .data(function(d)
      return copy.map(function(key) // Return copy
      return key: key+input, value: d[key+input] ; // Add input
      );
      );

      bars = bars
      .enter()
      .append("rect")
      .attr("class", "bars")
      .attr("fill", function(d) return teamColor(d.key); )
      .attr("width", x1.bandwidth())
      .attr("x", function(d) return x1(d.key); )
      .merge(bars)

      bars.transition().duration(durations)
      .attr("y", function(d) return y(d["value"]); )
      .attr("height", function(d) return height - y(d["value"]); );

      bars.exit().remove();

      g.selectAll("g.layer2").transition().duration(durations)
      .attr("transform", function(d, i)
      return "translate(" + x0(d.State) + ",0)";
      );

      let barsTotal = g.selectAll(".test")
      .data(data, function(d)
      return d.State;
      );

      barsTotal = barsTotal
      .enter()
      .append("rect")
      .attr("fill", "none")
      .attr("stroke","#999")
      .attr("stroke-width","1px")
      .attr("class","test")
      .attr("width", x0.bandwidth())
      .merge(barsTotal);

      barsTotal.transition().duration(durations)
      .attr("x", function(d)
      return x0(d.State);
      )
      .attr("y", function(d)
      return y(d.sliceTotal);
      )
      .attr("height", function(d)
      return height - y(d.sliceTotal);
      );

      barsTotal.exit().remove();

      );

      );

      dispatch.on("load.all", function()

      let margin = top: 35, right: 45, bottom: 35, left: 45,
      width = 150 - margin.left - margin.right,
      height = 420 - margin.top - margin.bottom;

      let g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform","translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleBand()
      .rangeRound([0, width])
      .paddingInner(0.1)
      .padding(0.1);

      var y = d3.scaleLinear()
      .rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x),
      yAxis = d3.axisLeft(y)
      .ticks(null, "s");

      g.append("g")
      .attr("class","axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      dispatch.on("update.all", function(dataInit, input)

      var keys = dataInit.columns.slice(1, 4);

      var copy =

      keys.forEach(function(s)
      s = s.slice(0, -2)
      copy.push(s)
      )

      let combined = ;

      copy.forEach(function(t)
      t = t + input
      combined.push(t)
      )

      var data = dataInit.filter(function(d)
      return d.State == "ALL"
      )

      y.domain([0, d3.max(data, function(d)
      return d3.sum(copy, function(key)
      return d[key + input];
      );
      )
      ]).nice();

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      teamColor.domain(combined);

      x.domain(data.map(function(d) return d.State; ));

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var stacking = d3.stack().keys(combined)(data)

      let barGroups = g.selectAll("g.layer")
      .data(stacking,function(d)
      return d.key.split(' ')[0] + d.key.split(' ')[1]
      );

      barGroups
      .enter()
      .append("g")
      .classed('layer', true);

      barGroups.exit().remove();

      g.selectAll("g.layer").transition().duration(durations)
      .attr("fill", function(d) return teamColor(d.key); );

      let bars = g.selectAll("g.layer").selectAll("rect")
      .data(function(d) return d; , d => d.data.State);

      bars = bars
      .enter()
      .append("rect")
      .attr("width", x.bandwidth())
      .merge(bars);

      bars.transition().duration(durations)
      .attr("x", function(d) return x(d.data.State); )
      .attr("y", function(d) return y(d[1]); )
      .attr("height", function(d) return y(d[0]) - y(d[1]); );

      );

      );

      </script>
      </body>








      share|improve this question










      share|improve this question




      share|improve this question









      asked Apr 7 at 14:03









      Robert Andersson

      1667




      1667




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          While you can do it using d3.dispatch, as you just found out, it doesn't seem to be a good practice:



          1. It's not necessary, you can do the same using regular functions (see below). The main reason why it is not needed is that, despite the fact that you have two events, load and update, you just need one, since you already have the necessary enter, update and exit selections, and their proper transitions.


          2. It's not idiomatic and adds needless complications to your code. Because it's not idiomatic, it will make harder to other D3 programmers trying to understand/maintain your code in the future.


          3. It creates a lot of duplications (in my solution below I saved you 100 lines of code, going from 379 to 279 lines).


          That being said, my proposed solution is: use regular functions.



          So, in your code, I put all the drawing parts inside a draw function...



          function draw(data, input) {


          ... which is called by the update:



          function update() 

          var input = d3.select('#category')
          .property('value');

          var data = d3.select('#year')
          .property('value') == '2017' ? data1 : data2;

          data.forEach(function(d, i, columns)
          for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
          ttl += d[columns[i]] = +d[columns[i]];
          d.total = ttl;
          d.sliceTotal = d3.sum([
          d["Team 1 " + input],
          d["Team 2 " + input],
          d["Team 3 " + input]
          ]);
          return d;
          )

          draw(data, input)



          After that, I removed all the parts that don't change and that you need to paint just once from draw, like the SVG and the axes selections.



          Last but not least, good on you for using the brand new D3 v5 and Promise.all!



          Here is the updated Plunker: https://plnkr.co/edit/t17PoC4dl2aSOhn2Dxz6?p=preview






          share|improve this answer























          • Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
            – Robert Andersson
            Apr 8 at 8:49










          • In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
            – Gerardo Furtado
            Apr 8 at 8:52











          • You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
            – Robert Andersson
            Apr 8 at 14:21










          • Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
            – Gerardo Furtado
            Apr 8 at 16:05







          • 1




            This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
            – Robert Andersson
            Apr 8 at 18:47










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191476%2fusing-dispatch-events-in-d3-js%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted










          While you can do it using d3.dispatch, as you just found out, it doesn't seem to be a good practice:



          1. It's not necessary, you can do the same using regular functions (see below). The main reason why it is not needed is that, despite the fact that you have two events, load and update, you just need one, since you already have the necessary enter, update and exit selections, and their proper transitions.


          2. It's not idiomatic and adds needless complications to your code. Because it's not idiomatic, it will make harder to other D3 programmers trying to understand/maintain your code in the future.


          3. It creates a lot of duplications (in my solution below I saved you 100 lines of code, going from 379 to 279 lines).


          That being said, my proposed solution is: use regular functions.



          So, in your code, I put all the drawing parts inside a draw function...



          function draw(data, input) {


          ... which is called by the update:



          function update() 

          var input = d3.select('#category')
          .property('value');

          var data = d3.select('#year')
          .property('value') == '2017' ? data1 : data2;

          data.forEach(function(d, i, columns)
          for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
          ttl += d[columns[i]] = +d[columns[i]];
          d.total = ttl;
          d.sliceTotal = d3.sum([
          d["Team 1 " + input],
          d["Team 2 " + input],
          d["Team 3 " + input]
          ]);
          return d;
          )

          draw(data, input)



          After that, I removed all the parts that don't change and that you need to paint just once from draw, like the SVG and the axes selections.



          Last but not least, good on you for using the brand new D3 v5 and Promise.all!



          Here is the updated Plunker: https://plnkr.co/edit/t17PoC4dl2aSOhn2Dxz6?p=preview






          share|improve this answer























          • Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
            – Robert Andersson
            Apr 8 at 8:49










          • In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
            – Gerardo Furtado
            Apr 8 at 8:52











          • You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
            – Robert Andersson
            Apr 8 at 14:21










          • Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
            – Gerardo Furtado
            Apr 8 at 16:05







          • 1




            This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
            – Robert Andersson
            Apr 8 at 18:47














          up vote
          1
          down vote



          accepted










          While you can do it using d3.dispatch, as you just found out, it doesn't seem to be a good practice:



          1. It's not necessary, you can do the same using regular functions (see below). The main reason why it is not needed is that, despite the fact that you have two events, load and update, you just need one, since you already have the necessary enter, update and exit selections, and their proper transitions.


          2. It's not idiomatic and adds needless complications to your code. Because it's not idiomatic, it will make harder to other D3 programmers trying to understand/maintain your code in the future.


          3. It creates a lot of duplications (in my solution below I saved you 100 lines of code, going from 379 to 279 lines).


          That being said, my proposed solution is: use regular functions.



          So, in your code, I put all the drawing parts inside a draw function...



          function draw(data, input) {


          ... which is called by the update:



          function update() 

          var input = d3.select('#category')
          .property('value');

          var data = d3.select('#year')
          .property('value') == '2017' ? data1 : data2;

          data.forEach(function(d, i, columns)
          for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
          ttl += d[columns[i]] = +d[columns[i]];
          d.total = ttl;
          d.sliceTotal = d3.sum([
          d["Team 1 " + input],
          d["Team 2 " + input],
          d["Team 3 " + input]
          ]);
          return d;
          )

          draw(data, input)



          After that, I removed all the parts that don't change and that you need to paint just once from draw, like the SVG and the axes selections.



          Last but not least, good on you for using the brand new D3 v5 and Promise.all!



          Here is the updated Plunker: https://plnkr.co/edit/t17PoC4dl2aSOhn2Dxz6?p=preview






          share|improve this answer























          • Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
            – Robert Andersson
            Apr 8 at 8:49










          • In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
            – Gerardo Furtado
            Apr 8 at 8:52











          • You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
            – Robert Andersson
            Apr 8 at 14:21










          • Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
            – Gerardo Furtado
            Apr 8 at 16:05







          • 1




            This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
            – Robert Andersson
            Apr 8 at 18:47












          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          While you can do it using d3.dispatch, as you just found out, it doesn't seem to be a good practice:



          1. It's not necessary, you can do the same using regular functions (see below). The main reason why it is not needed is that, despite the fact that you have two events, load and update, you just need one, since you already have the necessary enter, update and exit selections, and their proper transitions.


          2. It's not idiomatic and adds needless complications to your code. Because it's not idiomatic, it will make harder to other D3 programmers trying to understand/maintain your code in the future.


          3. It creates a lot of duplications (in my solution below I saved you 100 lines of code, going from 379 to 279 lines).


          That being said, my proposed solution is: use regular functions.



          So, in your code, I put all the drawing parts inside a draw function...



          function draw(data, input) {


          ... which is called by the update:



          function update() 

          var input = d3.select('#category')
          .property('value');

          var data = d3.select('#year')
          .property('value') == '2017' ? data1 : data2;

          data.forEach(function(d, i, columns)
          for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
          ttl += d[columns[i]] = +d[columns[i]];
          d.total = ttl;
          d.sliceTotal = d3.sum([
          d["Team 1 " + input],
          d["Team 2 " + input],
          d["Team 3 " + input]
          ]);
          return d;
          )

          draw(data, input)



          After that, I removed all the parts that don't change and that you need to paint just once from draw, like the SVG and the axes selections.



          Last but not least, good on you for using the brand new D3 v5 and Promise.all!



          Here is the updated Plunker: https://plnkr.co/edit/t17PoC4dl2aSOhn2Dxz6?p=preview






          share|improve this answer















          While you can do it using d3.dispatch, as you just found out, it doesn't seem to be a good practice:



          1. It's not necessary, you can do the same using regular functions (see below). The main reason why it is not needed is that, despite the fact that you have two events, load and update, you just need one, since you already have the necessary enter, update and exit selections, and their proper transitions.


          2. It's not idiomatic and adds needless complications to your code. Because it's not idiomatic, it will make harder to other D3 programmers trying to understand/maintain your code in the future.


          3. It creates a lot of duplications (in my solution below I saved you 100 lines of code, going from 379 to 279 lines).


          That being said, my proposed solution is: use regular functions.



          So, in your code, I put all the drawing parts inside a draw function...



          function draw(data, input) {


          ... which is called by the update:



          function update() 

          var input = d3.select('#category')
          .property('value');

          var data = d3.select('#year')
          .property('value') == '2017' ? data1 : data2;

          data.forEach(function(d, i, columns)
          for (var i = 1, ttl = 0, n = columns.length; i < n; ++i)
          ttl += d[columns[i]] = +d[columns[i]];
          d.total = ttl;
          d.sliceTotal = d3.sum([
          d["Team 1 " + input],
          d["Team 2 " + input],
          d["Team 3 " + input]
          ]);
          return d;
          )

          draw(data, input)



          After that, I removed all the parts that don't change and that you need to paint just once from draw, like the SVG and the axes selections.



          Last but not least, good on you for using the brand new D3 v5 and Promise.all!



          Here is the updated Plunker: https://plnkr.co/edit/t17PoC4dl2aSOhn2Dxz6?p=preview







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Apr 8 at 8:33


























          answered Apr 8 at 1:30









          Gerardo Furtado

          1,1342420




          1,1342420











          • Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
            – Robert Andersson
            Apr 8 at 8:49










          • In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
            – Gerardo Furtado
            Apr 8 at 8:52











          • You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
            – Robert Andersson
            Apr 8 at 14:21










          • Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
            – Gerardo Furtado
            Apr 8 at 16:05







          • 1




            This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
            – Robert Andersson
            Apr 8 at 18:47
















          • Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
            – Robert Andersson
            Apr 8 at 8:49










          • In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
            – Gerardo Furtado
            Apr 8 at 8:52











          • You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
            – Robert Andersson
            Apr 8 at 14:21










          • Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
            – Gerardo Furtado
            Apr 8 at 16:05







          • 1




            This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
            – Robert Andersson
            Apr 8 at 18:47















          Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
          – Robert Andersson
          Apr 8 at 8:49




          Thanks a lot! Although I like your solution, the reason I had my code setup like that (having margin, width etc not being global) is so that if I wanted to add another chart I wouldn't have to worry as much about naming variables, that might be a bad reason though.
          – Robert Andersson
          Apr 8 at 8:49












          In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
          – Gerardo Furtado
          Apr 8 at 8:52





          In that case nest two functions, and outer drawn and an inner update or whatever name you want. So the variables are confined inside draw.
          – Gerardo Furtado
          Apr 8 at 8:52













          You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
          – Robert Andersson
          Apr 8 at 14:21




          You don't happen to have an example of this? Because I tried doing it with functions at first but was unable to call the nested function from my event handler without also calling the function surrounding the update function
          – Robert Andersson
          Apr 8 at 14:21












          Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
          – Gerardo Furtado
          Apr 8 at 16:05





          Well, it's complicated to say something without seeing the real code and what you plan to do. You can always post a new question when you have a more complete version of it.
          – Gerardo Furtado
          Apr 8 at 16:05





          1




          1




          This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
          – Robert Andersson
          Apr 8 at 18:47




          This is what I meant, found a solution Plunker seems like everything works as intended, thanks for your help
          – Robert Andersson
          Apr 8 at 18:47












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191476%2fusing-dispatch-events-in-d3-js%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods