简体   繁体   中英

D3: call() not working for appended text element (Type error)

I´m trying to create a table in a svg graphic using D3 and jquery. Therefore i append three text elements to ag element and than call a function to fill each of the text elements with several tspan elements. The values for the tspan elements are coming from a json array.

Now when i load my page, only the first text element is filled with values and displayed normally. After that i get an error, saying:

TypeError: callback is undefined

So basically the function seems to work and i cannot figure out what´s the problem with the next two text elements. What am i overseeing here? I have to do it this way and cannot use something like foreignobject because it is not supported by internet explorer.

Here is my code:

var data = [
      {"month": "Jan", "tmp": 30, "pre": 50},
      {"month": "Feb", "tmp": 25, "pre": 50},
      {"month": "Mar", "tmp": 20, "pre": 50},
      {"month": "Apr", "tmp": 16, "pre": 100},
      {"month": "May", "tmp": 16, "pre": 200},
      {"month": "Jun", "tmp": 16, "pre": 200},
      {"month": "Jul", "tmp": 16, "pre": 300},
      {"month": "Aug", "tmp": 16, "pre": 201},
      {"month": "Sep", "tmp": 18, "pre": 100},
      {"month": "Oct", "tmp": 20, "pre": 60},
      {"month": "Nov", "tmp": 25, "pre": 50},
      {"month": "Dec", "tmp": 32, "pre": 30},
]

function fillColumn (column) {
    var col = chart.select("#" +column);

    col.append('tspan')
        .text("" +column);

    for (i = 0; i < 12; i++){
        var obj = data[i];

        $.each(obj, function(j, val) {
            if (j === column){
             col.append('tspan')
                .attr('x', table_x)
                .attr('y', table_y + (table_height/13)*(i+1))
                .text(val);
            }
        });
    }
}

chart.append('g')
    .attr('id', "table")
    .attr('x', table_x)
    .attr('y', table_y)
    .attr('width', table_width)
    .attr('height', table_height)
    .append('text')
    .attr('id', "month")
    .attr('x', table_x)
    .attr('y', table_y)
    .attr('text-anchor', 'middle')
    .call(fillColumn("month"));

chart.select('#table')
    .append('text')
    .attr('id', "tmp")
    .attr('x', table_x + table_width/3)
    .attr('y', table_y)
    .attr('text-anchor', 'middle')
    .call(fillColumn("tmp"));

chart.select('#table')
    .append('text')
    .attr('id', "pre")
    .attr('x', table_x + table_width*2/3)
    .attr('y', table_y)
    .attr('text-anchor', 'middle')
    .call(fillColumn("pre"));

The first argument to .call is a function -- you are calling a function and then passing the return to .call .

What you need is:

.call(fillColumn, "month");

And your fillColumn definition becomes:

function fillColumn(col, column) {

  col.append('tspan')
    .text("" + column);

Notice I don't seen to re-select anything since the first argument to fillColumn will be text selection you called call on.


As an aside, you don't really need jquery here, basic JavaScript would suffice:

for (key in obj){
    if (key === column){
      col.append('tspan')
        .attr('x', table_x)
        .attr('y', table_y + (table_height / 13) * (i + 1))
        .text(obj[key]);
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM