0

I am new to d3.js and I am trying to reproduce the example B is for breaking links in this tutorial.

As you can see in the jsfiddle of this example, the data is read from a <script type="application/json" id="mis"> tag, but what I want is to read it from a different file.

I used the d3.json() function as suggested in this Force-Layout example, but when I added the threshold slider which is supposed to break my links, nothing happens.

When I ran the console, it gave me the following error :

Uncaught TypeError: Cannot read property 'splice' of 
undefined
threshold @ index.html:82
onchange @ index.html:101

This is my code :

output.json

The file output.json is in this link.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}

h3 {
    color: #1ABC9C;
    text-align:center;  
    font-style: italic;
    font-size: 14px;
    font-family: "Helvetica";
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var width = 960,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var graph = d3.json("output.json", function(error, graph) {
  if (error) throw error;

  graphRec=JSON.parse(JSON.stringify(graph));

  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  node.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});

//adjust threshold
function threshold(thresh) {
    graph.links.splice(0, graph.links.length);
        for (var i = 0; i < graphRec.links.length; i++) {
            if (graphRec.links[i].value > thresh) {graph.links.push(graphRec.links[i]);}
        }
    restart();
}
//Restart the visualisation after any node and link changes
function restart() {
    link = link.data(graph.links);
    link.exit().remove();
    link.enter().insert("line", ".node").attr("class", "link");
    node = node.data(graph.nodes);
    node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag);
    force.start();
}

</script>

<form>
    <h3> Link threshold 0 <input type="range" id="thersholdSlider" name="points" value = 0 min="0" max="10" onchange="threshold(this.value)"> 10 </h3>
</form>

What did I do wrong ? And how can I fix it ?

Thanks!

12
  • try logging graph see what that gives you Commented Feb 3, 2016 at 10:09
  • whats ur output.json can you paste that too Commented Feb 3, 2016 at 10:09
  • @Cyril I just updated the post with a link to the output.json file. I tried to paste it to the post but it is too big. Commented Feb 3, 2016 at 10:20
  • @thisOneGuy can you tell me how can I do that? loging graph? Commented Feb 3, 2016 at 10:22
  • console.log(graph) just before you use it , in your threshold function ( where i take it the error gets thrown) Commented Feb 3, 2016 at 10:29

1 Answer 1

2

I could not find any bugs in your code. The only problem I could find is that the variable name graph used twice.

var graph = d3.json("output.json", function(error, graph) {
---------------------
---------------------
});

Edit: Try this code.

var graphRec, node, link;
d3.json("output.json", function(error, graph) {
   if (error) throw error;
   graph = JSON.parse(JSON.stringify(graph));

   force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

   graphRec = graph;

   link = svg.selectAll(".link")
      .data(graph.links)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

   node = svg.selectAll(".node")
      .data(graph.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

   ------------------------
   ------------------------
});

//adjust threshold
function threshold(thresh) {
    graphRec.links.splice(0, graphRec.links.length);
        for (var i = 0; i < graphRec.links.length; i++) {
            if (graphRec.links[i].value > thresh) {graphRec.links.push(graphRec.links[i]);}
        }
    restart();
}
//Restart the visualisation after any node and link changes
function restart() {
    link = link.data(graphRec.links);
    link.exit().remove();
    link.enter().insert("line", ".node").attr("class", "link");
    node = node.data(graphRec.nodes);
    node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag);
    force.start();
}

Working Code Snippet.

var width = 960,
  height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
  .charge(-120)
  .linkDistance(30)
  .size([width, height]);

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);
   
var graph = {"nodes":[{"name":"DOU,_H.","group":1},{"name":"QUONIAM","group":1},{"name":"DA_SILV","group":1},{"name":"GUIMARA","group":1},{"name":"SOARES_","group":0}],"links":[{"source":1,"target":0,"value":19,"oriented":false,"date":null},{"source":1,"target":2,"value":2,"oriented":false,"date":null},{"source":1,"target":3,"value":1,"oriented":false,"date":null},{"source":1,"target":4,"value":1,"oriented":false,"date":null},{"source":1,"target":3,"value":2,"oriented":false,"date":null}]};

  graph = JSON.parse(JSON.stringify(graph));

  force
    .nodes(graph.nodes)
    .links(graph.links)
    .start();

  graphRec = graph;

  var link = svg.selectAll(".link")
    .data(graph.links)
    .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function(d) {
      return Math.sqrt(d.value);
    });

  var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", 5)
    .style("fill", function(d) {
      return color(d.group);
    })
    .call(force.drag);

  node.append("title")
    .text(function(d) {
      return d.name;
    });

  force.on("tick", function() {
    link.attr("x1", function(d) {
        return d.source.x;
      })
      .attr("y1", function(d) {
        return d.source.y;
      })
      .attr("x2", function(d) {
        return d.target.x;
      })
      .attr("y2", function(d) {
        return d.target.y;
      });

    node.attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      });
  
});

//adjust threshold
function threshold(thresh) {
    graph.links.splice(0, graph.links.length);
    for (var i = 0; i < graphRec.links.length; i++) {
      if (graphRec.links[i].value > thresh) {
        graph.links.push(graphRec.links[i]);
      }
    }
    restart();
  }
  //Restart the visualisation after any node and link changes

function restart() {
  link = link.data(graph.links);
  link.exit().remove();
  link.enter().insert("line", ".node").attr("class", "link");
  node = node.data(graph.nodes);
  node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag);
  force.start();
}
.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.link {
  stroke: #999;
  stroke-opacity: .6;
}

h3 {
    color: #1ABC9C;
    text-align:center;  
    font-style: italic;
    font-size: 14px;
    font-family: "Helvetica";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<form>
    <h3> Link threshold 0 <input type="range" id="thersholdSlider" name="points" value = 0 min="0" max="10" onchange="threshold(this.value)"> 10 </h3>
</form>

Sign up to request clarification or add additional context in comments.

10 Comments

When I remove var graph = it gives me the error Uncaught ReferenceError: graph is not defined
Declare a new variable and assign graph to that variable inside d3.json callback function. Use the new variable inside threshold and restart functions.
Since you have a global variable called graphRec with the data, you can also use it instead of graph inside the threshold and restart functions.
It gives another error Uncaught ReferenceError: link is not defined in the functions restart and threshold
This is also because of the variable scope problem. Declare link and node variable outside of d3.json function. Just update the variable value inside the function. (The line link = link.data(graphRec.links);, in restart function causes this issue. Since link is out of scope of this function.)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.