1

I'm trying to apply this suggestion to catch the end of several transitions. But in my local file I get a Uncaught TypeError: t.call is not a function error. The code is as follows:

    var svg = d3.select('svg');

  function endall(transition, callback) { 
    if (typeof callback !== "function") throw new Error("Wrong callback in endall");
    if (transition.size() === 0) { callback() }
    var n = 0; 
    transition 
        .each(function() { ++n; }) 
        .each("end", function() { if (!--n) callback.apply(this, arguments); }); 
  } 


for (var i=0;i<5;i++) {

    svg.append('rect')
            .attr("x",i*60)
      .attr("y",50)
      .attr("height",50)
      .attr("width",50)
      .style("fill","#ff0000");
}

    svg.selectAll("rect:not(.active)")
      .transition()
      .duration(1000)
      .style("fill","#00ff00")
      .call(endall, function() { alert("all done") });

When I port it on jsfiddle using a D3 template, it works well. On the other hand, when I port it on jsfiddle without a D3 template, I get the same error.

Evidently I'm missing something, but I'm not able to understand what.

tic
  • 4,009
  • 15
  • 45
  • 86

1 Answers1

2

The fiddle that doesn't produce the error runs on v3, while the one that does runs on v5.

In d3v3, you could use transition.each("end",...) for events:

transition.each([type, ]listener)

If type is specified, adds a listener for transition events, supporting "start", "end" and "interrupt" events. The listener will be invoked for each individual element in the transition. (v3 docs)

In d3v4 and v5, this method was replaced with transition.on("end",...) for events:

selection.on(typenames[, listener[, options]]) <>

Adds or removes a listener to each selected element for the specified event typenames. (current docs)

transition.each(function) can still be used to perform an action on each item being transitioned, but can't be used for event listening. Because of this change between versions you get an error that is t.call is not a function (it's a string: "end"), and the alert never triggers.

For d3v4 or d3v5, instead use:

transition 
    .each(function() { ++n; }) 
    .on("end", function() { if (!--n) callback.apply(this, arguments); }); 

Updated fiddle.

Andrew Reid
  • 37,021
  • 7
  • 64
  • 83
  • Major versions are quite important with javascript libraries, and apparently jsfiddle doesn't keep massively up-to-date with them (was about to post a much less in-depth answer similar to yours, bravo on beating me by at least 3 minutes :) ) – Thymine Sep 07 '18 at 23:21