factor JavaScript and JSON into separate files
This commit is contained in:
268
public/js/calculator.js
Normal file
268
public/js/calculator.js
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
var bootcamps = ''
|
||||||
|
$.getJSON('/coding-bootcamp-cost-calculator.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').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 = ['Opportunity Cost at Current Wage', 'Financing Cost', 'Housing Cost', 'Tuition / 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 / 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: 'Opportunity Cost at Current Wage',
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -28,7 +28,7 @@ module.exports = function(app) {
|
|||||||
router.post('/get-pair', getPair);
|
router.post('/get-pair', getPair);
|
||||||
router.get('/chat', chat);
|
router.get('/chat', chat);
|
||||||
router.get('/coding-bootcamp-cost-calculator', bootcampCalculator);
|
router.get('/coding-bootcamp-cost-calculator', bootcampCalculator);
|
||||||
router.get('/bootcamp-calculator.json', bootcampCalculatorJson);
|
router.get('/coding-bootcamp-cost-calculator.json', bootcampCalculatorJson);
|
||||||
router.get('/twitch', twitch);
|
router.get('/twitch', twitch);
|
||||||
router.get('/pmi-acp-agile-project-managers', agileProjectManagers);
|
router.get('/pmi-acp-agile-project-managers', agileProjectManagers);
|
||||||
router.get('/pmi-acp-agile-project-managers-form', agileProjectManagersForm);
|
router.get('/pmi-acp-agile-project-managers-form', agileProjectManagersForm);
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
extends ../layout
|
extends ../layout
|
||||||
block content
|
block content
|
||||||
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/css/bootstrap2/bootstrap-switch.min.css')
|
script(src="../../../js/calculator.js")
|
||||||
script(src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/js/bootstrap-switch.min.js")
|
|
||||||
.panel.panel-info
|
.panel.panel-info
|
||||||
.panel-heading.text-center Coding Bootcamp Cost Calculator
|
.panel-heading.text-center Coding Bootcamp Cost Calculator
|
||||||
.panel-body
|
.panel-body
|
||||||
.row
|
.row
|
||||||
.col-xs-12.col-sm-10.col-sm-offset-1
|
.col-xs-12.col-sm-10.col-sm-offset-1
|
||||||
h3.text-primary#chosen Coming from _______, and making $_______, your true costs will be:
|
h3.text-primary#chosen Coming from _______, and making $_______, your true costs will be:
|
||||||
#chart-controls.initially-hidden
|
|
||||||
.text-center
|
|
||||||
button#transform.btn.btn-primary.btn-lg.animated Transform
|
|
||||||
#city-buttons
|
#city-buttons
|
||||||
h2 Where do you live?
|
h2 Where do you live?
|
||||||
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
||||||
@ -51,6 +47,7 @@ block content
|
|||||||
button#toronto.btn.btn-primary.btn-block.btn-lg Toronto
|
button#toronto.btn.btn-primary.btn-block.btn-lg Toronto
|
||||||
.col-xs-12.btn-nav
|
.col-xs-12.btn-nav
|
||||||
button#other.btn.btn-primary.btn-block.btn-lg Other
|
button#other.btn.btn-primary.btn-block.btn-lg Other
|
||||||
|
.spacer
|
||||||
#income.initially-hidden
|
#income.initially-hidden
|
||||||
h2 How much money did you make last year (in USD)?
|
h2 How much money did you make last year (in USD)?
|
||||||
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
||||||
@ -83,272 +80,16 @@ block content
|
|||||||
button#180000.btn.btn-primary.btn-block.btn-lg(href='#') $180,000
|
button#180000.btn.btn-primary.btn-block.btn-lg(href='#') $180,000
|
||||||
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
.col-xs-12.col-sm-6.col-md-4.btn-nav
|
||||||
button#200000.btn.btn-primary.btn-block.btn-lg(href='#') $200,000
|
button#200000.btn.btn-primary.btn-block.btn-lg(href='#') $200,000
|
||||||
|
.spacer
|
||||||
#chart.initially-hidden
|
#chart.initially-hidden
|
||||||
.d3-centered
|
.d3-centered
|
||||||
svg.chart
|
svg.chart
|
||||||
#explanation.initially-hidden
|
#explanation.initially-hidden
|
||||||
.text-center
|
.text-center
|
||||||
|
.text-center
|
||||||
|
button#transform.btn.btn-primary.btn-block.btn-lg Transform
|
||||||
|
.button-spacer
|
||||||
a(href='/coding-bootcamp-cost-calculator.json') View Data Source JSON
|
a(href='/coding-bootcamp-cost-calculator.json') View Data Source JSON
|
||||||
span •
|
span •
|
||||||
a(href='/coding-bootcamp-cost-calculator') Recalculate
|
a(href='/coding-bootcamp-cost-calculator') Recalculate
|
||||||
p.large-p Test
|
p.large-p Test
|
||||||
script.
|
|
||||||
$(document).ready(function () {
|
|
||||||
var bootcamps = !{JSON.stringify(bootcampJson)};
|
|
||||||
var city = "";
|
|
||||||
$( "body" ).data( "state", "stacked");
|
|
||||||
$('#city-buttons').on("click", "button", function () {
|
|
||||||
$(this).addClass('animated pulse');
|
|
||||||
setTimeout(function () {
|
|
||||||
$('#city-buttons').hide();
|
|
||||||
$('#chosen').text('Coming from ' + city.replace(/-/g, ' ').replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}));
|
|
||||||
$('#income').addClass('animated fadeIn').show();
|
|
||||||
}, 1000);
|
|
||||||
city = $(this).attr("id");
|
|
||||||
});
|
|
||||||
$('#income').on("click", "button", function() {
|
|
||||||
$(this).addClass('animated pulse');
|
|
||||||
setTimeout(function () {
|
|
||||||
$('#income').hide();
|
|
||||||
$('#chart').show();
|
|
||||||
$('#chart-controls').addClass('animated fadeIn').show();
|
|
||||||
$('#explanation').addClass('animated fadeIn').show();
|
|
||||||
}, 1000);
|
|
||||||
var lastYearsIncome = parseInt($(this).attr("id"));
|
|
||||||
$('#chosen').append(', and making $' + lastYearsIncome.toString().replace(/0000/, '0,000') + ', your true costs will be:');
|
|
||||||
var categoryNames = ['Opportunity Cost at Current Wage', 'Financing Cost', 'Housing Cost', 'Tuition / 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 / 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: 'Opportunity Cost at Current Wage',
|
|
||||||
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('pulse');
|
|
||||||
change();
|
|
||||||
setTimeout( function() {
|
|
||||||
$('#transform').removeClass('pulse');
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
Reference in New Issue
Block a user