freeCodeCamp/api-server/public/js/calculator.js

273 lines
8.2 KiB
JavaScript

$(document).ready(function () {
var bootcamps = ''
$.getJSON('/json/bootcamps.json', function(data) {
bootcamps = data;
});
var city = "";
$("body").data("state", "stacked");
$('#city-buttons').on("click", "button", function () {
$(this).addClass('animated pulse');
city = $(this).attr("id");
$('#chosen').text('Coming from ' + city.replace(/-/g, ' ').replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}) + ', and making $_______, your true costs will be:');
setTimeout(function () {
$('#city-buttons').hide();
$('#income').addClass('animated fadeIn').show();
}, 1000);
});
$('#income').on("click", "button", function () {
$(this).addClass('animated pulse');
setTimeout(function () {
$('#income').hide();
$('#chart').addClass('animated fadeIn').show();
$('#chart-controls').addClass('animated fadeIn').show();
$('#explanation').addClass('animated fadeIn').show();
}, 1000);
var lastYearsIncome = parseInt($(this).attr("id"));
$('#chosen').text('Coming from ' + city.replace(/-/g, ' ').replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}) + ', and making $' + lastYearsIncome.toString().replace(/0000$/, '0,000') + ', your true costs will be:');
var categoryNames = ['Lost Wages', 'Financing Cost', 'Housing Cost', 'Tuition / Est. Wage Garnishing'];
bootcamps.forEach(function (camp) {
var x0 = 0;
if (camp.cities.indexOf(city) > -1) {
weeklyHousing = 0;
} else {
weeklyHousing = +camp.housing;
}
camp.mapping = [{
name: camp.name,
label: 'Tuition / Est. Wage Garnishing',
value: +camp.cost,
x0: x0,
x1: x0 += +camp.cost
}, {
name: camp.name,
label: 'Financing Cost',
value: +Math.floor(camp.cost * .09519),
x0: +camp.cost,
x1: camp.finance ? x0 += +Math.floor(camp.cost * .09519) : 0
}, {
name: camp.name,
label: 'Housing Cost',
value: +weeklyHousing * camp.weeks,
x0: camp.finance ? +Math.floor(camp.cost * 1.09519) : camp.cost,
x1: x0 += weeklyHousing * camp.weeks
}, {
name: camp.name,
label: 'Lost Wages',
value: +(Math.floor(camp.weeks * lastYearsIncome / 50)),
x0: camp.finance ? +(Math.floor(camp.cost * 1.09519) + weeklyHousing * camp.weeks) : +camp.cost + weeklyHousing * camp.weeks,
x1: x0 += +(Math.floor(camp.weeks * lastYearsIncome / 50))
}];
camp.total = camp.mapping[camp.mapping.length - 1].x1;
});
bootcamps.sort(function (a, b) {
return a.total - b.total;
});
maxValue = 0;
bootcamps.forEach(function (camp) {
camp.mapping.forEach(function (elem) {
if (elem.value > maxValue) {
maxValue = elem.value;
}
});
});
var xStackMax = d3.max(bootcamps, function (d) {
return d.total;
}), //Scale for Stacked
xGroupMax = bootcamps.map(function (camp) {
return camp.mapping.reduce(function (a, b) {
return a.value > b.value ? a.value : b.value;
});
}).reduce(function (a, b) {
return a > b ? a : b;
});
var margin = {
top: 30,
right: 60,
bottom: 50,
left: 140
},
width = 800 - margin.left - margin.right,
height = 1200 - margin.top - margin.bottom;
var barHeight = 20;
var xScale = d3.scale.linear()
.domain([0, xStackMax])
.rangeRound([0, width]);
var y0Scale = d3.scale.ordinal()
.domain(bootcamps.map(function (d) {
return d.name;
}))
.rangeRoundBands([0, height], .1);
var y1Scale = d3.scale.ordinal()
.domain(categoryNames).rangeRoundBands([0, y0Scale.rangeBand()]);
var color = d3.scale.ordinal()
.range(["#215f1e", "#5f5c1e", "#1e215f", "#5c1e5f"])
.domain(categoryNames);
var svg = d3.select("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 selection = svg.selectAll(".series")
.data(bootcamps)
.enter().append("g")
.attr("class", "series")
.attr("transform", function (d) {
return "translate(0," + y0Scale(d.name) + ")";
});
var rect = selection.selectAll("rect")
.data(function (d) {
return d.mapping;
})
.enter().append("rect")
.attr("x", 0)
.attr("width", 0)
.attr("height", y0Scale.rangeBand())
.style("fill", function (d) {
return color(d.label);
})
.style("stroke", "white")
.on("mouseover", function (d) {
showPopover.call(this, d);
})
.on("mouseout", function (d) {
removePopovers();
});
rect.transition()
.delay(function (d, i) {
return i * 10;
})
.attr("x", function (d) {
return xScale(d.x0);
})
.attr("width", function (d) {
return xScale((d.x1) - (d.x0));
});
d3.selectAll("#transform").on("click", function () {
$('#transform').addClass('animated pulse');
change();
setTimeout(function () {
$('#transform').removeClass('animated pulse');
}, 1000);
});
d3.selectAll("#chart").on("click", function () {
change();
});
function change() {
if ($("body").data("state") === "stacked") {
transitionGrouped();
$("body").data("state", "grouped");
} else {
transitionStacked();
$("body").data("state", "stacked");
}
}
function transitionGrouped() {
xScale.domain = ([0, xGroupMax]);
rect.transition()
.duration(500)
.delay(function (d, i) {
return i * 10;
})
.attr("width", function (d) {
return xScale((d.x1) - (d.x0));
})
.transition()
.attr("y", function (d) {
return y1Scale(d.label);
})
.attr("x", 0)
.attr("height", y1Scale.rangeBand());
}
function transitionStacked() {
xScale.domain = ([0, xStackMax]);
rect.transition()
.duration(500)
.delay(function (d, i) {
return i * 10;
})
.attr("x", function (d) {
return xScale(d.x0);
})
.transition()
.attr("y", function (d) {
return y0Scale(d.label);
})
.attr("height", y0Scale.rangeBand());
}
//axes
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y0Scale)
.orient("left");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 300)
.attr("y", 35)
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text("Cost in $USD");
//tooltips
function removePopovers() {
$('.popover').each(function () {
$(this).remove();
});
}
function showPopover(d) {
$(this).popover({
title: d.name,
placement: 'auto top',
container: 'body',
trigger: 'manual',
html: true,
content: function () {
return d.label +
"<br/>$" +
d3.format(",")(d.value ? d.value : d.x1 - d.x0);
}
});
$(this).popover('show');
}
//legends
var legend = svg.selectAll(".legend")
.data(categoryNames.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) {
return "translate(30," + i * y0Scale.rangeBand() * 1.1 + ")";
});
legend.append("rect")
.attr("x", width - y0Scale.rangeBand())
.attr("width", y0Scale.rangeBand())
.attr("height", y0Scale.rangeBand())
.style("fill", color)
.style("stroke", "white");
legend.append("text")
.attr("x", width - y0Scale.rangeBand() * 1.2)
.attr("y", 12)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) {
return d;
});
});
});