I have several files into a directory and i use wamp server, is there a way to iterate over them, in a way i can call this function d3.csv("data.csv", function(error, data) { for each file?
little snippet:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.point {
stroke: #000;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var z = d3.scale.category10();
var svg = d3.select("body").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 + ")");
d3.csv("data.csv", function(error, data) {
if (error) throw error;
// Compute the series names ("y1", "y2", etc.) from the loaded CSV.
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x"; })
.sort();
// Map the data to an array of arrays of {x, y} tuples.
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +d.x, y: +d[series]};
});
});
// Compute the scales’ domains.
x.domain(d3.extent(d3.merge(series), function(d) { return d.x; })).nice();
y.domain(d3.extent(d3.merge(series), function(d) { return d.y; })).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.style("fill", function(d, i) { return z(i); })
.selectAll(".point")
.data(function(d) { return d; })
.enter().append("circle")
.attr("class", "point")
.attr("r", 4.5)
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); });
});
</script>
thanks in advance
Assuming this code is running in a browser, and assuming you're talking about a user's directory (i.e. client side), there is no way to iterate directly over a directory listing. You can, however, use a multiple file input and allow the user to select all files in a directory. The syntax for that would be similar to this: <input type="file" name="svg" multiple>.
Then given a reference to the input element, elem.files will give you a list of objects representing the files.
For more information, see how to select multiple files for upload.
Related
I have tried putting in the D3 js codes and styling and have added the dataset as shown in the picture below. However, the bar chart don't show in Power BI.The dataset type I am using is a text file (.txt)
These are the D3 js for the bar chart.
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = pbi.width - margin.left - margin.right, // ALTER: Changed fixed width with the 'pbi.width' variable
height = pbi.height - margin.top - margin.bottom; // ALTER: Changed fixed height with the 'pbi.height' variable
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.1, 0.2);
var y = d3.scale.linear()
.range([height, 0]);
var svg = d3.select("#chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// ALTER: Replaced the d3.tsv function with the pbi variant: pbi.dsv
pbi.dsv(type, function(letters) {
x.domain(letters.map(function(d) { return d.letter; }));
y.domain([0, d3.max(letters, function(d) { return d.frequency; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
svg.selectAll(".bar")
.data(letters)
.enter()
.append("rect")
.style("fill", pbi.colors[0]) // First color of provided color array
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
});
function type(d) {
d.frequency = +d.frequency;
return d;
}
These are the CSS for the bar chart.
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
I have tried to use the above D3 js and CSS codes, however, I don't know why does the bar chart not appear in Power BI.
Hello I am trying to build a multi-line chart that displays rates for each month year over year. I am getting a "TypeError: t is undefined" error in the console and while I can see the x and y axis populated, no lines are appearing in the chart. Any help appreciated!
The HTML file code is here:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
var y = d3.scale.linear().range([height, 0]);
var color = d3.scale.ordinal().range(["#666666", "#262626", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
var line = d3.svg.line().interpolate("basis").x(function(d) { return x(d.date); }).y(function(d) { return y(d.value); });
var svg = d3.select("body").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 + ")");
d3.json("yoy_values.json", function(error, data) {
if (error) throw error;
var myValues = d3.keys(data[0]).filter(function(key) { return key !== "date"; });
data.forEach(function(d) {
d.rates = myValues.map(function(name) { return {name: name, value: +d[name]}; });
console.log(d.rates);
});
x.domain(data.map(function(d) { return d.date; }));
y.domain([
d3.min(data, function(d) { return d3.min(d.rates, function(d) { return d.value; }); }),
d3.max(data, function(d) { return d3.max(d.rates, function(d) { return d.value; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Rates");
var state = svg.selectAll(".state")
.data(myValues.slice().reverse())
.enter().append("g")
.attr("class", "state")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
state.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.rates); })
.style("stroke", function(d) { return color(d.name); });
state.append("text")
.datum(function(d) { return {name: d.name, value: d.rates[d.rates.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value) + "," + y(d.name) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
</script>
The JSON file I am reading looks like this:
[
{"date":"Jan","2014":"0.0812","2015":"0.0780","2016":"0.0838"},
{"date":"Feb","2014":"0.0806","2015":"0.0768","2016":"0.0893"},
{"date":"Mar","2014":"0.0858","2015":"0.0847","2016":null},
{"date":"Apr","2014":"0.0848","2015":"0.0889","2016":null},
{"date":"May","2014":"0.0890","2015":"0.0890","2016":null},
{"date":"Jun","2014":"0.0928","2015":"0.0865","2016":null},
{"date":"Jul","2014":"0.0857","2015":"0.0799","2016":null},
{"date":"Aug","2014":"0.0905","2015":"0.0845","2016":null},
{"date":"Sep","2014":"0.1003","2015":"0.0934","2016":null},
{"date":"Oct","2014":"0.0971","2015":"0.0993","2016":null},
{"date":"Nov","2014":"0.0912","2015":"0.0973","2016":null},
{"date":"Dec","2014":"0.0800","2015":"0.0777","2016":null}
]
It's hard to tell from just code eyeballing, but I noticed:
You make a series of .rates properties from the non-"date" json data, so .rates for the first datum would be [{name:"2014", value:"0.0812"},{name:"2015", value:"0.0780"},{name:"2016", value:"0.0838"}]
d.rates = myValues.map(function(name) { return {name: name, value: +d[name]}; });
You then pass these to a d3.svg.line function
.attr("d", function(d) { return line(d.rates); })
But this line function has been previously set up to seemingly expect .date and .value properties not .name and .value
var line = d3.svg.line().interpolate("basis").x(function(d) { return x(d.date); }).y(function(d) { return y(d.value); });
And the scale x has been set up to expect .date (the month strings) as arguments, because they were set as the domain
x.domain(data.map(function(d) { return d.date; }));
In short, it seems the x scale and line function are expecting data objects categorised by month to draw one line per year, but you're passing in the .rates objects which are organised by year in the expectation of drawing one line per month?
I'm using on d3.js, and it's working fine.But i'm not figuring out why the scatter serie is not displayed.
this is my code:
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 70},
width = 1000 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%H-%M-%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Adds the plot
var svg = d3.select("body")
.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 + ")");
lineSerie();
scatterSerie();
function lineSerie(){
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
d3.csv("timeSeries.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".60em")
.style("text-anchor", "end")
.text("CPU RunQueue");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
}
function scatterSerie(){
d3.csv("scatterSerie.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); });
});
}
</script>
</body>
line serie:
date,close
05-17-14-Oct-14,223233.06250
05-18-14-Oct-14,223233.06250
05-19-14-Oct-14,223233.06250
05-20-14-Oct-14,223233.06250
05-21-14-Oct-14,223233.06250
05-22-14-Oct-14,223233.06250
05-23-14-Oct-14,223233.06250
05-24-14-Oct-14,223233.06250
05-25-14-Oct-14,223233.06250
line serie
date,close
10-27-02-Oct-14,223233.06250
10-28-02-Oct-14,223233.06250
10-29-02-Oct-14,223233.06250
10-30-02-Oct-14,223233.06250
10-31-02-Oct-14,223233.06250
10-32-02-Oct-14,223233.06250
10-33-02-Oct-14,223233.06250
10-34-02-Oct-14,223233.06250
10-35-02-Oct-14,223233.06250
10-36-02-Oct-14,223233.06250
10-37-02-Oct-14,223233.06250
10-38-02-Oct-14,223233.06250
the line serie is displayed, but the scatter serie is not being displayed.
Can someone tell me what's wrong?
thanks in advance.
In your scatterSerie() function, your select statement doesn't add up.
There's no such thing as a 'dot' element. You'll want to select all elements with class 'dot' like so (think jQuery):
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr('class','dot')
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); });
Don't forget to set that 'dot' class to your newly added elements, otherwise your future updates might go south.
One other thing you might wanna look into is the style of your circles. Right now they have no defined stroke color, stroke-width or fill. You can add those as CSS rules or add them within your d3 code.
I'm using code similar to this one, and actually plugged in this code to see if I get the same error and I do. This is the code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px Arial;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: start;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 40, bottom: 70, left: 50},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxisLeft = d3.svg.axis().scale(y0)
.orient("left").ticks(5);
var yAxisRight = d3.svg.axis().scale(y1)
.orient("right").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y0(d.close); });
var valueline2 = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y1(d.open); });
var svg = d3.select("body")
.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 data = [
{"date":"9-Apr-12","close":436,"open":9.04},
{"date":"7-Apr-12","close":221,"open":4.02},
{"date":"5-Apr-12","close":113,"open":9.02},
{"date":"4-Apr-12","close":64,"open":32.05},
{"date":"3-Apr-12","close":29,"open":46.03},
{"date":"2-Apr-12","close":18,"open":51.03}
];
// Get the data
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
d.open = +d.open;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y0.domain([0, d3.max(data, function(d) {
return Math.max(d.close); })]);
y1.domain([0, d3.max(data, function(d) {
return Math.max(d.open); })]);
svg.append("path")
.attr("class", "line")
.attr("id", "blueLine")
.attr("d", valueline(data));
svg.append("path")
.attr("class", "line")
.style("stroke", "red")
.attr("id", "redLine")
.attr("d", valueline2(data));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// edit the Y Axis Left
svg.append("g")
.attr("class", "y axis")
.style("fill", "steelblue")
.attr("id", "blueAxis")
.call(yAxisLeft);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + " ,0)")
.style("fill", "red")
.attr("id", "redAxis")
.call(yAxisRight);
// Add the blue line title
svg.append("text")
.attr("x", 0)
.attr("y", height + margin.top + 10)
.attr("class", "legend")
.style("fill", "steelblue")
.on("click", function(){
// Determine if current line is visible
var active = blueLine.active ? false : true,
newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.select("#blueLine").style("opacity", newOpacity);
d3.select("#blueAxis").style("opacity", newOpacity);
// Update whether or not the elements are active
blueLine.active = active;
})
.text("Blue Line");
// Add the red line title
svg.append("text")
.attr("x", 0)
.attr("y", height + margin.top + 30)
.attr("class", "legend")
.style("fill", "red")
.on("click", function(){
// Determine if current line is visible
var active = redLine.active ? false : true ,
newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.select("#redLine").style("opacity", newOpacity);
d3.select("#redAxis").style("opacity", newOpacity);
// Update whether or not the elements are active
redLine.active = active;
})
.text("Red Line");
</script>
</body>
I'm getting errors saying that 'blueline' and 'redline' are not defined.
Where do I define those?
I've looked at similar code where the html, css, and js are separated into their own files which is how I've done it also, and other than what I see in the code above I don't find those variables used anyplace else or defined beyond what is there.
I made a plunk with the code you have there and everything works just fine. Let me explain a little of what is going on though.
Instead of using HTML that is already there, D3 will often generate its own (in fact it has to generate its own to do the visualizations). You see this with statements like the following:
svg.append("path")
.attr("class", "line")
.attr("id", "blueLine")
.attr("d", valueline(data));
D3 just created a path element and appended it to the svg element it created earlier. It gives this particular element an id of blueLine which it uses later to apply styles. It did not exist in any HTML prior to this script running. D3 created it.
I am very new to D3, and wanted to see how an example would work locally. I copied and pasted the bar graph code to a local file called index.html, and also copied over the data.tsv. For some reason, absolutely nothing is showing up when I open the file on a browser! I tried changing the script src to "d3/d3.v3.min.js" because that is the folder the d3 I downloaded is in. However, this does not work either. For every example I have tried I have yet to successfully view a D3 example. Help would be appreciated!
The index.html code is as follows:
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="d3/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
var svg = d3.select("body").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 + ")");
d3.tsv("data.tsv", type, function(error, data) {
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
});
function type(d) {
d.frequency = +d.frequency;
return d;
}
</script>
and the data.tsv is in the following format:
letter frequency
A .08167
B .01492
C .02780
D .04253
E .12702
F .02288
G .02022
H .06094
I .06973
The d3.tsv method makes an AJAX request for data. On most browsers, this won't work locally due to the Same Origin Policy, which generally prohibits AJAX requests to file:/// urls.
To get an example that uses AJAX running locally, you'll need a local webserver. If you have Python, running
> python -m SimpleHTTPServer
from the command line in the directory with your files will do it.
and if you are using python 3
> python -m http.server 9000
If you prefer node.js, try http-server.
As an alternative, and I was myself suggested by Lars Kotthoff when trying to work with .tsv/.csv files, you can work directly for this purpose on:
http://plnkr.co/
This enables you to work with all the .json / .tsv / .csv files you like, and share them with people for collaboration. You can do this anonymously or not, what matters is that you don't lose the then-generated HTTP address of your plunker.
One thing to pay attention to: you cannot upload directly the files in the way you would do on an FTP server, but you should instead:
Click on "new file"
Type the name of your .csv / .tsv / .json
file as referred to in your code (including the extension)
Copy
and paste the code contained in this file as is.
Don't forget
to update the names of your .css / .js if required so the match with
that of your index.html
As already stated, you're most likely encountering a CORS issue with the XHR in the d3 library for an external resource to parse the JSON data.
However, here is another solution: use JSONP and Express/Node.js in conjunction with a jQuery function to initiate a client-side request for JSON, instead of using the original wrapper for d3 functions.
Had to remove the original d3.json wrapper and populate the adjacency diagrams with data from the request. Begin by cloning or downloading jsonp-d3-experiment and start the server using node server.js. Of course you need to have Node.js installed globally, beginning with Node Packaged Modules (npm). Copy your program into a subdirectory.
Put your JSON data in the jsonp-d3-experiment directory and modify server.js to route the request to your data:
// Return data from callback
server.get('/example', function(req, res)
{
// Read the JSON data and send to JSONP response
readJSON('example.json', function (e, json)
{
if (e) { throw e; }
res.jsonp(json);
});
});
Below is the code I modified for a co-occurrence matrix. I moved the entire script into $.getJSON and removed the d3.json function altogether.
<script>
$.getJSON("http://localhost:8080/example?callback=?", function(result){
miserables = result;
var margin = {
top: 80,
right: 0,
bottom: 10,
left: 80
},
width = 720,
height = 720;
var x = d3.scale.ordinal().rangeBands([0, width]),
z = d3.scale.linear().domain([0, 4]).clamp(true),
c = d3.scale.category10().domain(d3.range(10));
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var matrix = [],
nodes = miserables.nodes,
n = nodes.length;
// Compute index per node.
nodes.forEach(function(node, i) {
node.index = i;
node.count = 0;
matrix[i] = d3.range(n).map(function(j) {
return {
x: j,
y: i,
z: 0
};
});
});
// Convert links to matrix; count character occurrences.
miserables.links.forEach(function(link) {
matrix[link.source][link.target].z += link.value;
matrix[link.target][link.source].z += link.value;
matrix[link.source][link.source].z += link.value;
matrix[link.target][link.target].z += link.value;
nodes[link.source].count += link.value;
nodes[link.target].count += link.value;
});
// Precompute the orders.
var orders = {
name: d3.range(n).sort(function(a, b) {
return d3.ascending(nodes[a].name, nodes[b].name);
}),
count: d3.range(n).sort(function(a, b) {
return nodes[b].count - nodes[a].count;
}),
group: d3.range(n).sort(function(a, b) {
return nodes[b].group - nodes[a].group;
})
};
// The default sort order.
x.domain(orders.name);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
var row = svg.selectAll(".row")
.data(matrix)
.enter().append("g")
.attr("class", "row")
.attr("transform", function(d, i) {
return "translate(0," + x(i) + ")";
})
.each(row);
row.append("line")
.attr("x2", width);
row.append("text")
.attr("x", -6)
.attr("y", x.rangeBand() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "end")
.text(function(d, i) {
return nodes[i].name;
});
var column = svg.selectAll(".column")
.data(matrix)
.enter().append("g")
.attr("class", "column")
.attr("transform", function(d, i) {
return "translate(" + x(i) + ")rotate(-90)";
});
column.append("line")
.attr("x1", -width);
column.append("text")
.attr("x", 6)
.attr("y", x.rangeBand() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "start")
.text(function(d, i) {
return nodes[i].name;
});
function row(row) {
var cell = d3.select(this).selectAll(".cell")
.data(row.filter(function(d) {
return d.z;
}))
.enter().append("rect")
.attr("class", "cell")
.attr("x", function(d) {
return x(d.x);
})
.attr("width", x.rangeBand())
.attr("height", x.rangeBand())
.style("fill-opacity", function(d) {
return z(d.z);
})
.style("fill", function(d) {
return nodes[d.x].group == nodes[d.y].group ? c(nodes[d.x].group) : null;
})
.on("mouseover", mouseover)
.on("mouseout", mouseout);
}
function mouseover(p) {
d3.selectAll(".row text").classed("active", function(d, i) {
return i == p.y;
});
d3.selectAll(".column text").classed("active", function(d, i) {
return i == p.x;
});
}
function mouseout() {
d3.selectAll("text").classed("active", false);
}
d3.select("#order").on("change", function() {
clearTimeout(timeout);
order(this.value);
});
function order(value) {
x.domain(orders[value]);
var t = svg.transition().duration(2500);
t.selectAll(".row")
.delay(function(d, i) {
return x(i) * 4;
})
.attr("transform", function(d, i) {
return "translate(0," + x(i) + ")";
})
.selectAll(".cell")
.delay(function(d) {
return x(d.x) * 4;
})
.attr("x", function(d) {
return x(d.x);
});
t.selectAll(".column")
.delay(function(d, i) {
return x(i) * 4;
})
.attr("transform", function(d, i) {
return "translate(" + x(i) + ")rotate(-90)";
});
}
var timeout = setTimeout(function() {
order("group");
d3.select("#order").property("selectedIndex", 2).node().focus();
}, 5000);
});
</script>
Notice that now the JSON data is in result, so the easiest thing to do was to assign it to miserables.
Note: jQuery is required for this solution.
Now you should be able to locally open and render all your d3 visualizations without hosting them on a server--simply open them in your browser straight from your local filesystem.
HTH!