My goal is to create a webpage that presents a data-driven legend, and radio buttons. I would like the user's selection of radio buttons to change the legend.
The complicating factor is that the legend relies on a nesting function, and I can't figure out how to make the "key" of the nesting function responsive to the radio buttons.
Here's are the steps I've taken so far:
- Create the legend (nest data, then attach nest keys to rectangles).
- On the click of the radio button, make d3 select all the rectangles in the DOM.
- Send the radio button's selection to a function called
updateKey
, which contains the nest variable. Substitute thed.key
portion of nest with the radio button selection. - Change the fill attribute of the rectangle to
color(d.key)
.
My problem is that nest variable doesn't seem to change within the updateKey
function, even though my research on global variables indicates that it should change.
Code here:
var doc = URL.createObjectURL(new Blob([`Passed Category Owner Dup
yes msg Hailey yes
yes msg Hailey yes
yes doc Hailey yes
yes doc Robert yes
yes msg Laquila yes
no spreadsheet Hailey yes
`]));
d3.tsv(doc)
.row(function(d) {
return {
Passed: d.Passed,
Category: d.Category,
Owner: d.Owner,
Dup: d.Dup
};
})
.get(function(error, data) {
var svg = d3.select("#chart").append("svg")
.append("g");
//create a function for applying colours
var cat20 = d3.schemeCategory20
var colors = d3.scaleOrdinal()
.domain(function(d) {
return nest(d.key);
})
.range(cat20);
//pick one column of data and nest according to that column
nest = d3.nest()
.key(function(d) {
return d.Category
})
.sortKeys(d3.descending)
.entries(data)
var legend = d3.select("#legend")
//Make the legend
.append("svg")
.attr("class", "legend")
.selectAll("g")
.data(d3.range(20))
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * 25 + ")";
});
//make the legend squares
legend.append("rect")
.data(nest)
.attr("class", "rect")
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d) {
return colors(d.key)
})
.style('stroke', "Grey");
//make the legend text
legend.append("text")
.data(nest)
.attr("x", 24)
.attr("y", 9)
.attr("dy", ".35em")
.text(function(d) {
return d.key;
});
function updateKey(h) {
var nest = d3.nest()
.key(function(d) {
return (h)
})
.sortKeys(d3.descending)
.entries(data)
}
d3.selectAll(("input[name='stack']")).on("change", function(d) {
var colVar = this.value;
if (colVar == 'Category') {
d3.selectAll(".rect").style("fill", function(d) {
updateKey("d['" + colVar + "']")
return colors(d.key)
})
}
})
})
UPDATE: I have confirmed that the function is retrieving a new nest variable, because when I input console.log(nest)
in the last block of code, it returns the correct key-value object. However, if I add console log(d.key)
immediately below console.log(nest)
, it returns the keys of the nest variable that was set at the beginning of the code. This suggests that d.key
is somehow not changing, even though nest is changing. I think I need to set d.key explicitly.
UPDATE 2: My new strategy is to create all the legends, then use the buttons to appear/disappear legends based on class.