averageSalaryMap = (us) => {
const svg = d3.create("svg")
.attr("width", chloroplethMapWidth)
.attr("height", chloroplethMapHeight)
.attr("viewBox", [0, 0, 2400, chloroplethMapHeight]);
const averageTeacherSalaryFileType = "Average Teacher Salary By State in ";
const str = averageTeacherSalaryFileType + averageSalaryYearFilter;
const infoWindowText = svg.append("text")
.attr("x", 15)
.attr("y", 15)
.attr("transform", "translate(985,110)")
.attr("font-size", 18)
let rank;
let topFiveStates;
let bottomFiveStates;
let notableTeacherStrikesText = "";
let notableTeacherStrikesTextPart2 = "";
let notableTeacherStrikesTextPart3 = "";
let notableTeacherStrikesFacts = "";
let notableTeacherStrikesFactsPart2 = "";
let notableTeacherStrikesFactsPart3 = "";
let notableTeacherStrikesFactsPart4 = "";
let notableTeacherStrikesFactsPart5 = "";
let notableTeacherStrikesFactsPart6 = "";
let notableTeacherStrikesFactsPart7 = "";
if (str === averageTeacherSalaryFileType + "2010") {
rank = avgTeacherSalaryRank2010.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2010.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.reverse()
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2010.entries())
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([state, rank]) => state)
notableTeacherStrikesText = "Arizona, California, Michigan, Pennsylvania";
} else if (str === averageTeacherSalaryFileType + "2011") {
rank = avgTeacherSalaryRank2011.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2011.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2011.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "California, Chicago, New York, Wisconsin";
notableTeacherStrikesFacts = "Wisconsin's Act 10 on Collective Bargaining.";
} else if (str === averageTeacherSalaryFileType + "2012") {
rank = avgTeacherSalaryRank2012.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2012.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2012.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Chicago, Idaho";
notableTeacherStrikesFacts = "- Chicago's 600+ school closure during strikes.";
notableTeacherStrikesFactsPart2 = "- Wisconsin's Recall Governor Elections & Unions.";
notableTeacherStrikesFactsPart3 = "- Michigan's Right to Work (24th state to pass law).";
} else if (str === averageTeacherSalaryFileType + "2013") {
rank = avgTeacherSalaryRank2013.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2013.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2013.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Michigan, Pennsylvania, Washington";
notableTeacherStrikesFacts = "- Chicago's closure of 49 schools in low-income,";
notableTeacherStrikesFactsPart2 = "minority neighborhoods.";
} else if (str === averageTeacherSalaryFileType + "2014") {
rank = avgTeacherSalaryRank2014.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2014.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2014.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Chicago, Oregon, Washington, West Virginia";
notableTeacherStrikesFacts = "- Seattle's 50+ school closure during strikes.";
notableTeacherStrikesFactsPart2 = "- Chicago's 600+ school closure during strikes.";
} else if (str === averageTeacherSalaryFileType + "2015") {
rank = avgTeacherSalaryRank2015.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2015.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2015.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Chicago, Minnesota, Oklahoma, Washington";
} else if (str === averageTeacherSalaryFileType + "2016") {
rank = avgTeacherSalaryRank2016.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2016.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2016.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Massachusetts";
notableTeacherStrikesFacts = "- Supreme Court Friedrichs v. California Teachers";
notableTeacherStrikesFactsPart2 = "Association Case on Union Fees.";
notableTeacherStrikesFactsPart3 = "- Presidential Election & Education Policies.";
notableTeacherStrikesFactsPart4 = "- New Secretary of Education.";
} else if (str === averageTeacherSalaryFileType + "2017") {
rank = avgTeacherSalaryRank2017.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2017.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2017.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Arizona, Colorado, Kansas, Kentucky";
notableTeacherStrikesTextPart2 = "Massachusetts, Michigan, North Carolina,";
notableTeacherStrikesTextPart3 = "Oklahoma, Washington, West Virginia";
} else if (str === averageTeacherSalaryFileType + "2018") {
rank = avgTeacherSalaryRank2018.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2018.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2018.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Arizona, Colorado, Kentucky, North Carolina,";
notableTeacherStrikesTextPart2 = "Oklahoma, West Virginia";
notableTeacherStrikesFacts = "- Arizona: State approves 20% pay raise by 2020";
notableTeacherStrikesFactsPart2 = "(not in effect until following year)."
notableTeacherStrikesFactsPart3 = "- Michigan's 80+ school closure during strikes.";
notableTeacherStrikesFactsPart4 = "- Oklahoma: Approved $6,000 pay raise"
notableTeacherStrikesFactsPart5 = "(not in effect until following year).";
notableTeacherStrikesFactsPart6 = "- West Virginia: Approved 5% pay increase";
notableTeacherStrikesFactsPart7 = "(not in effect until following year).";
} else if (str === averageTeacherSalaryFileType + "2019") {
rank = avgTeacherSalaryRank2019.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2019.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2019.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "California, Colorado, Kentucky, West Virginia";
} else if (str === averageTeacherSalaryFileType + "2020") {
rank = avgTeacherSalaryRank2020.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2020.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2020.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "Arizona, California, Chicago, Colorado, Nevada";
notableTeacherStrikesFacts = "COVID-Related Strikes."
} else if (str === averageTeacherSalaryFileType + "2021") {
rank = avgTeacherSalaryRank2021.get(name);
bottomFiveStates = Array.from(avgTeacherSalaryRank2021.entries())
.sort((a, b) => d3.descending(a[1], b[1]))
.slice(0, 5)
.map(([state, rank]) => state);
topFiveStates = Array.from(avgTeacherSalaryRank2021.entries())
.filter(([key, value]) => value > 0)
.sort((a, b) => a[1] - b[1])
.slice(0, 5)
.map(([key, value]) => key)
notableTeacherStrikesText = "California, Chicago, Minnesota, Oregon, Virginia";
notableTeacherStrikesFacts = "COVID-Related Strikes."
}
infoWindowText.text(name)
.append("tspan")
.attr("x", 0)
.attr("y", 0)
.attr("dy", "1.2em")
.text("TOP 5 STATES");
topFiveStates.forEach((state, index) => {
infoWindowText.append("tspan")
.attr("x", 0)
.attr("dy", "1.2em")
.text(`${index + 1}. ${state}`);
})
infoWindowText.append("tspan")
.attr("x",200)
.attr("y", 0)
.attr("dy", "1.2em")
.text("BOTTOM 5 STATES");
bottomFiveStates.forEach((state, index) => {
infoWindowText.append("tspan")
.attr("x", 200)
.attr("dy", "1.2em")
.text(`${index + 46}. ${state}`);
});
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 180)
.attr("dy", "1.3em")
.text("NOTABLE TEACHER STRIKES");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "2.3em")
.text("States with Most Notable States:");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "3.3em")
.text(notableTeacherStrikesText);
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "4.3em")
.text(notableTeacherStrikesTextPart2 ? notableTeacherStrikesTextPart2 : "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "5.3em")
.text(notableTeacherStrikesTextPart3 ? notableTeacherStrikesTextPart3: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "7.3em")
.text("Comments:");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "8.3em")
.text(notableTeacherStrikesFacts ? notableTeacherStrikesFacts: "N/A");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "9.3em")
.text(notableTeacherStrikesFactsPart2 ? notableTeacherStrikesFactsPart2: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "10.3em")
.text(notableTeacherStrikesFactsPart3 ? notableTeacherStrikesFactsPart3: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "11.3em")
.text(notableTeacherStrikesFactsPart4 ? notableTeacherStrikesFactsPart4: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "12.3em")
.text(notableTeacherStrikesFactsPart5 ? notableTeacherStrikesFactsPart5: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "13.3em")
.text(notableTeacherStrikesFactsPart6 ? notableTeacherStrikesFactsPart6: "");
infoWindowText.append("tspan")
.attr("x", 0)
.attr("y", 200)
.attr("dy", "14.3em")
.text(notableTeacherStrikesFactsPart7 ? notableTeacherStrikesFactsPart7: "");
// Chloropleth Map Colors
let color;
// const salaryLegend = [40000, 50000, 60000, 70000];
// color = d3.scaleThreshold()
// .domain(salaryLegend)
// .range(d3.schemeBlues[4]);
// const salaryLegend = [30000, 40000, 50000, 60000, 70000, 80000];
// color = d3.scaleThreshold()
// .domain(salaryLegend)
// .range(d3.schemeGnBu[6]);
const salaryLegend = [40000, 50000, 60000, 70000, 80000];
// const salaryLegend = [30000, 40000, 50000, 60000, 70000];
color = d3.scaleLinear()
.domain(salaryLegend)
.range(d3.schemeBlues[5]);
// Add Color Schema Legend
svg.append("g")
.attr("transform", "translate(1003,30)")
.append(function(d) {
return legend({color, title: `Average Teacher Salary in dollars($)`, width: 350});
})
// Map Title
svg.append("text")
.attr("x", width / 4)
.attr("y", 0)
.attr("text-anchor", "start")
.style("font-size", "30px")
.style("font-weight", "bold")
.text(str);
// Baseline Map of Nations
svg.append("path")
.datum(nations)
.attr("fill", "black")
.attr("stroke", "none")
.attr("d", path);
// Baseline Map of States
svg.append("path")
.datum(states)
.attr("fill", "none")
.attr("stroke", "none")
.attr("d", path);
// SVG Show or Hide State Information
svg.append("g")
.selectAll("path")
.data(states.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", function (d) {
if (str === averageTeacherSalaryFileType + "2010") {
return color(avgTeacherSalary2010.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2011") {
return color(avgTeacherSalary2011.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2012") {
return color(avgTeacherSalary2012.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2013") {
return color(avgTeacherSalary2013.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2014") {
return color(avgTeacherSalary2014.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2015") {
return color(avgTeacherSalary2015.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2016") {
return color(avgTeacherSalary2016.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2017") {
return color(avgTeacherSalary2017.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2018") {
return color(avgTeacherSalary2018.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2019") {
return color(avgTeacherSalary2019.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2020") {
return color(avgTeacherSalary2020.get(d.properties.name));
} else if (str === averageTeacherSalaryFileType + "2021") {
return color(avgTeacherSalary2021.get(d.properties.name));
}
})
.attr("stroke", "white")
.on("mouseover", (event, d) => {
const [x, y] = d3.pointer(event);
const padding = 5;
const lengthOfStateName = d.properties.name.length * 10
const name = d.properties.name;
d3.select(event.currentTarget)
.attr("stroke", "black")
.raise();
let salary;
let rank;
let state_pop;
let num_teachers;
// Color Density Based on Average Teacher Salary Per State Per Year
if (str === averageTeacherSalaryFileType + "2010") {
salary = avgTeacherSalary2010.get(name);
rank = avgTeacherSalaryRank2010.get(name);
state_pop = statePopulation2010.get(name);
num_teachers = fteTeachers2010.get(name);
} else if (str === averageTeacherSalaryFileType + "2011") {
salary = avgTeacherSalary2011.get(name);
rank = avgTeacherSalaryRank2011.get(name);
state_pop = statePopulation2011.get(name);
num_teachers = fteTeachers2011.get(name);
} else if (str === averageTeacherSalaryFileType + "2012") {
salary = avgTeacherSalary2012.get(name);
rank = avgTeacherSalaryRank2012.get(name);
state_pop = statePopulation2012.get(name);
num_teachers = fteTeachers2012.get(name);
} else if (str === averageTeacherSalaryFileType + "2013") {
salary = avgTeacherSalary2013.get(name);
rank = avgTeacherSalaryRank2013.get(name);
state_pop = statePopulation2013.get(name);
num_teachers = fteTeachers2013.get(name);
} else if (str === averageTeacherSalaryFileType + "2014") {
salary = avgTeacherSalary2014.get(name);
rank = avgTeacherSalaryRank2014.get(name);
state_pop = statePopulation2014.get(name);
num_teachers = fteTeachers2014.get(name);
} else if (str === averageTeacherSalaryFileType + "2015") {
salary = avgTeacherSalary2015.get(name);
rank = avgTeacherSalaryRank2015.get(name);
state_pop = statePopulation2015.get(name);
num_teachers = fteTeachers2015.get(name);
} else if (str === averageTeacherSalaryFileType + "2016") {
salary = avgTeacherSalary2016.get(name);
rank = avgTeacherSalaryRank2016.get(name);
state_pop = statePopulation2016.get(name);
num_teachers = fteTeachers2016.get(name);
} else if (str === averageTeacherSalaryFileType + "2017") {
salary = avgTeacherSalary2017.get(name);
rank = avgTeacherSalaryRank2017.get(name);
state_pop = statePopulation2017.get(name);
num_teachers = fteTeachers2017.get(name);
} else if (str === averageTeacherSalaryFileType + "2018") {
salary = avgTeacherSalary2018.get(name);
rank = avgTeacherSalaryRank2018.get(name);
state_pop = statePopulation2018.get(name);
num_teachers = fteTeachers2018.get(name);
} else if (str === averageTeacherSalaryFileType + "2019") {
salary = avgTeacherSalary2019.get(name);
rank = avgTeacherSalaryRank2019.get(name);
state_pop = statePopulation2019.get(name);
num_teachers = fteTeachers2019.get(name);
} else if (str === averageTeacherSalaryFileType + "2020") {
salary = avgTeacherSalary2020.get(name);
rank = avgTeacherSalaryRank2020.get(name);
state_pop = statePopulation2020.get(name);
num_teachers = fteTeachers2020.get(name);
} else if (str === averageTeacherSalaryFileType + "2021") {
salary = avgTeacherSalary2021.get(name);
rank = avgTeacherSalaryRank2021.get(name);
state_pop = statePopulation2021.get(name);
num_teachers = fteTeachers2021.get(name);
}
tooltip.select("text")
.text(null)
.append("tspan")
.text(name)
.attr("font-size", "25px")
.append("tspan")
.attr("dy", "1.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(num_teachers ? `# FTE Teachers: ${commaSeparated(num_teachers)} teachers` : "")
.append("tspan")
.attr("dy", "2.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(state_pop ? `State Population: ${commaSeparated(state_pop)} people` : "")
.append("tspan")
.attr("dy", "4.4em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(salary ? `Average Teacher Salary: $${commaSeparated(salary)}` : "No 2010 Average Teacher Salary Available")
.append("tspan")
.attr("dy", "5.5em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(rank ? `Average Teacher Salary Rank: ${rank}` : "")
const textLength = tooltip.select('text').node().getComputedTextLength();
tooltip.select("rect")
.attr("width", textLength / 3)
.attr("height", 150)
.attr("x")
tooltip.attr("transform", `translate(${x},${y})`);
tooltip.style("display", "block");
})
.on("mouseout", (event, d) => {
tooltip.style("display", "none")
d3.select(event.currentTarget)
.attr("stroke", "white")
.lower();
});
// Right Side Info Window
const infoWindow = svg
.append("rect")
.attr("transform", "translate(970,100)")
.attr("width", 420)
.attr("height", 500)
.attr("fill", "none")
.attr("stroke", "black")
.raise();
// Tooltip
const rect = svg
.append("rect")
.attr("id", "tooltip-box")
.attr("height", 100)
const stateName = svg.append("text")
.attr("y", 20)
.attr("stroke", "black")
.attr("alignment-baseline", "middle");
const tooltip = svg
.append("g")
.attr("class", "tooltip")
.style("display", "none");
tooltip.append("rect")
.attr("width", 100)
.attr("height", 80)
.attr("fill", "white")
.attr("stroke", "black")
tooltip.append("text")
.attr("y", 25)
.attr("x", 20)
.attr("text-anchor", "start")
.text("");
return svg.node();
}