Merge pull request #2 from FreeCodeCamp/staging

Sync to staging
This commit is contained in:
Ben McMahon
2015-10-16 13:34:48 +01:00
74 changed files with 2282 additions and 561 deletions

View File

@ -1,31 +1,72 @@
// common namespace var common = (function() {
// all classes should be stored here // common namespace
var common = common || { // all classes should be stored here
// init is an array of functions that are var common = window.common || {
// called at the beginning of dom ready // init is an array of functions that are
init: [] // called at the beginning of dom ready
}; init: []
};
common.challengeName = common.challengeName || window.challenge_Name ? common.challengeName = common.challengeName || window.challenge_Name ?
window.challenge_Name : window.challenge_Name :
''; '';
common.challengeType = common.challengeType || window.challengeType ? common.challengeType = common.challengeType || window.challengeType ?
window.challengeType : window.challengeType :
0; 0;
common.challengeId = common.challengeId || window.challenge_Id; common.challengeId = common.challengeId || window.challenge_Id;
common.challengeSeed = common.challengeSeed || window.challengeSeed ? common.challengeSeed = common.challengeSeed || window.challengeSeed ?
window.challengeSeed : window.challengeSeed :
[]; [];
common.seed = common.challengeSeed.reduce(function(seed, line) { common.seed = common.challengeSeed.reduce(function(seed, line) {
return seed + line + '\n'; return seed + line + '\n';
}, ''); }, '');
common.replaceScriptTags = function replaceScriptTags(value) {
return value
.replace(/<script>/gi, 'fccss')
.replace(/<\/script>/gi, 'fcces');
};
common.replaceSafeTags = function replaceSafeTags(value) {
return value
.replace(/fccss/gi, '<script>')
.replace(/fcces/gi, '</script>');
};
common.replaceFormActionAttr = function replaceFormAction(value) {
return value.replace(/<form[^>]*>/, function(val) {
return val.replace(/action(\s*?)=/, 'fccfaa$1=');
});
};
common.replaceFccfaaAttr = function replaceFccfaaAttr(value) {
return value.replace(/<form[^>]*>/, function(val) {
return val.replace(/fccfaa(\s*?)=/, 'action$1=');
});
};
return common;
})();
// store code in the URL // store code in the URL
common.codeUri = (function(common, encode, decode, location, history) { common.codeUri = (function(common, encode, decode, location, history) {
var replaceScriptTags = common.replaceScriptTags;
var replaceSafeTags = common.replaceSafeTags;
var replaceFormActionAttr = common.replaceFormActionAttr;
var replaceFccfaaAttr = common.replaceFccfaaAttr;
function encodeFcc(val) {
return replaceScriptTags(replaceFormActionAttr(val));
}
function decodeFcc(val) {
return replaceSafeTags(replaceFccfaaAttr(val));
}
var codeUri = { var codeUri = {
encode: function(code) { encode: function(code) {
return encode(code); return encode(code);
@ -54,10 +95,14 @@ common.codeUri = (function(common, encode, decode, location, history) {
}, false); }, false);
}, },
isAlive: function() { isAlive: function() {
return codeUri.isInQuery(location.search) || return codeUri.enabled &&
codeUri.isInQuery(location.search) ||
codeUri.isInQuery(location.hash); codeUri.isInQuery(location.hash);
}, },
parse: function() { parse: function() {
if (!codeUri.enabled) {
return null;
}
var query; var query;
if (location.search && codeUri.isInQuery(location.search)) { if (location.search && codeUri.isInQuery(location.search)) {
query = location.search.replace(/^\?/, ''); query = location.search.replace(/^\?/, '');
@ -67,7 +112,7 @@ common.codeUri = (function(common, encode, decode, location, history) {
null, null,
location.href.split('?')[0] location.href.split('?')[0]
); );
location.hash = '#?' + query; location.hash = '#?' + encodeFcc(query);
} }
} else { } else {
query = location.hash.replace(/^\#\?/, ''); query = location.hash.replace(/^\#\?/, '');
@ -82,15 +127,21 @@ common.codeUri = (function(common, encode, decode, location, history) {
var key = param.split('=')[0]; var key = param.split('=')[0];
var value = param.split('=')[1]; var value = param.split('=')[1];
if (key === 'solution') { if (key === 'solution') {
return codeUri.decode(value); return decodeFcc(codeUri.decode(value || ''));
} }
return solution; return solution;
}, null); }, null);
}, },
querify: function(solution) { querify: function(solution) {
location.hash = '?solution=' + codeUri.encode(solution); if (!codeUri.enabled) {
return null;
}
location.hash = '?solution=' +
codeUri.encode(encodeFcc(solution));
return solution; return solution;
} },
enabled: true
}; };
common.init.push(function() { common.init.push(function() {
@ -306,12 +357,6 @@ var sandBox = (function(jailed, codeOutput) {
return sandBox; return sandBox;
}(window.jailed, common.codeOutput)); }(window.jailed, common.codeOutput));
function replaceSafeTags(value) {
return value
.replace(/fccss/gi, '<script>')
.replace(/fcces/gi, '</script>');
}
var BDDregex = new RegExp( var BDDregex = new RegExp(
'(expect(\\s+)?\\(.*\\;)|' + '(expect(\\s+)?\\(.*\\;)|' +
'(assert(\\s+)?\\(.*\\;)|' + '(assert(\\s+)?\\(.*\\;)|' +
@ -408,7 +453,6 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) {
common.init.push(function() { common.init.push(function() {
var editorValue; var editorValue;
if (common.codeUri.isAlive()) { if (common.codeUri.isAlive()) {
console.log('in query');
editorValue = common.codeUri.parse(); editorValue = common.codeUri.parse();
} else { } else {
editorValue = codeStorage.isAlive() ? editorValue = codeStorage.isAlive() ?
@ -416,7 +460,7 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) {
common.seed; common.seed;
} }
editor.setValue(replaceSafeTags(editorValue)); editor.setValue(common.replaceSafeTags(editorValue));
editor.refresh(); editor.refresh();
}); });
@ -445,6 +489,7 @@ function workerError(error) {
var housing = $('#testSuite'); var housing = $('#testSuite');
if (display.html() !== error) { if (display.html() !== error) {
display.remove(); display.remove();
housing.prepend( housing.prepend(
'<div class="runTimeError" style="font-size: 18px;"><code>' + '<div class="runTimeError" style="font-size: 18px;"><code>' +
error.replace(/j\$/gi, '$').replace(/jdocument/gi, 'document').replace(/jjQuery/gi, 'jQuery') + error.replace(/j\$/gi, '$').replace(/jdocument/gi, 'document').replace(/jjQuery/gi, 'jQuery') +
@ -471,7 +516,10 @@ function safeHTMLRun(test) {
var codeStorage = common.codeStorage; var codeStorage = common.codeStorage;
if (common.challengeType === '0') { if (common.challengeType === '0') {
var previewFrame = document.getElementById('preview'); var previewFrame = document.getElementById('preview');
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
var preview = previewFrame.contentDocument ||
previewFrame.contentWindow.document;
if (editor.getValue().match(/\<script\>/gi) !== null) { if (editor.getValue().match(/\<script\>/gi) !== null) {
var s = editor var s = editor
.getValue() .getValue()
@ -540,9 +588,11 @@ function updatePreview() {
if (typeof prodOrDev !== 'undefined') { if (typeof prodOrDev !== 'undefined') {
var nodeEnv = prodOrDev === 'production' ? /* eslint-disable no-unused-vars */
var nodeEnv = window.prodOrDev === 'production' ?
'http://www.freecodecamp.com' : 'http://www.freecodecamp.com' :
'http://localhost:3001'; 'http://localhost:3001';
/* eslint-enable no-unused-vars */
if (common.challengeType === '0') { if (common.challengeType === '0') {
setTimeout(updatePreview, 300); setTimeout(updatePreview, 300);
@ -553,8 +603,11 @@ if (typeof prodOrDev !== 'undefined') {
* "post" methods * "post" methods
*/ */
/* eslint-disable no-unused-vars */
var testResults = []; var testResults = [];
var postSuccess = function(data) { var postSuccess = function(data) {
/* eslint-enable no-unused-vars */
var testDoc = document.createElement('div'); var testDoc = document.createElement('div');
$(testDoc).html( $(testDoc).html(
"<div class='row'><div class='col-xs-2 text-center'><i class='ion-checkmark-circled big-success-icon'></i></div><div class='col-xs-10 test-output test-vertical-center wrappable'>" + "<div class='row'><div class='col-xs-2 text-center'><i class='ion-checkmark-circled big-success-icon'></i></div><div class='col-xs-10 test-output test-vertical-center wrappable'>" +
@ -600,7 +653,9 @@ function showCompletion() {
isInitRun = false; isInitRun = false;
return; return;
} }
var time = Math.floor(Date.now()) - started;
var time = Math.floor(Date.now()) - window.started;
ga( ga(
'send', 'send',
'event', 'event',
@ -658,8 +713,11 @@ function showCompletion() {
}); });
} }
/* eslint-disable no-unused-vars */
var resetEditor = function resetEditor() { var resetEditor = function resetEditor() {
editor.setValue(replaceSafeTags(common.seed)); /* eslint-enable no-unused-vars */
editor.setValue(common.replaceSafeTags(common.seed));
$('#testSuite').empty(); $('#testSuite').empty();
bonfireExecute(true); bonfireExecute(true);
common.codeStorage.updateStorage(); common.codeStorage.updateStorage();
@ -849,15 +907,15 @@ common.init.push((function() {
var nextStep = getNextStep($(stepClass)); var nextStep = getNextStep($(stepClass));
$(this) $(this)
.parent() .parent()
.addClass('animated fadeOutLeft') .addClass('animated fadeOutLeft fast-animation')
.delay(700) .delay(250)
.queue(function(next) { .queue(function(next) {
$(this).addClass('hidden'); $(this).addClass('hidden');
if (nextStep) { if (nextStep) {
$(nextStep) $(nextStep)
.removeClass('hidden') .removeClass('hidden')
.addClass('animated slideInRight') .addClass('animated slideInRight fast-animation')
.delay(1000) .delay(500)
.queue(function(next) { .queue(function(next) {
$(this).removeClass('slideInRight'); $(this).removeClass('slideInRight');
next(); next();
@ -865,14 +923,53 @@ common.init.push((function() {
} }
next(); next();
}); });
} }
function handleActionClick() { function handleActionClick(e) {
$(this) var props = common.challengeSeed[0] ||
.parent() { stepIndex: [] };
.find('.disabled')
.removeClass('disabled'); var $el = $(this);
var index = +$el.attr('id');
var propIndex = props.stepIndex.indexOf(index);
if (propIndex === -1) {
return $el
.parent()
.find('.disabled')
.removeClass('disabled');
}
// an API action
// prevent link from opening
e.preventDefault();
var prop = props.properties[propIndex];
var api = props.apis[propIndex];
if (common[prop]) {
return $el
.parent()
.find('.disabled')
.removeClass('disabled');
}
$
.post(api)
.done(function(data) {
// assume a boolean indicates passing
if (typeof data === 'boolean') {
return $el
.parent()
.find('.disabled')
.removeClass('disabled');
}
// assume api returns string when fails
$el
.parent()
.find('.disabled')
.replaceWith('<p>' + data + '</p>');
})
.fail(function() {
console.log('failed');
});
} }
function handleFinishClick(e) { function handleFinishClick(e) {

View File

@ -490,11 +490,17 @@ thead {
border-radius: 5px; border-radius: 5px;
} }
.story-section {
height: 500px;
}
.testimonial-copy { .testimonial-copy {
font-size: 20px; text-align: justify;
text-align: center; font-size: 18px !important;
margin-left: 20px;
margin-right: 20px;
@media (min-width: 991px) and (max-width: 1199px) { @media (min-width: 991px) and (max-width: 1199px) {
height: 120px; height: 140px;
} }
@media (min-width: 1200px) { @media (min-width: 1200px) {
height: 90px; height: 90px;

View File

@ -1,12 +1,21 @@
var mapShareKey = 'map-shares'; var main = window.main || {};
main.mapShareKey = 'map-shares';
main.ga = window.ga || function() {};
var lastCompleted = typeof lastCompleted !== 'undefined' ? var lastCompleted = typeof lastCompleted !== 'undefined' ?
lastCompleted : lastCompleted :
''; '';
function getMapShares() { function getMapShares() {
var alreadyShared = JSON.parse(localStorage.getItem(mapShareKey) || '[]'); var alreadyShared = JSON.parse(
localStorage.getItem(main.mapShareKey) ||
'[]'
);
if (!alreadyShared || !Array.isArray(alreadyShared)) { if (!alreadyShared || !Array.isArray(alreadyShared)) {
localStorage.setItem(mapShareKey, JSON.stringify([])); localStorage.setItem(main.mapShareKey, JSON.stringify([]));
alreadyShared = []; alreadyShared = [];
} }
return alreadyShared; return alreadyShared;
@ -23,7 +32,7 @@ function setMapShare(id) {
if (!found) { if (!found) {
alreadyShared.push(id); alreadyShared.push(id);
} }
localStorage.setItem(mapShareKey, JSON.stringify(alreadyShared)); localStorage.setItem(main.mapShareKey, JSON.stringify(alreadyShared));
return alreadyShared; return alreadyShared;
} }
@ -133,6 +142,7 @@ $(document).ready(function() {
type = 'html'; type = 'html';
break; break;
case challengeTypes.JAVASCRIPT: case challengeTypes.JAVASCRIPT:
case challengeTypes.BONFIRE:
type = 'javascript'; type = 'javascript';
break; break;
default: default:
@ -444,6 +454,7 @@ $(document).ready(function() {
'&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap'; '&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap';
setMapShare(challengeBlockName); setMapShare(challengeBlockName);
main.ga('send', 'event', 'FB_LINK', 'SHARE', 'Facebook map share');
window.location.href = link; window.location.href = link;
}); });
}); });

View File

@ -8,13 +8,17 @@ const initValue = {
points: 0 points: 0
}; };
export default Store(initValue) export default Store({
.refs({ displayName: 'AppStore' }) refs: {
.init(({ instance: appStore, args: [cat] }) => { displayName: 'AppStore',
value: initValue
},
init({ instance: appStore, args: [cat] }) {
const { setUser, setTitle } = cat.getActions('appActions'); const { setUser, setTitle } = cat.getActions('appActions');
const register = createRegistrar(appStore); const register = createRegistrar(appStore);
register(setter(fromMany(setUser, setTitle))); register(setter(fromMany(setUser, setTitle)));
return appStore; return appStore;
}); }
});

View File

@ -1,6 +1,6 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Button, Col, Row, Panel } from 'react-bootstrap'; import { Button, Col, Row, Panel } from 'react-bootstrap';
import { Navigation } from 'react-router'; import { History } from 'react-router';
import Vimeo from 'react-vimeo'; import Vimeo from 'react-vimeo';
import debugFactory from 'debug'; import debugFactory from 'debug';
@ -8,7 +8,7 @@ const debug = debugFactory('freecc:hikes');
export default React.createClass({ export default React.createClass({
displayName: 'Lecture', displayName: 'Lecture',
mixins: [Navigation], mixins: [History],
propTypes: { propTypes: {
currentHike: PropTypes.object, currentHike: PropTypes.object,
@ -20,7 +20,7 @@ export default React.createClass({
handleFinish() { handleFinish() {
debug('loading questions'); debug('loading questions');
const { dashedName } = this.props.params; const { dashedName } = this.props.params;
this.transitionTo(`/hikes/${dashedName}/questions/1`); this.history.pushState(null, `/hikes/${dashedName}/questions/1`);
}, },
renderTranscript(transcript, dashedName) { renderTranscript(transcript, dashedName) {

View File

@ -1,6 +1,6 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Spring } from 'react-motion'; import { Spring } from 'react-motion';
import { Navigation, TransitionHook } from 'react-router'; import { History, Lifecycle } from 'react-router';
import debugFactory from 'debug'; import debugFactory from 'debug';
import { import {
Button, Button,
@ -19,8 +19,8 @@ export default React.createClass({
displayName: 'Question', displayName: 'Question',
mixins: [ mixins: [
Navigation, History,
TransitionHook Lifecycle
], ],
propTypes: { propTypes: {
@ -150,7 +150,8 @@ export default React.createClass({
postJSON$('/completed-challenge', { id, name }).subscribeOnCompleted(() => { postJSON$('/completed-challenge', { id, name }).subscribeOnCompleted(() => {
if (tests[nextQuestionIndex]) { if (tests[nextQuestionIndex]) {
return this.transitionTo( return this.history.pushState(
null,
`/hikes/${ dashedName }/questions/${ nextQuestionIndex + 1 }` `/hikes/${ dashedName }/questions/${ nextQuestionIndex + 1 }`
); );
} }
@ -168,13 +169,13 @@ export default React.createClass({
}, null); }, null);
if (nextHike) { if (nextHike) {
return this.transitionTo(`/hikes/${ nextHike.dashedName }`); return this.history.pushState(null, `/hikes/${ nextHike.dashedName }`);
} }
debug( debug(
'next Hike was not found, currentHike %s', 'next Hike was not found, currentHike %s',
currentHike.dashedName currentHike.dashedName
); );
this.transitionTo('/hikes'); this.history.pushState(null, '/hikes');
}); });
}, },

View File

@ -3,7 +3,7 @@ import debugFactory from 'debug';
const debug = debugFactory('freecc:hikes:actions'); const debug = debugFactory('freecc:hikes:actions');
function getCurrentHike(hikes =[{}], dashedName, currentHike) { function getCurrentHike(hikes = [{}], dashedName, currentHike) {
if (!dashedName) { if (!dashedName) {
debug('no dashedName'); debug('no dashedName');
return hikes[0]; return hikes[0];

View File

@ -5,12 +5,16 @@ const initialValue = {
currentHike: {} currentHike: {}
}; };
export default Store(initialValue) export default Store({
.refs({ displayName: 'HikesStore'}) refs: {
.init(({ instance: hikeStore, args: [cat] }) => { displayName: 'HikesStore',
value: initialValue
},
init({ instance: hikeStore, args: [cat] }) {
let { setHikes } = cat.getActions('hikesActions'); let { setHikes } = cat.getActions('hikesActions');
hikeStore.register(setHikes); hikeStore.register(setHikes);
return hikeStore; return hikeStore;
}); }
});

View File

@ -6,9 +6,12 @@ const {
transformer transformer
} = Store; } = Store;
export default Store({ showModal: false }) export default Store({
.refs({ displayName: 'JobsStore' }) refs: {
.init(({ instance: jobsStore, args: [cat] }) => { displayName: 'JobsStore',
value: { showModal: false }
},
init({ instance: jobsStore, args: [cat] }) {
const { const {
setJobs, setJobs,
findJob, findJob,
@ -27,4 +30,5 @@ export default Store({ showModal: false })
register(transformer(findJob)); register(transformer(findJob));
register(handleForm); register(handleForm);
}); }
});

55
common/models/pledge.json Normal file
View File

@ -0,0 +1,55 @@
{
"name": "pledge",
"base": "PersistedModel",
"idInjection": true,
"trackChanges": false,
"properties": {
"nonprofit": {
"type": "string",
"index": true
},
"amount": {
"type": "number"
},
"dateStarted": {
"type": "date",
"defaultFn": "now"
},
"dateEnded": {
"type": "date"
},
"formerUserId": {
"type": "string"
},
"isOrphaned": {
"type": "boolean"
},
"isCompleted": {
"type": "boolean",
"default": "false"
}
},
"validations": [],
"relations": {
"user": {
"type": "hasMany",
"model": "user",
"foreignKey": "userId"
}
},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": []
}

View File

@ -322,7 +322,7 @@ module.exports = function(User) {
}) })
// no results means this is the first brownie point given by giver // no results means this is the first brownie point given by giver
// so return -1 to indicate receiver should receive point // so return -1 to indicate receiver should receive point
.firstOrDefault(null, -1) .first({ defaultValue: -1 })
.flatMap((browniePointsFromGiver) => { .flatMap((browniePointsFromGiver) => {
if (browniePointsFromGiver === -1) { if (browniePointsFromGiver === -1) {

View File

@ -102,14 +102,31 @@
}, },
"isLocked": { "isLocked": {
"type": "boolean", "type": "boolean",
"default": false "default": false,
"description": "Campers profile does not show challenges/certificates to the public"
}, },
"currentChallenge": { "currentChallenge": {
"type": {} "type": {}
}, },
"isUniqMigrated": { "isUniqMigrated": {
"type": "boolean", "type": "boolean",
"default": false "default": false,
"description": "Campers completedChallenges array is free of duplicates"
},
"isHonest": {
"type": "boolean",
"default": false,
"description": "Camper has signed academic honesty policy"
},
"isFrontEndCert": {
"type": "boolean",
"defaut": false,
"description": "Camper is front end certified"
},
"isFullStackCert": {
"type": "boolean",
"default": false,
"description": "Campers is full stack certified"
}, },
"completedChallenges": { "completedChallenges": {
"type": [ "type": [
@ -149,6 +166,11 @@
"type": "hasMany", "type": "hasMany",
"model": "userIdentity", "model": "userIdentity",
"foreignKey": "" "foreignKey": ""
},
"pledge": {
"type": "hasOne",
"model": "pledge",
"foreignKey": ""
} }
}, },
"acls": [ "acls": [

View File

@ -63,8 +63,8 @@
"json-loader": "^0.5.2", "json-loader": "^0.5.2",
"less": "~2.5.1", "less": "~2.5.1",
"lodash": "^3.9.3", "lodash": "^3.9.3",
"loopback": "https://github.com/FreeCodeCamp/loopback.git#fix/no-password", "loopback": "^2.22.0",
"loopback-boot": "2.8.2", "loopback-boot": "^2.13.0",
"loopback-component-passport": "https://github.com/FreeCodeCamp/loopback-component-passport.git#feature/flashfailure", "loopback-component-passport": "https://github.com/FreeCodeCamp/loopback-component-passport.git#feature/flashfailure",
"loopback-connector-mongodb": "^1.10.0", "loopback-connector-mongodb": "^1.10.0",
"lusca": "~1.0.2", "lusca": "~1.0.2",
@ -89,17 +89,17 @@
"react": "^0.13.3", "react": "^0.13.3",
"react-bootstrap": "~0.23.7", "react-bootstrap": "~0.23.7",
"react-motion": "~0.1.0", "react-motion": "~0.1.0",
"react-router": "^1.0.0-rc1", "react-router": "https://github.com/BerkeleyTrue/react-router.git#freecodecamp",
"react-vimeo": "^0.0.3", "react-vimeo": "^0.0.3",
"request": "~2.53.0", "request": "~2.53.0",
"rev-del": "^1.0.5", "rev-del": "^1.0.5",
"rx": "^2.5.3", "rx": "^4.0.0",
"sanitize-html": "~1.6.1", "sanitize-html": "~1.6.1",
"sort-keys": "^1.1.1", "sort-keys": "^1.1.1",
"source-map-support": "^0.3.2", "source-map-support": "^0.3.2",
"store": "https://github.com/berkeleytrue/store.js.git#feature/noop-server", "store": "https://github.com/berkeleytrue/store.js.git#feature/noop-server",
"thundercats": "^2.1.0", "thundercats": "^3.0.0",
"thundercats-react": "^0.1.0", "thundercats-react": "^0.3.0",
"twit": "~1.1.20", "twit": "~1.1.20",
"uglify-js": "~2.4.15", "uglify-js": "~2.4.15",
"validator": "^3.22.1", "validator": "^3.22.1",

BIN
public/fonts/saxmono.ttf Executable file

Binary file not shown.

View File

@ -1,6 +1,7 @@
{ {
"name": "Advanced Algorithm Scripting", "name": "Advanced Algorithm Scripting",
"order": 15, "order": 15,
"time": "50h",
"challenges": [ "challenges": [
{ {
"id": "aff0395860f5d3034dc0bfc9", "id": "aff0395860f5d3034dc0bfc9",
@ -39,7 +40,9 @@
"assert(telephoneCheck(\"27576227382\") === false, 'message: <code>telephoneCheck(\"27576227382\")</code> should return false.');", "assert(telephoneCheck(\"27576227382\") === false, 'message: <code>telephoneCheck(\"27576227382\")</code> should return false.');",
"assert(telephoneCheck(\"(275)76227382\") === false, 'message: <code>telephoneCheck(\"(275)76227382\")</code> should return false.');", "assert(telephoneCheck(\"(275)76227382\") === false, 'message: <code>telephoneCheck(\"(275)76227382\")</code> should return false.');",
"assert(telephoneCheck(\"2(757)6227382\") === false, 'message: <code>telephoneCheck(\"2(757)6227382\")</code> should return false.');", "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: <code>telephoneCheck(\"2(757)6227382\")</code> should return false.');",
"assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: <code>telephoneCheck(\"2(757)622-7382\")</code> should return false.');" "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: <code>telephoneCheck(\"2(757)622-7382\")</code> should return false.');",
"assert(telephoneCheck(\"555)-555-5555\") === false, 'message: <code>telephoneCheck(\"555)555-5555\")</code> should return false.');",
"assert(telephoneCheck(\"(555-555-5555\") === false, 'message: <code>telephoneCheck(\"(555-555-5555\")</code> should return false.');"
], ],
"challengeSeed": [ "challengeSeed": [
"function telephoneCheck(str) {", "function telephoneCheck(str) {",
@ -142,6 +145,7 @@
"assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"QUARTER\", 0.50]], 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]])</code> should return <code>[[\"QUARTER\", 0.50]]</code>.');", "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"QUARTER\", 0.50]], 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]])</code> should return <code>[[\"QUARTER\", 0.50]]</code>.');",
"assert.deepEqual(drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]], 'message: <code>drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]])</code> should return <code>[[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]]</code>.');", "assert.deepEqual(drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]]), [[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]], 'message: <code>drawer(3.26, 100.00, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.10], [\"QUARTER\", 4.25], [\"ONE\", 90.00], [\"FIVE\", 55.00], [\"TEN\", 20.00], [\"TWENTY\", 60.00], [\"ONE HUNDRED\", 100.00]])</code> should return <code>[[\"TWENTY\", 60.00], [\"TEN\", 20.00], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.50], [\"DIME\", 0.20], [\"PENNY\", 0.04]]</code>.');",
"assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Insufficient Funds\", 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return \"Insufficient Funds\".');", "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Insufficient Funds\", 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return \"Insufficient Funds\".');",
"assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1.00], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Insufficient Funds\", 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1.00], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return \"Insufficient Funds\".');",
"assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Closed\", 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return \"Closed\".');" "assert.deepEqual(drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), \"Closed\", 'message: <code>drawer(19.50, 20.00, [[\"PENNY\", 0.50], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])</code> should return \"Closed\".');"
], ],
"MDNlinks": [ "MDNlinks": [

View File

@ -1,6 +1,7 @@
{ {
"name": "AngularJS", "name": "AngularJS",
"order": 16, "order": 16,
"time": "5h",
"challenges": [ "challenges": [
{ {
"id": "bd7154d8c441eddfaeb5bdef", "id": "bd7154d8c441eddfaeb5bdef",

View File

@ -1,6 +1,7 @@
{ {
"name": "Automated Testing and Debugging", "name": "Automated Testing and Debugging",
"order": 14, "order": 14,
"time": "15m",
"challenges": [ "challenges": [
{ {
"id":"cf1111c1c16feddfaeb6bdef", "id":"cf1111c1c16feddfaeb6bdef",

View File

@ -1,6 +1,7 @@
{ {
"name": "Full Stack JavaScript Projects", "name": "Full Stack JavaScript Projects",
"order": 20, "order": 20,
"time": "300h",
"challenges": [ "challenges": [
{ {
"id": "bd7158d8c443eddfaeb5bcef", "id": "bd7158d8c443eddfaeb5bcef",
@ -52,7 +53,7 @@
"Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the <code>control + c</code> hotkey to shut down these processes.", "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the <code>control + c</code> hotkey to shut down these processes.",
"Run the following command in a Cloud9 terminal prompt tab: <code>npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login</code>. At this point, the terminal will prompt you to log in to Heroku from the command line.", "Run the following command in a Cloud9 terminal prompt tab: <code>npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login</code>. At this point, the terminal will prompt you to log in to Heroku from the command line.",
"Now run <code>yo angular-fullstack:heroku</code>. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", "Now run <code>yo angular-fullstack:heroku</code>. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.",
"Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: <code>cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:create mongolab</code>.", "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: <code>cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab</code>.",
"As you build your app, you should frequently commit changes to your codebase. Make sure you're in the <code>~/workspace</code> directory by running <code>cd ~/workspace</code>. Then you can use this code to stage the changes to your changes and commit them: <code>git commit -am \"your commit message\"</code>. Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the <code>~/workspace</code> directory by running <code>cd ~/workspace</code>. Then you can use this code to stage the changes to your changes and commit them: <code>git commit -am \"your commit message\"</code>. Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".",
"You can push these new commits to GitHub by running <code>git push origin master</code>, and to Heroku by running <code>grunt --force && grunt buildcontrol:heroku</code>.", "You can push these new commits to GitHub by running <code>git push origin master</code>, and to Heroku by running <code>grunt --force && grunt buildcontrol:heroku</code>.",
"If you need further guidance on using Yeoman Angular-Fullstack Generator, check out: <a href='https://github.com/clnhll/guidetobasejumps' target='_blank'>https://github.com/clnhll/guidetobasejumps</a>.", "If you need further guidance on using Yeoman Angular-Fullstack Generator, check out: <a href='https://github.com/clnhll/guidetobasejumps' target='_blank'>https://github.com/clnhll/guidetobasejumps</a>.",

View File

@ -1,6 +1,7 @@
{ {
"name": "Basic Algorithm Scripting", "name": "Basic Algorithm Scripting",
"order": 7, "order": 8,
"time": "50h",
"challenges": [ "challenges": [
{ {
"id": "ad7123c8c441eddfaeb5bdef", "id": "ad7123c8c441eddfaeb5bdef",
@ -60,7 +61,7 @@
" return str;", " return str;",
"}", "}",
"", "",
"reverseString(\"hello\", \"\");" "reverseString(\"hello\");"
], ],
"MDNlinks": [ "MDNlinks": [
"Global String Object", "Global String Object",
@ -103,7 +104,7 @@
" return num;", " return num;",
"}", "}",
"", "",
"factorialize(5, '');" "factorialize(5);"
], ],
"MDNlinks": [ "MDNlinks": [
"Arithmetic Operators" "Arithmetic Operators"
@ -224,7 +225,7 @@
" return str;", " return str;",
"}", "}",
"", "",
"titleCase(\"I'm a little tea pot\", \"\");" "titleCase(\"I'm a little tea pot\");"
], ],
"tests": [ "tests": [
"assert(typeof(titleCase(\"I&#39;m a little tea pot\")) === \"string\", 'message: <code>titleCase()</code> should return a string.');", "assert(typeof(titleCase(\"I&#39;m a little tea pot\")) === \"string\", 'message: <code>titleCase()</code> should return a string.');",
@ -300,13 +301,14 @@
" return str;", " return str;",
"}", "}",
"", "",
"end(\"Bastian\", \"n\", \"\");" "end(\"Bastian\", \"n\");"
], ],
"tests": [ "tests": [
"assert(end(\"Bastian\", \"n\") === true, 'message: <code>end(\"Bastian\", \"n\")</code> should return true.');", "assert(end(\"Bastian\", \"n\") === true, 'message: <code>end(\"Bastian\", \"n\")</code> should return true.');",
"assert(end(\"Connor\", \"n\") === false, 'message: <code>end(\"Connor\", \"n\")</code> should return false.');", "assert(end(\"Connor\", \"n\") === false, 'message: <code>end(\"Connor\", \"n\")</code> should return false.');",
"assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, 'message: <code>end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\")</code> should return false.');", "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, 'message: <code>end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\")</code> should return false.');",
"assert(end(\"He has to give me a new name\", \"name\") === true, 'message: <code>end(\"He has to give me a new name\", \"name\")</code> should return true.');", "assert(end(\"He has to give me a new name\", \"name\") === true, 'message: <code>end(\"He has to give me a new name\", \"name\")</code> should return true.');",
"assert(end(\"He has to give me a new name\", \"me\") === true, 'message: <code>end(\"He has to give me a new name\", \"me\")</code> should return true.');",
"assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: <code>end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")</code> should return false.');" "assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: <code>end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")</code> should return false.');"
], ],
"MDNlinks": [ "MDNlinks": [
@ -338,7 +340,7 @@
" return str;", " return str;",
"}", "}",
"", "",
"repeat(\"abc\", 3, \"\");" "repeat(\"abc\", 3);"
], ],
"tests": [ "tests": [
"assert(repeat(\"*\", 3) === \"***\", 'message: <code>repeat(\"*\", 3)</code> should return <code>\"***\"</code>.');", "assert(repeat(\"*\", 3) === \"***\", 'message: <code>repeat(\"*\", 3)</code> should return <code>\"***\"</code>.');",
@ -367,6 +369,7 @@
"description": [ "description": [
"Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a \"...\" ending.", "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a \"...\" ending.",
"Note that the three dots at the end add to the string length.", "Note that the three dots at the end add to the string length.",
"If the length of the string is less than or equal to 3 characters, then the length of the three dots is not added to the string length.",
"Remember to use <a href=\"//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck\" target=\"_blank\">Read-Search-Ask</a> if you get stuck. Write your own code." "Remember to use <a href=\"//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck\" target=\"_blank\">Read-Search-Ask</a> if you get stuck. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
@ -375,13 +378,14 @@
" return str;", " return str;",
"}", "}",
"", "",
"truncate(\"A-tisket a-tasket A green and yellow basket\", 11, \"\");" "truncate(\"A-tisket a-tasket A green and yellow basket\", 11);"
], ],
"tests": [ "tests": [
"assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", 1)</code> should return \"A-tisket...\".');", "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", 11) === \"A-tisket...\", 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", 11)</code> should return \"A-tisket...\".');",
"assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: <code>truncate(\"Peter Piper picked a peck of pickled peppers\", 14)</code> should return \"Peter Piper...\".');", "assert(truncate(\"Peter Piper picked a peck of pickled peppers\", 14) === \"Peter Piper...\", 'message: <code>truncate(\"Peter Piper picked a peck of pickled peppers\", 14)</code> should return \"Peter Piper...\".');",
"assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length)</code> should return \"A-tisket a-tasket A green and yellow basket\".');", "assert(truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length)</code> should return \"A-tisket a-tasket A green and yellow basket\".');",
"assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2)</code> should return \"A-tisket a-tasket A green and yellow basket\".');" "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: <code>truncate(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2)</code> should return \"A-tisket a-tasket A green and yellow basket\".');",
"assert(truncate(\"A-\", 1) === \"A...\", 'message: <code>truncate(\"A-\", 1)</code> should return \"A...\".');"
], ],
"MDNlinks": [ "MDNlinks": [
"String.slice()" "String.slice()"
@ -412,7 +416,7 @@
" return arr;", " return arr;",
"}", "}",
"", "",
"chunk([\"a\", \"b\", \"c\", \"d\"], 2, \"\");" "chunk([\"a\", \"b\", \"c\", \"d\"], 2);"
], ],
"tests": [ "tests": [
"assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: <code>chunk([\"a\", \"b\", \"c\", \"d\"], 2)</code> should return <code>[[\"a\", \"b\"], [\"c\", \"d\"]]</code>.');", "assert.deepEqual(chunk([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: <code>chunk([\"a\", \"b\", \"c\", \"d\"], 2)</code> should return <code>[[\"a\", \"b\"], [\"c\", \"d\"]]</code>.');",
@ -450,12 +454,13 @@
" return arr;", " return arr;",
"}", "}",
"", "",
"slasher([1, 2, 3], 2, \"\");" "slasher([1, 2, 3], 2);"
], ],
"tests": [ "tests": [
"assert.deepEqual(slasher([1, 2, 3], 2), [3], 'message: <code>slasher([1, 2, 3], 2, [3])</code> should return <code>[3]</code>.');", "assert.deepEqual(slasher([1, 2, 3], 2), [3], 'message: <code>slasher([1, 2, 3], 2)</code> should return <code>[3]</code>.');",
"assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'message: <code>slasher([1, 2, 3], 0)</code> should return <code>[1, 2, 3]</code>.');", "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'message: <code>slasher([1, 2, 3], 0)</code> should return <code>[1, 2, 3]</code>.');",
"assert.deepEqual(slasher([1, 2, 3], 9), [], 'message: <code>slasher([1, 2, 3], 9)</code> should return <code>[]</code>.');" "assert.deepEqual(slasher([1, 2, 3], 9), [], 'message: <code>slasher([1, 2, 3], 9)</code> should return <code>[]</code>.');",
"assert.deepEqual(slasher([1, 2, 3], 4), [], 'message: <code>slasher([1, 2, 3], 4)</code> should return <code>[]</code>.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Array.slice()", "Array.slice()",
@ -489,7 +494,7 @@
" return arr;", " return arr;",
"}", "}",
"", "",
"mutation([\"hello\", \"hey\"], \"\");" "mutation([\"hello\", \"hey\"]);"
], ],
"tests": [ "tests": [
"assert(mutation([\"hello\", \"hey\"]) === false, 'message: <code>mutation([\"hello\", \"hey\"])</code> should return false.');", "assert(mutation([\"hello\", \"hey\"]) === false, 'message: <code>mutation([\"hello\", \"hey\"])</code> should return false.');",
@ -531,7 +536,7 @@
" return arr;", " return arr;",
"}", "}",
"", "",
"bouncer([7, \"ate\", \"\", false, 9], \"\");" "bouncer([7, \"ate\", \"\", false, 9]);"
], ],
"tests": [ "tests": [
"assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: <code>bouncer([7, \"ate\", \"\", false, 9])</code> should return <code>[7, \"ate\", 9]</code>.');", "assert.deepEqual(bouncer([7, \"ate\", \"\", false, 9]), [7, \"ate\", 9], 'message: <code>bouncer([7, \"ate\", \"\", false, 9])</code> should return <code>[7, \"ate\", 9]</code>.');",
@ -568,7 +573,7 @@
" return arr;", " return arr;",
"}", "}",
"", "",
"destroyer([1, 2, 3, 1, 2, 3], 2, 3, \"\");" "destroyer([1, 2, 3, 1, 2, 3], 2, 3);"
], ],
"tests": [ "tests": [
"assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: <code>destroyer([1, 2, 3, 1, 2, 3], 2, 3)</code> should return <code>[1, 1]</code>.');", "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'message: <code>destroyer([1, 2, 3, 1, 2, 3], 2, 3)</code> should return <code>[1, 1]</code>.');",
@ -608,7 +613,7 @@
" return num;", " return num;",
"}", "}",
"", "",
"where([40, 60], 50, \"\");" "where([40, 60], 50);"
], ],
"MDNlinks": [ "MDNlinks": [
"Array.sort()" "Array.sort()"

View File

@ -1,6 +1,7 @@
{ {
"name": "Basic JavaScript", "name": "Basic JavaScript",
"order": 5, "order": 6,
"time": "3h",
"challenges": [ "challenges": [
{ {
"id":"bd7123c9c441eddfaeb4bdef", "id":"bd7123c9c441eddfaeb4bdef",
@ -529,7 +530,7 @@
], ],
"tests": [ "tests": [
"assert((function(d){if(d[0] == 'John' && d[1] == 23 && d[2] == undefined){return true;}else{return false;}})(myArray), 'message: <code>myArray</code> should only contain <code>[\"John\", 23]</code>.');", "assert((function(d){if(d[0] == 'John' && d[1] == 23 && d[2] == undefined){return true;}else{return false;}})(myArray), 'message: <code>myArray</code> should only contain <code>[\"John\", 23]</code>.');",
"assert((function(d){if(d[0] == 'cat' && d[1] == 2 && d[2] == undefined){return true;}else{return false;}})(removed), 'message: <code>removed</code> should only contain <code>[\"cat\"], 2</code>.');" "assert((function(d){if(d[0] == 'cat' && d[1] == 2 && d[2] == undefined){return true;}else{return false;}})(removed), 'message: <code>removed</code> should only contain <code>[\"cat\", 2]</code>.');"
], ],
"challengeSeed": [ "challengeSeed": [
"// var numbers = [1,2,3];", "// var numbers = [1,2,3];",
@ -802,7 +803,7 @@
"assert.deepEqual(myArray, [0,1,2,3,4], 'message: <code>myArray</code> should equal [0,1,2,3,4].');" "assert.deepEqual(myArray, [0,1,2,3,4], 'message: <code>myArray</code> should equal [0,1,2,3,4].');"
], ],
"challengeSeed":[ "challengeSeed":[
"ourArray = [];", "var ourArray = [];",
"for(var i = 0; i < 5; i++){", "for(var i = 0; i < 5; i++){",
" ourArray.push(i);", " ourArray.push(i);",
"}", "}",
@ -939,7 +940,7 @@
"var min = 0;", "var min = 0;",
"var max = 9;", "var max = 9;",
"function myFunction() {", "function myFunction() {",
" // Make myFunction return a random number between zero and nine instead of a decimal", " // Make myFunction return a random number between min and max values instead of a decimal",
" // Only change code below this line.", " // Only change code below this line.",
"", "",
" return Math.random();", " return Math.random();",
@ -1039,7 +1040,7 @@
], ],
"tests":[ "tests":[
"assert(test === 2, 'message: Your RegEx should have found two numbers in the <code>testString</code>.');", "assert(test === 2, 'message: Your RegEx should have found two numbers in the <code>testString</code>.');",
"assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'message: You should be using the following expression <code>/\\\\d+/gi</code> to find the numbers in the <code>testString</code>.');" "assert(editor.getValue().match(/\\/\\\\d\\+\\//g), 'message: You should be using the following expression <code>/\\d+/g</code> to find the numbers in the <code>testString</code>.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var test = (function() {", "var test = (function() {",
@ -1047,7 +1048,7 @@
"", "",
" // Only change code below this line.", " // Only change code below this line.",
"", "",
" var expression = /.+/gi;", " var expression = /.+/g;",
"", "",
" // Only change code above this line.", " // Only change code above this line.",
" // We use this function to show you the value of your variable in your output box.", " // We use this function to show you the value of your variable in your output box.",
@ -1059,17 +1060,18 @@
}, },
{ {
"id":"cf1111c1c12feddfaeb8bdef", "id":"cf1111c1c12feddfaeb8bdef",
"title": "Find White Space with Regular Expressions", "title": "Find Whitespace with Regular Expressions",
"difficulty":"9.986", "difficulty":"9.986",
"description":[ "description":[
"We can also use selectors like <code>\\s</code> to find spaces in a string.", "We can also use selectors like <code>\\s</code> to find whitespace in a string.",
"The whitespace characters are <code>\" \"</code> (space), <code>\\r</code> (carriage return), <code>\\n</code> (newline), <code>\\t</code> (tab), and <code>\\f</code> (form feed).",
"It is used like this:", "It is used like this:",
"<code>/\\s+/g</code>", "<code>/\\s+/g</code>",
"Select all the spaces in the sentence string." "Select all the whitespace characters in the sentence string."
], ],
"tests":[ "tests":[
"assert(test === 7, 'message: Your RegEx should have found seven spaces in the <code>testString</code>.');", "assert(test === 7, 'message: Your RegEx should have found seven spaces in the <code>testString</code>.');",
"assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'message: You should be using the following expression <code>/\\\\s+/gi</code> to find the spaces in the <code>testString</code>.');" "assert(editor.getValue().match(/\\/\\\\s\\+\\//g), 'message: You should be using the following expression <code>/\\s+/g</code> to find the spaces in the <code>testString</code>.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var test = (function(){", "var test = (function(){",
@ -1077,7 +1079,7 @@
"", "",
" // Only change code below this line.", " // Only change code below this line.",
"", "",
" var expression = /.+/gi;", " var expression = /.+/g;",
"", "",
" // Only change code above this line.", " // Only change code above this line.",
" // We use this function to show you the value of your variable in your output box.", " // We use this function to show you the value of your variable in your output box.",
@ -1092,12 +1094,12 @@
"title": "Invert Regular Expression Matches with JavaScript", "title": "Invert Regular Expression Matches with JavaScript",
"difficulty":"9.987", "difficulty":"9.987",
"description":[ "description":[
"Use <code>/\\S/gi</code> to match everything that isn't a space in the string.", "Use <code>/\\S/g</code> to match everything that isn't a space in the string.",
"You can invert any match by using the uppercase version of the selector <code>\\s</code> versus <code>\\S</code> for example." "You can invert any match by using the uppercase version of the selector <code>\\s</code> versus <code>\\S</code> for example."
], ],
"tests":[ "tests":[
"assert(test === 49, 'message: Your RegEx should have found forty nine non-space characters in the <code>testString</code>.');", "assert(test === 49, 'message: Your RegEx should have found forty nine non-space characters in the <code>testString</code>.');",
"assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'message: You should be using the following expression <code>/\\\\S/gi</code> to find non-space characters in the <code>testString</code>.');" "assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: You should be using the following expression <code>/\\S/g</code> to find non-space characters in the <code>testString</code>.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var test = (function(){", "var test = (function(){",
@ -1105,7 +1107,7 @@
"", "",
" // Only change code below this line.", " // Only change code below this line.",
"", "",
" var expression = /./gi;", " var expression = /./g;",
"", "",
" // Only change code above this line.", " // Only change code above this line.",
" // We use this function to show you the value of your variable in your output box.", " // We use this function to show you the value of your variable in your output box.",
@ -1127,10 +1129,10 @@
"<code>Math.floor(Math.random() * (3 - 1 + 1)) + 1;</code>" "<code>Math.floor(Math.random() * (3 - 1 + 1)) + 1;</code>"
], ],
"tests":[ "tests":[
"assert(typeof(runSlots($(\".slot\"))[0]) === \"number\", 'message: <code>slotOne</code> should be a random number.')", "assert(typeof(runSlots($(\".slot\"))[0]) === \"number\", '<code>slotOne</code> should be a random number.')",
"assert(typeof(runSlots($(\".slot\"))[1]) === \"number\", 'message: <code>slotTwo</code> should be a random number.')", "assert(typeof(runSlots($(\".slot\"))[1]) === \"number\", '<code>slotTwo</code> should be a random number.')",
"assert(typeof(runSlots($(\".slot\"))[2]) === \"number\", 'message: <code>slotThree</code> should be a random number.')", "assert(typeof(runSlots($(\".slot\"))[2]) === \"number\", '<code>slotThree</code> should be a random number.')",
"assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi) !== null){return editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi).length >= 3;}else{return false;}})(), 'message: You should have used <code>Math.floor(Math.random() * (3 - 1 + 1)) + 1;</code> three times to generate your random numbers.')" "assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi) !== null){return editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?3\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi).length >= 3;}else{return false;}})(), 'You should have used <code>Math.floor(Math.random() * (3 - 1 + 1)) + 1;</code> three times to generate your random numbers.')"
], ],
"challengeSeed":[ "challengeSeed":[
"fccss", "fccss",

View File

@ -1,50 +1,53 @@
{ {
"name": "Basic Front End Development Projects", "name": "Basic Front End Development Projects",
"order": 8, "order": 9,
"time": "100h",
"challenges": [ "challenges": [
{ {
"id": "bd7158d8c442eddfbeb5bd1f", "id": "bd7158d8c442eddfbeb5bd1f",
"title": "Get Set for Ziplines", "title": "Get Set for Ziplines",
"difficulty": 1.00, "challengeSeed": [],
"challengeSeed": ["125658022"],
"description": [ "description": [
"Now you're ready to start our Zipline challenges. These front-end development challenges will give you many opportunities to apply the HTML, CSS, jQuery and JavaScript you've learned to build static (database-less) applications.", [
"Whatever you do, don't get discouraged! Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.", "http://i.imgur.com/6WLULsC.gif",
"We'll build these challenges using CodePen, a popular tool for creating, sharing, and discovering static web applications.", "A gif showing how to create a Codepen account.",
"Go to <a href='http://codepen.io' target='_blank'>http://codepen.io</a> and create an account.", "For our front end Zipline challenges, we'll use a popular browser-based code editor called CodePen. Open CodePen and click \"Sign up\" in the upper right hand corner, then scroll down to the free plan and click \"Sign up\" again. Click the \"Use info from GitHub button\", then add your email address and create a password. Click the \"Sign up\" button. Then in the upper right hand corner, click \"New pen\".",
"Click your user image in the top right corner, then click the \"New pen\" button that drops down.", "http://codepen.io"
"Drag the windows around and press the buttons in the lower-right hand corner to change the orientation to suit your preference.", ],
"Click the gear next to CSS. Then under the \"Add External CSS\" section, use the \"Quick-add\" select box to select Bootstrap. Then click \"Save & Close\".", [
"Verify that bootstrap is active by adding the following code to your HTML: <code>&lt;h1 class='text-primary'&gt;Hello CodePen!&lt;/h1&gt;</code>. The text's color should be Bootstrap blue.", "http://i.imgur.com/U4y9RJ1.gif",
"Click the gear next to JavaScript. Click the \"Quick-add\" select box and choose jQuery (not jQuery UI).", "A gif showing that you can type \"hello world\" will output \"hello world\" in the preview window. You can also drag windows to resize them, and change their orientation.",
"Click the \"Quick-add\" select box again and choose Bootstrap. Then click \"Save & Close\".", "In the HTML box, create an h1 element with the text \"Hello World\". You can drag the frames around to resize them. You can also click the \"Change View\" button and change the orientation of the frames.",
"Now add the following code to your JavaScript: <code>$(document).ready(function() { $('.text-primary').text('Hi CodePen!') });</code>. Click the \"Save\" button at the top. Your \"Hello CodePen!\" should change to \"Hi CodePen!\". This means that jQuery is working.", ""
"You can use this CodePen that you've just created as a starting point for your Ziplines. Just click the \"fork\" button at the top of your CodePen and it will create a duplicate CodePen.", ],
"Now you're ready for your first Zipline. Click the \"I've completed this challenge\" button." [
"http://i.imgur.com/G9KFQDL.gif",
"A gif showing the process of adding Bootstrap to your pen.",
"Click the gear in the upper left hand corner of the CSS box, then scroll down to \"Quick add\" and choose Bootstrap. Now give your h1 element the class of \"text-primary\" to change its color and prove that Bootstrap is now available.",
""
],
[
"http://i.imgur.com/Gi3aig0.gif",
"A gif showing the process of adding Animate.css and jQuery to pen.",
"Click the gear in the upper left hand corner of the CSS box, then scroll down to \"Quick add\" and choose Animate.css. Click the gear in the upper left hand corner of the JS box, then scroll down to \"Quick add\" and choose jQuery. Let's prove that Animate.css and jQuery are loaded properly. In the JS box, add the following code to make your h1 element bounce: <code>$(document).ready(function(){ $(\"h1\").addClass(\"animated bounce\"); });</code>.",
""
],
[
"http://i.imgur.com/Wzt6Y9Y.gif",
"A gif showing the process of saving and forking a pen.",
"Save your pen with the \"Save\" button. Then click the \"Fork\" button. This will create a fork (copy) of your pen that you can experimient with.",
""
]
], ],
"type": "waypoint", "type": "Waypoint",
"challengeType": 2, "challengeType": 7,
"tests": [], "tests": [],
"nameCn": "", "nameCn": "",
"descriptionCn": [], "descriptionCn": [],
"nameFr": "", "nameFr": "",
"descriptionFr": [], "descriptionFr": [],
"nameRu": "Приготовьтесь к Zipline'ам", "nameRu": "",
"descriptionRu": [ "descriptionRu": [],
"Теперь вы готовы приступить к Zipline'ам. Это задания по фронт-энд разработке, в них вы примените ранее изученные HTML, CSS, jQuery и JavaScript и создадите статические (не использующие базу данных) приложения.",
"Ни в коем случае не унывайте! Воспользуйтесь <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a>, если что-то не получается.",
"Задания мы будем выполнять используя CodePen - популярный инструмент для создания и обмена статическими веб приложениями.",
"Перейдите по ссылке <a href='http://codepen.io' target='_blank'>http://codepen.io</a> и создайте аккаунт.",
"Нажмите на ваш аватар в правом верхнем углу, а затем в открывшемся меню на кнопку \"New pen\".",
"Выберите удобное расположение окон с помощью кнопок в правом нижнем углу, отрегулируйте их ширину.",
"Нажмите на звездочку рядом с CSS. Затем в секции \"Add External CSS\" выберите \"Quick-add\" и добавьте Bootstrap. Нажмите \"Save & Close\".",
"Проверьте, что Bootstrap подключен добавив следующий HTML код: <code>&lt;h1 class='text-primary'&gt;Hello CodePen!&lt;/h1&gt;</code>. Цвет текста должен быть синим.",
"Нажмите на звездочку рядом с JavaScript. Нажмите \"Quick-add\" и выберите jQuery (не jQuery UI). Нажмите \"Save & Close\".",
"Снова нажмите на поле \"Quick-add\", выберите Bootstrap и затем нажмите \"Save & Close\".",
"Теперь добавьте следующий код в окошко JavaScript: <code>$(document).ready(function() { $('.text-primary').text('Hi CodePen!') });</code>. Нажмите на кнопку \"Save\" расположенную наверху. Текст \"Hello CodePen!\" должен измениться на \"Hi CodePen!\". Это значит что jQuery работает.",
"CodePen, который мы создали, можно использовать в качестве отправной точки для ваших Zipline'ов. Кликните кнопку \"fork\", чтобы создать копию текущего CodePen'a.",
"Все готово для первого Zipline'а. Жмите кнопку \"I've completed this challenge\"."
],
"nameEs": "", "nameEs": "",
"descriptionEs": [], "descriptionEs": [],
"namePt": "", "namePt": "",
@ -53,7 +56,6 @@
{ {
"id": "bd7158d8c242eddfaeb5bd13", "id": "bd7158d8c242eddfaeb5bd13",
"title": "Build a Personal Portfolio Webpage", "title": "Build a Personal Portfolio Webpage",
"difficulty": 1.01,
"challengeSeed": ["133315782"], "challengeSeed": ["133315782"],
"description": [ "description": [
"<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/ThiagoFerreir4/full/eNMxEp' target='_blank'>http://codepen.io/ThiagoFerreir4/full/eNMxEp</a>.", "<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/ThiagoFerreir4/full/eNMxEp' target='_blank'>http://codepen.io/ThiagoFerreir4/full/eNMxEp</a>.",
@ -107,7 +109,6 @@
{ {
"id": "bd7158d8c442eddfaeb5bd13", "id": "bd7158d8c442eddfaeb5bd13",
"title": "Build a Random Quote Machine", "title": "Build a Random Quote Machine",
"difficulty": 1.02,
"challengeSeed": ["126415122"], "challengeSeed": ["126415122"],
"description": [ "description": [
"<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/AdventureBear/full/vEoVMw' target='_blank'>http://codepen.io/AdventureBear/full/vEoVMw</a>.", "<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/AdventureBear/full/vEoVMw' target='_blank'>http://codepen.io/AdventureBear/full/vEoVMw</a>.",
@ -117,7 +118,6 @@
"Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:", "Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:",
"<span class='text-info'>User Story:</span> As a user, I can click a button to show me a new random quote.", "<span class='text-info'>User Story:</span> As a user, I can click a button to show me a new random quote.",
"<span class='text-info'>Bonus User Story:</span> As a user, I can press a button to tweet out a quote.", "<span class='text-info'>Bonus User Story:</span> As a user, I can press a button to tweet out a quote.",
"Note that you can either put your quotes into an array and show them at random, or use an API to get quotes, such as <a href='http://forismatic.com/en/api/'>http://forismatic.com/en/api/</a>.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.", "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.", "When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>" "If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
@ -203,7 +203,7 @@
"Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:", "Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:",
"<span class='text-info'>User Story:</span> As a user, I can add, subtract, multiply and divide two numbers.", "<span class='text-info'>User Story:</span> As a user, I can add, subtract, multiply and divide two numbers.",
"<span class='text-info'>Bonus User Story:</span> I can clear the input field with a clear button.", "<span class='text-info'>Bonus User Story:</span> I can clear the input field with a clear button.",
"<span class='text-info'>Bonus User Story:</span> I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", "<span class='text-info'>Bonus User Story:</span> I can keep chaining mathematical operations together until I hit the equal button, and the calculator will tell me the correct output.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.", "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.", "When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>" "If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"

View File

@ -1,6 +1,7 @@
{ {
"name": "Responsive Design with Bootstrap", "name": "Responsive Design with Bootstrap",
"order": 3, "order": 3,
"time": "2h",
"challenges": [ "challenges": [
{ {
"id": "bad87fee1348bd9acde08712", "id": "bad87fee1348bd9acde08712",
@ -9,7 +10,7 @@
"Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.", "Now let's go back to our Cat Photo App. This time, we'll style it using the popular Bootstrap responsive CSS framework.",
"Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name <code>Responsive Design</code>.", "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name <code>Responsive Design</code>.",
"With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.", "With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.",
"You can add Bootstrap to any app just by including it with <code>&#60;link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/&#62;</code> at the top of your HTML. But we've gone ahead and automatically added it to your Cat Photo App for you.", "You can add Bootstrap to any app just by including it with <code>&#60;link rel=\"stylesheet\" href=\"//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/&#62;</code> at the top of your HTML. But we've added it for you to this page behind the scenes.",
"To get started, we should nest all of our HTML in a <code>div</code> element with the class <code>container-fluid</code>." "To get started, we should nest all of our HTML in a <code>div</code> element with the class <code>container-fluid</code>."
], ],
"tests": [ "tests": [
@ -2110,7 +2111,7 @@
"tests": [ "tests": [
"assert(editor.match(/<!--/g) && editor.match(/<!--/g).length > 0, 'Start a comment with <code>&#60;!--</code>.')", "assert(editor.match(/<!--/g) && editor.match(/<!--/g).length > 0, 'Start a comment with <code>&#60;!--</code>.')",
"assert(editor.match(/this line/g) && editor.match(/this line/g).length > 0, 'Your comment should have the text <code>You shouldn&#39;t need to modify code below this line</code>.')", "assert(editor.match(/this line/g) && editor.match(/this line/g).length > 0, 'Your comment should have the text <code>You shouldn&#39;t need to modify code below this line</code>.')",
"assert(editor.match(/-->/g) && editor.match(/-->/g).length > 0, 'Be sure to close your comment with <code>--&#62;</code>.')" "assert(editor.match(/-->.*\\n+.+/g), 'Be sure to close your comment with <code>--&#62;</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
"<div class=\"container-fluid\">", "<div class=\"container-fluid\">",

View File

@ -1,17 +1,41 @@
{ {
"name": "Claim Your Front End Development Certificate", "name": "Claim Your Front End Development Certificate",
"order": 12, "order": 12,
"time": "5m",
"challenges": [ "challenges": [
{ {
"id": "561add10cb82ac38a17513be", "id": "561add10cb82ac38a17513be",
"title": "Claim Your Front End Development Certificate", "title": "Claim Your Front End Development Certificate",
"difficulty": 0.00, "challengeSeed": [
"challengeSeed": [], {
"properties": ["isHonest", "isFrontEndCert"],
"apis": ["/certificate/honest", "/certificate/verify/front-end"],
"stepIndex": [1, 2]
}
],
"description": [ "description": [
[ [
"http://i.imgur.com/RlEk2IF.jpg", "http://i.imgur.com/syJxavV.jpg",
"a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", "An image of our Front End Development Certificate",
"Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", "This challenge will give you your verified Front End Development Certificate. Before we issue your certificate, we must verify that you have completed all of our basic and intermediate Bonfires, and all our basic and intermediate Ziplines. You must also accept our Academic Honesty Pledge. Click the button below to start this process.",
""
],
[
"http://i.imgur.com/HArFfMN.jpg",
"The definition of plagiarism: Plagiarism (noun) - copying someone elses work and presenting it as your own without crediting them",
"By clicking below, you pledge that all of your submitted code A) is code you or your pair personally wrote, or B) comes from open source libraries like jQuery, or C) has been clearly attributed to its original authors. You also give us permission to audit your challenge solutions and revoke your certificate if we discover evidence of plagiarism.",
"#"
],
[
"http://i.imgur.com/14F2Van.jpg",
"An image of the text \"Front End Development Certificate requirements\"",
"Let's confirm that you have completed all of our basic and intermediate Bonfires, and all our basic and intermediate Ziplines. Click the button below to verify this.",
"#"
],
[
"http://i.imgur.com/16SIhHO.jpg",
"An image of the word \"Congratulations\"",
"Congratulations! We've added your Front End Development Certificate to your certificate to your portfolio page. Unless you choose to hide your solutions, this certificate will remain publicly visible and verifiable.",
"" ""
] ]
], ],

View File

@ -1,17 +1,42 @@
{ {
"name": "Claim Your Full Stack Development Certificate", "name": "Claim Your Full Stack Development Certificate",
"order": 21, "order": 21,
"time": "5m",
"challenges": [ "challenges": [
{ {
"id": "660add10cb82ac38a17513be", "id": "660add10cb82ac38a17513be",
"title": "Claim Your Full Stack Development Certificate", "title": "Claim Your Full Stack Development Certificate",
"difficulty": 0.00, "difficulty": 0.00,
"challengeSeed": [], "challengeSeed": [
{
"properties": ["isHonest", "isFullStackCert"],
"apis": ["/certificate/honest", "/certificate/verify/full-stack"],
"stepIndex": [1, 2]
}
],
"description": [ "description": [
[ [
"http://i.imgur.com/RlEk2IF.jpg", "http://i.imgur.com/sKYQhdG.jpg",
"a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", "An image of our Full Stack Development Certificate",
"Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", "This challenge will give you your verified Full Stack Development Certificate. Before we issue your certificate, we must verify that you have completed all of Bonfires, Ziplines and Basejumps. You must also accept our Academic Honesty Pledge. Click the button below to start this process.",
""
],
[
"http://i.imgur.com/HArFfMN.jpg",
"The definition of plagiarism: Plagiarism (noun) - copying someone elses work and presenting it as your own without crediting them",
"By clicking below, you pledge that all of your submitted code A) is code you or your pair personally wrote, or B) comes from open source libraries like jQuery, or C) has been clearly attributed to its original authors. You also give us permission to audit your challenge solutions and revoke your certificate if we discover evidence of plagiarism.",
"#"
],
[
"http://i.imgur.com/2qn7tHp.jpg",
"An image of the text \"Full Stack Development Certificate requirements\"",
"Let's confirm that you have completed all of our Bonfires, Ziplines and Basejumps. Click the button below to verify this.",
"#"
],
[
"http://i.imgur.com/16SIhHO.jpg",
"An image of the word \"Congratulations\"",
"Congratulations! We've added your Full Stack Development Certificate to your certificate to your portfolio page. Unless you choose to hide your solutions, this certificate will remain publicly visible and verifiable.",
"" ""
] ]
], ],

View File

@ -0,0 +1,111 @@
{
"name": "Gear up for Success",
"order": 4,
"time": "10m",
"challenges": [
{
"id": "560add65cb82ac38a17513c2",
"title": "Browse Camper News",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/YNwsMXM.gif",
"A gif showing how you can access our Camper News page and click the \"upvote\" button to upvote a story.",
"Click the \"News\" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy.",
""
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
},
{
"id": "560add65cb82ac38a17513c1",
"title": "Reference our Wiki",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/4GO4zcI.gif",
"A gif showing how you can click the \"Wiki\" button in your upper-right corner to access the wiki.",
"Click the \"Wiki\" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.",
""
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
},
{
"id": "570add8ccb82ac38a17513c3",
"title": "Join our LinkedIn Alumni Network",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/vJyiXzU.gif",
"A gif showing how you can click the link below and fill in the necessary fields to add your Free Code Camp studies to your LinkedIn profile.",
"You can add Free Code Camp to your LinkedIn education background. Set your graduation date as next year. For \"Degree\", type \"Full Stack Web Development Certification\". For \"Field of study\", type \"Computer Software Engineering\". Then click \"Save Changes\".",
"https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp"
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
},
{
"id": "560add8ccb81ac38a17513c4",
"title": "Commit to a Goal and a Nonprofit",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/Og1ifsn.gif",
"A gif showing how you can commit to a goal for your Free Code Camp studies and pledge a monthly donation to a nonprofit to give you external motivation to reach that goal.",
"You can set a goal and pledge to donate to a nonprofit each month until you achieve that goal. give you external motivation in your quest to learn to code, as well as the opportunity to help nonprofits right away. Choose your goal, choose a monthly donation. When you click \"commit\", the nonprofit's donate page will open in a new tab. You can change your commitment or stop it at any time.",
"/commit"
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
}
]
}

View File

@ -1,6 +1,7 @@
{ {
"name": "Get Started with Free Code Camp", "name": "Get Started with Free Code Camp",
"order": 1, "order": 1,
"time": "10m",
"challenges": [ "challenges": [
{ {
"id": "560add10cb82ac38a17513be", "id": "560add10cb82ac38a17513be",
@ -9,13 +10,13 @@
"description": [ "description": [
[ [
"http://i.imgur.com/RlEk2IF.jpg", "http://i.imgur.com/RlEk2IF.jpg",
"a picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits", "A picture of Free Code Camp's 4 benefits: Get connected, Learn JavaScript, Build your Portfolio, Help nonprofits",
"Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.", "Welcome to Free Code Camp. We're an open source community of busy people who learn to code and help nonprofits.",
"" ""
], ],
[ [
"http://i.imgur.com/pYsTbjI.jpg", "http://i.imgur.com/pYsTbjI.jpg",
"a screenshot of our curriculum alongside a screenshot of our chat room.", "A screenshot of our curriculum alongside a screenshot of our chat room.",
"Learning to code is hard. To succeed, you'll need lots of practice and support. That's why we've created a rigorous curriculum and supportive community.", "Learning to code is hard. To succeed, you'll need lots of practice and support. That's why we've created a rigorous curriculum and supportive community.",
"" ""
], ],
@ -32,14 +33,14 @@
"" ""
], ],
[ [
"http://i.imgur.com/q4IjuCL.jpg", "http://i.imgur.com/sKYQhdG.jpg",
"a screenshot of our Front End Development Certificate", "A screenshot of our Front End Development Certificate",
"About half way through our curriculum, you'll earn a verified Front End Development Certificate. If you can finish our entire curriculum, you'll earn a verified Full Stack Development Certificate.", "About half way through our curriculum, you'll earn a verified Front End Development Certificate. If you can finish our entire curriculum, you'll earn a verified Full Stack Development Certificate.",
"" ""
], ],
[ [
"http://i.imgur.com/yXyxbDd.jpg", "http://i.imgur.com/yXyxbDd.jpg",
"a screen shot of our nonprofit project directory.", "A screen shot of our nonprofit project directory.",
"Then you'll build several real-life projects for nonprofits. By the time you finish, you'll have a portfolio of real apps that people use every day.", "Then you'll build several real-life projects for nonprofits. By the time you finish, you'll have a portfolio of real apps that people use every day.",
"" ""
] ]
@ -65,7 +66,7 @@
"description": [ "description": [
[ [
"http://i.imgur.com/EAR7Lvh.jpg", "http://i.imgur.com/EAR7Lvh.jpg",
"a screenshot of our one of our Gitter chat rooms.", "A screenshot of our one of our Gitter chat rooms.",
"Now let's join Free Code Camp's chat rooms. You can come here any time of day to hang out, ask questions, or find another camper to pair program with. First you'll need a GitHub account.", "Now let's join Free Code Camp's chat rooms. You can come here any time of day to hang out, ask questions, or find another camper to pair program with. First you'll need a GitHub account.",
"" ""
], ],
@ -82,15 +83,15 @@
"https://github.com/settings/profile" "https://github.com/settings/profile"
], ],
[ [
"http://i.imgur.com/OXL3G3n.gif", "http://i.imgur.com/pYk0wOk.gif",
"Click the link below to navigate to Free Code Camp's open-source repository. In the upper right hand corner, you can click the \"star\" button to star this repository.", "A gif showing how you can star a GitHub repo.",
"Go to Free Code Camp's open-source repository and \"star\" it. \"Starring\" is the GitHub equivalent of \"liking\" something.", "Go to Free Code Camp's open-source repository and \"star\" it. \"Starring\" is the GitHub equivalent of \"liking\" something.",
"https://github.com/freecodecamp/freecodecamp" "https://github.com/freecodecamp/freecodecamp"
], ],
[ [
"http://i.imgur.com/EZHzKCV.gif", "http://i.imgur.com/zwYPeQT.gif",
"A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.", "A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.",
" Now that you have a GitHub account, you can join our main chat room by logging in with GitHub. Introduce yourself by saying \"Hello world!\". Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", "Now that you have a GitHub account, you can join our main chat room by logging in with GitHub. Introduce yourself by saying \"Hello world!\". Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.",
"https://gitter.im/FreeCodeCamp/FreeCodeCamp" "https://gitter.im/FreeCodeCamp/FreeCodeCamp"
], ],
[ [
@ -112,7 +113,7 @@
"" ""
], ],
[ [
"http://i.imgur.com/SLQ27Gr.gif", "http://i.imgur.com/WvQvNGN.gif",
"A gif showing how you can click the link below to download a native chat room app for your computer.", "A gif showing how you can click the link below to download a native chat room app for your computer.",
"You can also download the chat room app to your computer or phone.", "You can also download the chat room app to your computer or phone.",
"https://gitter.im/apps" "https://gitter.im/apps"
@ -134,51 +135,13 @@
}, },
{ {
"id": "560add56cb82ac38a17513c0", "id": "560add56cb82ac38a17513c0",
"title": "Configure your Public Profile", "title": "Configure your Code Portfolio",
"challengeSeed": [], "challengeSeed": [],
"description": [ "description": [
[ [
"http://i.imgur.com/FkEzbto.gif", "http://i.imgur.com/tP2ccTE.gif",
"A gif showing how you can click your profile image in your upper right hand corner to access the account page and connect GitHub.", "A gif showing how you can click your profile image in your upper right hand corner to your code portfolio and connect GitHub.",
"Check out your portfolio page. Click your picture your upper right hand corner. To activate your portfolio page, you'll need to link your GitHub account with Free Code Camp.", "Check out your code portfolio. Click your picture in your upper right hand corner. To activate your code portfolio, you'll need to link your GitHub account with Free Code Camp. Your code portfolio shows your progress and how many Brownie Points you have. You can get Brownie Points by completing challenges and by helping other campers in our chat rooms. If you get Brownie Points on several days in a row, you'll get a streak.",
""
],
[
"http://i.imgur.com/WKzEr1q.gif",
"A gif showing how you can access your profile page and hover over different days to see how many brownie points you got on those days.",
"Your portfolio page shows your progress and how many Brownie Points you have. You can get Brownie Points by completing challenges and by helping other campers in our chat rooms. If you get Brownie Points on several days in a row, you'll get a streak.",
""
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
},
{
"id": "560add65cb82ac38a17513c1",
"title": "Try our Wiki and Camper News",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/DoOqkNW.gif",
"A gif showing how you can click the \"Wiki\" button in your upper-right corner to access the wiki.",
"Try this: Click the \"Wiki\" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.",
""
],
[
"http://i.imgur.com/nmSiMy1.gif",
"A gif showing how you can access our Camper News page and click the \"upvote\" button to upvote a story.",
"Click the \"News\" button in your upper right hand corner. You can browse links on Camper News and upvote ones that you enjoy.",
"" ""
] ]
], ],
@ -208,9 +171,9 @@
"" ""
], ],
[ [
"http://i.imgur.com/EZHzKCV.gif", "http://i.imgur.com/fTFMjwf.gif",
"A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.", "A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.",
"Find your city on this list, click the \"Facebook\" link, then click the \"Join group\" button to apply to join your city's Facebook group (someone from the campsite should approve you shortly). If your city isn't on this list, scroll to the bottom of the wiki article for instructions for how you can create your city's Campsite.", "Find your city on this list and click it. This will take you to your city's Campsite's Facebook group. Click the \"Join group\" button to apply to join your city's Facebook group. Someone from the campsite should approve you shortly. If your city isn't on this list, scroll to the bottom of the wiki article for instructions for how you can create your city's Campsite.",
"https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites" "https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites"
] ]
], ],
@ -228,38 +191,6 @@
"namePt": "", "namePt": "",
"descriptionPt": [] "descriptionPt": []
}, },
{
"id": "560add8ccb82ac38a17513c3",
"title": "Join our Alumni Network and Commit to Your Goal",
"challengeSeed": [],
"description": [
[
"http://i.imgur.com/P7qfJXt.gif",
"A gif showing how you can click the link below and fill in the necessary fields to add your Free Code Camp studies to your LinkedIn profile.",
"You can add Free Code Camp to your LinkedIn education background. Set your graduation date as next year. For \"Degree\", type \"Full Stack Web Development\". For \"Field of study\", type \"Computer Software Engineering\". Then click \"Save Changes\".",
"https://www.linkedin.com/profile/edit-education?school=Free+Code+Camp"
],
[
"",
"",
"Free Code Camp will always be free. If you want to feel more motivated to earn our certificates faster, we encourage you to instead donate each month to a nonprofit.",
""
]
],
"type": "Waypoint",
"challengeType": 7,
"tests": [],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
"descriptionFr": [],
"nameRu": "",
"descriptionRu": [],
"nameEs": "",
"descriptionEs": [],
"namePt": "",
"descriptionPt": []
},
{ {
"id": "560add8ccb82ac38a17513c4", "id": "560add8ccb82ac38a17513c4",
"title": "Learn What to Do If You Get Stuck", "title": "Learn What to Do If You Get Stuck",
@ -290,8 +221,8 @@
"https://gitter.im/FreeCodeCamp/Help" "https://gitter.im/FreeCodeCamp/Help"
], ],
[ [
"http://i.imgur.com/WsfzvVo.gif", "http://i.imgur.com/ZRgXraT.gif",
"A gif showing us clicking the \"map\" button in our upper right hand corner and browsing our challenge map.", "A gif showing us scrolling through our challenge map.",
"Now you're ready to start coding! The \"Map\" button in your upper right hand corner will show you our challenge map. This map shows all our coding challenges. We recommend that you complete these from top to bottom, at a sustainable pace. You can also return to your next challenge by clicking the \"Learn\" button.", "Now you're ready to start coding! The \"Map\" button in your upper right hand corner will show you our challenge map. This map shows all our coding challenges. We recommend that you complete these from top to bottom, at a sustainable pace. You can also return to your next challenge by clicking the \"Learn\" button.",
"" ""
] ]

View File

@ -1,6 +1,7 @@
{ {
"name": "Git", "name": "Git",
"order" : 17, "order" : 17,
"time": "3h",
"challenges": [ "challenges": [
{ {
"id": "bd7353d8c341eddeaeb5bd0f", "id": "bd7353d8c341eddeaeb5bd0f",

View File

@ -1,6 +1,7 @@
{ {
"name": "Hikes", "name": "Hikes",
"order": 0.050, "order": 0.050,
"time": "3h",
"challenges": [ "challenges": [
{ {
"id": "bd7128d8c441eddfbeb5bddf", "id": "bd7128d8c441eddfbeb5bddf",

View File

@ -1,6 +1,7 @@
{ {
"name": "HTML5 and CSS", "name": "HTML5 and CSS",
"order": 2, "order": 2,
"time": "3h",
"challenges": [ "challenges": [
{ {
"id": "bd7123c8c441eddfaeb5bdef", "id": "bd7123c8c441eddfaeb5bdef",
@ -541,7 +542,6 @@
"assert($(\"p\").length > 1, 'You need 2 <code>p</code> elements with Kitty Ipsum text.')", "assert($(\"p\").length > 1, 'You need 2 <code>p</code> elements with Kitty Ipsum text.')",
"assert(editor.match(/<\\/p>/g) && editor.match(/<\\/p>/g).length === editor.match(/<p/g).length, 'Make sure each of your <code>p</code> elements has a closing tag.')", "assert(editor.match(/<\\/p>/g) && editor.match(/<\\/p>/g).length === editor.match(/<p/g).length, 'Make sure each of your <code>p</code> elements has a closing tag.')",
"assert.isTrue((/Purr\\s+jump\\s+eat/gi).test($(\"p\").text()), 'Your <code>p</code> element should contain the first few words of the provided additional <code>kitty ipsum text</code>.')", "assert.isTrue((/Purr\\s+jump\\s+eat/gi).test($(\"p\").text()), 'Your <code>p</code> element should contain the first few words of the provided additional <code>kitty ipsum text</code>.')",
"assert($(\"p.red-text\").length === 2, 'Give each of your <code>p</code> elements the <code>red-text</code> class.')",
"assert($(\"p\").css(\"font-size\") === \"16px\", 'Give elements with the <code>red-text</code> class a <code>font-size</code> of 16px.')" "assert($(\"p\").css(\"font-size\") === \"16px\", 'Give elements with the <code>red-text</code> class a <code>font-size</code> of 16px.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -1122,7 +1122,7 @@
"assert($(\"a\").text().match(/cat\\sphotos/gi), 'Your <code>a</code> element should have the anchor text of \"cat photos\"')", "assert($(\"a\").text().match(/cat\\sphotos/gi), 'Your <code>a</code> element should have the anchor text of \"cat photos\"')",
"assert($(\"p\") && $(\"p\").length > 2, 'Create a new <code>p</code> element around your <code>a</code> element.')", "assert($(\"p\") && $(\"p\").length > 2, 'Create a new <code>p</code> element around your <code>a</code> element.')",
"assert($(\"a[href=\\\"http://www.freecatphotoapp.com\\\"]\").parent().is(\"p\"), 'Your <code>a</code> element should be nested within your new <code>p</code> element.')", "assert($(\"a[href=\\\"http://www.freecatphotoapp.com\\\"]\").parent().is(\"p\"), 'Your <code>a</code> element should be nested within your new <code>p</code> element.')",
"assert($(\"p\").text().match(/^View\\smore\\s/gi), 'Your <code>p</code> element should have the text \"View more \" (with a space after it).')", "assert($(\"p\").text().match(/^\\s*View\\smore\\s/gi), 'Your <code>p</code> element should have the text \"View more \" (with a space after it).')",
"assert(!$(\"a\").text().match(/View\\smore/gi), 'Your <code>a</code> element should <em>not</em> have the text \"View more\".')", "assert(!$(\"a\").text().match(/View\\smore/gi), 'Your <code>a</code> element should <em>not</em> have the text \"View more\".')",
"assert(editor.match(/<\\/p>/g) && editor.match(/<p/g) && editor.match(/<\\/p>/g).length === editor.match(/<p/g).length, 'Make sure each of your <code>p</code> elements has a closing tag.')", "assert(editor.match(/<\\/p>/g) && editor.match(/<p/g) && editor.match(/<\\/p>/g).length === editor.match(/<p/g).length, 'Make sure each of your <code>p</code> elements has a closing tag.')",
"assert(editor.match(/<\\/a>/g) && editor.match(/<a/g) && editor.match(/<\\/a>/g).length === editor.match(/<a/g).length, 'Make sure each of your <code>a</code> elements has a closing tag.')" "assert(editor.match(/<\\/a>/g) && editor.match(/<a/g) && editor.match(/<\\/a>/g).length === editor.match(/<a/g).length, 'Make sure each of your <code>a</code> elements has a closing tag.')"
@ -1411,7 +1411,7 @@
"assert($(\"ul\").length > 0, 'Create a <code>ul</code> element.')", "assert($(\"ul\").length > 0, 'Create a <code>ul</code> element.')",
"assert($(\"ul li\").length > 2, 'You should have three <code>li</code> elements within your <code>ul</code> element.')", "assert($(\"ul li\").length > 2, 'You should have three <code>li</code> elements within your <code>ul</code> element.')",
"assert(editor.match(/<\\/ul>/g) && editor.match(/<ul/g) && editor.match(/<\\/ul>/g).length === editor.match(/<ul/g).length, 'Make sure your <code>ul</code> element has a closing tag.')", "assert(editor.match(/<\\/ul>/g) && editor.match(/<ul/g) && editor.match(/<\\/ul>/g).length === editor.match(/<ul/g).length, 'Make sure your <code>ul</code> element has a closing tag.')",
"assert(editor.match(/<\\/li>/g) && editor.match(/<li>/g) && editor.match(/<\\/li>/g).length === editor.match(/<li>/g).length, 'Make sure your <code>li</code> element has a closing tag.')" "assert(editor.match(/<\\/li>/g) && editor.match(/<li[\\s>]/g) && editor.match(/<\\/li>/g).length === editor.match(/<li[\\s>]/g).length, 'Make sure your <code>li</code> elements have closing tags.')"
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
@ -3702,7 +3702,7 @@
"Let's replace the hex code in our <code>body</code> element's background color with the RGB value for black: <code>rgb(0, 0, 0)</code>" "Let's replace the hex code in our <code>body</code> element's background color with the RGB value for black: <code>rgb(0, 0, 0)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(0, 0, 0)\", 'Give your <code>body</code> element the <code>background-color</code> of black.')", "assert($(\"body\").css(\"background-color\") === \"rgb(0, 0, 0)\", 'Your <code>body</code> element should have a black background.')",
"assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*0\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of black. For example <code>body { color&#58; rgb&#40;0&#44; 0&#44; 0&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*0\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of black. For example <code>body { color&#58; rgb&#40;0&#44; 0&#44; 0&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3736,7 +3736,7 @@
"Change the <code>body</code> element's background color from the RGB value for black to the <code>rgb</code> value for white: <code>rgb(255, 255, 255)</code>" "Change the <code>body</code> element's background color from the RGB value for black to the <code>rgb</code> value for white: <code>rgb(255, 255, 255)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(255, 255, 255)\", 'Give your <code>body</code> element the <code>background-color</code> of white.')", "assert($(\"body\").css(\"background-color\") === \"rgb(255, 255, 255)\", 'Your <code>body</code> should have a white background.')",
"assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*255\\s*,\\s*255\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of white. For example <code>body { background-color&#58; rgb&#40;255&#44; 255 &#44; 255&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*255\\s*,\\s*255\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of white. For example <code>body { background-color&#58; rgb&#40;255&#44; 255 &#44; 255&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3770,7 +3770,7 @@
"Change the <code>body</code> element's background color to the RGB value red: <code>rgb(255, 0, 0)</code>" "Change the <code>body</code> element's background color to the RGB value red: <code>rgb(255, 0, 0)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(255, 0, 0)\", 'Give your <code>body</code> element the <code>background-color</code> of red.')", "assert($(\"body\").css(\"background-color\") === \"rgb(255, 0, 0)\", 'Your <code>body</code> should have a red background.')",
"assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*0\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of red. For example <code>body { background-color&#58; rgb&#40;255&#44; 0&#44; 0&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*0\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of red. For example <code>body { background-color&#58; rgb&#40;255&#44; 0&#44; 0&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3802,7 +3802,7 @@
"Now change the <code>body</code> element's background color to the <code>rgb</code> value green: <code>rgb(0, 255, 0)</code>" "Now change the <code>body</code> element's background color to the <code>rgb</code> value green: <code>rgb(0, 255, 0)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(0, 255, 0)\", 'Give your <code>body</code> element the <code>background-color</code> of green.')", "assert($(\"body\").css(\"background-color\") === \"rgb(0, 255, 0)\", 'Your <code>body</code> element should have a green background.')",
"assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*255\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of green. For example <code>body { background-color&#58; rgb&#40;0&#44; 255&#44; 0&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*255\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of green. For example <code>body { background-color&#58; rgb&#40;0&#44; 255&#44; 0&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3834,7 +3834,7 @@
"Change the <code>body</code> element's background color to the RGB value blue: <code>rgb(0, 0, 255)</code>" "Change the <code>body</code> element's background color to the RGB value blue: <code>rgb(0, 0, 255)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(0, 0, 255)\", 'Give your <code>body</code> element the background-color of blue.')", "assert($(\"body\").css(\"background-color\") === \"rgb(0, 0, 255)\", 'Your <code>body</code> element should have a blue background.')",
"assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*0\\s*,\\s*255\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of blue. For example <code>body { background-color&#58; rgb&#40;0&#44; 0&#44; 255&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*0\\s*,\\s*0\\s*,\\s*255\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of blue. For example <code>body { background-color&#58; rgb&#40;0&#44; 0&#44; 255&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3867,7 +3867,7 @@
"Change the <code>body</code> element's background color to the RGB value orange: <code>rgb(255, 165, 0)</code>" "Change the <code>body</code> element's background color to the RGB value orange: <code>rgb(255, 165, 0)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(255, 165, 0)\", 'Give your <code>body</code> element the background-color of orange.')", "assert($(\"body\").css(\"background-color\") === \"rgb(255, 165, 0)\", 'Your <code>body</code> element should have an orange background.')",
"assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*165\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of orange. For example <code>body { background-color&#58; rgb&#40;255&#44; 165&#44; 0&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*255\\s*,\\s*165\\s*,\\s*0\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of orange. For example <code>body { background-color&#58; rgb&#40;255&#44; 165&#44; 0&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [
@ -3900,7 +3900,7 @@
"Change the <code>body</code> element's background color to the RGB value for gray: <code>rgb(128, 128, 128)</code>" "Change the <code>body</code> element's background color to the RGB value for gray: <code>rgb(128, 128, 128)</code>"
], ],
"tests": [ "tests": [
"assert($(\"body\").css(\"background-color\") === \"rgb(128, 128, 128)\", 'Give your <code>body</code> element the background-color of gray.')", "assert($(\"body\").css(\"background-color\") === \"rgb(128, 128, 128)\", 'Your <code>body</code> element should have a gray background.')",
"assert(editor.match(/rgb\\s*\\(\\s*128\\s*,\\s*128\\s*,\\s*128\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of gray. For example <code>body { background-color&#58; rgb&#40;128&#44; 128&#44; 128&#41;; }</code>.')" "assert(editor.match(/rgb\\s*\\(\\s*128\\s*,\\s*128\\s*,\\s*128\\s*\\)/ig), 'Use <code>rgb</code> to give your <code>body</code> element the <code>background-color</code> of gray. For example <code>body { background-color&#58; rgb&#40;128&#44; 128&#44; 128&#41;; }</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [

View File

@ -1,6 +1,7 @@
{ {
"name": "Intermediate Algorithm Scripting", "name": "Intermediate Algorithm Scripting",
"order": 9, "order": 10,
"time": "50h",
"challenges": [ "challenges": [
{ {
"id": "a3566b1109230028080c9345", "id": "a3566b1109230028080c9345",
@ -65,7 +66,9 @@
"assert.deepEqual(diff([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[]</code>.');", "assert.deepEqual(diff([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[]</code>.');",
"assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: <code>[1, 2, 3, 5], [1, 2, 3, 4, 5]</code> should return <code>[4]</code>.');", "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: <code>[1, 2, 3, 5], [1, 2, 3, 4, 5]</code> should return <code>[4]</code>.');",
"assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: <code>[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]</code> should return <code>[\"piglet\", 4]</code>.');", "assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: <code>[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]</code> should return <code>[\"piglet\", 4]</code>.');",
"assert.deepEqual(diff([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: <code>[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code> should return <code>[\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code>.');" "assert.deepEqual(diff([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: <code>[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code> should return <code>[\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code>.');",
"assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: <code>[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]</code> should return <code>[1, \"calf\", 3, \"piglet\", 7, \"filly\"]</code>.');",
"assert.deepEqual(diff([1, 2, 3, 3], [1]), [2, 3], 'message: <code>[1, 2, 3, 3], [1]</code> should return <code>[2, 3]</code>.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Comparison Operators", "Comparison Operators",
@ -355,7 +358,7 @@
"assert.strictEqual(boo([].slice), false, 'message: <code>boo([].slice)</code> should return false.');", "assert.strictEqual(boo([].slice), false, 'message: <code>boo([].slice)</code> should return false.');",
"assert.strictEqual(boo({ \"a\": 1 }), false, 'message: <code>boo({ \"a\": 1 })</code> should return false.');", "assert.strictEqual(boo({ \"a\": 1 }), false, 'message: <code>boo({ \"a\": 1 })</code> should return false.');",
"assert.strictEqual(boo(1), false, 'message: <code>boo(1)</code> should return false.');", "assert.strictEqual(boo(1), false, 'message: <code>boo(1)</code> should return false.');",
"assert.strictEqual(boo(NaN), false, 'message: <code>boo(NaN)</code> should return true.');", "assert.strictEqual(boo(NaN), false, 'message: <code>boo(NaN)</code> should return false.');",
"assert.strictEqual(boo(\"a\"), false, 'message: <code>boo(\"a\")</code> should return false.');" "assert.strictEqual(boo(\"a\"), false, 'message: <code>boo(\"a\")</code> should return false.');"
], ],
"MDNlinks": [ "MDNlinks": [
@ -511,7 +514,7 @@
"sumFibs(4);" "sumFibs(4);"
], ],
"tests": [ "tests": [
"assert(typeof(sumFibs(1)) === \"number\", 'message: <code>sumFibs()</code> should return a number.');", "assert(typeof(sumFibs(1)) === \"number\", 'message: <code>sumFibs(1)</code> should return a number.');",
"assert.deepEqual(sumFibs(1000), 1785, 'message: <code>sumFibs(1000)</code> should return 1785.');", "assert.deepEqual(sumFibs(1000), 1785, 'message: <code>sumFibs(1000)</code> should return 1785.');",
"assert.deepEqual(sumFibs(4000000), 4613732, 'message: <code>sumFibs(4000000)</code> should return 4613732.');", "assert.deepEqual(sumFibs(4000000), 4613732, 'message: <code>sumFibs(4000000)</code> should return 4613732.');",
"assert.deepEqual(sumFibs(4), 5, 'message: <code>sumFibs(4)</code> should return 5.');", "assert.deepEqual(sumFibs(4), 5, 'message: <code>sumFibs(4)</code> should return 5.');",
@ -823,7 +826,7 @@
"assert.isUndefined(add(2)([3]), 'message: <code>add(2)([3])</code> should return undefined.');" "assert.isUndefined(add(2)([3]), 'message: <code>add(2)([3])</code> should return undefined.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Global Function Object", "Closures",
"Arguments object" "Arguments object"
], ],
"type": "bonfire", "type": "bonfire",

View File

@ -1,6 +1,7 @@
{ {
"name": "Intermediate Front End Development Projects", "name": "Intermediate Front End Development Projects",
"order": 11, "order": 11,
"time": "200h",
"challenges": [ "challenges": [
{ {
"id": "bd7158d8c442eddfaeb5bd10", "id": "bd7158d8c442eddfaeb5bd10",

View File

@ -1,6 +1,7 @@
{ {
"name": "jQuery", "name": "jQuery",
"order": 4, "order": 5,
"time": "2h",
"challenges": [ "challenges": [
{ {
"id": "bad87fee1348bd9acdd08826", "id": "bad87fee1348bd9acdd08826",

View File

@ -1,23 +0,0 @@
{
"name": "JSON APIs and Ajax",
"order": 10,
"challenges": [
{
"id": "bad88fee1348bd9ae8c08416",
"title": "Stand in challenge",
"dashedName": "waypoint-stand-in-challenge",
"difficulty": 3.24,
"description": [
""
],
"tests": [
],
"challengeSeed": [
""
],
"challengeType": 0,
"type": "waypoint"
}
]
}

View File

@ -1,6 +1,7 @@
{ {
"name": "MongoDB", "name": "MongoDB",
"order" : 19, "order" : 19,
"time": "3h",
"challenges": [ "challenges": [
{ {
"id": "bd7243d8c341eddeaeb5bd0f", "id": "bd7243d8c341eddeaeb5bd0f",

View File

@ -1,6 +1,7 @@
{ {
"name": "Node.js and Express.js", "name": "Node.js and Express.js",
"order" : 18, "order" : 18,
"time": "20h",
"challenges": [ "challenges": [
{ {
"id": "bd7153d8c441eddfaeb5bd0f", "id": "bd7153d8c441eddfaeb5bd0f",
@ -33,13 +34,7 @@
"Complete \"Publish\"", "Complete \"Publish\"",
"Complete \"Version\"", "Complete \"Version\"",
"Complete \"Publish Again\"", "Complete \"Publish Again\"",
"Complete \"Dist Tag\"", "Note Once you've completed these steps, you can skip the rest (which are currently buggy) and move on to our next challenge."
"Complete \"Dist Tag Removal\"",
"Complete \"Outdated\"",
"Complete \"Update\"",
"Complete \"RM\"",
"Complete \"Finale\"",
"Once you've completed these steps, move on to our next challenge."
], ],
"type": "waypoint", "type": "waypoint",
"challengeType": 2, "challengeType": 2,

View File

@ -1,6 +1,7 @@
{ {
"name": "Object Oriented and Functional Programming", "name": "Object Oriented and Functional Programming",
"order": 6, "order": 7,
"time": "1h",
"note": [ "note": [
"Methods", "Methods",
"Closures", "Closures",
@ -185,7 +186,7 @@
], ],
"tests":[ "tests":[
"assert.deepEqual(array, [4,5,6,7,8], 'message: You should add three to each value in the array.');", "assert.deepEqual(array, [4,5,6,7,8], 'message: You should add three to each value in the array.');",
"assert(editor.getValue().match(/\\.map\\(/gi), 'message: You should be making use of the map method.');", "assert(editor.getValue().match(/\\.map\\s*\\(/gi), 'message: You should be making use of the map method.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'message: You should only modify the array with <code>.map</code>.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'message: You should only modify the array with <code>.map</code>.');"
], ],
"challengeSeed":[ "challengeSeed":[
@ -206,14 +207,14 @@
"title":"Condense arrays with .reduce", "title":"Condense arrays with .reduce",
"difficulty":0, "difficulty":0,
"description":[ "description":[
"Reduce can be useful for condensing an array or numbers into one value.", "Reduce can be useful for condensing an array of numbers into one value.",
"<code>var singleVal = array.reduce(function(previousVal, currentVal){</code>", "<code>var singleVal = array.reduce(function(previousVal, currentVal){</code>",
"<code>&thinsp;&thinsp;return previousVal+currentVal;</code>", "<code>&thinsp;&thinsp;return previousVal+currentVal;</code>",
"<code>});</code>" "<code>});</code>"
], ],
"tests":[ "tests":[
"assert(singleVal == 30, 'message: <code>singleVal</code> should have been set to the result of you reduce operation.');", "assert(singleVal == 30, 'message: <code>singleVal</code> should have been set to the result of your reduce operation.');",
"assert(editor.getValue().match(/\\.reduce\\(/gi), 'message: You should have made use of the reduce method.');" "assert(editor.getValue().match(/\\.reduce\\s*\\(/gi), 'message: You should have made use of the reduce method.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = [4,5,6,7,8];", "var array = [4,5,6,7,8];",
@ -240,8 +241,8 @@
"<code>});</code>" "<code>});</code>"
], ],
"tests":[ "tests":[
"assert.deepEqual(array, [1,2,3,4], 'message: You should have removed all the values from the array that are greater than 4.');", "assert.deepEqual(array, [1,2,3,4,5], 'message: You should have removed all the values from the array that are greater than 5.');",
"assert(editor.getValue().match(/array\\.filter\\(/gi), 'message: You should be using the filter method to remove the values from the array.');", "assert(editor.getValue().match(/array\\.filter\\s*\\(/gi), 'message: You should be using the filter method to remove the values from the array.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'message: You should only be using <code>.filter</code> to modify the contents of the array.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'message: You should only be using <code>.filter</code> to modify the contents of the array.');"
], ],
"challengeSeed":[ "challengeSeed":[
@ -269,7 +270,7 @@
"tests":[ "tests":[
"assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'message: You should have sorted the array alphabetically.');", "assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'message: You should have sorted the array alphabetically.');",
"assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'message: You should be sorting the array using sort.');", "assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'message: You should be sorting the array using sort.');",
"assert(editor.getValue().match(/\\.sort\\(\\)/gi), 'message: You should have made use of the sort method.');" "assert(editor.getValue().match(/\\.sort\\s*\\(\\)/gi), 'message: You should have made use of the sort method.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = ['beta', 'alpha', 'charlie'];", "var array = ['beta', 'alpha', 'charlie'];",
@ -291,7 +292,7 @@
], ],
"tests": [ "tests": [
"assert.deepEqual(array, [7,6,5,4,3,2,1], 'message: You should reverse the array.');", "assert.deepEqual(array, [7,6,5,4,3,2,1], 'message: You should reverse the array.');",
"assert(editor.getValue().match(/\\.reverse\\(\\)/gi), 'message: You should use the reverse method.');", "assert(editor.getValue().match(/\\.reverse\\s*\\(\\)/gi), 'message: You should use the reverse method.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), 'message: You should return <code>[7,6,5,4,3,2,1]</code>.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), 'message: You should return <code>[7,6,5,4,3,2,1]</code>.');"
], ],
"challengeSeed": [ "challengeSeed": [
@ -315,7 +316,7 @@
], ],
"tests": [ "tests": [
"assert.deepEqual(array, [1,2,3,4,5,6], 'You should concat the two arrays together.');", "assert.deepEqual(array, [1,2,3,4,5,6], 'You should concat the two arrays together.');",
"assert(editor.getValue().match(/\\.concat\\(/gi), 'message: You should be use the concat method to merge the two arrays.');", "assert(editor.getValue().match(/\\.concat\\s*\\(/gi), 'message: You should be use the concat method to merge the two arrays.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'message: You should only modify the two arrays without changing the origional ones.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'message: You should only modify the two arrays without changing the origional ones.');"
], ],
"challengeSeed": [ "challengeSeed": [

View File

@ -1,6 +1,7 @@
{ {
"name": "Upper Intermediate Algorithm Scripting", "name": "Upper Intermediate Algorithm Scripting",
"order": 13, "order": 13,
"time": "50h",
"challenges": [ "challenges": [
{ {
"id": "a2f1d72d9b908d0bd72bb9f6", "id": "a2f1d72d9b908d0bd72bb9f6",
@ -27,7 +28,12 @@
"assert.deepEqual(bob.lastName, undefined, 'message: <code>bob.lastName</code> should return undefined.');", "assert.deepEqual(bob.lastName, undefined, 'message: <code>bob.lastName</code> should return undefined.');",
"assert.deepEqual(bob.getFirstName(), 'Bob', 'message: <code>bob.getFirstName()</code> should return \"Bob\".');", "assert.deepEqual(bob.getFirstName(), 'Bob', 'message: <code>bob.getFirstName()</code> should return \"Bob\".');",
"assert.deepEqual(bob.getLastName(), 'Ross', 'message: <code>bob.getLastName()</code> should return \"Ross\".');", "assert.deepEqual(bob.getLastName(), 'Ross', 'message: <code>bob.getLastName()</code> should return \"Ross\".');",
"assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: <code>bob.getFullName()</code> should return \"Bob Ross\".');" "assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: <code>bob.getFullName()</code> should return \"Bob Ross\".');",
"assert.strictEqual((function () { bob.setFirstName(\"Haskell\"); return bob.getFullName(); })(), 'Haskell Ross', 'message: <code>bob.getFullName()</code> should return \"Haskell Ross\" after <code>bob.setFirstName(\"Haskell\")</code>.');",
"assert.strictEqual((function () { bob.setLastName(\"Curry\"); return bob.getFullName(); })(), 'Bob Curry', 'message: <code>bob.getFullName()</code> should return \"Bob Curry\" after <code>bob.setLastName(\"Curry\")</code>.');",
"assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFullName(); })(), 'Haskell Curry', 'message: <code>bob.getFullName()</code> should return \"Haskell Curry\" after <code>bob.setFullName(\"Haskell Curry\")</code>.');",
"assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFirstName(); })(), 'Haskell', 'message: <code>bob.getFirstName()</code> should return \"Haskell\" after <code>bob.setFullName(\"Haskell Curry\")</code>.');",
"assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getLastName(); })(), 'Curry', 'message: <code>bob.getLastName()</code> should return \"Curry\" after <code>bob.setFullName(\"Haskell Curry\")</code>.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Closures", "Closures",
@ -105,10 +111,10 @@
], ],
"tests": [ "tests": [
"assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11, 'message: <code>pairwise([1, 4, 2, 3, 0, 5], 7)</code> should return 11.');", "assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11, 'message: <code>pairwise([1, 4, 2, 3, 0, 5], 7)</code> should return 11.');",
"expect(pairwise([1, 3, 2, 4], 4), 1, 'message: <code>pairwise([1, 3, 2, 4], 4), 1</code> should return 1.');", "assert.deepEqual(pairwise([1, 3, 2, 4], 4), 1, 'message: <code>pairwise([1, 3, 2, 4], 4), 1</code> should return 1.');",
"expect(pairwise([1,1,1], 2), 1, 'message: <code>pairwise([1,1,1], 2)</code> should return 1.');", "assert.deepEqual(pairwise([1,1,1], 2), 1, 'message: <code>pairwise([1,1,1], 2)</code> should return 1.');",
"expect(pairwise([0, 0, 0, 0, 1, 1], 1), 10, 'message: <code>pairwise([0, 0, 0, 0, 1, 1], 1)</code> should return 10.');", "assert.deepEqual(pairwise([0, 0, 0, 0, 1, 1], 1), 10, 'message: <code>pairwise([0, 0, 0, 0, 1, 1], 1)</code> should return 10.');",
"expect(pairwise([], 100), 0, 'message: <code>pairwise([], 100)</code> should return 0.');" "assert.deepEqual(pairwise([], 100), 0, 'message: <code>pairwise([], 100)</code> should return 0.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Array.reduce()" "Array.reduce()"

View File

@ -43,6 +43,7 @@ Challenge.destroyAll(function(err, info) {
var challengeSpec = require('./challenges/' + file); var challengeSpec = require('./challenges/' + file);
var order = challengeSpec.order; var order = challengeSpec.order;
var block = challengeSpec.name; var block = challengeSpec.name;
var isBeta = !!challengeSpec.isBeta;
// challenge file has no challenges... // challenge file has no challenges...
if (challengeSpec.challenges.length === 0) { if (challengeSpec.challenges.length === 0) {
@ -66,6 +67,8 @@ Challenge.destroyAll(function(err, info) {
challenge.order = order; challenge.order = order;
challenge.suborder = index + 1; challenge.suborder = index + 1;
challenge.block = block; challenge.block = block;
challenge.isBeta = challenge.isBeta || isBeta;
challenge.time = challengeSpec.time;
return challenge; return challenge;
}); });

172
server/boot/certificate.js Normal file
View File

@ -0,0 +1,172 @@
import _ from 'lodash';
import dedent from 'dedent';
import { Observable } from 'rx';
import debugFactory from 'debug';
import {
ifNoUser401,
ifNoUserSend
} from '../utils/middleware';
import {
saveUser,
observeQuery
} from '../utils/rx';
import {
frontEndChallangeId,
fullStackChallangeId
} from '../utils/constantStrings.json';
import {
completeCommitment$
} from '../utils/commit';
const debug = debugFactory('freecc:certification');
const sendMessageToNonUser = ifNoUserSend(
'must be logged in to complete.'
);
function isCertified(frontEndIds, { completedChallenges, isFrontEndCert }) {
if (isFrontEndCert) {
return true;
}
return _.every(frontEndIds, ({ id }) => {
return _.some(completedChallenges, (challenge) => {
return challenge.id === id || challenge._id === id;
});
});
}
export default function certificate(app) {
const router = app.loopback.Router();
const { Challenge } = app.models;
const frontEndChallangeIds$ = observeQuery(
Challenge,
'findById',
frontEndChallangeId,
{
id: true,
tests: true,
name: true,
challengeType: true
}
)
.shareReplay();
const fullStackChallangeIds$ = observeQuery(
Challenge,
'findById',
fullStackChallangeId,
{
id: true,
tests: true,
name: true,
challengeType: true
}
)
.shareReplay();
router.post(
'/certificate/verify/front-end',
ifNoUser401,
verifyCert
);
router.post(
'/certificate/verify/full-stack',
ifNoUser401,
verifyCert
);
router.post(
'/certificate/honest',
sendMessageToNonUser,
postHonest
);
app.use(router);
function verifyCert(req, res, next) {
const isFront = req.path.split('/').pop() === 'front-end';
Observable.just({})
.flatMap(() => {
if (isFront) {
return frontEndChallangeIds$;
}
return fullStackChallangeIds$;
})
.flatMap(challenge => {
const { user } = req;
const {
id,
tests,
name,
challengeType
} = challenge;
if (
isFront && !user.isFrontEndCert && isCertified(tests, user) ||
!isFront && !user.isFullStackCert && isCertified(tests, user)
) {
debug('certified');
if (isFront) {
user.isFrontEndCert = true;
} else {
user.isFullStackCert = true;
}
user.completedChallenges.push({
id,
name,
completedDate: new Date(),
challengeType
});
return saveUser(user)
// If user has commited to nonprofit,
// this will complete his pledge
.flatMap(
user => completeCommitment$(user),
(user, pledgeOrMessage) => {
if (typeof pledgeOrMessage === 'string') {
debug(pledgeOrMessage);
}
// we are only interested in the user object
// so we ignore return from completeCommitment$
return user;
}
);
}
return Observable.just(user);
})
.subscribe(
user => {
if (
isFront && user.isFrontEndCert ||
!isFront && user.isFullStackCert
) {
return res.status(200).send(true);
}
return res.status(200).send(
dedent`
Looks like you have not completed the neccessary steps.
Please return to the challenge map.
`
);
},
next
);
}
function postHonest(req, res, next) {
const { user } = req;
user.isHonest = true;
saveUser(user)
.subscribe(
(user) => {
res.status(200).send(!!user.isHonest);
},
next
);
}
}

View File

@ -9,17 +9,18 @@ import utils from '../utils';
import { import {
saveUser, saveUser,
observeMethod, observeMethod,
observableQueryFromModel observeQuery
} from '../utils/rx'; } from '../utils/rx';
import { import {
userMigration,
ifNoUserSend ifNoUserSend
} from '../utils/middleware'; } from '../utils/middleware';
const isDev = process.env.NODE_ENV !== 'production';
const isBeta = !!process.env.BETA;
const debug = debugFactory('freecc:challenges'); const debug = debugFactory('freecc:challenges');
const challengesRegex = /^(bonfire|waypoint|zipline|basejump)/i; const challengesRegex = /^(bonfire|waypoint|zipline|basejump)/i;
const firstChallenge = 'waypoint-say-hello-to-html-elements'; const firstChallenge = 'waypoint-learn-how-free-code-camp-works';
const challengeView = { const challengeView = {
0: 'coursewares/showHTML', 0: 'coursewares/showHTML',
1: 'coursewares/showJS', 1: 'coursewares/showJS',
@ -48,12 +49,12 @@ function updateUserProgress(user, challengeId, completedChallenge) {
let { completedChallenges } = user; let { completedChallenges } = user;
// migrate user challenges object to remove // migrate user challenges object to remove
if (!user.isUniqMigrated) { /* if (!user.isUniqMigrated) {
user.isUniqMigrated = true; user.isUniqMigrated = true;
completedChallenges = user.completedChallenges = completedChallenges = user.completedChallenges =
makeChallengesUnique(completedChallenges); makeChallengesUnique(completedChallenges);
} }*/
const indexOfChallenge = _.findIndex(completedChallenges, { const indexOfChallenge = _.findIndex(completedChallenges, {
id: challengeId id: challengeId
@ -106,6 +107,9 @@ module.exports = function(app) {
null, null,
Scheduler.default Scheduler.default
)) ))
// filter out all challenges that have isBeta flag set
// except in development or beta site
.filter(challenge => isDev || isBeta || !challenge.isBeta)
.shareReplay(); .shareReplay();
// create a stream of challenge blocks // create a stream of challenge blocks
@ -147,8 +151,6 @@ module.exports = function(app) {
completedBonfire completedBonfire
); );
// the follow routes are covered by userMigration
router.use(userMigration);
router.get('/map', challengeMap); router.get('/map', challengeMap);
router.get( router.get(
'/challenges/next-challenge', '/challenges/next-challenge',
@ -183,9 +185,9 @@ module.exports = function(app) {
'could not find challenge block for ' + challenge.block 'could not find challenge block for ' + challenge.block
); );
} }
const nextBlock$ = blocks$.elementAt(blockIndex + 1); const firstChallengeOfNextBlock$ = blocks$
const firstChallengeOfNextBlock$ = nextBlock$ .elementAt(blockIndex + 1, {})
.map(block => block.challenges[0]); .map(({ challenges = [] }) => challenges[0]);
return blocks$ return blocks$
.elementAt(blockIndex) .elementAt(blockIndex)
@ -214,6 +216,9 @@ module.exports = function(app) {
}); });
}) })
.map(nextChallenge => { .map(nextChallenge => {
if (!nextChallenge) {
return null;
}
nextChallengeName = nextChallenge.dashedName; nextChallengeName = nextChallenge.dashedName;
return nextChallengeName; return nextChallengeName;
}) })
@ -254,7 +259,7 @@ module.exports = function(app) {
.filter((challenge) => { .filter((challenge) => {
return testChallengeName.test(challenge.name); return testChallengeName.test(challenge.name);
}) })
.lastOrDefault(null) .last({ defaultValue: null })
.flatMap(challenge => { .flatMap(challenge => {
// Handle not found // Handle not found
@ -270,12 +275,13 @@ module.exports = function(app) {
} }
if (dasherize(challenge.name) !== origChallengeName) { if (dasherize(challenge.name) !== origChallengeName) {
return Observable.just( let redirectUrl = `/challenges/${dasherize(challenge.name)}`;
'/challenges/' +
dasherize(challenge.name) + if (solutionCode) {
'?solution=' + redirectUrl += `?solution=${encodeURIComponent(solutionCode)}`;
encodeURIComponent(solutionCode) }
);
return Observable.just(redirectUrl);
} }
// save user does nothing if user does not exist // save user does nothing if user does not exist
@ -330,7 +336,7 @@ module.exports = function(app) {
challengeType: 5 challengeType: 5
}; };
observableQueryFromModel( observeQuery(
User, User,
'findOne', 'findOne',
{ where: { username: ('' + completedWith).toLowerCase() } } { where: { username: ('' + completedWith).toLowerCase() } }
@ -458,7 +464,7 @@ module.exports = function(app) {
verified: false verified: false
}; };
observableQueryFromModel( observeQuery(
User, User,
'findOne', 'findOne',
{ where: { username: completedWith.toLowerCase() } } { where: { username: completedWith.toLowerCase() } }
@ -542,12 +548,15 @@ module.exports = function(app) {
} }
return sum; return sum;
}, 0); }, 0);
const isBeta = _.every(blockArray, 'isBeta');
return { return {
isBeta,
name: blockArray[0].block, name: blockArray[0].block,
dashedName: dasherize(blockArray[0].block), dashedName: dasherize(blockArray[0].block),
challenges: blockArray, challenges: blockArray,
completed: completedCount / blockArray.length * 100 completed: completedCount / blockArray.length * 100,
time: blockArray[0] && blockArray[0].time || "???"
}; };
}) })
.filter(({ name }) => name !== 'Hikes') .filter(({ name }) => name !== 'Hikes')

224
server/boot/commit.js Normal file
View File

@ -0,0 +1,224 @@
import _ from 'lodash';
import { Observable } from 'rx';
import debugFactory from 'debug';
import dedent from 'dedent';
import nonprofits from '../utils/commit.json';
import {
commitGoals,
completeCommitment$
} from '../utils/commit';
import {
unDasherize
} from '../utils';
import {
observeQuery,
saveInstance
} from '../utils/rx';
import {
ifNoUserRedirectTo
} from '../utils/middleware';
const sendNonUserToFront = ifNoUserRedirectTo('/');
const sendNonUserToCommit = ifNoUserRedirectTo(
'/commit',
'Must be signed in to update commit'
);
const debug = debugFactory('freecc:commit');
function findNonprofit(name) {
let nonprofit;
if (name) {
nonprofit = _.find(nonprofits, (nonprofit) => {
return name === nonprofit.name;
});
}
nonprofit = nonprofit || nonprofits[0];
return nonprofit;
}
export default function commit(app) {
const router = app.loopback.Router();
const { Pledge } = app.models;
router.get(
'/commit',
commitToNonprofit
);
router.get(
'/commit/pledge',
sendNonUserToFront,
pledge
);
router.get(
'/commit/directory',
renderDirectory
);
router.post(
'/commit/stop-commitment',
sendNonUserToCommit,
stopCommit
);
router.post(
'/commit/complete-goal',
sendNonUserToCommit,
completeCommitment
);
app.use(router);
function commitToNonprofit(req, res, next) {
const { user } = req;
let nonprofitName = unDasherize(req.query.nonprofit);
debug('looking for nonprofit', nonprofitName);
const nonprofit = findNonprofit(nonprofitName);
Observable.just(user)
.flatMap(user => {
if (user) {
debug('getting user pledge');
return observeQuery(user, 'pledge');
}
return Observable.just();
})
.subscribe(
pledge => {
if (pledge) {
debug('found previous pledge');
req.flash('info', {
msg: dedent`
Looks like you already have a pledge to ${pledge.displayName}.
Hitting commit here will replace your old commitment.
`
});
}
res.render(
'commit/',
Object.assign(
{
title: 'Commit to a nonprofit. Commit to your goal.',
pledge,
frontEndCert: commitGoals.frontEndCert,
fullStackCert: commitGoals.fullStackCert
},
nonprofit
)
);
},
next
);
}
function pledge(req, res, next) {
const { user } = req;
const {
nonprofit: nonprofitName = 'girl develop it',
amount = '5',
goal = commitGoals.frontEndCert
} = req.query;
const nonprofit = findNonprofit(nonprofitName);
observeQuery(user, 'pledge')
.flatMap(oldPledge => {
// create new pledge for user
const pledge = Pledge(
Object.assign(
{
amount,
goal,
userId: user.id
},
nonprofit
)
);
if (oldPledge) {
debug('user already has pledge, creating a new one');
// we orphan last pledge since a user only has one pledge at a time
oldPledge.userId = '';
oldPledge.formerUser = user.id;
oldPledge.endDate = new Date();
oldPledge.isOrphaned = true;
return saveInstance(oldPledge)
.flatMap(() => {
return saveInstance(pledge);
});
}
return saveInstance(pledge);
})
.subscribe(
({ displayName, goal, amount }) => {
req.flash('success', {
msg: dedent`
Congratulations, you have committed to giving
${displayName} $${amount} each month until you have completed
your ${goal}.
`
});
res.redirect('/' + user.username);
},
next
);
}
function renderDirectory(req, res) {
res.render('commit/directory', {
title: 'Commit Directory',
nonprofits
});
}
function completeCommitment(req, res, next) {
const { user } = req;
return completeCommitment$(user)
.subscribe(
msgOrPledge => {
if (typeof msgOrPledge === 'string') {
return res.send(msgOrPledge);
}
return res.send(true);
},
next
);
}
function stopCommit(req, res, next) {
const { user } = req;
observeQuery(user, 'pledge')
.flatMap(pledge => {
if (!pledge) {
return Observable.just();
}
pledge.formerUserId = pledge.userId;
pledge.userId = null;
pledge.isOrphaned = true;
pledge.dateEnded = new Date();
return saveInstance(pledge);
})
.subscribe(
pledge => {
let msg = `You have successfully stopped your pledge.`;
if (!pledge) {
msg = `No pledge found for user ${user.username}.`;
}
req.flash('errors', { msg });
return res.redirect(`/${user.username}`);
},
next
);
}
}

0
server/boot/labs.js Normal file
View File

View File

@ -5,6 +5,8 @@ var Rx = require('rx'),
request = require('request'), request = require('request'),
debug = require('debug')('freecc:cntr:resources'), debug = require('debug')('freecc:cntr:resources'),
constantStrings = require('../utils/constantStrings.json'), constantStrings = require('../utils/constantStrings.json'),
labs = require('../resources/labs.json'),
testimonials = require('../resources/testimonials.json'),
secrets = require('../../config/secrets'); secrets = require('../../config/secrets');
module.exports = function(app) { module.exports = function(app) {
@ -27,11 +29,12 @@ module.exports = function(app) {
router.get('/nonprofits', nonprofits); router.get('/nonprofits', nonprofits);
router.get('/nonprofits-form', nonprofitsForm); router.get('/nonprofits-form', nonprofitsForm);
router.get('/our-sponsors', sponsors); router.get('/our-sponsors', sponsors);
router.get('/jobs-form', jobsForm);
router.get('/unsubscribe/:email', unsubscribe); router.get('/unsubscribe/:email', unsubscribe);
router.get('/unsubscribed', unsubscribed); router.get('/unsubscribed', unsubscribed);
router.get('/get-started', getStarted); router.get('/get-started', getStarted);
router.get('/submit-cat-photo', submitCatPhoto); router.get('/submit-cat-photo', submitCatPhoto);
router.get('/labs', showLabs);
router.get('/stories', showTestimonials);
app.use(router); app.use(router);
@ -96,10 +99,10 @@ module.exports = function(app) {
}); });
}, },
challenges: function (callback) { challenges: function(callback) {
Challenge.find( Challenge.find(
{ fields: { name: true } }, { fields: { name: true } },
function (err, challenges) { function(err, challenges) {
if (err) { if (err) {
debug('Challenge err: ', err); debug('Challenge err: ', err);
callback(err); callback(err);
@ -116,10 +119,10 @@ module.exports = function(app) {
} }
}); });
}, },
stories: function (callback) { stories: function(callback) {
Story.find( Story.find(
{ field: { link: true } }, { field: { link: true } },
function (err, stories) { function(err, stories) {
if (err) { if (err) {
debug('Story err: ', err); debug('Story err: ', err);
callback(err); callback(err);
@ -137,7 +140,7 @@ module.exports = function(app) {
} }
); );
}, },
nonprofits: function (callback) { nonprofits: function(callback) {
Nonprofit.find( Nonprofit.find(
{ field: { name: true } }, { field: { name: true } },
function(err, nonprofits) { function(err, nonprofits) {
@ -180,6 +183,20 @@ module.exports = function(app) {
res.redirect('https://gitter.im/FreeCodeCamp/FreeCodeCamp'); res.redirect('https://gitter.im/FreeCodeCamp/FreeCodeCamp');
} }
function showLabs(req, res) {
res.render('resources/labs', {
title: 'Projects Built by Free Code Camp Students',
projects: labs
});
}
function showTestimonials(req, res) {
res.render('resources/stories', {
title: 'Stories from Happy Free Code Camp Campers',
stories: testimonials
});
}
function submitCatPhoto(req, res) { function submitCatPhoto(req, res) {
res.send('Submitted!'); res.send('Submitted!');
} }
@ -190,20 +207,6 @@ module.exports = function(app) {
}); });
} }
function jobsForm(req, res) {
res.render('resources/jobs-form', {
title: 'Employer Partnership Form for Job Postings,' +
' Recruitment and Corporate Sponsorships'
});
}
function catPhotoSubmit(req, res) {
res.send(
'Success! You have submitted your cat photo. Return to your website ' +
'by typing any letter into your code editor.'
);
}
function sponsors(req, res) { function sponsors(req, res) {
res.render('sponsors/sponsors', { res.render('sponsors/sponsors', {
title: 'The Sponsors who make Free Code Camp Possible' title: 'The Sponsors who make Free Code Camp Possible'
@ -247,7 +250,7 @@ module.exports = function(app) {
return next(err); return next(err);
} }
user.sendMonthlyEmail = false; user.sendMonthlyEmail = false;
user.save(function () { user.save(function() {
if (err) { if (err) {
return next(err); return next(err);
} }
@ -302,7 +305,7 @@ module.exports = function(app) {
secrets.github.clientSecret secrets.github.clientSecret
].join(''), ].join(''),
githubHeaders, githubHeaders,
function (err, status2, issues) { function(err, status2, issues) {
if (err) { return next(err); } if (err) { return next(err); }
issues = ((pulls === parseInt(pulls, 10)) && issues) ? issues = ((pulls === parseInt(pulls, 10)) && issues) ?
Object.keys(JSON.parse(issues)).length - pulls : Object.keys(JSON.parse(issues)).length - pulls :
@ -336,7 +339,7 @@ module.exports = function(app) {
'https://www.googleapis.com/blogger/v3/blogs/2421288658305323950/' + 'https://www.googleapis.com/blogger/v3/blogs/2421288658305323950/' +
'posts?key=' + 'posts?key=' +
secrets.blogger.key, secrets.blogger.key,
function (err, status, blog) { function(err, status, blog) {
if (err) { return next(err); } if (err) { return next(err); }
blog = (status && status.statusCode === 200) ? blog = (status && status.statusCode === 200) ?

View File

@ -1,13 +1,26 @@
import _ from 'lodash';
import dedent from 'dedent'; import dedent from 'dedent';
import moment from 'moment'; import moment from 'moment';
import { Observable } from 'rx';
import debugFactory from 'debug'; import debugFactory from 'debug';
import {
frontEndChallangeId,
fullStackChallangeId
} from '../utils/constantStrings.json';
import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware'; import { ifNoUser401, ifNoUserRedirectTo } from '../utils/middleware';
import { observeQuery } from '../utils/rx';
const debug = debugFactory('freecc:boot:user'); const debug = debugFactory('freecc:boot:user');
const daysBetween = 1.5; const daysBetween = 1.5;
const sendNonUserToMap = ifNoUserRedirectTo('/map'); const sendNonUserToMap = ifNoUserRedirectTo('/map');
function replaceScriptTags(value) {
return value
.replace(/<script>/gi, 'fccss')
.replace(/<\/script>/gi, 'fcces');
}
function calcCurrentStreak(cals) { function calcCurrentStreak(cals) {
const revCals = cals.concat([Date.now()]).slice().reverse(); const revCals = cals.concat([Date.now()]).slice().reverse();
let streakBroken = false; let streakBroken = false;
@ -52,7 +65,16 @@ function dayDiff([head, tail]) {
module.exports = function(app) { module.exports = function(app) {
var router = app.loopback.Router(); var router = app.loopback.Router();
var User = app.models.User; var User = app.models.User;
// var Story = app.models.Story; function findUserByUsername$(username, fields) {
return observeQuery(
User,
'findOne',
{
where: { username },
fields
}
);
}
router.get('/login', function(req, res) { router.get('/login', function(req, res) {
res.redirect(301, '/signin'); res.redirect(301, '/signin');
@ -85,7 +107,18 @@ module.exports = function(app) {
); );
router.get('/vote1', vote1); router.get('/vote1', vote1);
router.get('/vote2', vote2); router.get('/vote2', vote2);
// Ensure this is the last route!
// Ensure these are the last routes!
router.get(
'/:username/front-end-certification',
showCert
);
router.get(
'/:username/full-stack-certification',
showCert
);
router.get('/:username', returnUser); router.get('/:username', returnUser);
app.use(router); app.use(router);
@ -131,7 +164,10 @@ module.exports = function(app) {
const username = req.params.username.toLowerCase(); const username = req.params.username.toLowerCase();
const { path } = req; const { path } = req;
User.findOne( User.findOne(
{ where: { username } }, {
where: { username },
include: 'pledge'
},
function(err, profileUser) { function(err, profileUser) {
if (err) { if (err) {
return next(err); return next(err);
@ -142,6 +178,7 @@ module.exports = function(app) {
}); });
return res.redirect('/'); return res.redirect('/');
} }
profileUser = profileUser.toJSON();
var cals = profileUser var cals = profileUser
.progressTimestamps .progressTimestamps
@ -188,10 +225,17 @@ module.exports = function(app) {
title: 'Camper ' + profileUser.username + '\'s portfolio', title: 'Camper ' + profileUser.username + '\'s portfolio',
username: profileUser.username, username: profileUser.username,
name: profileUser.name, name: profileUser.name,
isMigrationGrandfathered: profileUser.isMigrationGrandfathered, isMigrationGrandfathered: profileUser.isMigrationGrandfathered,
isGithubCool: profileUser.isGithubCool, isGithubCool: profileUser.isGithubCool,
isLocked: !!profileUser.isLocked, isLocked: !!profileUser.isLocked,
pledge: profileUser.pledge,
isFrontEndCert: profileUser.isFrontEndCert,
isFullStackCert: profileUser.isFullStackCert,
isHonest: profileUser.isHonest,
location: profileUser.location, location: profileUser.location,
calender: data, calender: data,
@ -210,12 +254,103 @@ module.exports = function(app) {
moment, moment,
longestStreak: profileUser.longestStreak, longestStreak: profileUser.longestStreak,
currentStreak: profileUser.currentStreak currentStreak: profileUser.currentStreak,
replaceScriptTags
}); });
} }
); );
} }
function showCert(req, res, next) {
const username = req.params.username.toLowerCase();
const { user } = req;
const showFront = req.path.split('/').pop() === 'front-end-certification';
Observable.just(user)
.flatMap(user => {
if (user && user.username === username) {
return Observable.just(user);
}
return findUserByUsername$(username, {
isGithubCool: true,
isFrontEndCert: true,
isFullStackCert: true,
isHonest: true,
completedChallenges: true,
username: true,
name: true
});
})
.subscribe(
(user) => {
if (!user) {
req.flash('errors', {
msg: `404: We couldn't find the user ${username}`
});
return res.redirect('/');
}
if (!user.isGithubCool) {
req.flash('errors', {
msg: dedent`
This user needs to link GitHub with their account
in order to display this certificate to the public.
`
});
return res.redirect('back');
}
if (user.isLocked) {
req.flash('errors', {
msg: dedent`
${username} has chosen to hide their work from the public.
They need to unhide their work in order for this certificate to
be verifiable.
`
});
return res.redirect('back');
}
if (!user.isHonest) {
req.flash('errors', {
msg: dedent`
${username} has not agreed to our Academic Honesty Pledge yet.
`
});
return res.redirect('back');
}
if (
showFront && user.isFrontEndCert ||
!showFront && user.isFullStackCert
) {
var { completedDate = new Date() } =
_.find(user.completedChallenges, {
id: showFront ?
frontEndChallangeId :
fullStackChallangeId
}) || {};
return res.render(
showFront ?
'certificate/front-end.jade' :
'certificate/full-stack.jade',
{
username: user.username,
date: moment(new Date(completedDate))
.format('MMMM, Do YYYY'),
name: user.name
}
);
}
req.flash('errors', {
msg: showFront ?
`Looks like user ${username} is not Front End certified` :
`Looks like user ${username} is not Full Stack certified`
});
res.redirect('back');
},
next
);
}
function toggleLockdownMode(req, res, next) { function toggleLockdownMode(req, res, next) {
if (req.user.isLocked === true) { if (req.user.isLocked === true) {
req.user.isLocked = false; req.user.isLocked = false;
@ -297,11 +432,6 @@ module.exports = function(app) {
}); });
} }
/**
* POST /forgot
* Create a random token, then the send user an email with a reset link.
*/
function postForgot(req, res) { function postForgot(req, res) {
const errors = req.validationErrors(); const errors = req.validationErrors();
const email = req.body.email.toLowerCase(); const email = req.body.email.toLowerCase();

View File

@ -15,7 +15,7 @@
"initial": { "initial": {
"compression": {}, "compression": {},
"morgan": { "morgan": {
"params": "dev" "params": ":status :method :response-time ms - :url"
} }
}, },
"session": { "session": {

View File

@ -47,6 +47,10 @@
"dataSource": "db", "dataSource": "db",
"public": true "public": true
}, },
"pledge": {
"dataSource": "db",
"public": true
},
"user": { "user": {
"dataSource": "db", "dataSource": "db",
"public": true "public": true

View File

@ -0,0 +1,30 @@
[
{
"camper": "johnstonbl01",
"name": "Clementine.js",
"url": "http://johnstonbl01.github.io/clementinejs/",
"description": "The elegant and lightweight boilerplate for full stack JavaScript.",
"image": "http://i.imgur.com/ib1wOho.png"
},
{
"camper": "akiralaine",
"name": "Camper News Bot",
"url": "https://twitter.com/campernewsbot",
"description": "This twitter bot tweets out Camper News stories once they hit 5 upvotes.",
"image": "https://pbs.twimg.com/media/CLXOFLPWIAEHYPJ.png"
},
{
"camper": "adventurebear",
"name": "Coding Bootcamp Cost Calculator",
"url": "http://www.freecodecamp.com/coding-bootcamp-cost-calculator",
"description": "This d3.js-powered coding bootcamp cost calculator takes into account tuition, financing, lost wages and cost of living.",
"image": "https://qph.is.quoracdn.net/main-qimg-670d6a0c5b01f74138e777732994240f?convert_to_webp=true"
},
{
"camper": "ericdouglas",
"name": "Open Source Society",
"url": "https://github.com/open-source-society/computer-science",
"description": "A path to a free education in Computer Science.",
"image": "https://camo.githubusercontent.com/c42438055d3fee26b29e6d046fd8d06ebff3db20/687474703a2f2f692e696d6775722e636f6d2f6838786a72726a2e706e67"
}
]

View File

@ -0,0 +1,555 @@
[
{
"camper": "Meta Hirschl",
"quote": "By building a robust and highly functional web app I was able to not only increase my confidence but was able to show potential employers what I was able to create. Both were huge for me and led me to getting a fantastic job.",
"github": "MetaCoderHirschl",
"linkedin": "https://www.linkedin.com/profile/view?id=ADEAAAKX2fEBfeZ1GVdOh-c0zzkYZKw38o8qzow&authType=NAME_SEARCH&authToken=hfRS&locale=en_US&srchid=147930701444634954491&srchindex=1&srchtotal=1&trk=vsrp_people_res_photo&trkInfo=VSRPsearchId%3A147930701444634954491%2CVSRPtargetId%3A43506161%2CVSRPcmpt%3Aprimary%2CVSRPnm%3Atrue%2CauthType%3ANAME_SEARCH",
"image": "https://media.licdn.com/media/p/6/005/0ac/31c/05f0e58.jpg"
},
{
"camper": "Branden Byers",
"quote": "My goal was to become employed by the end of 2015. Instead, I ended up with a job at the beginning of 2015. This was directly related to my work at Free Code Camp.",
"github": "brandenbyers",
"linkedin": "https://www.linkedin.com/in/brandenbyers",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/005/0a0/1e4/378908c.jpg"
},
{
"camper": "Bruna Torman Reseres Franasa",
"quote": "Im now receiving offers for internships. I have no experience in IT, but now good things are happening!",
"github": "brunatrf",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABVPh9IB730qyshrsqO1hDNNRUL-X_4i8n0&authType=NAME_SEARCH&authToken=YYn-&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A357533650%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907147451%2Ctas%3Abruna",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/8/005/09e/16e/32c3d3f.jpg"
},
{
"camper": "Maxim Orlov",
"quote": "I started Free Code Camp with zero knowledge of web development. 6 months later, I landed my first job as a back end engineer.",
"github": "Maximization",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAo83nwBF57LpD9mZlm5dH6OcovOpYKPs3k&authType=NAME_SEARCH&authToken=yG4h&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A171761276%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635014777%2Ctas%3AMaxim%20Orlov",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAALJAAAAJGI5ZGFhODA0LWI4MzAtNDU5Ny04NjU3LTIwMjdhMmIxYjFjNg.jpg"
},
{
"camper": "Alexander Black, Jr.",
"quote": "My work on a nonprofit project gave me the opportunity to learn how to build Chrome extensions and showcase my skills as a full-stack developer.",
"github": "alexblackjr",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA553L4BgfgBR-M9RQc7x5matd6FUx3a6-I&authType=NAME_SEARCH&authToken=TW_a&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A242867390%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444634592237%2Ctas%3Aalexander%20black%20jr",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAANmAAAAJDQ1ZWIxMmVjLTAwNjUtNDFlNS04OWVhLTk4ZGZkNmViODkxNw.jpg"
},
{
"camper": "Cristiane Henriques",
"quote": "I am getting more work contacts after including Free Code Camp on my CV and my LinkedIn.",
"github": "CrisHenriques",
"linkedin": "https://www.linkedin.com/in/crishenriques",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAKEAAAAJGFjMTBjZWY5LTE2ZWMtNGU2OC05MTk3LTdkZjUyYWI1NjA5NQ.jpg"
},
{
"camper": "Viktor Bakurin",
"quote": "During my work on Free Code Camp's nonprofit projects, I found a MEAN stack position outside of my home country. Now I work in Budapest.",
"github": "letalumil",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAq6G3QBA1DIwFZGrS4DGqDzBDTzFjrbNQo&authType=NAME_SEARCH&authToken=QoJ0&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A179968884%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635040141%2Ctas%3AViktor%20Bakurin",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAM3AAAAJDVkZThkNjk3LWY4MTgtNGNmMS05MTZkLTkxZDljOGEzMGM5Nw.jpg"
},
{
"camper": "Ashley Drake",
"quote": "Free Code Camp helped me get my first engineering job. This amazing community made my career switch a lot easier and more fun.",
"github": "aldraco",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABcdBycB1iVHvcW7N3yVK-18ES7Nrxx2jbE&authType=NAME_SEARCH&authToken=gKNN&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A387778343%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635725853%2Ctas%3Aashley%20",
"image": "http://i.imgur.com/xzDoJef.jpg"
},
{
"camper": "Brian Grant",
"quote": "I've received new employment opportunities and I have not even finished Free Code Camp's first 800 hours of training yet.",
"github": "codeseekingman",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAEUqXoBFOq1SWQrBsTMHG4ij9Ss4Qqnrtg&authType=NAME_SEARCH&authToken=a85-&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A18131322%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635878707%2Ctas%3Abrian%20grant",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAANEAAAAJGY5ZjZkMDVjLTJhY2EtNDZjYS1iMDk5LTY0ZDliN2EyODUxMQ.jpg"
},
{
"camper": "Thomas Joseph Izen",
"quote": "After spending lots of time trying different sites that aim to teach people how to code, FreeCodeCamp has been different from the beginning. They provide the best and most organized track for anyone at any level to learn how to code and build an amazing, marketable portfolio.",
"github": "TommyIzen",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA79qIYB_RHmvOP59S6VPK3Lm06oG8fM6dw&authType=NAME_SEARCH&authToken=PfeR&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A251504774%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444636112016%2Ctas%3AThomas%20%20Izen",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAMaAAAAJGRjZTQ4MTdmLTZmZGItNGFhNS1hNTE0LWJmYjFhZDY3YmM3MQ.jpg"
},
{
"camper": "Lori Becker",
"quote": "After graduating with a Masters degree in computer science, I could not share any of my code with employers (university policy: fear of aiding cheating). With FreeCodeCamp, I was able to develop a small portfolio.",
"github": "LCBecker",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAADrtuwBOA_0ihkKIbUFXoXskXikQT9uVeo&authType=NAME_SEARCH&authToken=sctO&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A15447788%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907195702%2Ctas%3Alori",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/1/005/080/392/295a574.jpg"
},
{
"camper": "Robert Trammel",
"quote": "I'm working a job integrating JavaScript into FileMaker and doing some custom web publishing for a school district. I've also have job offers from Apple and a few technology firms around the country. If it wasn't for Free Code Camp, I'd still be in the dark with some really awesome but irrelevant skills.",
"github": "comajama",
"linkedin": "https://www.linkedin.com/profile/view?id=AAIAABQsM30BEAI6xyAhk-OqbBNUJL0WD2uA3GE&authType=NAME_SEARCH&authToken=4xB-&trk=Skyline_click_NPS&sl=NPS%3B147930701444636308659%3B1%3B147930701444636308659%3B",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAAIBAAAAJDI5YjRmMTRmLTFjNWItNGQ5ZC05MTNjLTA0MWQ0YjRhOTdhNQ.jpg"
},
{
"camper": "Brian Atkins",
"quote": "I'm spending less time then I am used to on Free Code Camp because people have begun to hire me to work on their projects. Free Code Camp has provided me the foundation I have needed to get these jobs.",
"github": "BrianAtk",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAABtTx0BmDzmB7eDGOkAJbRw8RZdvysreso&authType=NAME_SEARCH&authToken=CecH&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A7163677%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444636556530%2Ctas%3ABrian%20Atkins",
"image": "https://media.licdn.com/media/p/8/000/2aa/36c/2d218a8.jpg"
},
{
"camper": "Andrea Goulet",
"quote": "Before enrolling in Free Code Camp, I was nervous when people asked me, \"Do you code?\", Now, I answer with a confident \"YES!\"",
"github": "andreagoulet",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAA4KWYB-mCMwEU3LvDHXt6H0rVHbBvszq0&authType=NAME_SEARCH&authToken=hUBG&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A3680614%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907386771%2Ctas%3Aandrea%20go",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAMyAAAAJDI1MWU4OWU4LTZmNTAtNGFmMS1iYzcxLTA5Y2IwYzIyMWIxYQ.jpg"
},
{
"camper": "David McGill",
"quote": "Even if you have a CS degree like I do, you still need projects to prove to employers that you care about coding. Free Code Camp provided me with a platform for doing this. It's all laid out for you - you just have step up and step into the map!",
"github": "dmcgill50",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAEBy74BHsJCpgrbohr2dJxbdXuvMuJDx6k&authType=NAME_SEARCH&authToken=9k8t&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A16894910%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444637012056%2Ctas%3ADavid%20McGill",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAANdAAAAJGE4YWI5NjFiLTQ5MzUtNGQwNC04YThiLWYxMTI4NWM3YmFlMQ.jpg"
},
{
"camper": "Qing Huang",
"quote": "Free Code Camp gives me more confidence at work. Code doesnt look as foreign anymore.",
"github": "qingillustrates",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAOjjjoBDaPY1dtpvngnr8ednNTran6KA3s&authType=NAME_SEARCH&authToken=4zvM&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A61050426%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907310565%2Ctas%3Aqing",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAKsAAAAJDVlNmNkMzUwLWFjNzAtNDQ4OS05NWI5LWYyYmYzOWQzZjRlOQ.jpg"
},
{
"camper": "John Ellis",
"quote": "Free Code Camp has been one of the major contributors to my career in software development. I started as an apps analyst, spent 3 months going through the coursework in my off time and weekends, and just landed a job as a business systems developer.",
"github": "johnmellis",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAbrISEBqAVYOBfhni9mB3YoFFzzrAbYvvo&authType=NAME_SEARCH&authToken=jurJ&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A116072737%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907670143%2Ctas%3Ajohn%20ellis",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/5/000/268/01a/0492529.jpg"
},
{
"camper": "Jonathan Lucas",
"quote": "Free Code Camp has been nothing but supportive and helpful, taking me from a rather basic knowledge of front end technologies to a better, more complete understanding from a full stack perspective.",
"github": "jonslucas",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAATn9H4BI7BP7MBpZ0NR1EvldkWTvAdGy2w&authType=NAME_SEARCH&authToken=hLmG&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A82310270%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635490853%2Ctas%3AJon%20Lucas",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAIcAAAAJGMxMjY3MmEwLTM0ODgtNGU3OS1hZjFiLTJjZjNhMDM3YTUyZQ.jpg"
},
{
"camper": "Alex Dixon",
"quote": "I was hired by the owner of the company, a programmer with 25 years of experience in web development. I graduated from university with a degree in English and had no programming experience prior to attending FreeCodeCamp.",
"github": "alex-dixon",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABhCmLMBLAR1AXskaJXDMT-uLPZ8M7TynPQ&authType=NAME_SEARCH&authToken=k8uX&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A407017651%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444633871133%2Ctas%3Aalex%20dixon",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAMcAAAAJGZhM2Y2ZTU5LWNjODAtNDM5My1hYjAzLTYyYjFlOTcwZjVmZg.jpg"
},
{
"camper": "Ryan Lindeman",
"quote": "Free Code Camp has been great in giving me a direct path to the full stack development skills I wanted to become more involved in projects at work.",
"github": "fai1whale",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAkMT1EBFCY849rMWYSDIEj6kosBJSH9n2s&authType=NAME_SEARCH&authToken=acmj&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A151801681%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907181695%2Ctas%3Aryan%20lind",
"image": "https://media.licdn.com/media/p/4/000/145/24d/18e8af8.jpg"
},
{
"camper": "Stephanie Brown",
"quote": "Free Code Camp has given me structure and a direction while learning to code.",
"github": "strawmitch",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAARqP5cBDDdBxPUzluctvjUhOP3UsiowRtM&authType=NAME_SEARCH&authToken=TDfV&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A74071959%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907473116%2Ctas%3Astephanie%20brown",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAALJAAAAJGI5ZWY1MmNjLTJhMTUtNGI2NS04YTExLTFiOGZlYTRiMTNiOA.jpg"
},
{
"camper": "Jimson Sulit",
"quote": "Aside from the fact that Im learning full stack web development, Free Code Camp has also given me the opportunity to lead local community projects.",
"github": "webdevjedi25",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAWqUccBopX2Wo_P1gYgy0iIEqChwXPTh2k&authType=NAME_SEARCH&authToken=kd5y&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A95048135%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907446780%2Ctas%3Ajimson",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAPzAAAAJDYyOGMxYmEyLTY1NTQtNDE3NS1iMmVkLWUwM2M4NjJiZWFhZg.jpg"
},
{
"camper": "Brian Emory",
"quote": "I like to learn by doing but with the books, while very informative, there was more reading than doing. I came across Free Code Camp which has allowed me to learn by doing. Whereas before I was struggling to learn, I am now not only learning but learning while building cool projects.",
"github": "thebrianemory",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABc3jXwB-iZdZKZIVAvL93RHGB7_J9gDbVA&authType=NAME_SEARCH&authToken=w1Km&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A389516668%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907166795%2Ctas%3Abrian%20emory",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAJOAAAAJDgyZWFhYWFjLTNhZGYtNGQzOC04M2JjLWE1Nzk1NmRiMDY4MA.jpg"
},
{
"camper": "Brian Barrow",
"quote": "Free Code Camp has given me confidence that I can become a web developer.",
"github": "briancbarrow",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAVH-osBCI8WZTtv3Om5WjeD2rYnjQ6z7zA&authType=NAME_SEARCH&authToken=-yWK&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A88603275%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907213309%2Ctas%3Abrian%20barr",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/5/005/07e/272/050fd0e.jpg"
},
{
"camper": "Ralph Cachero",
"quote": "I am a software QA engineer. Free Code Camp has helped me understand what the developers go through.",
"github": "rcachero",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAJEF88BiUtMoxS3Ww7ooI9QmTZdrgP272Q&authType=NAME_SEARCH&authToken=2tza&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A38016975%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907225816%2Ctas%3Aralph",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/1/000/09f/2eb/0ec94ae.jpg"
},
{
"camper": "Ina Tsetsova",
"quote": "Bonfires really make me think and combine programming concepts creatively.",
"github": "Tsetsova",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAjPoIcBJsAF91dqwgxFQ4qct88yFcljXNU&authType=NAME_SEARCH&authToken=l8zY&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A147824775%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907239742%2Ctas%3Aina%20",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/005/0ad/379/050ce9d.jpg"
},
{
"camper": "Adam Goswick",
"quote": "Free Code Camp is helping me learn web development when I cant afford to go back to school.",
"github": "thegoz85",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAObbhkBzeCKrzuEB0ssE_iGrBX0Xnu9URc&authType=NAME_SEARCH&authToken=xKaK&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A60517913%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907256670%2Ctas%3Aadam%20g",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/1/005/08d/084/0eeb904.jpg"
},
{
"camper": "Josh Cronkhite",
"quote": "My resume has been bolstered by adding a completely new stack, providing value to my clients and opening up the pool of potential clients that I would have otherwise referred to peers.",
"github": "joshcronkhite",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAGTPvoBg__9rivrYrYgo8sDJ561JpAfhHk&authType=NAME_SEARCH&authToken=6X77&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A26427130%2CauthType%3ANAME_SEARCH%2Cidx%3A1-3-3%2CtarId%3A1441907269831%2Ctas%3Ajosh",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/7/000/276/003/191e9f3.jpg"
},
{
"camper": "Ryan Jones",
"quote": "Learning to code with Free Code Camp has given me a leg up in my career. It has helped to train my brain to think with the logic that computers use. This is a tremendous aid in the field of digital forensics.",
"github": "ryanmjones",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABPJt1MBxC4Yero3PJPhF9rrr_Y7WfOGcCU&authType=NAME_SEARCH&authToken=Dre1&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A331986771%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907281816%2Ctas%3Aryan%20jones",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAbSAAAAJDUwY2RiZTUxLTg1YTktNDQ2Yy05YTZlLTU2NmY2YThlMmY0Yw.jpg"
},
{
"camper": "Kristin Anthony",
"quote": "The layout, pacing, and resources of Free Code Camp have given me focus and shown me a path to mastery. Just being able to tell people in my field that Im learning full stack JavaScript and having projects to show for it has been immensely helpful both with my current position and in my job search.",
"github": "anthkris",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAZRM5MBACvQe36s4cvpe5ZHWEfgxprDUFg&authType=NAME_SEARCH&authToken=pozh&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A105984915%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907298390%2Ctas%3Akristin%20",
"image": "https://media.licdn.com/media/p/4/005/0b3/377/381a362.jpg"
},
{
"camper": "Jimmy Epperson",
"quote": "I learned to build websites, which is now a new service I offer to local businesses.",
"github": "jimmyepp",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAADg3N8BTBm_D58gu8Tgq6UPa3OQ_19CrSE&authType=NAME_SEARCH&authToken=W7Eg&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A14736607%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907323386%2Ctas%3Ajimmy%20epper",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAALWAAAAJDUwZDc5YzYwLTc2MjYtNDIzYy1iYzAyLWNlNzZmMTNjM2M1NA.jpg"
},
{
"camper": "Sara Powell",
"quote": "Ive progressed from not coding very much at all, to coding well enough to land job interviews for front end development positions.",
"github": "newtcobell",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAy1jmQBRjoGSUWd6Zib7FtekpSMBVHr7Vw&authType=NAME_SEARCH&authToken=wpT6&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A213225060%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907337130%2Ctas%3Asara%20powell",
"image": "https://media.licdn.com/media/p/8/000/1be/159/281c5b8.jpg"
},
{
"camper": "John Bull",
"quote": "I am now able to add customized branding and layouts to web applications that fellow employees and customers use everyday. Im now looking to move away from desktop support and into development roles.",
"github": "Jbull328",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABAyfz8BsjE-oGv1k3URGzhRyeupnTGuK3I&authType=NAME_SEARCH&authToken=bnIc&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A271744831%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907350044%2Ctas%3Ajohn%20bull",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAL8AAAAJDliMGU0MTk0LWQ3YTUtNDY0NS1hMTg1LTdhN2Q1NTBlMzA5MQ.jpg"
},
{
"camper": "Rhonadale Florentino",
"quote": "I can now confidently tell clients that I can design their website.",
"github": "None Given",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAI53oUBmy6MPKp1UeHxBy3_y0cyTS4bWow&authType=NAME_SEARCH&authToken=gz62&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A37346949%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907434768%2Ctas%3Arhona",
"image": "https://media.licdn.com/media/p/7/005/0aa/319/1aaa08f.jpg"
},
{
"camper": "Justin Clay Lane",
"quote": "Free Code Camp provided a structured learning experience more akin to an actual class, compared to other free learning sites. I was recently hired to update and maintain the website for a local doctors office. The extra money and experience from that is wonderful.",
"github": "jclane",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAYZYQ4BBY337OqRUhMnZqDJNX1wNXjT7Bk&authType=NAME_SEARCH&authToken=8TbF&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A102326542%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907405129%2Ctas%3Ajustin%20lane",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAI5AAAAJDNmNzViYzdmLTdkMTEtNDllYS1iNTRmLWVmZjgzZTY3ZWNjNQ.jpg"
},
{
"camper": "Angshuman Gupta",
"quote": "Im a co-founder of a startup. We had been coding with PHP, but always wanted to shift to meteor.js. Free Code Camp gave me a structured JavaScript guide.",
"github": "codingang",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAhIipMB6vAXaratEs0MtUd3GgyYm70cvbE&authType=NAME_SEARCH&authToken=pbTj&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A138971795%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907423626%2Ctas%3Aangsh",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAAKPAAAAJGRjMmQwZjY5LTViMmUtNDQyZS04Y2Y3LTRhYjZiYWJlZDQzNw.jpg"
},
{
"camper": "Nick Galluzzo",
"quote": "I currently work in a support role for a tech startup (www.knackhq.com). The more I learn about JavaScript, the more Im able to contribute to a product I really believe in!",
"github": "ngalluzzo",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAjQl1EBZPrbUQ6zGPXmKIuNzpCyqqsnox4&authType=NAME_SEARCH&authToken=9w-G&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A147887953%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907461071%2Ctas%3Anick%20gall",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAANtAAAAJDE3YWZmYjE0LTg4ODYtNDg1Mi1hZDhjLThkZmZhMjkxYWI3Mg.jpg"
},
{
"camper": "Genavieve Clausen",
"quote": "Free Code Camp has benefitted me in numerous ways, including the opportunity to learn in a self-paced, supportive environment. I am excited to be a part of a growing community making lasting connections for the career and lifestyle I am pursuing.",
"github": "GenavieveMarie",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAOISlMBAi43m1SG-xM_S2B8Vy05yiQz5rE&authType=NAME_SEARCH&authToken=AY6E&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A59263571%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907488270%2Ctas%3Agenav",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAWUAAAAJDc2ODU4MjVkLTlmMDUtNDM4My05OTY2LTliMTQxNzFlZmY0OQ.jpg"
},
{
"camper": "Nicholas Slaven",
"quote": "Free Code Camp has given me the courage to open the door to the idea of programming for a career.",
"github": "nslaven22",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA5HGyIBmpNcXY_tfHBkWxXI6OtwsFAeHRQ&authType=NAME_SEARCH&authToken=IIqr&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A239541026%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907370759%2Ctas%3Aslaven",
"image": "https://media.licdn.com/media/p/3/000/222/0d1/2606078.jpg"
},
{
"camper": "Tim Stauffer",
"quote": "I found Free Code Camp more helpful than my MS degree, so I quit college. Learning so much. Also saving $50,000.",
"github": "timstauffer",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAADVcVIBz8UCNjQKl2GUy9ka8UGnQXAXAYw&authType=NAME_SEARCH&authToken=7Hkg&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A13988178%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907522559%2Ctas%3Astauffer",
"image": "https://avatars1.githubusercontent.com/u/3429096?v=3&s=460"
},
{
"camper": "Marquina M Iliev-Piselli",
"quote": "Im re-designing a site for my full-time job.",
"github": "Marquina",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAACYvVUBTuu8dNRHthN1TFiyk137PLDqnv4&authType=NAME_SEARCH&authToken=V_iG&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A10009941%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907639677%2Ctas%3Amarquin",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAZLAAAAJDQ5Nzg4MjJmLWUyMjQtNDI5Ny05NmY5LTE5Yjc1Y2Q1YWFhOA.jpg"
},
{
"camper": "Pete Considine",
"quote": "The guided and structured lessons have been really helpful, as has the relatively slow pace that new concepts are introduced. I had been taking a Udemy course and it really seemed to be skimming the surface of JavaScript in the interest of \"getting to everything.\"",
"github": "Pjconsidine",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAAi8-8BxUVpoi_VuJQmeGWN5zhMBgbvPbs&authType=NAME_SEARCH&authToken=WCEU&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A2290671%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907557932%2Ctas%3Apete%20c",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/3/005/06c/3b2/0ab8c08.jpg"
},
{
"camper": "Khatra Ahmed",
"quote": "I can learn to code with support by my side. Everyone is so helpful and it makes learning to code less of a struggle.",
"github": "Mystfreak",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAbdUsIBApacWEmL7CIxe2q7aevMn7aQvmQ&authType=NAME_SEARCH&authToken=a_zs&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A115167938%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907569985%2Ctas%3Akhatra",
"image": "https://avatars0.githubusercontent.com/u/11299138?v=3&s=460"
},
{
"camper": "Marcus Lyons",
"quote": "Free Code Camp has helped me gain the confidence to automate part of my work responsibilities. I was able to use skills I learned from Free Code Camp to help with writing a bash script to search through mobile app database log files to find errors.",
"github": "auron1223",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA_1aLABo1pVJH9ijSqz8PvLgpzVYkIsjVc&authType=NAME_SEARCH&authToken=cNE6&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A267741360%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441925486836%2Ctas%3Alyons",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAM9AAAAJDA4YjM1NGIxLThjZWYtNDllMi04N2NkLWMzMzk1YWI1MTYyMg.jpg"
},
{
"camper": "Reynald Emmanuel Endaya",
"quote": "There is an active community (even in Manila) and its interactive, unlike all the MOOCs I tried before where I had to listen to somebody speak for a long time. I am learning a lot here and I have not yet lost my momentum.",
"github": "None Given",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAUlm8oBQuXm_Y89_LDC9mb2vOjjQH_pZDo&authType=NAME_SEARCH&authToken=4WJf&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A86350794%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907601893%2Ctas%3Areynald",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/2/000/1a7/0ab/089b5aa.jpg"
},
{
"camper": "Victoria Kariolic",
"quote": "I discovered a coding partner through the Free Code Camp groups who has been able to cover gaps for my client work.",
"github": "Niaskywalk",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAEFmXMBlTFIR2j1G-vJhAMsUOPONILGrLM&authType=NAME_SEARCH&authToken=yGV-&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A17144179%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907613265%2Ctas%3Avictoria%20",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/8/005/025/299/0d297ae.jpg"
},
{
"camper": "Cameron Eshgh",
"quote": "Free Code Camp enables me as a digital marketer to dive right into whatever asset or content and fix things that havent been working, as well as roll up my sleeves when our web developers are not available.",
"github": "eshghitude",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAVdU1MBFFiei4ZYNImnVDcR3H_EiuS6qLY&authType=NAME_SEARCH&authToken=TlgU&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A90002259%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907626390%2Ctas%3Acameron%20",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/6/005/0a4/178/079a07b.jpg"
},
{
"camper": "Devarsh Ruparelia",
"quote": "Even though I am still just a high school student. The startup I intern for said that if I finish the full track of Free Code Camp, they will strongly consider me for their programming jobs. Thanks Free Code Camp!",
"github": "devarsh1997",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAApxpP8BZBcHQzr6Ci3xmkkZX-OSH_oLuJs&authType=NAME_SEARCH&authToken=wdjb&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A175219967%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907682493%2Ctas%3Adevarsh",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/7/005/087/339/14535ee.jpg"
},
{
"camper": "Miranda Bashore",
"quote": "I want to be able to freelance and create dynamic websites. Free Code Camp makes that more of a reality for me, as I cannot afford an expensive bootcamp while getting my Masters degree.",
"github": "DutchBay",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA8KmJMBTtvvgJzjeAUo_YOssh2yLZZlvlk&authType=NAME_SEARCH&authToken=fWay&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A252352659%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907584953%2Ctas%3Amiranda",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/5/005/078/187/0ca3604.jpg"
},
{
"camper": "Christian Morera",
"quote": "Free Code Camp has been a great experience. Ive learned so many things. I am in the process of transitioning from content developer to full stack developer.",
"github": "chrmorfeus",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAMc-tYBtYri0H1KHz1WNQjWxZ23jg0tMNU&authType=NAME_SEARCH&authToken=NzUg&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A52230870%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907694834%2Ctas%3Achristian",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAa-AAAAJDVkYmQyNTdmLTJkM2UtNDRjNi04NjZkLThlMmE3ZTg0NzhlZQ.jpg"
},
{
"camper": "James Allen",
"quote": "I finally feel like I can learn to code in my own time and progress to the point of employability.",
"github": "None Given",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA4OrsIB5WyfuqeECSQO7HYisImVMDiFBl0&authType=NAME_SEARCH&authToken=Uxjm&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A235843266%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907723968%2Ctas%3Ajames%20allen",
"image": "https://media.licdn.com/media/p/5/000/228/30b/1bb1c6f.jpg"
},
{
"camper": "Jason Arnold",
"quote": "I like self-paced learning, so Free Code Camp has been great. The challenges are difficult enough to push boundaries but not so tough to scare people off.",
"github": "thejasonfile",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAABlImsBwAEZ3u3A5NIlCegho8WZ2j4h0w0&authType=NAME_SEARCH&authToken=gaxA&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A6627947%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907738051%2Ctas%3Ajason%20arn",
"image": "https://media.licdn.com/media/p/6/005/05d/271/0bdaef1.jpg"
},
{
"camper": "Kaveet Laxmidas",
"quote": "Free Code Camp is inspiring me to overhaul some of my old open source projects using more modern approaches and technologies.",
"github": "kaveet",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABZooOgBZJg_0MAJ09pd5vROk83oBFA1cEE&authType=NAME_SEARCH&authToken=52Ju&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A375955688%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907749550%2Ctas%3Akaveet%20",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAMiAAAAJDlhMGNiYzdjLTNlZmEtNDI3MC04Mzg4LTU4YTBkYjkxYTg5Zg.jpg"
},
{
"camper": "Brett Guillory",
"quote": "Free Code Camp has given me a great, goal oriented curriculum to learn exactly what I was looking for. And best of all its 100% free!",
"github": "Kurzninja",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAUMPqMBa6GwMTkA_oHUeqnZzyD95FisjwM&authType=NAME_SEARCH&authToken=-mt1&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A84688547%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907760167%2Ctas%3Abrett",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/5/005/054/0cd/0fee17b.jpg"
},
{
"camper": "Kory J. Campbell",
"quote": "I just graduated university, so my financial status is pretty meager, however this camp has definitely helped me improve my skills.",
"github": "@koryjcampbell [sic]",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAtxvTgB0N_uJhW-87Dew4wHyeqLUP-XyZk&authType=NAME_SEARCH&authToken=0hqw&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A192003384%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907770739%2Ctas%3Akory",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/000/17a/3cd/3b781f4.jpg"
},
{
"camper": "Bryon Christopher Miller",
"quote": "Free Code Camp has given me a free, online opportunity to study full stack JavaScript in a structured, community-based format. I am very grateful for this opportunity.",
"github": "bryonmiller",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABEXhHoBxj3Uiq7I0a5v1pVkeJ1gWycbm90&authType=NAME_SEARCH&authToken=4klF&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A286753914%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907784405%2Ctas%3Abryon",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/7/005/07d/040/1d3ca82.jpg"
},
{
"camper": "Darren Joy",
"quote": "Great learning opportunity. Good coding challenges and Im meeting some very motivated people.",
"github": "Darrenfj",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAARv6UIBWeXw4ZfCJ70kBKgnhcv8XgnVsa8&authType=NAME_SEARCH&authToken=fMvj&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A74443074%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907795737%2Ctas%3Adarren",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAANwAAAAJGRiNjA5Zjg4LTE0OTEtNGVlNi1hZjdlLWFkOWZhNzk2YzJiNg.jpg"
},
{
"camper": "Stephen Mayeux",
"quote": "Free Code Camp is helpful because its not 100% hand-holding, and it pushes me out of my comfort zone.",
"github": "stephenmayeux",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAjTe7cBhjovoz6zTE_M6MwZ_rr3szhiSOM&authType=NAME_SEARCH&authToken=s6xI&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A148077495%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907806830%2Ctas%3Astephen",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAUmAAAAJDg3MzIzMGVlLWYzZGEtNGE0Yi05ODkzLTFkODkyOWI5N2NjYg.jpg"
},
{
"camper": "John Hillegass",
"quote": "Free Code Camp has given me the confidence that I need when heading into high level client meetings and developer scrum sessions.",
"github": "Ohillio",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAWEO3AB51y8eR2tYF8nydQb8kANkdPwR5U&authType=NAME_SEARCH&authToken=Pzvi&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A92552048%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907818081%2Ctas%3Ajohn%20hille",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/2/000/1cd/27b/2ab4573.jpg"
},
{
"camper": "Eric Hartline",
"quote": "The community is very helpful, and I have already accomplished so much more than what I did with other self-guided courses.",
"github": "wildlifehexagon",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAFitUwByB_tgxdExntMnakgQnTK1H3eEd8&authType=NAME_SEARCH&authToken=230A&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A23246156%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907829391%2Ctas%3Aeric%20har",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/2/000/1e1/095/12800b6.jpg"
},
{
"camper": "Danielle J Moss",
"quote": "Aside from learning to code in a fun way, I also know Im not alone and have somewhere to go when I do get stuck and need help.",
"github": "psykobilliethekid",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAV4ccABlbMXZ5VfzvlYentPOIKzFbjgbZM&authType=NAME_SEARCH&authToken=D-EU&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A91779520%2CauthType%3ANAME_SEARCH%2Cidx%3A1-4-4%2CtarId%3A1441907855210%2Ctas%3Adanielle%20",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/5/000/1be/2cb/16e5e39.jpg"
},
{
"camper": "Orcun Tonyali",
"quote": "The thorough curriculum helped a lot in managing my companys website.",
"github": "orcuntonyali",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAVwBQIBvE3-M8pDWxzep9umHDnV6JjKmTU&authType=NAME_SEARCH&authToken=h4NM&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A91227394%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907869032%2Ctas%3Aorcun",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAI7AAAAJDE2ZGVkY2IxLTkyZDEtNDUwNS1iNmU0LWI5ZWUzYjUxZDIyMw.jpg"
},
{
"camper": "Brendan Murphy",
"quote": "I like that it isnt just a 9 week course. The chat room and partner coding were also very helpful.",
"github": "dendari",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAA06V8BqPNnPod-FGRuvifILht-QwZX3YY&authType=NAME_SEARCH&authToken=9SFh&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A3467615%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907882775%2Ctas%3Abrendan%20m",
"image": "https://media.licdn.com/media/p/5/000/2be/073/198504b.jpg"
},
{
"camper": "Michael Berry",
"quote": "Free Code Camp has helped me learn JavaScript, jQuery, and Bootstrap as well as helped me brush up on my HTML and CSS skills. I was laid off from Boeing in April. Im hoping to land a job as a JavaScript developer as I get closer to finishing the curriculum. I wish I had known about Free Code Camp sooner.",
"github": "Karnblack ",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAGRqf4BwCI3cdJw9wAPc6NlReG3fzOIQq0&authType=NAME_SEARCH&authToken=SqNG&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A26323454%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907895359%2Ctas%3Amichael%20berr",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAM3AAAAJDc2YTRmMjY1LTcxNjQtNDJjOC1hYWJmLTJkMGFkMWVhYjE3Mw.jpg"
},
{
"camper": "Angie Canon",
"quote": "Free Code Camp is helping my career. I work with developers and Im beginning to understand their world better. I can phrase questions more clearly, and begin to guess what an issue might be related to.",
"github": "angiecan",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAACfWbABAMsll9ovljvvsLpH317o47hNHX0&authType=NAME_SEARCH&authToken=UmUf&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A10443184%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907913670%2Ctas%3Aangie%20canon",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/8/000/20b/098/273de00.jpg"
},
{
"camper": "Irfan Kucuk",
"quote": "Ive long been looking for a place that could keep me interested in learning how to code. Ive tried several Codecademy and comparable places, but none have proven as engaging as Free Code Camp.",
"github": "Ikucuk",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAA5ripkBiFAjXkB3ndO6sKiiq6gD21mk6bw&authType=NAME_SEARCH&authToken=46t_&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A241928857%2CauthType%3ANAME_SEARCH%2Cidx%3A1-2-2%2CtarId%3A1441907929553%2Ctas%3Airfan%20kuc",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/005/027/3f1/08ce9a4.jpg"
},
{
"camper": "Jonathan Kvicky",
"quote": "Free Code Camp has given me a strong foundational advantage into pursuing a career in software/web development, and has also served as a great platform for connecting with others who share the same passion for software engineering.",
"github": "jonkvix",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABk3i9YB_hcw1AyVg2QHaf8KMQ8ADQ_R_vg&authType=NAME_SEARCH&authToken=0yLa&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A423070678%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907942441%2Ctas%3Ajonathan%20kv",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAANTAAAAJDk3ZGMwMjFlLTZkNDYtNDgwYy05NGE0LTk5ZjgwNGQ4NWU0OA.jpg"
},
{
"camper": "Susannah Skyer Gupta",
"quote": "As a jack-of-all-trades at a small educational software company, Im already putting my coding skills to work, beginning to submit my own pull requests for bug fixes instead of just opening a problem ticket and waiting for someone else to fix it.",
"github": "SuzGupta",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAFIosEBLewkmbuudMwAqiTM5YE3wHvcE4A&authType=NAME_SEARCH&authToken=dFye&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A21537473%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907953988%2Ctas%3Asusanna",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/7/005/025/20f/3d29475.jpg"
},
{
"camper": "Puneet Shivanand",
"quote": "Free Code Camp has helped me create and maintain a website for a local bioinformatics conference.",
"github": "puneet-shivanand",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAArBgXABw4qoSJQoGjqrvU6_vBX1gUmcwGg&authType=NAME_SEARCH&authToken=bARS&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A180453744%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907966038%2Ctas%3Apuneet",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAUYAAAAJGI3NmNlMGNhLWM1NDEtNGNlNS1iNmQzLTY0OTM3OGEzMTk0Yg.jpg"
},
{
"camper": "Ian Seabrook",
"quote": "Ive made connections with people I never would have approached before Free Code Camp.",
"github": "ianseabrook",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAuVUi4BSJ3K6fcyTa2fnZr_9Oosb3nKM34&authType=NAME_SEARCH&authToken=b7uD&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A194335278%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907982480%2Ctas%3Aian%20seabroo",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAJNAAAAJDVkMmI1MDYxLTc1ZmEtNDY0Yy05MTRhLTY1ZjVkNWQyNWI1Ng.jpg"
},
{
"camper": "Oleh Kuchuk",
"quote": "The coding exercises helped me to prepare for my first job interview.",
"github": "drkraken",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAABgy6MwBva2OKpsffAU-OBBeTC7qahTYpGw&authType=NAME_SEARCH&authToken=Xm_u&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A405989580%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441907996469%2Ctas%3Aoleh%20kuchuk",
"image": "https://pbs.twimg.com/profile_images/518155039781580800/djkuOlrL.jpeg"
},
{
"camper": "Larisa Bekerman",
"quote": "Free Code Camp has made me more comfortable with certain aspects of code and helped me review and understand concepts in a more hands-on style. Some people learn by reading theory, I dont understand things until Ive made them work myself!",
"github": "xaosqueen",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAB-SHUBga96BB-iaHe7QFI-S2dFmeUQaq0&authType=NAME_SEARCH&authToken=CWOo&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A8276085%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441908013366%2Ctas%3Alarisa%20beker",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/8/005/093/243/2c06287.jpg"
},
{
"camper": "Jesse Mull",
"quote": "I learned more using Free Code Camp in three months than I ever could have at a traditional university.",
"github": "jessemull",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAr2HfcBswHtmQeLM1rxDEg7GdCuxvNin5s&authType=NAME_SEARCH&authToken=nca0&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A183901687%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441908026733%2Ctas%3Ajesse%20mull",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/3/005/016/3ff/006213a.jpg"
},
{
"camper": "Mihai Popescu",
"quote": "The exercises helped me hone my skills and get an internship at a tech startup. My projects were a great talking point in the interview, showing them what I did and how I approached the problems. Great thing you are doing here.",
"github": "Mihaisavezi",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAApQxGQBYz-WAQu_0zXPTkW-R7QbdaXEZeA&authType=NAME_SEARCH&authToken=r84S&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A173065316%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441908038920%2Ctas%3Amihai%20p",
"image": "https://lh6.googleusercontent.com/-4JB6FPzm9ZE/VakUEj7WYsI/AAAAAAAALkU/4C0ILUwn-B8/w888-h891-no/profilepic.png"
},
{
"camper": "Normandy Real",
"quote": "I'm doing Free Code Camp to transition from mainframe programming to front end development.",
"github": "mandyreal",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAdebIIBHfcSRnxGI-j6g5y6crfOXSg55Dc&authType=NAME_SEARCH&authToken=xLNy&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A123628674%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444636619442%2Ctas%3ANormandy%20Real",
"image": "https://media.licdn.com/media/AAEAAQAAAAAAAAMrAAAAJDAxMmE0ZWI1LWU0MjctNDRjYS1hNjdkLTYwZTI5NjUxMDhjYw.jpg"
},
{
"camper": "Zlatko Cabric",
"quote": "I am still in school, pursuing an AS in web development. The JavaScript course in college was a breeze thanks to Free Code Camp.",
"github": "zlajac ",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAsCCFMBUlE24Ie41G_YS3XhdtQMDl5vCZA&authType=NAME_SEARCH&authToken=h1m7&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A184682579%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441908055072%2Ctas%3Azlat",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAALQAAAAJDMzNjY4M2UwLWVlYWEtNGQwYS04MDY0LTVjNGVhNGNhYWM5OQ.jpg"
},
{
"camper": "Travis Wouters",
"quote": "Free Code Camp helped me add skillsets to my resume that show experience instead of knowledge without practical application.",
"github": "",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAABHP0YBddxsmaf2OghV2jAy17RVMhig4RM&authType=NAME_SEARCH&authToken=a7pC&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A4669254%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444634846844%2Ctas%3ATravis%20Wouters",
"image": "https://media.licdn.com/media/p/8/005/07d/2f1/1792a44.jpg"
},
{
"camper": "Geoff Storbeck",
"quote": "I've been able to build tools that has helped moved my current career further and has opened up many more doors in the field.",
"github": "storbeck",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAdVQZYBHPYLt5efKwqZmiDM5SqIdH0_AR4&authType=NAME_SEARCH&authToken=EDd-&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A123027862%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1444635255807%2Ctas%3AGeoff%20Storbeck%09",
"image": "https://media.licdn.com/media/p/1/000/124/306/339eee6.jpg"
},
{
"camper": "Anthony DePaolo",
"quote": "I can learn web development at my own pace, which is great with my crazy lifes schedule. It also doesnt cost $10k-$17k, which I just cant fork over right now.",
"github": "adepaolo",
"linkedin": "https://www.linkedin.com/profile/view?id=AAkAAAOCUkABzCvw3p1mBiPbbFWq91BEFXGXKxA&authType=NAME_SEARCH&authToken=7zb7&locale=en_US&trk=tyah&trkInfo=clickedVertical%3Amynetwork%2CclickedEntityId%3A58872384%2CauthType%3ANAME_SEARCH%2Cidx%3A1-1-1%2CtarId%3A1441908068309%2Ctas%3Aanthony%20depa",
"image": "https://media.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAJPAAAAJGI4NGY3ZGI1LWM2N2UtNGQ2Ni1iZDUwLTFkN2I4YWM2YThjMQ.jpg"
}
]

View File

@ -2,7 +2,8 @@ require('dotenv').load();
var pmx = require('pmx'); var pmx = require('pmx');
pmx.init(); pmx.init();
var uuid = require('node-uuid'), var _ = require('lodash'),
uuid = require('node-uuid'),
assign = require('lodash').assign, assign = require('lodash').assign,
loopback = require('loopback'), loopback = require('loopback'),
boot = require('loopback-boot'), boot = require('loopback-boot'),
@ -16,6 +17,7 @@ var getUsernameFromProvider = require('./utils/auth').getUsernameFromProvider;
var generateKey = var generateKey =
require('loopback-component-passport/lib/models/utils').generateKey; require('loopback-component-passport/lib/models/utils').generateKey;
var isBeta = !!process.env.BETA;
var app = loopback(); var app = loopback();
expressState.extend(app); expressState.extend(app);
@ -92,16 +94,19 @@ Object.keys(passportProviders).map(function(strategy) {
); );
}); });
app.start = function() { app.start = _.once(function() {
app.listen(app.get('port'), function() { app.listen(app.get('port'), function() {
app.emit('started'); app.emit('started');
console.log( console.log(
'FreeCodeCamp server listening on port %d in %s mode', 'FreeCodeCamp server listening on port %d in %s',
app.get('port'), app.get('port'),
app.get('env') app.get('env')
); );
if (isBeta) {
console.log('Free Code Camp is in beta mode');
}
}); });
}; });
module.exports = app; module.exports = app;

View File

@ -0,0 +1,4 @@
{
"frontEndCert": "Front End Development Certification",
"fullStackCert": "Full Stack Development Certification"
}

36
server/utils/commit.js Normal file
View File

@ -0,0 +1,36 @@
import dedent from 'dedent';
import debugFactory from 'debug';
import { Observable } from 'rx';
import commitGoals from './commit-goals.json';
const debug = debugFactory('freecc:utils/commit');
export { commitGoals };
export function completeCommitment$(user) {
const { isFrontEndCert, isFullStackCert } = user;
return Observable.fromNodeCallback(user.pledge, user)()
.flatMap(pledge => {
if (!pledge) {
return Observable.just('No pledge found');
}
const { goal } = pledge;
if (
isFrontEndCert && goal === commitGoals.frontEndCert ||
isFullStackCert && goal === commitGoals.fullStackCert
) {
debug('marking goal complete');
pledge.isCompleted = true;
pledge.dateEnded = new Date();
pledge.formerUserId = pledge.userId;
pledge.userId = null;
return Observable.fromNodeCallback(pledge.save, pledge)();
}
return Observable.just(dedent`
You have not yet reached your goal of completing the ${goal}
Please retry when you have met the requirements.
`);
});
}

18
server/utils/commit.json Normal file
View File

@ -0,0 +1,18 @@
[
{
"name": "girl develop it",
"displayName": "Girl Develop It",
"donateUrl": "https://www.girldevelopit.com/donate",
"description": "Girl Develop It provides in-person classes for women to learn to code.",
"imgAlt": "Girl Develop It participants coding at tables.",
"imgUrl": "http://i.imgur.com/U1CyEuA.jpg"
},
{
"name": "black girls code",
"displayName": "Black Girls CODE",
"donateUrl": "http://www.blackgirlscode.com/",
"description": "Black Girls CODE is devoted to showing the world that black girls can code, and do so much more.",
"imgAlt": "Girls developing code with instructor",
"imgUrl": "http://i.imgur.com/HBVrdaj.jpg"
}
]

View File

@ -1,3 +1,5 @@
{ {
"gitHubUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.3 Safari/537.36" "gitHubUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1521.3 Safari/537.36",
"frontEndChallangeId": "561add10cb82ac38a17513be",
"fullStackChallangeId": "660add10cb82ac38a17513be"
} }

View File

@ -1,60 +1,30 @@
var R = require('ramda'); export function ifNoUserRedirectTo(url, message) {
/*
* Middleware to migrate users from fragmented challenge structure to unified
* challenge structure
*
* @param req
* @param res
* @returns null
*/
exports.userMigration = function userMigration(req, res, next) {
if (!req.user || req.user.completedChallenges.length !== 0) {
return next();
}
req.user.completedChallenges = R.filter(function(elem) {
// getting rid of undefined
return elem;
}, R.concat(
req.user.completedCoursewares,
req.user.completedBonfires.map(function(bonfire) {
return ({
completedDate: bonfire.completedDate,
id: bonfire.id,
name: bonfire.name,
completedWith: bonfire.completedWith,
solution: bonfire.solution,
githubLink: '',
verified: false,
challengeType: 5
});
})
)
);
return next();
};
exports.ifNoUserRedirectTo = function ifNoUserRedirectTo(url) {
return function(req, res, next) { return function(req, res, next) {
const { path } = req;
if (req.user) { if (req.user) {
return next(); return next();
} }
req.flash('errors', {
msg: message || `You must be signed to go to ${path}`
});
return res.redirect(url); return res.redirect(url);
}; };
}; }
exports.ifNoUserSend = function ifNoUserSend(sendThis) { export function ifNoUserSend(sendThis) {
return function(req, res, next) { return function(req, res, next) {
if (req.user) { if (req.user) {
return next(); return next();
} }
return res.status(200).send(sendThis); return res.status(200).send(sendThis);
}; };
}; }
exports.ifNoUser401 = function ifNoUser401(req, res, next) { export function ifNoUser401(req, res, next) {
if (req.user) { if (req.user) {
return next(); return next();
} }
return res.status(401).end(); return res.status(401).end();
}; }

View File

@ -1,7 +1,9 @@
var Rx = require('rx'); import Rx from 'rx';
var debug = require('debug')('freecc:rxUtils'); import debugFactory from 'debug';
exports.saveInstance = function saveInstance(instance) { const debug = debugFactory('freecc:rxUtils');
export function saveInstance(instance) {
return new Rx.Observable.create(function(observer) { return new Rx.Observable.create(function(observer) {
if (!instance || typeof instance.save !== 'function') { if (!instance || typeof instance.save !== 'function') {
debug('no instance or save method'); debug('no instance or save method');
@ -17,16 +19,15 @@ exports.saveInstance = function saveInstance(instance) {
observer.onCompleted(); observer.onCompleted();
}); });
}); });
}; }
// alias saveInstance // alias saveInstance
exports.saveUser = exports.saveInstance; export const saveUser = saveInstance;
exports.observeQuery = exports.observableQueryFromModel = export function observeQuery(Model, method, query) {
function observableQueryFromModel(Model, method, query) { return Rx.Observable.fromNodeCallback(Model[method], Model)(query);
return Rx.Observable.fromNodeCallback(Model[method], Model)(query); }
};
exports.observeMethod = function observeMethod(context, methodName) { export function observeMethod(context, methodName) {
return Rx.Observable.fromNodeCallback(context[methodName], context); return Rx.Observable.fromNodeCallback(context[methodName], context);
}; }

View File

@ -5,38 +5,38 @@ block content
var challengeName = 'Profile View'; var challengeName = 'Profile View';
if (user && user.username === username) if (user && user.username === username)
.panel.panel-info .panel.panel-info
.panel-heading.text-center Update Your Portfolio .panel-heading.text-center Update your code portfolio
.panel-body .panel-body
.row .row
.col-xs-12 .col-xs-12
if (!user.isGithubCool) if (!user.isGithubCool)
a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github')
i.fa.fa-github i.fa.fa-github
| Link my GitHub to unlock this profile | Link my GitHub to unlock my portfolio
else else
a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github') a.btn.btn-lg.btn-block.btn-github.btn-link-social(href='/link/github')
i.fa.fa-github i.fa.fa-github
| Update my profile from GitHub | Update my portfolio from GitHub
if (!user.twitter) if (!user.twitter)
a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter')
i.fa.fa-twitter i.fa.fa-twitter
| Add my Twitter to my profile | Add my Twitter to my portfolio
if (!user.facebook) if (!user.facebook)
a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook') a.btn.btn-lg.btn-block.btn-facebook.btn-link-social(href='/link/facebook')
i.fa.fa-facebook i.fa.fa-facebook
| Add my Facebook to my profile | Add my Facebook to my portfolio
if (!user.linkedin) if (!user.linkedin)
a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin') a.btn.btn-lg.btn-block.btn-linkedin.btn-link-social(href='/link/linkedin')
i.fa.fa-linkedin i.fa.fa-linkedin
| Add my LinkedIn to my profile | Add my LinkedIn to my portfolio
if (!user.google) if (!user.google)
a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google') a.btn.btn-lg.btn-block.btn-google-plus.btn-link-social(href='/link/google')
i.fa.fa-google-plus i.fa.fa-google-plus
| Add my Google+ to my profile | Add my Google+ to my portfolio
.panel.panel-info .panel.panel-info
.panel-heading.text-center .panel-heading.text-center
h1 #{username}'s portfolio h1 #{username}'s code portfolio
.panel-body .panel-body
.row .row
.col-xs-12.col-sm-10.col-sm-offset-1.col-md-8.col-md-offset-2.text-center .col-xs-12.col-sm-10.col-sm-offset-1.col-md-8.col-md-offset-2.text-center
@ -58,10 +58,22 @@ block content
h1.flat-top.wrappable= name h1.flat-top.wrappable= name
h1.flat-top.wrappable= location h1.flat-top.wrappable= location
h1.flat-top.text-primary= "[ " + (progressTimestamps.length) + " ]" h1.flat-top.text-primary= "[ " + (progressTimestamps.length) + " ]"
if (user && user.username !== username) if pledge
a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/link/twitter') .spacer
i.fa.fa-plus-square h4
| Add them to my personal leaderboard | This camper has committed to giving $#{pledge.amount} to
a(href='#{pledge.donateUrl}?ref=freecodecamp.com' target='_blank') #{pledge.displayName}
| each month until they have completed their #{pledge.goal}.
.spacer
if isFrontEndCert
a.btn.btn-primary(href='/' + username + '/front-end-certification') View My Front End Development Certification
if isFullStackCert
.button-spacer
a.btn.btn-success(href='/' + username + '/full-stack-certification') View My Full Stack Development Certification
//if (user && user.username !== username)
// a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/leaderboard/add?username=#{username}')
// i.fa.fa-plus-square
// | Add them to my personal leaderboard
.spacer .spacer
.hidden-xs.hidden-sm.col-md-12 .hidden-xs.hidden-sm.col-md-12
@ -126,7 +138,7 @@ block content
td.col-xs-4= bonfire.name td.col-xs-4= bonfire.name
td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY")
td.col-xs-6 td.col-xs-6
a(href='/challenges/' + bonfire.name + '?solution=' + encodeURIComponent(bonfire.solution), target='_blank') View my solution a(href='/challenges/' + bonfire.name + '?solution=' + encodeURIComponent(replaceScriptTags(bonfire.solution)), target='_blank') View my solution
if (waypoints.length > 0) if (waypoints.length > 0)
.col-sm-12 .col-sm-12
table.table.table-striped table.table.table-striped
@ -141,14 +153,18 @@ block content
td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY")
td.col-xs-6 td.col-xs-6
if (challenge.solution) if (challenge.solution)
a(href='/challenges/' + challenge.name + '?solution=' + encodeURIComponent(challenge.solution), target='_blank') View my solution a(href='/challenges/' + challenge.name + '?solution=' + encodeURIComponent(replaceScriptTags(challenge.solution)), target='_blank') View my solution
else else
a(href='/challenges/' + challenge.name) View this challenge a(href='/challenges/' + challenge.name) View this challenge
if (user && user.username === username) if (user && user.username === username)
.panel.panel-info .panel.panel-info
.panel-heading.text-center Manage Your Account .panel-heading.text-center Manage your account
.panel-body .panel-body
.col-xs-12
a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout')
span.ion-android-exit
| Sign me out of Free Code Camp
.col-xs-12 .col-xs-12
a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com') a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com')
span.ion-email span.ion-email
@ -164,9 +180,9 @@ block content
span.ion-unlocked span.ion-unlocked
| Let other people see all my solutions | Let other people see all my solutions
.col-xs-12 .col-xs-12
a.btn.btn-lg.btn-block.btn-warning.btn-link-social(href='/logout') a.btn.btn-lg.btn-block.btn-success.btn-link-social(href='/commit')
span.ion-android-exit span.ion-edit
| Sign me out of Free Code Camp | Edit my pledge
.col-xs-12 .col-xs-12
a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion a.btn.btn-lg.btn-block.btn-danger.btn-link-social.confirm-deletion
span.ion-trash-b span.ion-trash-b

View File

@ -0,0 +1,45 @@
style.
@font-face {
font-family: "Sax Mono";
src: url("/fonts/saxmono.ttf") format("truetype");
}
body {
display: inline-block;
font-family: "Sax Mono", monospace;
margin: 0;
position: absolute;
text-align: center;
}
.img-abs {
left 0;
position: relative;
top: 0;
width: 2000px
}
.cert-name {
font-size: 64px;
left: 1000px;
position: absolute;
top: 704px;
z-index: 1000;
}
.cert-date {
font-size: 60px;
left: 760px;
position: absolute;
top: 1004.8px;
z-index: 1000;
}
.cert-link {
font-size: 22px;
left: 120px;
position: absolute;
top: 1488px;
z-index: 1000;
}

View File

@ -0,0 +1,6 @@
include font
#name.cert-name= name
img#cert.img-abs(src='http://i.imgur.com/ToFZKBd.jpg')
.cert-date= date
.cert-link verify this certification at: http://freecodecamp.com/#{username}/front-end-certification
include script

View File

@ -0,0 +1,6 @@
include font
#name.cert-name= name
img#cert.img-abs(src='http://i.imgur.com/Z4PgjBQ.jpg')
.cert-date= date
.cert-link verify this certification at: http://freecodecamp.com/#{username}/full-stack-certification
include script

View File

@ -0,0 +1,7 @@
extends ../layout
block content
.panel.panel-info
.panel-heading.text-center
h1 Certificate
.panel-body
p foo

View File

@ -0,0 +1,8 @@
script.
(function() {
var containerWidth = document.getElementById('cert').offsetWidth;
var nameDiv = document.getElementById('name');
var nameWidth = nameDiv.offsetWidth;
console.log(containerWidth, nameWidth);
nameDiv.style.left = ((containerWidth - nameWidth) / 2) + 15;
})();

View File

@ -18,35 +18,17 @@ block content
span.text-primary #{daysRunning} &thinsp; span.text-primary #{daysRunning} &thinsp;
| days ago. | days ago.
.spacer .spacer
if (user && !user.tshirtVote && user.progressTimestamps.length > 5) if (user && user.progressTimestamps.length > 5)
h3.text-center Vote for the T-shirt design you like the most. #tshirt-notice.col-xs-12.col-md-8.col-md-offset-2.hidden
h4.text-center We'll announce the winning design during our Summit on Saturday at Noon EST on&thinsp; h2.text-center Get our first-edition t-shirt
a(href='https://twitch.tv/freecodecamp' target='_blank') Twitch.tv img.thumbnail.img-center.img-responsive(src="http://i.imgur.com/o07uuOL.png")
| &thinsp;and it will become our community's first official t-shirt (in women's and men's sizes). p.text-justify Our community has voted. Get our winning design emblazoned on a durable, American-made American Apparel shirt (available in women's and men's sizes).&thinsp;
.row a(href="https://teespring.com/free-code-camp-shirt-eu" target="_blank") Also ships from Europe
.col-xs-6 | .
a(href="http://i.imgur.com/LlXGa5y.png" data-lightbox="img-enlarge") a.button.btn.btn-block.signup-btn(href="https://teespring.com/get-free-code-camp-t-shirt" target="_blank") Get yours
img.img-responsive(src='http://i.imgur.com/LlXGa5y.png' alt="t-shirt option 1 women's") .button-spacer
.col-xs-6 #hideTshirtNoticeButton.button.btn.btn-block.btn-info Hide this forever
a(href="http://i.imgur.com/aefwnnv.png" data-lightbox="img-enlarge") .spacer
img.img-responsive(src='http://i.imgur.com/aefwnnv.png' alt="t-shirt option 2 women's")
.button-spacer
.row
.col-xs-6
a(href="http://i.imgur.com/aYH0aqf.png" data-lightbox="img-enlarge")
img.img-responsive(src='http://i.imgur.com/aYH0aqf.png' alt="t-shirt option 1 men's")
.col-xs-6
a(href="http://i.imgur.com/v9KlV4g.png" data-lightbox="img-enlarge")
img.img-responsive(src='http://i.imgur.com/v9KlV4g.png' alt="t-shirt option 2 men's")
.button-spacer
.row
.col-xs-6
h3.text-center "Minified JavaScript Logo"
a.button.btn.btn-block.btn-primary(href='/vote1') Vote for this Design
.col-xs-6
h3.text-center "Function Call Logo"
a.button.btn.btn-block.btn-primary(href='/vote2') Vote for this design
.spacer
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2 .col-xs-12.col-sm-8.col-sm-offset-2
h3 800 Hours of Practice: h3 800 Hours of Practice:
@ -103,58 +85,56 @@ block content
.spacer.negative-55 .spacer.negative-55
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2 .hidden-xs.col-sm-3.col-md-2
h3 #{challengeBlock.name} h3.text-primary.text-right.nowrap
i.fa.fa-clock-o &thinsp;#{challengeBlock.time}
.col-xs-12.col-sm-9.col-md-10
h3 #{challengeBlock.name} &thinsp;
.row .row
.col-xs-12 ol
ol for challenge in challengeBlock.challenges
for challenge in challengeBlock.challenges if challenge.completed
if challenge.completed
.row
.hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.map-p.negative-10
.col-xs-12.col-sm-9.col-md-10
li.faded.map-p.negative-10
a(href="/challenges/#{challenge.dashedName}")
span.capitalize= challenge.type + ': '
span= challenge.title
span.sr-only= " Complete"
else
.row
.hidden-xs.col-sm-3.col-md-2
span.negative-10
.col-xs-12.col-sm-9.col-md-10
li.map-p.negative-10
a(href="/challenges/#{challenge.dashedName}")
span.capitalize= challenge.type + ': '
span= challenge.title
span.sr-only= " Incomplete"
if (challengeBlock.completed === 100)
.button-spacer
.row .row
.col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.map-p.negative-10
a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends. .col-xs-12.col-sm-9.col-md-10
.hidden(id="#{challengeBlock.name}") li.faded.map-p.negative-10
a(href="/challenges/#{challenge.dashedName}")
span.capitalize= challenge.type + ': '
span= challenge.title
span.sr-only= " Complete"
else
.row
.hidden-xs.col-sm-3.col-md-2
span.negative-10
.col-xs-12.col-sm-9.col-md-10
li.map-p.negative-10
a(href="/challenges/#{challenge.dashedName}")
span.capitalize= challenge.type + ': '
span= challenge.title
span.sr-only= " Incomplete"
if (challengeBlock.completed === 100)
.button-spacer
.row
.col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden
a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends.
.hidden(id="#{challengeBlock.name}")
script. script.
var username = !{JSON.stringify(user && user.username || '')}; var username = !{JSON.stringify(user && user.username || '')};
var lastCompleted = !{JSON.stringify(lastCompleted || false)} var lastCompleted = !{JSON.stringify(lastCompleted || false)}
// #announcementModal.modal(tabindex='-1') $(document).ready(function () {
// .modal-dialog.animated.fadeInUp.fast-animation if (!localStorage || !localStorage.hideTshirtNotice) {
// .modal-content $("#tshirt-notice").removeClass("hidden");
// .modal-header.challenge-list-header Add us to your LinkedIn profile }
// a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × $("#hideTshirtNoticeButton").on("click", function() {
// .modal-body $("#tshirt-notice").addClass('animated fadeOut');
// h3.text-left LinkedIn now recognizes Free Code Camp as a university. setTimeout(function() {
// img.img-responsive.img-center(src='https://www.evernote.com/l/AHTzkHwtg-BHj57bqqDL7WFF8WgrI5V8cxwB/image.png') $("#tshirt-notice").hide();
// h3.text-left It takes less than a minute to add Free Code Camp to your LinkedIn profile. }, 1000);
// a.btn.btn-lg.btn-info.btn-block(name='_csrf', value=_csrf, aria-hidden='true', href='/linkedin', target='_blank') Show me how to do this localStorage.hideTshirtNotice = "true";
// a.btn.btn-lg.btn-primary.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Thanks for the heads-up });
//script. });
// $(document).ready(function () {
// if (!localStorage || !localStorage.linkedIn) {
// $('#announcementModal').modal('show');
// localStorage.linkedIn = "true";
// }
// });

View File

@ -0,0 +1,20 @@
extends ../layout
block content
.panel.panel-info
.panel-heading.text-center Commit to one of these nonprofits
.panel-body
.row
.col-xs-12.col-sm-10.col-sm-offset-1
for nonprofit in nonprofits
.col-xs-12.col-sm-6.col-md-4.story-section
.text-center
h2= nonprofit.displayName
img.testimonial-image.img-responsive.img-center(src=nonprofit.imgUrl)
.button-spacer
a.text-center(href='/commit?nonprofit=#{nonprofit.name}') Commit to #{nonprofit.displayName}
p= nonprofit.description
.spacer
.col-xs-12
a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='mailto:team@freecodecamp.com?subject=Supporting%20Nonprofits')
span.ion-email
| Email us about adding your nonprofit here

View File

@ -0,0 +1,90 @@
extends ../layout
block content
.panel.panel-info
.panel-body
h2.text-center Commit to yourself. Commit to a nonprofit.
.row
.col-xs-12.col-sm-6.col-sm-offset-3
p Give yourself external motivation and help nonprofits right away. Pledge a monthly donation to a nonprofit until youve earned either your Front End or Full Stack Development Certification.
.row
.col-xs-12.col-sm-6.col-sm-offset-3.text-center
h3 Pledge to #{displayName}&thinsp;
.button-spacer
a(href='#{imgUrl}' data-lightbox='img-enlarge' alt='#{imgAlt}')
img.img-responsive(src='#{imgUrl}' alt='#{imgAlt}')
p.large-p
= description
a(href='/commit/directory') ...or see other nonprofits
.spacer
form.form(name='commit')
.hidden
input(type='text' value='#{name}' name='nonprofit')
.row
.col-xs-12.col-sm-6.col-sm-offset-3
h3 Step 1: Choose your goal
.btn-group.btn-group-justified(data-toggle='buttons' role='group')
label.btn.btn-primary.btn-lg.active
input(type='radio' id=frontEndCert value=frontEndCert name='goal' checked="checked")
| Front End Development Certification (takes about 400 hours)
label.btn.btn-primary.btn-lg
input(type='radio' id=fullStackCert value=fullStackCert name='goal')
| Full Stack Development Certification (takes about 800 hours)
.spacer
.row
.col-xs-12.col-sm-6.col-sm-offset-3
h3 Step 2: Choose your monthly pledge
.btn-group.btn-group-justified(data-toggle='buttons' role='group')
label.btn.btn-success
input(type='radio' id='5-dollar-pledge' value='5' name='amount')
| $5 per month
label.btn.btn-success.active
input(type='radio' id='10-dollar-pledge' value='10' name='amount' checked="checked")
| $10 per month
label.btn.btn-success
input(type='radio' id='25-dollar-pledge' value='25' name='amount')
| $25 per month
label.btn.btn-success
input(type='radio' id='50-dollar-pledge' value='50' name='amount')
| $50 per month
.spacer
.col-xs-12.col-sm-6.col-sm-offset-3
h3 Step 3: Set up your monthly donation
.row
.col-xs-12.col-sm-6.col-sm-offset-3.text-center
a#commit-btn-donate.btn.btn-block.btn-lg.btn-primary(href=donateUrl target='_blank') Open the #{displayName} donation page
.spacer
.col-xs-12.col-sm-6.col-sm-offset-3
h3#commit-step4-text.disabled
Step 4: Confirm
span#commit-step4-hidden.disabled (Do step 3 first)
span#commit-step4-show.hidden your commitment to your goal
.row
.col-xs-12.col-sm-6.col-sm-offset-3.text-center
button#commit-btn-submit.btn.btn-block.btn-lg.btn-primary.disabled Commit
if pledge
form.row(name='stop-pledge' action='/commit/stop-commitment' method='post')
.col-xs-12.col-sm-6.col-sm-offset-3.text-center
.button-spacer
button.btn.btn-block.btn-lg.btn-default(name='submit' type='submit') Stop my current pledge
else
.row
.col-xs-12.col-sm-6.col-sm-offset-3.text-center
.button-spacer
a.btn.btn-block.btn-lg.btn-default(href='/map') Maybe later
.spacer
script.
$(function() {
$('#commit-btn-donate').click(function() {
$('#commit-btn-submit').removeClass('disabled');
$('#commit-step4-text').removeClass('disabled');
$('#commit-step4-hidden').hide();
$('#commit-step4-show').removeClass('hidden');
});
$('#commit-btn-submit').click(function() {
window.location.href = '/commit/pledge?' + $('form').serialize();
});
});

View File

@ -0,0 +1,15 @@
extends ../layout
block content
.panel.panel-info
.panel-body
h3.text-center You've commited!
.row
.col-xs-12.col-sm-6.col-sm-offset-3
p Congratulations, you have commit to giving
span(style='text-transform: capitalize') #{nonprofit}
| #{amount} dollars a month until you have reached your goal
| of completing your #{goal}
.row
.col-xs-12.col-sm-6.col-sm-offset-3
img.img-responsive(src='http://i.imgur.com/U1CyEuA.jpg' alt="Girl Develop It participants coding at tables.")
p Girl Develop It is a nonprofit that provides in-person classes for women to learn to code.

View File

@ -106,7 +106,7 @@ block content
if (user) if (user)
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter) #submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
if (user.progressTimestamps.length > 2) if (user.progressTimestamps.length > 2)
a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript") a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript", onclick="ga('send', 'event', 'twitter', 'share', 'challenge completion share');")
i.fa.fa-twitter &thinsp; i.fa.fa-twitter &thinsp;
= phrase = phrase
else else

View File

@ -2,14 +2,13 @@ extends ../layout-wide
block content block content
.row .row
.col-md-8.col-md-offset-2 .col-md-8.col-md-offset-2
.jumbotron
for step, index in description for step, index in description
.thumbnail.challenge-step(class=index !== 0 ? 'hidden': '') .thumbnail.challenge-step(class=index !== 0 ? 'hidden': '')
img.gif-block.img-center.img-responsive.thumbnail(src='#{step[0]}' alt='#{step[1]}') img.gif-block.img-center.img-responsive.thumbnail(src='#{step[0]}' alt='#{step[1]}')
.caption .caption
p.large-p= step[2] p.large-p!= step[2]
if step[3] if step[3]
a.btn.btn-block.btn-primary.challenge-step-btn-action(href='#{step[3]}' target='_blank') Go To Link a.btn.btn-block.btn-primary.challenge-step-btn-action(id='#{index}' href='#{step[3]}' target='_blank') Open link in new tab
if index + 1 === description.length if index + 1 === description.length
.btn.btn-block.btn-primary.challenge-step-btn-finish(id='last' class=step[3] ? 'disabled' : '') Finish challenge .btn.btn-block.btn-primary.challenge-step-btn-finish(id='last' class=step[3] ? 'disabled' : '') Finish challenge
else else
@ -27,13 +26,17 @@ block content
.spacer .spacer
.row .row
if (user) if (user)
#challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter) #challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge
else else
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
script(src=rev('/js', 'commonFramework.js')) script(src=rev('/js', 'commonFramework.js'))
script. script.
var common = common || { init: [] }; var common = window.common || { init: [] };
common.challengeId = !{JSON.stringify(challengeId)}; common.challengeId = !{JSON.stringify(challengeId)};
common.challengeName = !{JSON.stringify(name)}; common.challengeName = !{JSON.stringify(name)};
common.challengeType = 7; common.challengeType = 7;
common.dashedName = !{JSON.stringify(dashedName || '')}; common.dashedName = !{JSON.stringify(dashedName || '')};
common.isHonest = !{JSON.stringify(isHonest || false)};
common.isFrontEndCert = !{JSON.stringify(isFrontEndCert || false)};
common.isFullStackCert = !{JSON.stringify(isFullStackCert || false)};
common.challengeSeed = !{JSON.stringify(challengeSeed || [])};

View File

@ -27,26 +27,27 @@ block content
a.btn.btn-cta.signup-btn.btn-block(href="/login") Start learning to code (it's free) a.btn.btn-cta.signup-btn.btn-block(href="/login") Start learning to code (it's free)
.button-spacer .button-spacer
a.btn.btn-cta.btn-success.btn-block(href="/nonprofits") My nonprofit needs coding help a.btn.btn-cta.btn-success.btn-block(href="/nonprofits") My nonprofit needs coding help
h2 As featured in h2 As featured in:
img.img-center.img-responsive(src='https://s3.amazonaws.com/freecodecamp/as-seen-on.png') img.img-center.img-responsive(src='https://s3.amazonaws.com/freecodecamp/as-seen-on.png')
.spacer .spacer
h2 We're a proven way to start your software engineering career:
img.img-center.img-responsive(src='https://s3.amazonaws.com/freecodecamp/linkedin-alumni.png')
.spacer
h2 Campers you'll hang out with: h2 Campers you'll hang out with:
.row .row
.col-xs-12.col-sm-12.col-md-4 .col-xs-12.col-sm-12.col-md-4
img.img-responsive.testimonial-image.img-center(src="https://s3.amazonaws.com/freecodecamp/testimonial-jen.jpg", alt="@jenthebest's testimonial image") img.img-responsive.testimonial-image.img-center(src="http://i.imgur.com/xzDoJef.jpg", alt="'s testimonial image")
.testimonial-copy Getting back on track with Free Code Camp and committing to a new career in 2015! p.testimonial-copy Free Code Camp helped me get my first engineering job. This amazing community made my career switch a lot easier and more fun.
h3 - @jenbestyoga h3 - Ashley Drake
.col-xs-12.col-sm-12.col-md-4 .col-xs-12.col-sm-12.col-md-4
img.img-responsive.testimonial-image.img-center(src="https://s3.amazonaws.com/freecodecamp/testimonial-tate.jpg", alt="@TateThurston's testimonial image") img.img-responsive.testimonial-image.img-center(src="http://i.imgur.com/wjlDigg.jpg", alt="Maxim Orlov's LinkedIn photo")
.testimonial-copy Just built my company's website with skills I've learned from Free Code Camp! p.testimonial-copy I started Free Code Camp with zero knowledge of web development. 6 months later, I landed my first job as a back end engineer.
h3 - @TateThurston h3 - Maxim Orlov
.col-xs-12.col-sm-12.col-md-4 .col-xs-12.col-sm-12.col-md-4
img.img-responsive.testimonial-image.img-center(src="https://s3.amazonaws.com/freecodecamp/testimonial-cynthia.jpg", alt="@cynthialanel's testimonial image") img.img-responsive.testimonial-image.img-center(src="http://i.imgur.com/dE2Di78.jpg", alt="'s testimonial image")
.testimonial-copy I'm currently working through Free Code Camp to improve my JavaScript. The community is very welcoming! p.testimonial-copy Free Code Camp gives me more confidence at work. Code doesnt look as foreign anymore.
h3 - @cynthialanel h3 - Qing Huang
.spacer
.row
.col-xs-12.col-sm-8.col-sm-offset-2
a.btn.btn-lg.btn-primary.btn-primary-ghost.btn-block(href='/stories') Hear from more of our campers
.big-break .big-break
h2 Skills you'll learn: h2 Skills you'll learn:
.text-center.negative-35 .text-center.negative-35

View File

@ -14,7 +14,7 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height
li li
a(href='//gitter.im/FreeCodeCamp/FreeCodeCamp', target='_blank') Chat a(href='//gitter.im/FreeCodeCamp/FreeCodeCamp', target='_blank') Chat
li li
a(href='/news') News a(href='/news', target='_blank') News
li li
a(href='//github.com/FreeCodeCamp/freecodecamp/wiki/Home', target='_blank') Wiki a(href='//github.com/FreeCodeCamp/freecodecamp/wiki/Home', target='_blank') Wiki
if !user if !user
@ -27,3 +27,19 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height
.hidden-xs.hidden-sm .hidden-xs.hidden-sm
a(href='/' + user.username) a(href='/' + user.username)
img.profile-picture.float-right(src='#{user.picture}') img.profile-picture.float-right(src='#{user.picture}')
script.
$(document).ready(function() {
$('.learn-btn').click(function(e) {
var challengeDashedName = null;
e.preventDefault();
if (typeof dashedName === "string") {
return location.reload();
}
if (typeof localStorage !== 'undefined') {
challengeDashedName = localStorage.getItem('currentDashedName');
}
window.location = challengeDashedName ?
'/challenges/' + challengeDashedName :
'/map';
});
});

View File

@ -1,3 +1,11 @@
script.
(function(i,s,o,g,r,a,m){ i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-55446531-1', 'auto');
ga('require', 'displayfeatures');
ga('send', 'pageview');
script(src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js")
script. script.
window.jQuery || document.write('<script src="/bower_components/jquery/dist/jquery.min.js"><\/script>'); window.jQuery || document.write('<script src="/bower_components/jquery/dist/jquery.min.js"><\/script>');
@ -29,11 +37,3 @@ script(src=rev('/js', 'main.js'))
script(src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js") script(src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js")
script(src="/bower_components/ramda/dist/ramda.min.js") script(src="/bower_components/ramda/dist/ramda.min.js")
script(src='/bower_components/lightbox2/dist/js/lightbox.min.js') script(src='/bower_components/lightbox2/dist/js/lightbox.min.js')
script.
(function(i,s,o,g,r,a,m){ i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-55446531-1', 'auto');
ga('require', 'displayfeatures');
ga('send', 'pageview');

View File

@ -1,7 +1,7 @@
script(src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js")
script(src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js")
link(rel='stylesheet', href='/bower_components/font-awesome/css/font-awesome.min.css') link(rel='stylesheet', href='/bower_components/font-awesome/css/font-awesome.min.css')
link(rel='stylesheet', href=rev('/css', 'main.css')) link(rel='stylesheet', href='/css/main.css')
link(rel='stylesheet', href='/css/Vimeo.css') link(rel='stylesheet', href='/css/Vimeo.css')
// End **REQUIRED** includes // End **REQUIRED** includes

View File

@ -0,0 +1,22 @@
extends ../layout
block content
.panel.panel-info
.panel-heading.text-center Projects Created by Free Code Camp Campers
.panel-body.text-left
.row
.col-xs-12.col-sm-10.col-sm-offset-1
for project in projects
.spacer
.row
.col-xs-12.col-sm-3
img.img-responsive(src=project.image)
.col-xs-12.col-sm-9.negative-15
h3
a(href=project.url) #{project.name}
h4 by&thinsp;
a(href='/' + project.camper) #{project.camper}
p= project.description
if !user
a.btn.btn-cta.signup-btn.btn-primary(href="/login") Start learning to code (it's free)
.spacer

View File

@ -0,0 +1,23 @@
extends ../layout
block content
.panel.panel-info
.panel-heading.text-center Stories from happy campers
.panel-body.text-left
.row
.col-xs-12.col-sm-10.col-sm-offset-1
.row
for story in stories
.col-xs-12.col-sm-6.col-md-4
.story-section
a(href=story.linkedin target='_blank')
img.testimonial-image.img-responsive.img-center(src=story.image)
h3.text-center= story.camper
| &nbsp;
a.fa.fa-linkedin-square.text-primary(alt="#{story.camper}'s LinkedIn Profile", href=story.linkedin, target='_blank')
p.text-justify= story.quote
if !user
.text-center
a.btn.btn-cta.signup-btn(href="/login") Start learning to code (it's free)
.spacer

View File

@ -47,8 +47,8 @@
"<br>" + "<br>" +
(typeof username !== 'undefined' ? (typeof username !== 'undefined' ?
"<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</button>" : "<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</button>" :
"<a href='/signup' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</a>") + "<a href='/signin' class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost btn-upvote'>upvote</a>") +
"<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/news/" + linkedName + "'>more info</a>" + "<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost hidden' href='/news/" + linkedName + "'>more info</a>" +
"</div>" + "</div>" +
"</div>" + "</div>" +
"<div class='hidden-xs row media-stories'>" + "<div class='hidden-xs row media-stories'>" +
@ -69,7 +69,7 @@
(typeof username !== 'undefined' ? (typeof username !== 'undefined' ?
"<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost btn-upvote'>upvote</button>" : "<button id='" + data[i].id + "' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost btn-upvote'>upvote</button>" :
"<a href='/signin' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost'>upvote</a>") + "<a href='/signin' class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost'>upvote</a>") +
" · <a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/news/" + linkedName + "'>more info</a> · " + "<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost hidden' href='/news/" + linkedName + "'>more info</a> · " +
rank + (rank > 1 ? " points" : " point") + " · posted " + rank + (rank > 1 ? " points" : " point") + " · posted " +
moment(data[i].timePosted).fromNow() + moment(data[i].timePosted).fromNow() +
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + "</a> " + " by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + "</a> " +