From e2deaa3f9d29209f2b3ac31ab197e6bce8077fe6 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 24 Jun 2015 09:34:32 -0700 Subject: [PATCH 001/186] add calculator view --- views/resources/calculator.jade | 114 ++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 views/resources/calculator.jade diff --git a/views/resources/calculator.jade b/views/resources/calculator.jade new file mode 100644 index 0000000000..285272b93d --- /dev/null +++ b/views/resources/calculator.jade @@ -0,0 +1,114 @@ +extends ../layout-wide +block content + script(src="../../../js/calculator.js") + .row + .col-xs-12.col-sm-10.col-md-8.col-lg-6.col-sm-offset-1.col-md-offset-2.col-lg-offset-3 + h1.text-center Coding Bootcamp Cost Calculator + h3.text-center.text-primary#chosen Coming from _______, and making $_______, your true costs will be: + #city-buttons + .spacer + h2.text-center Where do you live? + .spacer + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#atlanta.btn.btn-primary.btn-block.btn-lg Atlanta + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#austin.btn.btn-primary.btn-block.btn-lg Austin + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#brisbane.btn.btn-primary.btn-block.btn-lg Brisbane + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#boulder.btn.btn-primary.btn-block.btn-lg Boulder + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#chicago.btn.btn-primary.btn-block.btn-lg Chicago + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#denver.btn.btn-primary.btn-block.btn-lg Denver + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#hong-kong.btn.btn-primary.btn-block.btn-lg Hong Kong + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#london.btn.btn-primary.btn-block.btn-lg London + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#los-angeles.btn.btn-primary.btn-block.btn-lg Los Angeles + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#manchester.btn.btn-primary.btn-block.btn-lg Manchester + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#melbourne.btn.btn-primary.btn-block.btn-lg Melbourne + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#new-york-city.btn.btn-primary.btn-block.btn-lg New York City + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#portland.btn.btn-primary.btn-block.btn-lg Portland + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#raleigh-durham.btn.btn-primary.btn-block.btn-lg Raleigh-Durham + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#san-francisco.btn.btn-primary.btn-block.btn-lg San Fransisco + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#seattle.btn.btn-primary.btn-block.btn-lg Seattle + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#singapore.btn.btn-primary.btn-block.btn-lg Singapore + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#toronto.btn.btn-primary.btn-block.btn-lg Toronto + .col-xs-12.btn-nav + button#other.btn.btn-primary.btn-block.btn-lg Other + .spacer + #income.initially-hidden + .spacer + h2.text-center How much money did you make last year (in USD)? + .spacer + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#0.btn.btn-primary.btn-block.btn-lg(href='#') $0 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#20000.btn.btn-primary.btn-block.btn-lg(href='#') $20,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#30000.btn.btn-primary.btn-block.btn-lg(href='#') $30,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#40000.btn.btn-primary.btn-block.btn-lg(href='#') $40,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#50000.btn.btn-primary.btn-block.btn-lg(href='#') $50,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#60000.btn.btn-primary.btn-block.btn-lg(href='#') $60,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#70000.btn.btn-primary.btn-block.btn-lg(href='#') $70,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#80000.btn.btn-primary.btn-block.btn-lg(href='#') $80,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#90000.btn.btn-primary.btn-block.btn-lg(href='#') $90,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#100000.btn.btn-primary.btn-block.btn-lg(href='#') $100,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#120000.btn.btn-primary.btn-block.btn-lg(href='#') $120,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#140000.btn.btn-primary.btn-block.btn-lg(href='#') $140,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#160000.btn.btn-primary.btn-block.btn-lg(href='#') $160,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#180000.btn.btn-primary.btn-block.btn-lg(href='#') $180,000 + .col-xs-12.col-sm-12.col-md-4.btn-nav + button#200000.btn.btn-primary.btn-block.btn-lg(href='#') $200,000 + .spacer + #chart.initially-hidden + .d3-centered + svg.chart + #explanation.initially-hidden + .col-xs-12.col-sm-10.col-sm-offset-1 + .text-center + button#transform.btn.btn-primary.btn-lg Transform + .button-spacer + a(href='/coding-bootcamp-cost-calculator.json') View Data Source JSON + span   •   + a(href='/coding-bootcamp-cost-calculator') Recalculate + h3 Notes: + ol + li.large-li We assumed an APR of 6% and a term of 3 years. If you happen to have around $15,000 in cash set aside for a coding bootcamp, please ignore this cost. + li.large-li We assume a cost of living of $500 for cities like San Francisco and New York City, and $400 per week for everywhere else. + li.large-li The most substantial cost for most people is lost wages. A 40-hour-per-week job at the US Federal minimum wage would pay at least $15,000 per year. You can read more about economic cost + a(href='https://en.wikipedia.org/wiki/Economic_cost' target='_blank') here + | . + li.large-li Free Code Camp. We don't charge tuition or garnish wages. We're fully online so you don't have to move. We're self-paced so you don't have to quit your job. Thus, your true cost of attending Free Code Camp will be $0. + .spacer + .row + .col-xs-12.col-sm-4.col-md-3 + img.img-responsive.testimonial-image(src='https://www.evernote.com/l/AHRIBndcq-5GwZVnSy1_D7lskpH4OcJcUKUB/image.png') + .col-xs-12.col-sm-8.col-md-9 + h3 Built by Suzanne Atkinson + p.large-p Suzanne is an emergency medicine physician, triathlon coach and web developer from Pittsburgh. You should   + a(href='https://twitter.com/intent/user?screen_name=SteelCityCoach' target='_blank') follow her on Twitter + | . + .spacer From 09656a0f34bf771af493a8dd01a0aa1edd75fdab Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 24 Jun 2015 09:44:30 -0700 Subject: [PATCH 002/186] add more calculator logic --- app.js | 3 + controllers/bootcamps.json | 231 +++++++++++++++++++++++++++++++++++++ controllers/resources.js | 16 ++- 3 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 controllers/bootcamps.json diff --git a/app.js b/app.js index a265e530de..9cde852619 100755 --- a/app.js +++ b/app.js @@ -239,6 +239,9 @@ app.get('/chat', resourcesController.chat); app.get('/twitch', resourcesController.twitch); +app.get('/coding-bootcamp-cost-calculator', resourcesController.bootcampCalculator); +app.get('/coding-bootcamp-cost-calculator.json', resourcesController.bootcampCalculatorJson); + app.get('/cats.json', function(req, res) { res.send( [ diff --git a/controllers/bootcamps.json b/controllers/bootcamps.json new file mode 100644 index 0000000000..f993befcd7 --- /dev/null +++ b/controllers/bootcamps.json @@ -0,0 +1,231 @@ +[ + { + "name": "Hack Reactor", + "cost": "17780", + "housing": "500", + "weeks": "12", + "finance": true, + "cities": [ + "new-york-city", + "san-francisco" + ] + }, { + "name": "Hack Reactor Online", + "cost": "17780", + "housing": "0", + "weeks": "12", + "finance": true, + "cities": [ + "online" + ] +}, { + "name": "Hackbright Academy", + "cost": "15000", + "housing": "500", + "weeks": "10", + "finance": true, + "cities": [ + "san-francisco" + ] +}, { + "name": "Dev Bootcamp", + "cost": "13950", + "finance": true, + "housing": "500", + "weeks": "19", + "cities": [ + "new-york-city", + "san-francisco", + "chicago" + ] +}, { + "name": "General Asssembly", + "cost": "11500", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "washington-dc", + "austin", + "boston", + "chicago", + "hong-kong", + "london", + "los-angeles", + "melbourne", + "new-york-city", + "san-francisco", + "seattle", + "singapore" + ] +}, { + "name": "Angel Hack", + "cost": "14250", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "san-francisco" + ] +}, { + "name": "Bitmaker Labs", + "cost": "12000", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "toronto" + ] +}, { + "name": "CoderVox", + "cost": "9980", + "housing": "400", + "finance": true, + "weeks": "12", + "cities": [ + "austin" + ] +}, { + "name": "Coding Dojo", + "cost": "12500", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "new-york-city", + "san-francisco", + "chicago" + ] +}, { + "name": "Epicodus", + "cost": "4500", + "housing": "400", + "finance": false, + "weeks": "15", + "cities": [ + "portland" + ] +}, { + "name": "Flat Iron School", + "cost": "15000", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "new-york-city" + ] +}, { + "name": "Galvanize", + "cost": "21000", + "housing": "500", + "finance": true, + "weeks": "24", + "cities": [ + "boulder", + "denver", + "seattle", + "san-francisco" + ] +}, { + "name": "The Iron Yard", + "cost": "12000", + "housing": "500", + "finance": true, + "weeks": "19", + "cities": [ + "austin", + "washington-dc", + "raleigh-durham", + "atlanta" + ] +}, { + "name": "Launch Academy", + "cost": "12500", + "housing": "500", + "finance": true, + "weeks": "10", + "cities": [ + "boston" + ] +}, { + "name": "Maker Square", + "cost": "16920", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "los-angeles", + "san-francisco", + "austin" + ] +}, { + "name": "Refactor U", + "cost": "13500", + "housing": "400", + "finance": true, + "weeks": "10", + "cities": [ + "boulder" + ] +}, { + "name": "Rocket U", + "cost": "12500", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "new-york-city", + "san-francisco", + "chicago" + ] +}, { + "name": "Sabio", + "cost": "13450", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "los-angeles" + ] +}, { + "name": "Shillington School", + "cost": "12950", + "housing": "500", + "finance": true, + "weeks": "12", + "cities": [ + "new-york-city", + "sydney", + "brisbane", + "london", + "manchester", + "melbourne" + ] +}, { + "name": "The Tech Academy", + "cost": "9000", + "housing": "400", + "finance": true, + "weeks": "20", + "cities": [ + "portland" + ] +}, { + "name": "Turing School", + "cost": "17500", + "housing": "400", + "finance": true, + "weeks": "27", + "cities": [ + "denver" + ] +}, { + "name": "Free Code Camp", + "cost": "0", + "housing": "0", + "finance": false, + "weeks": "0", + "cities": [ + "online" + ] +}] diff --git a/controllers/resources.js b/controllers/resources.js index 9101f82edf..1bd1bb7dd3 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -8,8 +8,7 @@ var async = require('async'), R = require('ramda'), _ = require('lodash'), fs = require('fs'), - - + bootcampJson = require('./bootcamps.json'), constantStrings = require('./constantStrings.json'), User = require('../models/User'), Challenge = require('./../models/Challenge'), @@ -247,6 +246,8 @@ module.exports = { ); }, + + nonprofits: function nonprofits(req, res) { res.render('resources/nonprofits', { title: 'A guide to our Nonprofit Projects' @@ -277,6 +278,17 @@ module.exports = { }); }, + bootcampCalculator: function bootcampCalculator(req, res) { + res.render('resources/calculator', { + title: 'Coding Bootcamp Cost Calculator', + bootcampJson: bootcampJson + }); + }, + + bootcampCalculatorJson: function bootcampCalculatorJson(req, res) { + res.send(bootcampJson); + }, + unsubscribe: function unsubscribe(req, res, next) { User.findOne({ email: req.params.email }, function(err, user) { if (user) { From ca5cef08bfdd9d2fa7ec8c338b14c87ed5f5e47e Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 24 Jun 2015 09:51:44 -0700 Subject: [PATCH 003/186] finished fixing coding bootcamp cost calculator --- public/css/main.less | 23 +++ public/js/calculator.js | 272 ++++++++++++++++++++++++++++++++ views/resources/calculator.jade | 8 +- 3 files changed, 299 insertions(+), 4 deletions(-) create mode 100644 public/js/calculator.js diff --git a/public/css/main.less b/public/css/main.less index 245fc0a974..42222bf5a0 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -1108,6 +1108,29 @@ hr { } } +// Calculator styles + +.initially-hidden { + display: none; +} + +.chart rect { + fill: steelblue; +} + +.chart text { + font-size: 14px; + text-anchor: end; +} + +.axis path, +.axis line { + fill: none; + stroke: #121401; + stroke-width: 2px; + shape-rendering: crispEdges; +} + //uncomment this to see the dimensions of all elements outlined in red //* { // border-color: red; diff --git a/public/js/calculator.js b/public/js/calculator.js new file mode 100644 index 0000000000..7434f0ebc7 --- /dev/null +++ b/public/js/calculator.js @@ -0,0 +1,272 @@ +$(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').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']; + 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', + 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 + + "
$" + + 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; + }); + }); +}); diff --git a/views/resources/calculator.jade b/views/resources/calculator.jade index 285272b93d..7d51bc7666 100644 --- a/views/resources/calculator.jade +++ b/views/resources/calculator.jade @@ -1,6 +1,6 @@ extends ../layout-wide block content - script(src="../../../js/calculator.js") + script(src="/js/calculator.js") .row .col-xs-12.col-sm-10.col-md-8.col-lg-6.col-sm-offset-1.col-md-offset-2.col-lg-offset-3 h1.text-center Coding Bootcamp Cost Calculator @@ -104,9 +104,9 @@ block content li.large-li Free Code Camp. We don't charge tuition or garnish wages. We're fully online so you don't have to move. We're self-paced so you don't have to quit your job. Thus, your true cost of attending Free Code Camp will be $0. .spacer .row - .col-xs-12.col-sm-4.col-md-3 - img.img-responsive.testimonial-image(src='https://www.evernote.com/l/AHRIBndcq-5GwZVnSy1_D7lskpH4OcJcUKUB/image.png') - .col-xs-12.col-sm-8.col-md-9 + .col-xs-12.col-sm-5.col-md-5 + img.testimonial-image(src='https://www.evernote.com/l/AHRIBndcq-5GwZVnSy1_D7lskpH4OcJcUKUB/image.png') + .col-xs-12.col-sm-7.col-md-7 h3 Built by Suzanne Atkinson p.large-p Suzanne is an emergency medicine physician, triathlon coach and web developer from Pittsburgh. You should   a(href='https://twitter.com/intent/user?screen_name=SteelCityCoach' target='_blank') follow her on Twitter From 80e995e98f327426438bc9a22e673c6055e3e5b7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 27 Jun 2015 15:29:39 -0700 Subject: [PATCH 004/186] update field guide cities --- seed_data/field-guides.json | 47 ++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/seed_data/field-guides.json b/seed_data/field-guides.json index 136433aab4..e05849510f 100644 --- a/seed_data/field-guides.json +++ b/seed_data/field-guides.json @@ -320,13 +320,17 @@ "
  • Albany
  • ", "
  • Alameda
  • ", "
  • Amsterdam
  • ", + "
  • Ann Arbor
  • ", "
  • Apucarana
  • ", "
  • Aracaju
  • ", "
  • Asheville
  • ", + "
  • Asuncion
  • ", "
  • Atlanta
  • ", + "
  • Auckland
  • ", "
  • Austin
  • ", "
  • Baltimore
  • ", "
  • Bandung
  • ", + "
  • Bangkok
  • ", "
  • Belem
  • ", "
  • Belgrade
  • ", "
  • Bellingham
  • ", @@ -336,6 +340,8 @@ "
  • Berlin
  • ", "
  • Bhaktapur
  • ", "
  • Bijeljina
  • ", + "
  • Bydgoszcz
  • ", + "
  • Birmingham
  • ", "
  • Birmingham, Alabama
  • ", "
  • Bismarck, ND
  • ", "
  • Bogota
  • ", @@ -343,18 +349,22 @@ "
  • Boulder
  • ", "
  • Brasilia
  • ", "
  • Bratislava
  • ", + "
  • Brno
  • ", "
  • Brussels
  • ", + "
  • Bucaramanga
  • ", "
  • Buenos Aires
  • ", "
  • Bucharest
  • ", "
  • Budapest
  • ", "
  • Cairo
  • ", "
  • Calgary
  • ", "
  • Campinas
  • ", + "
  • Cape Cod
  • ", "
  • Cape Town
  • ", "
  • Caracas
  • ", "
  • Charlotte
  • ", "
  • Chattanooga
  • ", "
  • Chennai
  • ", + "
  • Chiang Mai
  • ", "
  • Chicago
  • ", "
  • Cincinnati
  • ", "
  • Clarksville
  • ", @@ -368,8 +378,11 @@ "
  • Des Moines
  • ", "
  • Detroit
  • ", "
  • Dhaka
  • ", + "
  • Dnipropetrovsk
  • ", "
  • Doha
  • ", "
  • Dubai
  • ", + "
  • Dublin
  • ", + "
  • Durango
  • ", "
  • Edmonton
  • ", "
  • Firenze
  • ", "
  • Flagstaff
  • ", @@ -377,11 +390,14 @@ "
  • Fort Worth
  • ", "
  • Frankfurt
  • ", "
  • Freehold
  • ", + "
  • Galveston
  • ", + "
  • Gdynia
  • ", "
  • Geneva
  • ", "
  • Guntur
  • ", - "
  • Glendora
  • ", + "
  • Granada
  • ", "
  • Guarapuava
  • ", "
  • Hampton Roads
  • ", + "
  • Hanoi
  • ", "
  • Hartford
  • ", "
  • Hermosillo
  • ", "
  • Ho Chi Minh City
  • ", @@ -404,44 +420,60 @@ "
  • Karachi
  • ", "
  • Kathmandu
  • ", "
  • Kemerovo
  • ", + "
  • Kerch
  • ", "
  • Kiev
  • ", "
  • Kolkata
  • ", "
  • Krasnodar
  • ", "
  • Kryvyi Rih
  • ", + "
  • La Crosse
  • ", + "
  • La Paz
  • ", "
  • Lagos
  • ", "
  • Lahore
  • ", "
  • Leesburg
  • ", "
  • Lehi
  • ", "
  • Lima
  • ", "
  • Limassol
  • ", + "
  • Lisbon
  • ", "
  • London
  • ", "
  • Los Angeles
  • ", "
  • Lubbock
  • ", + "
  • Madrid
  • ", "
  • Manila
  • ", "
  • Melbourne
  • ", + "
  • Mexico City
  • ", "
  • Miami
  • ", "
  • Minneapolis
  • ", + "
  • Mississippi Gulf Coast
  • ", "
  • Missoula
  • ", + "
  • Montgomery
  • ", "
  • Montreal
  • ", "
  • Moscow
  • ", "
  • Munich
  • ", "
  • Mysore
  • ", "
  • Nairobi
  • ", + "
  • Nashik
  • ", "
  • Nashville
  • ", "
  • New Haven
  • ", "
  • New Orleans
  • ", "
  • New Paltz
  • ", "
  • New York City
  • ", + "
  • Nicosia
  • ", + "
  • North Platte
  • ", "
  • Oakland
  • ", "
  • Oklahoma City
  • ", "
  • Omaha
  • ", "
  • Orange County
  • ", - "
  • Orlando
  • ", + "
  • Orlando
  • ", "
  • Parana
  • ", "
  • Paris
  • ", + "
  • Pasadena
  • ", + "
  • Pasto
  • ", + "
  • Penang
  • ", "
  • Philadelphia
  • ", "
  • Pittsburgh
  • ", "
  • Poitiers
  • ", + "
  • Porto
  • ", + "
  • Pune
  • ", "
  • Phoenix
  • ", "
  • Portland
  • ", "
  • Prescott
  • ", @@ -453,6 +485,7 @@ "
  • Recife
  • ", "
  • Richmond
  • ", "
  • Rio de Janeiro
  • ", + "
  • Roma
  • ", "
  • Rotterdam
  • ", "
  • Sacramento
  • ", "
  • Saint George
  • ", @@ -463,17 +496,24 @@ "
  • San Diego
  • ", "
  • San Francisco
  • ", "
  • San Jose
  • ", + "
  • Santa Barbara
  • ", + "
  • Santa Cruz
  • ", "
  • Sao Paulo
  • ", "
  • Scottsdale
  • ", "
  • Sedona
  • ", "
  • Seattle
  • ", + "
  • Sidoarjo
  • ", "
  • Singapore
  • ", + "
  • Skopje
  • ", "
  • Solo
  • ", + "
  • Stuttgart
  • ", "
  • Taipei
  • ", "
  • Tampa
  • ", + "
  • Temecula
  • ", "
  • Tempe
  • ", "
  • Tirana
  • ", "
  • Toronto
  • ", + "
  • Tucson
  • ", "
  • Tulsa
  • ", "
  • Verde Valley
  • ", "
  • Valencia
  • ", @@ -481,6 +521,7 @@ "
  • Washington, DC
  • ", "
  • Winnipeg
  • ", "
  • Yaounde
  • ", + "
  • Znojmo
  • ", "
  • Zurich
  • ", " ", " ", @@ -509,7 +550,7 @@ " A screen shot showing you the group description box on the Facebook page.", "
  • Click the \"Upload a photo button. To start out, you'll probably just want to use Free Code Camp's banner (download it here), or a scenic shot of your city. Later you can update this with a picture from one of your city's Free Code Camp events.
  • ", " A screenshot showing the \"Upload a photo\" button.", - "
  • Message @quincylarson in Slack with a link to your city's group page and he'll include it here.
  • ", + "
  • Message @quincylarson on Gitter with a link to your city's group page and he'll include it here.
  • ", "
  • Join our Local Leaders Facebook group, where we share ideas about involving campers in your city.
  • ", " ", "

    ", From 968676da728259d0830e070452e13b1cf4a02810 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 28 Jun 2015 15:38:42 -0700 Subject: [PATCH 005/186] fix entities bonfire tests --- seed_data/challenges/basic-bonfires.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index a40b1f917b..ac5b09dcec 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -1078,7 +1078,11 @@ ], "tests": [ "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", - "assert.strictEqual('<>', '<>', 'should escape characters');", + "assert.strictEqual(convert('Hamburgers < Pizza < Tacos'), 'Hamburgers < Pizza < Tacos', 'should escape characters');", + "assert.strictEqual(convert('Sixty > twelve'), 'Sixty > twelve', 'should escape characters');", + "assert.strictEqual(convert('Stuff in \"quotation marks\"'), 'Stuff in "quotation marks"', 'should escape characters');", + "assert.strictEqual(convert(\"Shindler's List\"), 'Shindler's List', 'should escape characters');", + "assert.strictEqual(convert('<>'), '<>', 'should escape characters');", "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" ], "MDNlinks": [ From af8295ec75db4d93790cf68a8ae811d894f6d797 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 28 Jun 2015 18:19:54 -0700 Subject: [PATCH 006/186] fix modal copy --- views/partials/challenge-modals.jade | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/views/partials/challenge-modals.jade b/views/partials/challenge-modals.jade index 5270e77cd4..1a0872a2ee 100644 --- a/views/partials/challenge-modals.jade +++ b/views/partials/challenge-modals.jade @@ -4,12 +4,11 @@ .modal-header.challenge-list-header Ready to pair program? a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × .modal-body.text-center - h3 This will create a pair programming request. h3 You'll need   a(href='/field-guide/how-do-i-install-screenhero' target='_blank') Screen Hero | . - h3 Other campers may then message you about pair programming. - a.btn.btn-lg.btn-primary.btn-block#i-want-to-pair(name='_csrf', value=_csrf) Create my pair request + h3 Tell your fellow campers which challenge you are interested in pair programming on. + a.btn.btn-lg.btn-primary.btn-block#i-want-to-pair(name='_csrf', value=_csrf) Take me to the Pair Programming room a.btn.btn-lg.btn-info.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel #issue-modal.modal(tabindex='-1') @@ -33,7 +32,6 @@ a(href='/field-guide/how-do-i-get-help-when-i-get-stuck' target='_blank') RSAP | . h3 If you've already read the errors and searched Google, you should ask for help. - h3 This will open a help request in our Help chat room. a.btn.btn-lg.btn-primary.btn-block#i-want-help(name='_csrf', value=_csrf) Ask for help a.btn.btn-lg.btn-info.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel @@ -47,6 +45,5 @@ a(href='/field-guide/how-do-i-get-help-when-i-get-stuck' target='_blank') RSAP | . h3 If you've already read the errors and searched Google, you should ask for help. - h3 This will open a help request in our Help chat room. a.btn.btn-lg.btn-primary.btn-block#i-want-help-editorless(name='_csrf', value=_csrf) Ask for help a.btn.btn-lg.btn-info.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel From e5df5120ff517dd2ed14974e3ad04c558c3bde8d Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 28 Jun 2015 18:30:34 -0700 Subject: [PATCH 007/186] fix #1147 --- seed_data/challenges/bootstrap.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index abf29c33b5..ae20843697 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -618,8 +618,8 @@ "The \"row\" class is applied to a div, and the buttons themselves can be wrapped within it." ], "tests": [ - "assert($('div.row:has(button)'), 'Your buttons should all be wrapped within the same div element with the class \"row\".')", - "assert($('div.col-xs-4:has(button)').length > 2, 'Each of your Bootstrap buttons should be wrapped within its own a div element with the class \"col-xs-4\".')", + "assert($('div.row:has(button)').length > 0, 'Your buttons should all be wrapped within the same div element with the class \"row\".')", + "assert($('div.col-xs-4:has(button)').length > 2, 'Each of your Bootstrap buttons should be wrapped within its own div element with the class \"col-xs-4\".')", "assert(editor.match(/<\\/button>/g) && editor.match(/