L = {
const L = await require("leaflet/dist/leaflet.js");
if (!L._style) {
const href = await require.resolve("leaflet/dist/leaflet.css");
document.head.appendChild(L._style = html`<link href=${href} rel=stylesheet>`);
}
return L;
};
data = transpose(raw_data);
class_data = transpose(raw_class_data);
map_data = transpose(raw_map_data);
summary_data = transpose(raw_sum_data);
class_sum = transpose(sum_class_data);
year_counts = transpose(year_count_data);
affiliations = transpose(raw_affiliations);
org_type = transpose(raw_org_type);
assets = transpose(raw_assets);
income = transpose(raw_income);
finances = transpose(raw_finances);
filterOptions = [...new Set(data.map(d => d.NTEE_Core_Description))];
filteredData = {
if (selectedGroup === "" || selectedGroup === "all") {
return data;
} else {
return data.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredAffiliations = {
if (selectedGroup === "" || selectedGroup === "all") {
return affiliations;
} else {
return affiliations.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredOrgType = {
if (selectedGroup === "" || selectedGroup === "all") {
return org_type;
} else {
return org_type.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredAssets = {
if (selectedGroup === "" || selectedGroup === "all") {
return assets;
} else {
return assets.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredIncome = {
if (selectedGroup === "" || selectedGroup === "all") {
return income;
} else {
return income.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredFinances = {
if (selectedGroup === "" || selectedGroup === "all") {
return finances;
} else {
return finances.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredClassData = {
if (selectedGroup === "" || selectedGroup === "all") {
return class_data;
} else {
return class_data.filter(d => d.NTEE_Core_Description === selectedGroup);
}
}
filteredYearCounts = {
if (selectedGroup === "" || selectedGroup == "all"){
return year_counts
//.filter(d => d.Ruling_Year >= 1900)
.filter(d => d.Ruling_Year < 2025);
} else {
return year_counts
.filter(d => d.NTEE_Core_Description === selectedGroup)
//.filter(d => d.Ruling_Year >= 1900)
.filter(d => d.Ruling_Year < 2025);
}
}
viewof selectedGroup = html`<select id="ntee-select">
<option value="All">All</option>
${filterOptions.map(option => `<option value="${option}">${option}</option>`)}
</select>
`
html`
<em style = "font-size: 20px;">Choose an NTEE activity from the dropdown menu to filter results by that activity.</em>
`
container = {
let x = d3.create("div")
x.attr("style", `width:100%;height:${window.outerHeight * 0.69}px`);
return x.node();
};
map = L.map(container, {zoomSnap: 0.25});
tilelayer = L.tileLayer('https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological Survey</a>', maxZoom: 20
}).addTo(map);
markerLayerGroup = L.layerGroup().addTo(map);
markerIcon = L.icon({
iconUrl: `https://raw.githubusercontent.com/primer/octicons/ede8e1acef3c7c036799af286f1ee2d755f04225/icons/info-24.svg`,
iconSize: [31, 46],
popupAnchor: [0, -10]
});
//setTimeout(() => {
reactiveMapUpdate = {
markerLayerGroup.clearLayers();
const filteredLocations = selectedGroup === "" || selectedGroup === "All"
? map_data
: map_data.filter(d => d.NTEE_Core_Description === selectedGroup);
const defaultMarker = L.icon({
iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
iconAnchor: [12, 41],
shadowAnchor: [4, 62],
popupAnchor: [-3, -76]
});
filteredLocations.forEach(location => {
L.marker([location.lat, location.long], {icon: defaultMarker})
.bindTooltip(`<b>${location.NAME}</b><br>In Care of: ${location.ICO}<br>NTEE Code: ${location.NTEE_Core_Description}<br><em>Full NTEE Description: ${location.NTEE_Full_Description}</em>`)
.addTo(markerLayerGroup); // Add markers to the layer group
});
map.setView([44.8582, -113.7420], 6.25);
setTimeout(() => {
L.marker([47.9, -109.9], {icon: markerIcon}).addTo(map)
.bindPopup('All data in this dashboard comes from<br>Idaho IRS 990 Extract Data')
.openPopup();
}, 50);
return undefined;
};
{
summary_data.sort((a,b) => b.Count - a.Count);
const initialWidth = 600; // Initial width for viewBox
const initialHeight = 500; // Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(summary_data, d => d.Count)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(summary_data.map(d => d.NTEE_Core_Description))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(summary_data)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Count); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.NTEE_Core_Description); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.NTEE_Core_Description); })
.attr("width", function(d) { return x(d.Count); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title")
.text("# of Nonprofits by Activity");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Activity: ${d.NTEE_Core_Description}<br>Count: ${d.Count}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
{
filteredData.sort((a,b) => b.Count - a.Count);
const columnValues = filteredData.map(d => d.NTEE_Full_Description);
const uniqueValues = [...new Set(columnValues)];
const uniqueCount = uniqueValues.length;
const initialWidth = 600; // Initial width for viewBox
const initialHeight = uniqueCount * 15;// Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(filteredData, d => d.Count)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(filteredData.map(d => d.NTEE_Full_Description))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(filteredData)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Count); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.NTEE_Full_Description); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.NTEE_Full_Description); })
.attr("width", function(d) { return x(d.Count); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title");
svg.selectAll(".chart-title")
.data([selectedGroup])
.join("text")
.text(d => d ? `Sub-activities among ${d} Nonprofits`: "All Categories");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Sub-Activity: ${d.NTEE_Full_Description}<br>Count: ${d.Count}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
{
summary_data.sort((a,b) => b.Perc_of_Assets - a.Perc_of_Assets);
const initialWidth = 600; // Initial width for viewBox
const initialHeight = 500; // Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(summary_data, d => d.Perc_of_Assets)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(summary_data.map(d => d.NTEE_Core_Description))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x)
.tickFormat(d3.format(".0%")));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(summary_data)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Perc_of_Assets); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.NTEE_Core_Description); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.NTEE_Core_Description); })
.attr("width", function(d) { return x(d.Perc_of_Assets); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title")
.text("% of Nonprofit Sector Assets by Activity");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
const formatter = d3.format(".1%");
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Activity: ${d.NTEE_Core_Description}<br>% of Assets: ${formatter(d.Perc_of_Assets)}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
{
filteredData.sort((a,b) => b.Core_Assets - a.Core_Assets)
.filter(d => d.Perc_of_Assets > 0.0);
const columnValues = filteredData.map(d => d.NTEE_Full_Description);
const uniqueValues = [...new Set(columnValues)];
const uniqueCount = uniqueValues.length;
const initialWidth = 600; // Initial width for viewBox
const initialHeight = uniqueCount * 15; // Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(filteredData, d => d.Core_Assets)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(filteredData.map(d => d.NTEE_Full_Description))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x)
.tickFormat(d3.format("$,.2s")));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(filteredData)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Core_Assets); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.NTEE_Full_Description); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.NTEE_Full_Description); })
.attr("width", function(d) { return x(d.Core_Assets); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title");
svg.selectAll(".chart-title")
.data([selectedGroup])
.join("text")
.text(d => d ? `Total Assets by Sub-Activity among ${d} Nonprofits`: "All Categories");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
const formatter = d3.format("$,.3s")
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Activity: ${d.NTEE_Full_Description}<br>Total Assets: ${formatter(d.Core_Assets)}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
{
const initialWidth = 600; // Initial width for viewBox
const initialHeight = 500; // Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(class_sum, d => d.Count)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(class_sum.map(d => d.Classification_Type))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(class_sum)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Count); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.Classification_Type); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.Classification_Type); })
.attr("width", function(d) { return x(d.Count); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title")
.text("Idaho Nonprofit Classifications");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Classification: ${d.Classification_Type}<br>Count: ${d.Count}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
{
const initialWidth = 600; // Initial width for viewBox
const initialHeight = 500; // Initial height for viewBox
const margin = {top: 25, right: 30, bottom: 40, left: 300};
//const width = 1000 - margin.left - margin.right;
//const height = 500 - margin.top - margin.bottom;
var svg = d3.create("svg")
.attr("viewBox", [0, 0, initialWidth, initialHeight]) // Set the viewBox
.attr("width", "100%") // Make it responsive width-wise
.attr("height", "100%"); // Make it responsive height-wise
//.attr("width", width + margin.left + margin.right)
//.attr("height", height + margin.top + margin.bottom);
var x = d3.scaleLinear()
.domain([0, d3.max(filteredClassData, d => d.Count)])
.range([0, initialWidth - margin.left - margin.right]);
var y = d3.scaleBand()
.range([0, initialHeight - margin.top - margin.bottom])
.domain(filteredClassData.map(d => d.Classification_Type))
.padding(0.1);
var plotGroup = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Corrected x-axis placement
plotGroup.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0,${initialHeight - margin.top - margin.bottom})`) // Place at the bottom
.call(d3.axisBottom(x));
plotGroup.append("g")
.attr("class", "yAxis")
.call(d3.axisLeft(y))
.selectAll("text")
.style("text-anchor", "end");
const bars = plotGroup.selectAll("rect")
.data(filteredClassData)
.join(
enter => enter.append("rect")
.attr("x", x(0)+1)
.attr("y", initialHeight)
.attr("width", function(d) { return x(d.Count); })
.attr("height", 0) // Corrected height calculation
.attr("fill", "#69B3A2")
.call(enter => enter.transition()
.duration(500)
.attr("y", function(d) { return y(d.Classification_Type); })
.attr("height", y.bandwidth())),
update => update
.call(update => update.transition()
.duration(500)
.attr("x", x(0)+1)
.attr("y", function(d) { return y(d.Classification_Type); })
.attr("width", function(d) { return x(d.Count); })
.attr("height", y.bandwidth())),
exit => exit
.call(exit => exit.transition()
.duration(500)
.attr("y", initialHeight)
.attr("height", 0)
.remove()) //left off here - some kind of error
);
svg.append("text")
.attr("x", margin.left)
.attr("y", margin.top - 7)
.attr("text-anchor", "middle")
.attr("class", "chart-title");
svg.selectAll(".chart-title")
.data([selectedGroup])
.join("text")
.text(d => d ? `Classifications of ${d} Nonprofits`: "All Categories");
let tooltip = d3.select("body").select(".tooltip");
if (tooltip.empty()) {
tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "10px")
.style("pointer-events", "none"); // To prevent blocking mouse events
}
bars.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`Classification: ${d.Classification_Type}<br>Count: ${d.Count}`) // Customize tooltip content
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mousemove", function(event) {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function() {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
return svg.node();
}
Plot.plot({
//title: "When organizations were ruled to be exempt...",
marginLeft: 65,
marginTop: 55,
marginBottom: 85,
marks: [
Plot.barY(
filteredYearCounts,
{
x: "Ruling_Year",
y: "count",
title: d=> `${d.count} nonprofits were ruled exempt in ${d.Ruling_Year}`
}),
Plot.text([`When organizations were first ruled to be exempt...`], {frameAnchor: "top-left", dy: -40, textAnchor: "start", fontWeight: "bold", fontSize: "20", fontFamily: "Gotham"})
] ,
x: {
label: "Year Ruled Exempt",
tickFormat: (d) => String(Number(d)),
tickRotate: -90
},
y: {
label: ""
}
})
Plot.plot({
marginLeft: 550,
marginTop: 55,
marginBottom: 100,
marks: [
Plot.barX(
filteredAffiliations,
{
x: "count",
y: "Affiliation_Coded",
title: d=> `${d.count} nonprofits are affiliated as ${d.Affiliation_Coded}`,
sort: {y: "x", reverse: true}
}),
Plot.text([`Affiliation Status`], {frameAnchor: "top-left", dy: -40, textAnchor: "start", fontWeight: "bold", fontSize: "24", fontFamily: "Gotham"})
] ,
x: {
label: "Number of Organizations",
//tickFormat: (d) => String(Number(d)),
tickRotate: -90
},
y: {
label: "Affiliation Category"
}
})
Plot.plot({
marginLeft: 220,
marginTop: 55,
marginBottom: 100,
marks: [
Plot.barX(
filteredOrgType,
{
x: "count",
y: "Organization_Coded",
title: d=> `${d.count} nonprofits are classified as ${d.Organization_Coded}`,
sort: {y: "x", reverse: true}
}),
Plot.text([`Organization Type`], {frameAnchor: "top-left", dy: -40, textAnchor: "start", fontWeight: "bold", fontSize: "24", fontFamily: "Gotham"})
] ,
x: {
label: "Number of Organizations",
tickRotate: -90
},
y: {
label: "Organization Type"
}
})
filteredAssets2 = {
if (selectedZero === "No") {
return filteredAssets;
} else {
return filteredAssets.filter(d => d.Assets_Coded != "$0");
}
}
filteredIncome2 = {
if (selectedZero === "No") {
return filteredIncome;
} else {
return filteredIncome.filter(d => d.Income_Coded != "$0");
}
}
filteredFinances2 = {
if (selectedZero === "No") {
return filteredFinances;
} else {
return filteredFinances.filter(d => d.Revenue_Coded != "$0");
}
}
{
const height = Math.min(width, 750);
const radius = Math.min(width, height) / 2;
const marginTop = 60;
const marginLeft = 40;
const minAngle = 0.15;
const arc = d3.arc()
.innerRadius(radius * 0.67)
.outerRadius(radius - 1);
const pie = d3.pie()
.padAngle(1 / radius)
.sort(null)
.value(d => d.count);
const color = d3.scaleOrdinal()
.domain(filteredAssets2.map(d => d.Assets_Coded))
.range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), filteredAssets2.length).reverse());
const svg = d3.create("svg")
//.attr("width", width)
.attr("height", height)
.attr("viewBox", [-radius - marginLeft, -radius - marginTop, 2 * radius + marginLeft + 40, 2 * radius + marginTop])
.attr("style", "max-width: 100%; height: auto;");
const tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid #ccc")
.style("padding", "8px")
.style("border-radius", "4px")
.style("font-size", "14px");
svg.append("g")
.selectAll()
.data(pie(filteredAssets2))
.join("path")
.attr("fill", d => color(d.data.Assets_Coded))
.attr("d", arc)
.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`${d.data.count.toLocaleString()} orgs have ${d.data.Assets_Coded} assets`)
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
d3.select(this)
.style("opacity", 0.8);
})
.on("mouseout", function(event, d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
d3.select(this)
.style("opacity", 1);
});
// .append("title")
// .text(d => `${d.data.count.toLocaleString()} orgs have ${d.data.Assets_Coded} assets`);
const textGroup = svg.append("g")
.attr("font-family", "Gotham")
.attr("font-size", 14)
.attr("text-anchor", "middle")
.selectAll()
.data(pie(filteredAssets2))
.join("g")
.attr("transform", d => {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const scaleFactor = 0.84;
const newX = x * scaleFactor;
const newY = y * scaleFactor;
return `translate(${newX},${newY})`;
})
.filter(d => (d.endAngle - d.startAngle) > minAngle)
.each(function(d) {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const angle = Math.atan2(y, x) * 180 / Math.PI;
const adjustedAngle = (angle > 90 || angle < -90) ? angle + 180 : angle;
d3.select(this)
.attr("transform", `${this.getAttribute("transform")} rotate(${adjustedAngle})`)
.attr("text-anchor", (d) => (x > 0) ? "start" : "end");
});
textGroup.append("text")
.attr("y", "-0.4em")
.attr("font-weight", "bold")
.text(d => d.data.Assets_Coded);
textGroup.append("text")
.attr("x", 0)
.attr("y", "0.7em")
.attr("fill-opacity", 1)
.text(d => `${d.data.count.toLocaleString()} orgs`);
svg.append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.style("font-family", "Gotham")
.style("font-size", "2em")
.style("font-weight", "bold")
.text("Assets");
return svg.node();
}
{
const height = Math.min(width, 750);
const radius = Math.min(width, height) / 2;
const marginTop = 60;
const marginLeft = 40;
const minAngle = 0.15;
const arc = d3.arc()
.innerRadius(radius * 0.67)
.outerRadius(radius - 1);
const pie = d3.pie()
.padAngle(1 / radius)
.sort(null)
.value(d => d.count);
const color = d3.scaleOrdinal()
.domain(filteredIncome2.map(d => d.Income_Coded))
.range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), filteredIncome2.length).reverse());
const svg = d3.create("svg")
//.attr("width", width)
.attr("height", height)
.attr("viewBox", [-radius - marginLeft, -radius - marginTop, 2 * radius + marginLeft + 40, 2 * radius + marginTop])
.attr("style", "max-width: 100%; height: auto;");
const tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid #ccc")
.style("padding", "8px")
.style("border-radius", "4px")
.style("font-size", "14px");
svg.append("g")
.selectAll()
.data(pie(filteredIncome2))
.join("path")
.attr("fill", d => color(d.data.Income_Coded))
.attr("d", arc)
.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`${d.data.count.toLocaleString()} orgs have ${d.data.Income_Coded} income`)
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
d3.select(this)
.style("opacity", 0.8);
})
.on("mouseout", function(event, d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
d3.select(this)
.style("opacity", 1);
});
// .append("title")
// .text(d => `${d.data.count.toLocaleString()} orgs have ${d.data.Assets_Coded} assets`);
const textGroup = svg.append("g")
.attr("font-family", "Gotham")
.attr("font-size", 14)
.attr("text-anchor", "middle")
.selectAll()
.data(pie(filteredIncome2))
.join("g")
.attr("transform", d => {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const scaleFactor = 0.84;
const newX = x * scaleFactor;
const newY = y * scaleFactor;
return `translate(${newX},${newY})`;
})
.filter(d => (d.endAngle - d.startAngle) > minAngle)
.each(function(d) {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const angle = Math.atan2(y, x) * 180 / Math.PI;
const adjustedAngle = (angle > 90 || angle < -90) ? angle + 180 : angle;
d3.select(this)
.attr("transform", `${this.getAttribute("transform")} rotate(${adjustedAngle})`)
.attr("text-anchor", (d) => (x > 0) ? "start" : "end");
});
textGroup.append("text")
.attr("y", "-0.4em")
.attr("font-weight", "bold")
.text(d => d.data.Income_Coded);
textGroup.append("text")
.attr("x", 0)
.attr("y", "0.7em")
.attr("fill-opacity", 1)
.text(d => `${d.data.count.toLocaleString()} orgs`);
svg.append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.style("font-family", "Gotham")
.style("font-size", "2em")
.style("font-weight", "bold")
.text("Income");
return svg.node();
}
{
const height = Math.min(width, 750);
const radius = Math.min(width, height) / 2;
const marginTop = 60;
const marginLeft = 40;
const minAngle = 0.15;
const chartTitle = "Revenue";
const arc = d3.arc()
.innerRadius(radius * 0.67)
.outerRadius(radius - 1);
const pie = d3.pie()
.padAngle(1 / radius)
.sort(null)
.value(d => d.count);
const color = d3.scaleOrdinal()
.domain(filteredFinances2.map(d => d.Revenue_Coded))
.range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0.1), filteredFinances2.length).reverse());
const svg = d3.create("svg")
// .attr("width", width)
.attr("height", height)
.attr("viewBox", [-radius - marginLeft, -radius - marginTop, 2 * radius + marginLeft + 40, 2 * radius + marginTop])
.attr("style", "max-width: 100%; height: auto;");
const tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute")
.style("background-color", "white")
.style("border", "1px solid #ccc")
.style("padding", "8px")
.style("border-radius", "4px")
.style("font-size", "14px");
svg.append("g")
.selectAll()
.data(pie(filteredFinances2))
.join("path")
.attr("fill", d => color(d.data.Revenue_Coded))
.attr("d", arc)
.on("mouseover", function(event, d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html(`${d.data.count.toLocaleString()} orgs have ${d.data.Revenue_Coded} revenue`)
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
d3.select(this)
.style("opacity", 0.8);
})
.on("mouseout", function(event, d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
d3.select(this)
.style("opacity", 1);
});
// .append("title")
// .text(d => `${d.data.count.toLocaleString()} orgs have ${d.data.Assets_Coded} assets`);
const textGroup = svg.append("g")
.attr("font-family", "Gotham")
.attr("font-size", 14)
.attr("text-anchor", "middle")
.selectAll()
.data(pie(filteredFinances2))
.join("g")
.attr("transform", d => {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const scaleFactor = 0.84;
const newX = x * scaleFactor;
const newY = y * scaleFactor;
return `translate(${newX},${newY})`;
})
.filter(d => (d.endAngle - d.startAngle) > minAngle)
.each(function(d) {
const centroid = arc.centroid(d);
const x = centroid[0];
const y = centroid[1];
const angle = Math.atan2(y, x) * 180 / Math.PI;
const adjustedAngle = (angle > 90 || angle < -90) ? angle + 180 : angle;
d3.select(this)
.attr("transform", `${this.getAttribute("transform")} rotate(${adjustedAngle})`)
.attr("text-anchor", (d) => (x > 0) ? "start" : "end");
});
textGroup.append("text")
.attr("y", "-0.4em")
.attr("font-weight", "bold")
.text(d => d.data.Revenue_Coded);
textGroup.append("text")
.attr("x", 0)
.attr("y", "0.7em")
.attr("fill-opacity", 1)
.text(d => `${d.data.count.toLocaleString()} orgs`);
svg.append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.style("font-family", "Gotham")
.style("font-size", "2em")
.style("font-weight", "bold")
.text(chartTitle);
return svg.node();
}