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.keyportion 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.