Merge branch 'staging' into feature/jobs

Conflicts:
	seed/jobs.json
This commit is contained in:
Quincy Larson
2015-11-02 00:07:16 -08:00
38 changed files with 604 additions and 910 deletions

View File

@ -1,7 +1,6 @@
language: node_js
node_js:
- 'node'
- '1.6.4'
- '4.2.1'
sudo: false

View File

@ -659,7 +659,11 @@ function ctrlEnterClickHandler(e) {
// ctrl + enter
if (e.ctrlKey && e.keyCode === 13) {
$('#complete-courseware-dialog').off('keydown', ctrlEnterClickHandler);
$('#submit-challenge').click();
if ($('#submit-challenge').length > 0) {
$('#submit-challenge').click();
} else {
window.location = '/challenges/next-challenge?id=' + common.challengeId;
}
}
}
@ -781,7 +785,7 @@ var scrapeTests = function(userJavaScript) {
};
function removeComments(userJavaScript) {
var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g);
var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|([ \n]\/\/[^\n]*)/g);
return userJavaScript.replace(regex, '');
}
@ -892,12 +896,32 @@ var runTests = function(err, data) {
// step challenge
common.init.push((function() {
var stepClass = '.challenge-step';
var prevBtnClass = '.challenge-step-btn-prev';
var nextBtnClass = '.challenge-step-btn-next';
var actionBtnClass = '.challenge-step-btn-action';
var finishBtnClass = '.challenge-step-btn-finish';
var submitBtnId = '#challenge-step-btn-submit';
var submitModalId = '#challenge-step-modal';
function getPreviousStep($challengeSteps) {
var length = $challengeSteps.length;
var $prevStep = false;
var prevStepIndex = 0;
$challengeSteps.each(function(index) {
var $step = $(this);
if (
!$step.hasClass('hidden') &&
index + 1 !== length
) {
prevStepIndex = index - 1;
}
});
$prevStep = $challengeSteps[prevStepIndex];
return $prevStep;
}
function getNextStep($challengeSteps) {
var length = $challengeSteps.length;
var $nextStep = false;
@ -917,11 +941,36 @@ common.init.push((function() {
return $nextStep;
}
function handlePrevStepClick(e) {
e.preventDefault();
var prevStep = getPreviousStep($(stepClass));
$(this)
.parent()
.removeClass('fadeOutLeft')
.addClass('animated fadeOutRight fast-animation')
.delay(250)
.queue(function(prev) {
$(this).addClass('hidden');
if (prevStep) {
$(prevStep)
.removeClass('hidden')
.removeClass('slideInRight')
.addClass('animated slideInLeft fast-animation')
.delay(500)
.queue(function(prev) {
prev();
});
}
prev();
});
}
function handleNextStepClick(e) {
e.preventDefault();
var nextStep = getNextStep($(stepClass));
$(this)
.parent()
.removeClass('fadeOutRight')
.addClass('animated fadeOutLeft fast-animation')
.delay(250)
.queue(function(next) {
@ -929,10 +978,10 @@ common.init.push((function() {
if (nextStep) {
$(nextStep)
.removeClass('hidden')
.removeClass('slideInLeft')
.addClass('animated slideInRight fast-animation')
.delay(500)
.queue(function(next) {
$(this).removeClass('slideInRight');
next();
});
}
@ -1035,6 +1084,7 @@ common.init.push((function() {
}
return function($) {
$(prevBtnClass).click(handlePrevStepClick);
$(nextBtnClass).click(handleNextStepClick);
$(actionBtnClass).click(handleActionClick);
$(finishBtnClass).click(handleFinishClick);

View File

@ -694,6 +694,24 @@ iframe.iphone {
transition: background .2s ease-in-out, border .2s ease-in-out;
}
.btn-warning-ghost {
background: transparent;
color: @brand-warning;
/* CSS Transition */
-webkit-transition: background .2s ease-in-out, border .2s ease-in-out;
-moz-transition: background .2s ease-in-out, border .2s ease-in-out;
-ms-transition: background .2s ease-in-out, border .2s ease-in-out;
-o-transition: background .2s ease-in-out, border .2s ease-in-out;
transition: background .2s ease-in-out, border .2s ease-in-out;
}
.population-table {
@media (max-width: 767px) {
font-size: 16px;
}
}
@media (max-width: 991px) {
.navbar-header {
float: none;

View File

@ -86,6 +86,9 @@
"solutions": {
"type": "array",
"default": []
},
"releasedOn": {
"type": "string"
}
},
"validations": [],

View File

@ -13,7 +13,11 @@
"prestart-production": "bower cache clean && bower install && gulp build",
"start-production": "node pm2Start",
"lint": "eslint --ext=.js,.jsx .",
"test": "gulp test-challenges"
"lint-challenges": "jsonlint -q seed/challenges/*.json",
"lint-nonprofits": "jsonlint -q seed/nonprofits.json",
"test-challenges": "babel-node seed/test-challenges.js | tnyan",
"pretest": "npm run lint-challenges && npm run lint-nonprofits",
"test": "npm run test-challenges"
},
"license": "(BSD-3-Clause AND CC-BY-SA-4.0)",
"dependencies": {
@ -127,11 +131,14 @@
"chai": "~1.10.0",
"envify": "^3.4.0",
"istanbul": "^0.3.15",
"jsonlint": "^1.6.2",
"loopback-explorer": "^1.7.2",
"loopback-testing": "^1.1.0",
"mocha": "~2.0.1",
"multiline": "~1.0.1",
"supertest": "~0.15.0",
"tap-nyan": "0.0.2",
"tape": "^4.2.2",
"vinyl-source-stream": "^1.1.0"
}
}

View File

@ -1,44 +0,0 @@
require('dotenv').load();
var bonfires = require('./bonfires.json'),
app = require('../server/server'),
mongodb = require('mongodb'),
MongoClient = mongodb.MongoClient,
User = app.models.User,
UserIdentity = app.models.userIdentity,
oldUri='mongodb://localhost:27017/app30893198',
coursewares = require('./coursewares.json');
MongoClient.connect(oldUri, function(err, database) {
database.collection('users').find({}).batchSize(20).toArray(function(err, users) {
if (users !== null && users.length !== 0) {
var mappedUserArray = users.map(function(user) {
Object.keys(user.profile).forEach(function(prop) {
user[prop] = user.profile[prop];
});
Object.keys(user.portfolio).forEach(function(prop) {
user[prop] = user.portfolio[prop];
});
user.completedCoursewares = Object.keys(user.challengesHash)
.filter(function(key) {
return user.challengesHash[key] !== 0;
})
.map(function(key) {
return({
id: coursewares[key].id,
completedDate: user.challengesHash[key]
});
});
return user;
});
User.create(mappedUserArray, function(err) {
if (err) {
console.log(err);
}
console.log("a batch finished");
});
}
});
});

View File

@ -1,226 +0,0 @@
[
{
"oldNumber": "0",
"newId": "bd7124d8c441eddfaeb5bdef"
},
{
"oldNumber": "1",
"newId": "bd7125d8c441eddfaeb5bd0f"
},
{
"oldNumber": "2",
"newId": ""
},
{
"oldNumber": "3",
"newId": "bd7127d8c441eddfaeb5bdef"
},
{
"oldNumber": "4",
"newId": "bd7128d8c441eddfaeb5bdef"
},
{
"oldNumber": "5",
"newId": "bd8129d8c441eddfaeb5bdef"
},
{
"oldNumber": "6",
"newId": ""
},
{
"oldNumber": "7",
"newId": ""
},
{
"oldNumber": "8",
"newId": "bd7112d8c441eddfaeb5bdef"
},
{
"oldNumber": "9",
"newId": "bd7113d8c441eddfaeb5bdef"
},
{
"oldNumber": "10",
"newId": "bd7114d8c441eddfaeb5bdef"
},
{
"oldNumber": "11",
"newId": "bd7115d8c441eddfaeb5bdef"
},
{
"oldNumber": "12",
"newId": "bd7116d8c441eddfaeb5bdef"
},
{
"oldNumber": "13",
"newId": "bd7117d8c441eddfaeb5bdef"
},
{
"oldNumber": "14",
"newId": "bd7118d8c441eddfaeb5bdef"
},
{
"oldNumber": "15",
"newId": ""
},
{
"oldNumber": "16",
"newId": ""
},
{
"oldNumber": "17",
"newId": ""
},
{
"oldNumber": "18",
"newId": ""
},
{
"oldNumber": "19",
"newId": "bd7123d8c441eddfaeb5bdef"
},
{
"oldNumber": "20",
"newId": "bd8124d8c441eddfaeb5bdef"
},
{
"oldNumber": "21",
"newId": "bd8126d8c441eddfaeb5bdef"
},
{
"oldNumber": "22",
"newId": "bd8127d8c441eddfaeb5bdef"
},
{
"oldNumber": "23",
"newId": "bd8128d8c441eddfaeb5bdef"
},
{
"oldNumber": "24",
"newId": "bd7129d8c441eddfaeb5bdef"
},
{
"oldNumber": "25",
"newId": "bd7130d8c441eddfaeb5bdef"
},
{
"oldNumber": "26",
"newId": "bd7131d8c441eddfaeb5bdef"
},
{
"oldNumber": "27",
"newId": "bd7132d8c441eddfaeb5bdef"
},
{
"oldNumber": "28",
"newId": "bd7133d8c441eddfaeb5bdef"
},
{
"oldNumber": "29",
"newId": "bd7134d8c441eddfaeb5bdef"
},
{
"oldNumber": "30",
"newId": "bd7135d8c441eddfaeb5bdef"
},
{
"oldNumber": "31",
"newId": "bd7136d8c441eddfaeb5bdef"
},
{
"oldNumber": "32",
"newId": ""
},
{
"oldNumber": "33",
"newId": "bd7138d8c441eddfaeb5bdef"
},
{
"oldNumber": "34",
"newId": "bd7137d8c441eddfaeb5bdef"
},
{
"oldNumber": "35",
"newId": "bd7140d8c441eddfaeb5bdef"
},
{
"oldNumber": "36",
"newId": ""
},
{
"oldNumber": "37",
"newId": ""
},
{
"oldNumber": "38",
"newId": ""
},
{
"oldNumber": "39",
"newId": ""
},
{
"oldNumber": "40",
"newId": ""
},
{
"oldNumber": "41",
"newId": ""
},
{
"oldNumber": "42",
"newId": ""
},
{
"oldNumber": "43",
"newId": ""
},
{
"oldNumber": "44",
"newId": ""
},
{
"oldNumber": "45",
"newId": ""
},
{
"oldNumber": "46",
"newId": ""
},
{
"oldNumber": "47",
"newId": ""
},
{
"oldNumber": "48",
"newId": "bd7153d8c441eddfaeb5bd2f"
},
{
"oldNumber": "49",
"newId": "bd7154d8c441eddfaeb5bdef"
},
{
"oldNumber": "50",
"newId": "bd7155d8c441eddfaeb5bdef"
},
{
"oldNumber": "51",
"newId": "bd7156d8c441eddfaeb5bdef"
},
{
"oldNumber": "52",
"newId": "bd7157d8c441eddfaeb5bdef"
},
{
"oldNumber": "53",
"newId": "bd7158d8c441eddfaeb5bdef"
},
{
"oldNumber": "54",
"newId": ""
},
{
"oldNumber": "55",
"newId": ""
}
]

View File

@ -157,7 +157,6 @@
"Global Object"
],
"solutions": [
"var VALUES = [1, 5, 10, 25, 100, 500, 1000, 2000, 10000];\n\nfunction drawer(price, cash, cid) {\n cash = ~~(cash * 100);\n price = ~~(price * 100);\n var diff = cash-price;\n cid.forEach(function(c) {\n c[1] = ~~(c[1] * 100);\n });\n var totalCid = cid.reduce(function(a, c) {\n return a + c[1];\n }, 0);\n if (diff > totalCid) {\n return \"Insufficient Funds\";\n }\n if (diff === totalCid) {\n return \"Closed\";\n }\n \n var change = []; \n var index = cid.length;\n while (diff > 0 && --index > -1) {\n var t = 0;\n var value = VALUES[index];\n while (diff >= value && cid[index][1] > 0) {\n t += value;\n cid[index][1] -= value;\n diff -= value;\n }\n if (t) {\n change.push([cid[index][0], t/100]);\n }\n console.log(JSON.stringify(change));\n }\n // Here is your change, ma'am.\n return change;\n}\n\n// Example cash-in-drawer array:\n// [['PENNY', 1.01],\n// ['NICKEL', 2.05],\n// ['DIME', 3.10],\n// ['QUARTER', 4.25],\n// ['ONE', 90.00],\n// ['FIVE', 55.00],\n// ['TEN', 20.00],\n// ['TWENTY', 60.00],\n// ['ONE HUNDRED', 100.00]]\n\ndrawer(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]]);\n"
],
"type": "bonfire",
"challengeType": 5,

View File

@ -14,7 +14,12 @@
],
"type": "waypoint",
"challengeType": 2,
"tests": [],
"tests": [
"assert(true, 'No test needed');"
],
"solutions": [
"/* no test needed */"
],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
@ -37,7 +42,12 @@
],
"type": "waypoint",
"challengeType": 2,
"tests": [],
"tests": [
"assert(true, 'No test needed');"
],
"solutions": [
"/* no test needed */"
],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
@ -60,7 +70,12 @@
],
"type": "waypoint",
"challengeType": 2,
"tests": [],
"tests": [
"assert(true, 'No test needed');"
],
"solutions": [
"/* no test needed */"
],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
@ -82,7 +97,12 @@
],
"type": "waypoint",
"challengeType": 2,
"tests": [],
"tests": [
"assert(true, 'No test needed');"
],
"solutions": [
"/* no test needed */"
],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",
@ -105,7 +125,12 @@
],
"type": "waypoint",
"challengeType": 2,
"tests": [],
"tests": [
"assert(true, 'No test needed');"
],
"solutions": [
"/* no test needed */"
],
"nameCn": "",
"descriptionCn": [],
"nameFr": "",

View File

@ -116,7 +116,7 @@
"Arithmetic Operators"
],
"solutions": [
"function factorialize(num) {\n return num === 1 ? 1 : num * factorialize(num-1);\n}\n\nfactorialize(5);\n"
"function factorialize(num) {\n return num < 1 ? 1 : num * factorialize(num-1);\n}\n\nfactorialize(5);\n"
],
"type": "bonfire",
"challengeType": 5,
@ -169,7 +169,6 @@
"String.toLowerCase()"
],
"solutions": [
"function palindrome(str) {\n var a = str.toLowerCase().replace(/[^a-z]/g, '');\n console.log(a.split('').reverse().join(''));\n return a == a.split('').reverse().join('');\n}\n\n\n\npalindrome(\"eye\");\npalindrome(\"A man, a plan, a canal. Panama\");\n"
],
"type": "bonfire",
"challengeType": 5,
@ -243,8 +242,8 @@
"titleCase(\"I'm a little tea pot\");"
],
"tests": [
"assert(typeof(titleCase(\"I&#39;m a little tea pot\")) === \"string\", 'message: <code>titleCase()</code> should return a string.');",
"assert(titleCase(\"I&#39;m a little tea pot\") === \"I&#39;m A Little Tea Pot\", 'message: <code>titleCase(\"I&#39;m a little tea pot\")</code> should return \"I&#39;m A Little Tea Pot\".');",
"assert(typeof(titleCase(\"I'm a little tea pot\")) === \"string\", 'message: <code>titleCase()</code> should return a string.');",
"assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: <code>titleCase(\"I&#39;m a little tea pot\")</code> should return \"I&#39;m A Little Tea Pot\".');",
"assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: <code>titleCase(\"sHoRt AnD sToUt\")</code> should return \"Short And Stout\".');",
"assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: <code>titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")</code> should return \"Here Is My Handle Here Is My Spout\".');"
],
@ -273,7 +272,6 @@
"description": [
"Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.",
"Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .",
"If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays.",
"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": [
@ -418,7 +416,6 @@
"String.slice()"
],
"solutions": [
"function truncate(str, num) {\n if (str.length > num) {\n return str.substring(0, num-3) + '...';\n }\n return str;\n}\n\ntruncate('A-tisket a-tasket A green and yellow basket', 11);\n"
],
"type": "bonfire",
"challengeType": 5,
@ -664,9 +661,7 @@
"MDNlinks": [
"Array.sort()"
],
"solutions": [
"function where(arr, num) {\n // Find my place in this sorted array.\n return num;\n}\n\nwhere([40, 60], 50);\n"
],
"solutions": [],
"tests": [
"assert(where([10, 20, 30, 40, 50], 35) === 3, 'message: <code>where([10, 20, 30, 40, 50], 35)</code> should return <code>3</code>.');",
"assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: <code>where([10, 20, 30, 40, 50], 30)</code> should return <code>2</code>.');",

View File

@ -653,7 +653,7 @@
"In JavaScript, we can divide up our code into reusable parts called functions.",
"Here's an example of a function:",
"<code>function functionName(a, b) {</code>",
"<code>&thinsp;&thinsp;return a + b;</code>",
"<code>&nbsp;&nbsp;return a + b;</code>",
"<code>}</code>",
"After writing the above lines in our code, we can then pass values to our function and the result following the <code>return</code> statement will be returned.",
"For example, we can pass numbers <code>4</code> and <code>2</code> by “calling” the function later in our code like this: <code>functionName(4, 2)</code>.",
@ -694,10 +694,10 @@
"Objects are similar to <code>arrays</code>, except that instead of using indexes to access and modify their data, you access the data in objects through what are called <code>properties</code>.",
"Here's a sample object:",
"<code>var cat = {</code>",
"<code>&thinsp;&thinsp;\"name\": \"Whiskers\",</code>",
"<code>&thinsp;&thinsp;\"legs\": 4,</code>",
"<code>&thinsp;&thinsp;\"tails\": 1,</code>",
"<code>&thinsp;&thinsp;\"enemies\": [\"Water\", \"Dogs\"]</code>",
"<code>&nbsp;&nbsp;\"name\": \"Whiskers\",</code>",
"<code>&nbsp;&nbsp;\"legs\": 4,</code>",
"<code>&nbsp;&nbsp;\"tails\": 1,</code>",
"<code>&nbsp;&nbsp;\"enemies\": [\"Water\", \"Dogs\"]</code>",
"<code>};</code>",
"</code>",
"Objects are useful for storing data in a structured way, and can represent real world objects, like a cat.",
@ -741,10 +741,10 @@
"After you've created a JavaScript object, you can update its properties at any time just like you would update any other variable.",
"For example, let's look at <code>ourDog</code>:",
"<code>var ourDog = {</code>",
"<code>&thinsp;&thinsp;\"name\": \"Camper\",</code>",
"<code>&thinsp;&thinsp;\"legs\": 4,</code>",
"<code>&thinsp;&thinsp;\"tails\": 1,</code>,",
"<code>&thinsp;&thinsp;\"friends\": [\"everything!\"]</code>",
"<code>&nbsp;&nbsp;\"name\": \"Camper\",</code>",
"<code>&nbsp;&nbsp;\"legs\": 4,</code>",
"<code>&nbsp;&nbsp;\"tails\": 1,</code>,",
"<code>&nbsp;&nbsp;\"friends\": [\"everything!\"]</code>",
"<code>};</code>",
"Since he's a particularly happy dog, let's change his name to \"Happy Camper\". Here's how we update his object's name property:",
"<code>ourDog.name = \"Happy Camper\";</code>",
@ -868,16 +868,16 @@
"The most common type of JavaScript loop is called a \"for loop\" because it runs \"for\" a specific number of times.",
"For loops are declared with three optional expressions seperated by semicolons:",
"<code>for([initialization]; [condition]; [final-expression])</code>",
"The <code>initialization</code> statement is executed one time only before the loop starts. It is typically used to define and setup your loop varaible.",
"The <code>condition</code> statement is evaluated at the beginning of every loop and will continue as long as it evalutes <code>true</code>. When <code>condition</code> is <code>false</code> at the start of the loop, the loop will stop executing. This means if <code>condition</code> starts as <code>false</code>, your loop will never execute.",
"The <code>initialization</code> statement is executed one time only before the loop starts. It is typically used to define and setup your loop variable.",
"The <code>condition</code> statement is evaluated at the beginning of every loop iteration and will continue as long as it evalutes to <code>true</code>. When <code>condition</code> is <code>false</code> at the start of the iteration, the loop will stop executing. This means if <code>condition</code> starts as <code>false</code>, your loop will never execute.",
"The <code>final-expression</code> is executed at the end of each loop iteration, prior to the next <code>condition</code> check and is usually used to increment or decrement your loop counter.",
"We'll initialize with <code>i = 0</code> and loop while our condition <code>i < 5</code> is true. We'll increment <code>i</code> by 1 each loop with <code>i++</code> as our <code>final-expression</code>.",
"In the following example we initialize with <code>i = 0</code> and iterate while our condition <code>i < 5</code> is true. We'll increment <code>i</code> by <code>1</code> in each loop iteration with <code>i++</code> as our <code>final-expression</code>.",
"<code>var ourArray = [];</code>",
"<code>for(var i = 0; i < 5; i++) {</code>",
"<code>&thinsp;&thinsp;ourArray.push(i);</code>",
"<code>&nbsp;&nbsp;ourArray.push(i);</code>",
"<code>}</code>",
"<code>ourArray</code> will now contain [0,1,2,3,4] ",
"Let's try getting a for loop to work by pushing values to an array."
"<code>ourArray</code> will now contain <code>[0,1,2,3,4]</code>.",
"Let's try getting a <code>for</code> loop to work by pushing values to an array."
],
"tests": [
"assert(editor.getValue().match(/for\\s*\\(/g).length > 1, 'message: You should be using a <code>for</code> loop for this.');",
@ -912,7 +912,7 @@
"We'll start at <code>i = 0</code> and loop while <code>i < 10</code>. We'll increment <code>i</code> by 2 each loop with <code>i += 2</code>.",
"<code>var ourArray = [];</code>",
"<code>for(var i = 0; i < 10; i += 2) {</code>",
"<code>&thinsp;&thinsp;ourArray.push(i);</code>",
"<code>&nbsp;&nbsp;ourArray.push(i);</code>",
"<code>}</code>",
"<code>ourArray</code> will now contain [0,2,4,6,8] ",
"Let's change our <code>initialization</code> and <code>final-expression</code> so we can count by odd numbers.",
@ -925,7 +925,7 @@
"challengeSeed":[
"var ourArray = [];",
"",
"for(var i = 1; i < 10; i += 2){",
"for(var i = 0; i < 10; i += 2){",
" ourArray.push(i);",
"}",
"",
@ -952,7 +952,7 @@
"We'll start at <code>i = 10</code> and loop while <code>i > 0</code>. We'll decrement <code>i</code> by 2 each loop with <code>i -= 2</code>.",
"<code>var ourArray = [];</code>",
"<code>for(var i = 10; i > 0; i -= 2) {</code>",
"<code>&thinsp;&thinsp;ourArray.push(i);</code>",
"<code>&nbsp;&nbsp;ourArray.push(i);</code>",
"<code>}</code>",
"<code>ourArray</code> will now contain <code>[10,8,6,4,2]</code>",
"Let's change our <code>initialization</code> and <code>final-expression</code> so we can count backward by twos for numbers.",
@ -992,8 +992,8 @@
"<code>var ourArray = [];</code>",
"<code>var i = 0;</code>",
"<code>while(i < 5) {</code>",
"<code>&thinsp;&thinsp;ourArray.push(i);</code>",
"<code>&thinsp;&thinsp;i++;</code>",
"<code>&nbsp;&nbsp;ourArray.push(i);</code>",
"<code>&nbsp;&nbsp;i++;</code>",
"<code>}</code>",
"Let's try getting a while loop to work by pushing values to an array.",
"Push the numbers 0 through 4 to <code>myArray</code> using a <code>while loop</code>."
@ -1093,7 +1093,7 @@
"Here's the formula we'll use. Take a moment to read it and try to understand what this code is doing:",
"<code>Math.floor(Math.random() * (max - min + 1)) + min</code>",
"Define two variables: <code>myMin</code> and </code>myMax</code>, and set them both equal to numbers.",
"Then create a function called <code>myFunction</code> that returns a random number that's greater than or equal to <code>myMin</code>, and is less than <code>myMax</code>."
"Then create a function called <code>myFunction</code> that returns a random number that's greater than or equal to <code>myMin</code>, and is less than or equal to <code>myMax</code>."
],
"tests": [
"assert(myFunction() >= myMin, 'message: The random number generated by <code>myFunction</code> should be greater than or equal to your minimum number, <code>myMin</code>.');",
@ -1140,9 +1140,9 @@
"<code>if</code> statements require some sort of boolean condition to evaluate.",
"For example:",
"<code>if (1 === 2) {</code>",
"<code>&thinsp;&thinsp;return true;</code>",
"<code>&nbsp;&nbsp;return true;</code>",
"<code>} else {</code>",
"<code>&thinsp;&thinsp;return false;</code>",
"<code>&nbsp;&nbsp;return false;</code>",
"<code>}</code>",
"Let's use <code>if</code> and <code>else</code> statements to make a coin-flip game.",
"Create <code>if</code> and <code>else</code> statements to return the string <code>\"heads\"</code> if the flip variable is zero, or else return the string <code>\"tails\"</code> if the flip variable is not zero."
@ -1183,7 +1183,7 @@
"<code>i</code> means that we want to ignore the case (uppercase or lowercase) when searching for the pattern.",
"<code>Regular expressions</code> are written by surrounding the pattern with <code>/</code> symbols.",
"Let's try selecting all the occurrences of the word <code>and</code> in the string <code>Ada Lovelace and Charles Babbage designed the first computer and the software that would have run on it</code>.",
"We can do this by replacing the <code>.</code> part of our regular expression with the current <code>regular expression</code> with the word <code>and</code>."
"We can do this by replacing the <code>.</code> part of our regular expression with the word <code>and</code>."
],
"tests": [
"assert(test==2, 'message: Your <code>regular expression</code> should find two occurrences of the word <code>and</code>.');",
@ -1460,7 +1460,7 @@
"If all three numbers match, we should return the number that we have in three of slots or leave it as <code>null</code>.",
"Let's create an <code>if statement</code> with multiple conditions in order to check whether all numbers are equal.",
"<code>if(slotOne !== slotTwo || slotTwo !== slotThree){</code>",
"<code>&thinsp;&thinsp;return null;</code>",
"<code>&nbsp;&nbsp;return null;</code>",
"<code>}</code>"
],
"tests": [

View File

@ -183,7 +183,8 @@
"<code>&#60h2 class=\"red-text text-center\"&#62your text&#60/h2&#62</code>"
],
"tests": [
"assert($(\"h2\").hasClass(\"text-center\"), 'Your <code>h2</code> element should be centered by applying the class <code>text-center</code>')"
"assert($(\"h2\").hasClass(\"text-center\"), 'Your <code>h2</code> element should be centered by applying the class <code>text-center</code>')",
"assert($(\"h2\").hasClass(\"red-text\"), 'Your <code>h2</code> element should still have the class <code>red-text</code>')"
],
"challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",

View File

@ -381,7 +381,7 @@
"<code>&#60;/style&#62;</code>",
"Inside that style element, you can create a <code>CSS selector</code> for all <code>h2</code> elements. For example, if you wanted all <code>h2</code> elements to be red, your style element would look like this:",
"<code>&#60;style&#62;</code>",
"&thinsp;&thinsp;<code>h2 {color: red;}</code>",
"&nbsp;&nbsp;<code>h2 {color: red;}</code>",
"<code>&#60;/style&#62;</code>",
"Note that it's important to have both opening and closing curly braces (<code>{</code> and <code>}</code>) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles.",
"Delete your <code>h2</code> element's style attribute and instead create a CSS <code>style</code> element. Add the necessary CSS to turn all <code>h2</code> elements blue."
@ -390,7 +390,7 @@
"assert(!$(\"h2\").attr(\"style\"), 'Remove the style attribute from your <code>h2</code> element.')",
"assert($(\"style\") && $(\"style\").length > 1, 'Create a <code>style</code> element.')",
"assert($(\"h2\").css(\"color\") === \"rgb(0, 0, 255)\", 'Your <code>h2</code> element should be blue.')",
"assert(editor.match(/h2\\s*\\{\\s*color:\\s*blue;\\s*\\}/g), 'Ensure that your stylesheet <code>h2</code> declaration is valid with a semicolon and closing brace')",
"assert(editor.match(/h2\\s*\\{\\s*color\\s*:\\s*blue;\\s*\\}/g), 'Ensure that your stylesheet <code>h2</code> declaration is valid with a semicolon and closing brace')",
"assert(editor.match(/<\\/style>/g) && editor.match(/<\\/style>/g).length === (editor.match(/<style((\\s)*((type|media|scoped|title|disabled)=\"[^\"]*\")?(\\s)*)*>/g) || []).length, 'Make sure all your <code>style</code> elements are valid and have a closing tag.')"
],
"challengeSeed": [
@ -436,9 +436,9 @@
"Classes are reusable styles that can be added to HTML elements.",
"Here's an example CSS class declaration:",
"<code>&#60;style&#62;</code>",
"<code>&thinsp;&thinsp;.blue-text {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;color: blue;</code>",
"<code>&thinsp;&thinsp;}</code>",
"<code>&nbsp;&nbsp;.blue-text {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;color: blue;</code>",
"<code>&nbsp;&nbsp;}</code>",
"<code>&#60;/style&#62;</code>",
"You can see that we've created a CSS class called <code>blue-text</code> within the <code>&#60;style&#62;</code> tag.",
"You can apply a class to an HTML element like this:",
@ -504,7 +504,7 @@
"Remember that you can attach classes to HTML elements by using <code>class=\"your-class-here\"</code> within the relevant element's opening tag.",
"Remember that CSS class selectors require a period at the beginning like this:",
"<code>.blue-text {</code>",
"<code>&thinsp;&thinsp;color: blue;</code>",
"<code>&nbsp;&nbsp;color: blue;</code>",
"<code>}</code>",
"But also remember that class declarations don't use a period, like this:",
"<code>&#60;h2 class=\"blue-text\"&#62;CatPhotoApp&#60;h2&#62;</code>",
@ -556,7 +556,7 @@
"description": [
"Font size is controlled by the <code>font-size</code> CSS property, like this:",
"<code>h1 {</code>",
"<code>&thinsp;&thinsp;font-size: 30px;</code>",
"<code>&nbsp;&nbsp;font-size: 30px;</code>",
"}</code>",
"See if you can figure out how to give both of your <code>p</code> elements the font-size of 16 pixels (<code>16px</code>). You can do this inside the same <code>&#60;style&#62;</code> tag that we created for your <code>red-text</code> class.",
"Create a second <code>p</code> element with the following kitty ipsum text: <code>Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.</code>",
@ -611,7 +611,7 @@
"You can set an element's font by using the <code>font-family</code> property.",
"For example, if you wanted to set your <code>h2</code> element's font to <code>Sans-serif</code>, you would use the following CSS:",
"<code>h2 {</code>",
"<code>&thinsp;&thinsp;font-family: Sans-serif;</code>",
"<code>&nbsp;&nbsp;font-family: Sans-serif;</code>",
"<code>}</code>",
"Make all of your <code>p</code> elements use the <code>Monospace</code> font."
],
@ -715,7 +715,7 @@
"When one font isn't available, you can tell the browser to \"degrade\" to another font.",
"For example, if you wanted an element to use the <code>Helvetica</code> font, but also degrade to the <code>Sans-Serif</code> font when <code>Helvetica</code> wasn't available, you could use this CSS style:",
"<code>p {</code>",
"<code>&thinsp;&thinsp;font-family: Helvetica, Sans-Serif;</code>",
"<code>&nbsp;&nbsp;font-family: Helvetica, Sans-Serif;</code>",
"<code>}</code>",
"Now comment out your call to Google Fonts, so that the <code>Lobster</code> font isn't available. Notice how it degrades to the <code>Monospace</code> font."
],
@ -832,9 +832,9 @@
"CSS has a property called <code>width</code> that controls an element's width. Just like with fonts, we'll use <code>px</code> (pixels) to specify the image's width.",
"For example, if we wanted to create a CSS class called <code>larger-image</code> that gave HTML elements a width of 500 pixels, we'd use:",
"<code>&#60;style&#62;</code>",
"<code>&thinsp;&thinsp;.larger-image {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;width: 500px;</code>",
"<code>&thinsp;&thinsp;}</code>",
"<code>&nbsp;&nbsp;.larger-image {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;width: 500px;</code>",
"<code>&nbsp;&nbsp;}</code>",
"<code>&#60;/style&#62;</code>",
"Create a class called <code>smaller-image</code> and use it to resize the image so that it's only 100 pixels wide."
],
@ -892,11 +892,11 @@
"CSS borders have properties like <code>style</code>, <code>color</code> and <code>width</code>",
"For example, if we wanted to create a red, 5 pixel border around an HTML element, we could use this class:",
"<code>&#60;style&#62;</code>",
"<code>&thinsp;&thinsp;.thin-red-border {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;border-color: red;</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;border-width: 5px;</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;border-style: solid;</code>",
"<code>&thinsp;&thinsp;}</code>",
"<code>&nbsp;&nbsp;.thin-red-border {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;border-color: red;</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;border-width: 5px;</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;border-style: solid;</code>",
"<code>&nbsp;&nbsp;}</code>",
"<code>&#60;/style&#62;</code>",
"Create a class called <code>thick-green-border</code> that puts a 10-pixel-wide green border with a style of <code>solid</code> around an HTML element, and apply that class to your cat photo.",
"Remember that you can apply multiple classes to an element by separating each class with a space within its <code>class</code> attribute. For example:",
@ -1172,7 +1172,7 @@
"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($(\"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(/^\\s*View\\smore\\s/gi), 'Your <code>p</code> element should have the text \"View more \" (with a space after it).')",
"assert($(\"a[href=\\\"http://www.freecatphotoapp.com\\\"]\").parent().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(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.')"
@ -1453,11 +1453,11 @@
"Unordered lists start with a <code>&#60;ul&#62;</code> element. Then they contain some number of <code>&#60;li&#62;</code> elements.",
"For example: ",
"<code>&#60;ul&#62;</code>",
"&thinsp;&thinsp;<code>&#60;li&#62;milk&#60;/li&#62;</code>",
"&thinsp;&thinsp;<code>&#60;li&#62;cheese&#60;/li&#62;</code>",
"&nbsp;&nbsp;<code>&#60;li&#62;milk&#60;/li&#62;</code>",
"&nbsp;&nbsp;<code>&#60;li&#62;cheese&#60;/li&#62;</code>",
"<code>&#60;/ul&#62;</code>",
"would create a bullet point-style list of \"milk\" and \"cheese\".",
"Replace your <code>p</code> elements with an unordered list of three things that cats love."
"Remove the last two <code>p</code> elements and create an unordered list of three things that cats love at the bottom of the page."
],
"tests": [
"assert($(\"ul\").length > 0, 'Create a <code>ul</code> element.')",
@ -1530,8 +1530,8 @@
"Ordered lists start with a <code>&#60;ol&#62;</code> element. Then they contain some number of <code>&#60;li&#62;</code> elements.",
"For example:",
"<code>&#60;ol&#62;</code>",
"&thinsp;&thinsp;<code>&#60;li&#62;Garfield&#60;/li&#62;</code>",
"&thinsp;&thinsp;<code>&#60;li&#62;Sylvester&#60;/li&#62;</code>",
"&nbsp;&nbsp;<code>&#60;li&#62;Garfield&#60;/li&#62;</code>",
"&nbsp;&nbsp;<code>&#60;li&#62;Sylvester&#60;/li&#62;</code>",
"<code>&#60;/ol&#62;</code>",
"would create a numbered list of \"Garfield\" and \"Sylvester\".",
"Create an ordered list of the top 3 things cats hate the most."
@ -2024,7 +2024,7 @@
"All related radio buttons should have the same <code>name</code> attribute.",
"Here's an example of a radio button:",
"<code>&#60;label&#62;&#60;input type=\"radio\" name=\"indoor-outdoor\"&#62; Indoor&#60;/label&#62;</code>",
"Add to your form a pair of radio buttons. Each radio button should be nested within its own <code>label</code> element. They should share a common <code>name</code> attribute. One should have the option of <code>indoor</code> and the other should have the option of <code>outdoor</code>."
"Add a pair of radio buttons to your form. One should have the option of <code>indoor</code> and the other should have the option of <code>outdoor</code>."
],
"tests": [
"assert($('input[type=\"radio\"]').length > 1, 'Your page should have two radio button elements.')",
@ -2386,7 +2386,7 @@
"You can set an element's background color with the <code>background-color</code> property.",
"For example, if you wanted an element's background color to be <code>green</code>, you'd put this within your <code>style</code> element:",
"<code>.green-background {</code>",
"<code>&thinsp;&thinsp;background-color: green;</code>",
"<code>&nbsp;&nbsp;background-color: green;</code>",
"<code>}</code>",
"Create a class called <code>gray-background</code> with the <code>background-color</code> of gray. Assign this class to your <code>div</code> element."
],
@ -2566,7 +2566,7 @@
"One cool thing about <code>id</code> attributes is that, like classes, you can style them using CSS.",
"Here's an example of how you can take your element with the <code>id</code> attribute of <code>cat-photo-element</code> and give it the background color of green. In your <code>style</code> element:",
"<code>#cat-photo-element {</code>",
"<code>&thinsp;&thinsp;background-color: green;</code>",
"<code>&nbsp;&nbsp;background-color: green;</code>",
"<code>}</code>",
"Note that inside your <code>style</code> element, you always reference classes by putting a <code>.</code> in front of their names. You always reference ids by putting a <code>#</code> in front of their names.",
"Try giving your form, which now has the <code>id</code> attribute of <code>cat-photo-form</code>, a green background."
@ -3153,7 +3153,7 @@
"We can prove that the <code>body</code> element exists here by giving it a <code>background-color</code> of black.",
"We can do this by adding the following to our <code>style</code> element:",
"<code>body {</code>",
"<code>&thinsp;&thinsp;background-color: black;</code>",
"<code>&nbsp;&nbsp;background-color: black;</code>",
"<code>}</code>"
],
"tests": [
@ -3316,7 +3316,7 @@
"Leave the <code>blue-text</code> and <code>pink-text</code> classes on your <code>h1</code> element.",
"Create a CSS declaration for your <code>orange-text</code> id in your <code>style</code> element. Here's an example of what this looks like:",
"<code>#brown-text {</code>",
"<code>&thinsp;&thinsp;color: brown;</code>",
"<code>&nbsp;&nbsp;color: brown;</code>",
"<code>}</code>"
],
"tests": [

View File

@ -31,7 +31,7 @@
"Array.reduce()"
],
"solutions": [
"function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}\n\nsumAll([1, 4]);\n"
"function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -80,7 +80,7 @@
"Array.concat()"
],
"solutions": [
"function diff(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}\n\ndiff([1, 2, 3, 5], [1, 2, 3, 4, 5]);\n"
"function diff(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -138,7 +138,7 @@
"Array.join()"
],
"solutions": [
"function convert(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}\n\nconvert(36);\n"
"function convert(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -181,7 +181,7 @@
"Object.keys()"
],
"solutions": [
"function where(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}\n\nwhere([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });\n"
"function where(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -227,7 +227,7 @@
"Array.join()"
],
"solutions": [
"function replace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}\n\nreplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");\n"
"function myReplace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -273,7 +273,7 @@
"String.split()"
],
"solutions": [
"function translate(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}\n\ntranslate(\"consonant\");\n"
"function translate(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -316,7 +316,7 @@
"String.split()"
],
"solutions": [
"var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pair(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}\n\npair(\"GCG\");\n"
"var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pair(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -357,7 +357,7 @@
"String.fromCharCode()"
],
"solutions": [
"function fearNotLetter(str) {\n var s = str.split('').map(function(c) {return c.charCodeAt(0);});\n for (var i = 1; i < s.length; i++) {\n if (s[i]-1 != s[i-1]) {\n return String.fromCharCode(s[i]-1);\n }\n }\n}\n\nfearNotLetter('abce');\n"
"function fearNotLetter(str) {\n var s = str.split('').map(function(c) {return c.charCodeAt(0);});\n for (var i = 1; i < s.length; i++) {\n if (s[i]-1 != s[i-1]) {\n return String.fromCharCode(s[i]-1);\n }\n }\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -402,7 +402,7 @@
"Boolean Objects"
],
"solutions": [
"function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return typeof(bool) === \"boolean\";\n}\n\nboo(null);\n"
"function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return typeof(bool) === \"boolean\";\n}\n\nboo(null);"
],
"type": "bonfire",
"challengeType": 5,
@ -445,7 +445,7 @@
"Array.reduce()"
],
"solutions": [
"function unite(arr1, arr2, arr3) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}\n\nunite([1, 2, 3], [5, 2, 1, 4], [2, 1]);\n"
"function unite(arr1, arr2, arr3) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -489,7 +489,7 @@
"HTML Entities"
],
"solutions": [
"var MAP = { '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&apos;'};\n\nfunction convert(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}\n\nconvert('Dolce & Gabbana');\n"
"var MAP = { '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&apos;'};\n\nfunction convert(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -531,7 +531,7 @@
"String.replace()"
],
"solutions": [
"function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}\n\nspinalCase('This Is Spinal Tap');\n"
"function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -574,7 +574,7 @@
"Remainder"
],
"solutions": [
"function sumFibs(num) {\n var a = 1; \n var b = 1;\n var s = 0;\n while (a <= num) {\n if (a % 2 !== 0) { \n s += a; \n }\n a = [b, b=b+a][0];\n }\n return s;\n}\n\nsumFibs(4);\n"
"function sumFibs(num) {\n var a = 1; \n var b = 1;\n var s = 0;\n while (a <= num) {\n if (a % 2 !== 0) { \n s += a; \n }\n a = [b, b=b+a][0];\n }\n return s;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -615,7 +615,7 @@
"Array.push()"
],
"solutions": [
"function eratosthenesArray(n) {\n var primes = [];\n if (n > 2) {\n var half = n>>1;\n var sieve = Array(half);\n for (var i = 1, limit = Math.sqrt(n)>>1; i <= limit; i++) {\n if (!sieve[i]) {\n for (var step = 2*i+1, j = (step*step)>>1; j < half; j+=step) {\n sieve[j] = true;\n }\n }\n }\n primes.push(2);\n for (var p = 1; p < half; p++) {\n if (!sieve[p]) primes.push(2*p+1);\n }\n }\n return primes;\n}\n\nfunction sumPrimes(num) {\n return eratosthenesArray(num+1).reduce(function(a,b) {return a+b;}, 0);\n}\n\nsumPrimes(10);\n"
"function eratosthenesArray(n) {\n var primes = [];\n if (n > 2) {\n var half = n>>1;\n var sieve = Array(half);\n for (var i = 1, limit = Math.sqrt(n)>>1; i <= limit; i++) {\n if (!sieve[i]) {\n for (var step = 2*i+1, j = (step*step)>>1; j < half; j+=step) {\n sieve[j] = true;\n }\n }\n }\n primes.push(2);\n for (var p = 1; p < half; p++) {\n if (!sieve[p]) primes.push(2*p+1);\n }\n }\n return primes;\n}\n\nfunction sumPrimes(num) {\n return eratosthenesArray(num+1).reduce(function(a,b) {return a+b;}, 0);\n}\n\nsumPrimes(10);"
],
"type": "bonfire",
"challengeType": 5,
@ -657,7 +657,7 @@
"Smallest Common Multiple"
],
"solutions": [
"function gcd(a, b) {\n while (b !== 0) {\n a = [b, b = a % b][0];\n }\n return a;\n}\n\nfunction lcm(a, b) {\n return (a * b) / gcd(a, b);\n}\n\nfunction smallestCommons(arr) {\n arr.sort(function(a,b) {return a-b;});\n var rng = [];\n for (var i = arr[0]; i <= arr[1]; i++) {\n rng.push(i);\n }\n return rng.reduce(lcm);\n}\n\n\nsmallestCommons([1,5]);\n"
"function gcd(a, b) {\n while (b !== 0) {\n a = [b, b = a % b][0];\n }\n return a;\n}\n\nfunction lcm(a, b) {\n return (a * b) / gcd(a, b);\n}\n\nfunction smallestCommons(arr) {\n arr.sort(function(a,b) {return a-b;});\n var rng = [];\n for (var i = arr[0]; i <= arr[1]; i++) {\n rng.push(i);\n }\n return rng.reduce(lcm);\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -695,7 +695,7 @@
"Array.filter()"
],
"solutions": [
"function find(arr, func) {\n var num;\n arr.some(function(e) {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n return num;\n}\n\nfind([1, 2, 3, 4], function(num){ return num % 2 === 0; });\n"
"function find(arr, func) {\n var num;\n arr.some(function(e) {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n return num;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -736,7 +736,7 @@
"Array.shift()"
],
"solutions": [
"(function drop(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}\n\ndrop([1, 2, 3], function(n) {return n < 3; });\n)"
"function drop(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -776,7 +776,7 @@
"Array.isArray()"
],
"solutions": [
"function steamroller(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamroller(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}\n\nsteamroller([1, [2], [3, [[4]]]]);\n"
"function steamroller(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamroller(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -815,7 +815,7 @@
"String.fromCharCode()"
],
"solutions": [
"function binaryAgent(str) {\n return str.split(' ').map(function(s) { return parseInt(s, 2); }).map(function(b) { return String.fromCharCode(b);}).join('');\n}\n\nbinaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');\n"
"function binaryAgent(str) {\n return str.split(' ').map(function(s) { return parseInt(s, 2); }).map(function(b) { return String.fromCharCode(b);}).join('');\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -858,7 +858,7 @@
"assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: <code>every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")</code> should return false');"
],
"solutions": [
"function every(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}\n\nevery([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');\n"
"function every(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}"
],
"type": "bonfire",
"challengeType": 5,
@ -904,8 +904,7 @@
"Arguments object"
],
"solutions": [
"function add() {\n if (arguments.length == 1) {\n var a = arguments[0];\n if (!isNumber(a)) return;\n return function(b) {\n if (!isNumber(b)) return;\n return a+b;\n };\n }\n if (![].slice.call(arguments).every(isNumber)) return;\n return arguments[0] + arguments[1];\n}\n \nfunction isNumber(obj) {\n return toString.call(obj) == '[object Number]';\n}\n\nadd(2,3);\n",
"function add() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}\n\nadd(2,3);\n"
"function add() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}"
],
"type": "bonfire",
"challengeType": 5,

View File

@ -8,7 +8,7 @@
"title": "Show the Local Weather",
"challengeSeed": ["126415127"],
"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/FreeCodeCamp/pen/avqvgJ' target='_blank'>http://codepen.io/FreeCodeCamp/pen/avqvgJ</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/FreeCodeCamp/full/avqvgJ' target='_blank'>http://codepen.io/FreeCodeCamp/full/avqvgJ</a>.",
"<span class='text-info'>Rule #1:</span> Don't look at the example project's code on CodePen. Figure it out for yourself.",
"<span class='text-info'>Rule #2:</span> You may use whichever libraries or APIs you need.",
"<span class='text-info'>Rule #3:</span> Reverse engineer the example project's functionality, and also feel free to personalize it.",
@ -64,7 +64,7 @@
"<span class='text-info'>User Story:</span> As a user, if Free Code Camp is streaming, I can see additional details about what they are streaming.",
"<span class='text-info'>Bonus User Story:</span> As a user, I can search through the streams listed.",
"<span class='text-info'>Bonus User Story:</span> As a user, I will see a placeholder notification if a streamer has closed their Twitch account. You can verify this works by adding brunofin and comster404 to your array of Twitch streamers.",
"<span class='text-info'>Hint:</span> Here's an example call to Twitch.tv's JSON API: <code>https://api.twitch.tv/kraken/streams/freecodecamp</code>.",
"<span class='text-info'>Hint:</span> See an example call to Twitch.tv's JSONP API at <code>https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Zipline-Use-the-Twitchtv-JSON-API</code>.",
"<span class='text-info'>Hint:</span> The relevant documentation about this API call is here: <a href='https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel' target='_blank'>https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel</a>.",
"<span class='text-info'>Hint:</span> Here's an array of the Twitch.tv usernames of people who regularly stream coding: <code>[\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]</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.",

View File

@ -59,7 +59,7 @@
"jQuery often selects an HTML element with a <code>selector</code>, then does something to that element.",
"For example, let's make all of your <code>button</code> elements bounce. Just add this code inside your document ready function:",
"<code>$(\"button\").addClass(\"animated bounce\")</code>",
"Note that we've already included both the jQuery library and the Animate.css library in your code editor. So you are using jQuery to apply the Animate.css <code>bounce</code> class to your <code>button</code> elements."
"Note that we've already included both the jQuery library and the Animate.css library in the background so that you can use them in the editor. So you are using jQuery to apply the Animate.css <code>bounce</code> class to your <code>button</code> elements."
],
"tests": [
"assert($(\"button\").hasClass(\"animated\") && $(\"button\").hasClass(\"bounce\"), 'Use the jQuery <code>addClass&#40&#41</code> function to give the classes <code>animated</code> and <code>bounce</code> to your <code>button</code> elements.')",
@ -645,27 +645,29 @@
"",
"<!-- Only change code above this line. -->",
"",
"<div class=\"container-fluid\">",
" <h3 class=\"text-primary text-center\">jQuery Playground</h3>",
" <div class=\"row\">",
" <div class=\"col-xs-6\">",
" <h4>#left-well</h4>",
" <div class=\"well\" id=\"left-well\">",
" <button class=\"btn btn-default target\" id=\"target1\">#target1</button>",
" <button class=\"btn btn-default target\" id=\"target2\">#target2</button>",
" <button class=\"btn btn-default target\" id=\"target3\">#target3</button>",
"<body>",
" <div class=\"container-fluid\">",
" <h3 class=\"text-primary text-center\">jQuery Playground</h3>",
" <div class=\"row\">",
" <div class=\"col-xs-6\">",
" <h4>#left-well</h4>",
" <div class=\"well\" id=\"left-well\">",
" <button class=\"btn btn-default target\" id=\"target1\">#target1</button>",
" <button class=\"btn btn-default target\" id=\"target2\">#target2</button>",
" <button class=\"btn btn-default target\" id=\"target3\">#target3</button>",
" </div>",
" </div>",
" </div>",
" <div class=\"col-xs-6\">",
" <h4>#right-well</h4>",
" <div class=\"well\" id=\"right-well\">",
" <button class=\"btn btn-default target\" id=\"target4\">#target4</button>",
" <button class=\"btn btn-default target\" id=\"target5\">#target5</button>",
" <button class=\"btn btn-default target\" id=\"target6\">#target6</button>",
" <div class=\"col-xs-6\">",
" <h4>#right-well</h4>",
" <div class=\"well\" id=\"right-well\">",
" <button class=\"btn btn-default target\" id=\"target4\">#target4</button>",
" <button class=\"btn btn-default target\" id=\"target5\">#target5</button>",
" <button class=\"btn btn-default target\" id=\"target6\">#target6</button>",
" </div>",
" </div>",
" </div>",
" </div>",
"</div>"
"</body>"
],
"type": "waypoint",
"challengeType": 0

View File

@ -7,7 +7,7 @@
"id": "bb000000000000000000001",
"title": "Trigger Click Events with jQuery",
"description": [
"In this section, we'll learn how to get data from APIs. APIs - or Application Interfaces - are tools that computers use to communicate with one another.",
"In this section, we'll learn how to get data from APIs. APIs - or Application Programming Interfaces - are tools that computers use to communicate with one another.",
"We'll also learn how to update HTML with the data we get from these APIs using a technology called Ajax.",
"First, let's review what the <code>$(document).ready()</code> function does. This function makes it so all code inside of it only runs once our page loads.",
"Let's make our \"Get Message\" button change the text of the element with the class <code>message</code>.",
@ -31,21 +31,21 @@
"",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
@ -58,7 +58,7 @@
"When our click event happens, we can use Ajax to update an HTML element.",
"Let's make it so that when a user clicks the \"Get Message\" button, we change the text of the element with the class <code>message</code> to say \"Here is the message\".",
"We can do this by adding the following code within our click event:",
"<code>&thinsp;&thinsp;$(\".message\").html(\"Here is the message\");</code>"
"<code>&nbsp;&nbsp;$(\".message\").html(\"Here is the message\");</code>"
],
"tests": [
"assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\.message(?:'|\")\\s*?\\)\\s*?\\.html\\s*?\\(\\s*?(?:'|\")Here\\sis\\sthe\\smessage(?:'|\")\\s*?\\);/gi), 'Clicking the \"Get Message\" button should give the element with the class <code>message</code> the text \"Here is the message\".')"
@ -68,30 +68,29 @@
" $(document).ready(function() {",
" $(\"#getMessage\").on(\"click\", function(){",
" // Only change code below this line.",
"",
" ",
" // Only change code above this line.",
" });",
" });",
"fcces",
"",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
@ -102,55 +101,55 @@
"title": "Get JSON with the jQuery getJSON Method",
"description": [
"You can also request data from an external source. This is where APIs come into play.",
"Remember that APIs - or Application Interfaces - are tools that computers use to communicate with one another.",
"Remember that APIs - or Application Programming Interfaces - are tools that computers use to communicate with one another.",
"Most web APIs transfer data in a format called JSON. JSON stands for JavaScript Object Notation.",
"You've already been using JSON whenever you create a JavaScript object. JSON is nothing more than object properties and their current values, sandwiched between a <code>{</code> and a <code>}</code>.",
"These properties and their values are often referred to as \"key-value pairs\".",
"Let's get the JSON from Free Code Camp's Cat Photo API.",
"Here's the code you can put in your click event to do this:",
"<code>&thinsp;&thinsp;$.getJSON(\"/json/cats.json?callback=\", function( json ) {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;$(\".message\").html(JSON.stringify(json))</code>",
"<code>&thinsp;&thinsp;});</code>",
"<code>&nbsp;&nbsp;$.getJSON(\"/json/cats.json\", function(json) {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;$(\".message\").html(JSON.stringify(json));</code>",
"<code>&nbsp;&nbsp;});</code>",
"Once you've added this, click the \"Get Message\" button. Your Ajax function will replace the \"The message will go here\" text with the raw JSON output from the Free Code Camp Cat Photo API."
],
"tests": [
"assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\#getMessage(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?on\\s*?\\(\\s*?(\\\"|\\')click(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'You should have a click handler on the getMessage button to trigger the AJAX request.')",
"assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least on closing set of brackets and parenthesis.')",
"assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi), 'You should have at least one closing set of brackets and parenthesis.')",
"assert(editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi) && editor.match(/\\,\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi) && editor.match(/\\s*?\\}\\s*?\\)\\s*?\\;/gi).length === editor.match(/\\s*?function\\s*?\\(\\s*?\\w*?\\s*?\\)\\s*?\\{/gi).length, 'Each callback function should have a closing set of brackets and parenthesis.')",
"assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?\"\\\/json\\\/cats\\.json\\?callback\\=\"\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file.')",
"assert(editor.match(/\\$\\s*?\\(\\s*?\\\"\\.message\\\"\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the <code>.html</code> change the contents of the message box so that it contains the result of the getJSON.')"
"assert(editor.match(/\\$\\s*?\\.\\s*?getJSON\\s*?\\(\\s*?(\\\"|\\')\\\/json\\\/cats\\.json(\\\"|\\')\\s*?\\,\\s*?function\\s*?\\(\\s*?json\\s*?\\)\\s*?\\{/gi), 'You should be making use of the getJSON method given in the description to load data from the json file.')",
"assert(editor.match(/\\$\\s*?\\(\\s*?(\\\"|\\')\\.message(\\\"|\\')\\s*?\\)\\s*?\\.\\s*?html\\s*?\\(\\s*?JSON\\s*?\\.\\s*?stringify\\s*?\\(\\s*?json\\s*?\\)\\s*?\\)/gi), 'Don\\'t forget to make the <code>.html</code> change the contents of the message box so that it contains the result of the getJSON.')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" ",
" $(\"#getMessage\").on(\"click\", function(){",
" // Only change code below this line.",
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function(){",
" // Only change code below this line.",
" ",
" ",
" ",
" // Only change code above this line.",
" });",
"",
"",
" // Only change code above this line.",
" });",
" ",
" });",
" });",
"fcces",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
@ -166,9 +165,12 @@
"Then, let's loop through our JSON, adding more HTML to that variable. When the loop is finished, we'll render it.",
"Here's the code that does this:",
"<code>json.map(function(val) {</code>",
"<code>&thinsp;&thinsp;html = html + \"&lt;div class = 'cat'&gt;\"</code>",
"<code>&thinsp;&thinsp;html = html + '&lt;div&gt;' + val + '&lt;/div&gt;';</code>",
"<code>&thinsp;&thinsp;html = html + \"&lt;/div&gt;&lt;br/&gt;\"</code>",
"<code>&nbsp;&nbsp;var keys = Object.keys(val);</code>",
"<code>&nbsp;&nbsp;html += \"&lt;div class = 'cat'&gt;\";</code>",
"<code>&nbsp;&nbsp;keys.map(function(key) {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;html += \"&lt;b&gt;\" + key + \"&lt;/b&gt;: \" + val[key] + \"&lt;br&gt;\";</code>",
"<code>&nbsp;&nbsp;});</code>",
"<code>&nbsp;&nbsp;html += \"&lt;/div&gt;&lt;br&gt;\";</code>",
"<code>});</code>"
],
"tests": [
@ -179,18 +181,13 @@
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
" $.getJSON(\"/json/cats.json\", function(json) {",
"",
" var html = \"\";",
" // Only change code below this line.",
"",
"",
"",
"",
"",
"",
"",
"",
"",
" ",
" ",
" ",
" // Only change code above this line.",
"",
" $(\".message\").html(html);",
@ -201,20 +198,20 @@
"fcces",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here"," </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here"," </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
@ -225,35 +222,34 @@
"title": "Render Images from Data Sources",
"description": [
"In the JSON that we receive data from Free Code Camp's Cat Photo API.",
"When we're looping through these strings, let's check whether they are links. If it is, instead of outputing the image link, let's render the image.",
"We've seen from the last two lessons that each object in our JSON array contains an <code>imageLink</code> key with a value that is the url of a cat's image.",
"When we're looping through these objects, let's use this <code>imageLink</code> property to display this image in an <code>img</code> element.",
"Here's the code that does this:",
"<code>if(val.match(\"http\")) {</code>",
"<code>&thinsp;&thinsp;html = html + '&lt;img src = \"' + val + '\"&gt;';</code>",
"<code>}</code>"
"<code>&nbsp;&nbsp;html += \"&lt;img src = '\" + val.imageLink + \"'&gt;\";</code>"
],
"tests": [
"assert(editor.match(/val.match/gi), 'You should have checked whether the strings contain links.')"
"assert(editor.match(/val.imageLink/gi), 'You should have used the <code>imageLink</code> property to display the images.')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
" $.getJSON(\"/json/cats.json\", function(json) {",
"",
" var html = \"\";",
"",
" json.map(function(val) {",
"",
" html = html + \"<div class = 'cat'>\"",
" html += \"<div class = 'cat'>\";",
"",
" // Only change code below this line.",
" // Only change code below this line.",
" ",
" ",
" ",
" // Only change code above this line.",
"",
"",
"",
" // Only change code above this line.",
"",
" html = html + \"</div>\"",
" html += \"</div>\";",
"",
" });",
"",
@ -265,21 +261,21 @@
"fcces",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
@ -293,7 +289,7 @@
"Let's filter out the cat who's \"id\" key has a value of 1.",
"Here's the code to do this:",
"<code>json = json.filter(function(val) {</code>",
"<code>&thinsp;&thinsp;return(val.id !== 1);</code>",
"<code>&nbsp;&nbsp;return(val.id !== 1);</code>",
"<code>});</code>"
],
"tests": [
@ -304,25 +300,23 @@
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
" $.getJSON(\"/json/cats.json\", function(json) {",
"",
" var html = \"\";",
"",
" // Only change code below this line.",
"",
"",
"",
" ",
" ",
" ",
" // Only change code above this line.",
"",
" json.map(function(val){",
"",
" val = \"<img src = '\" + val.imageLink + \"'/>\"",
" html += \"<div class = 'cat'>\"",
"",
" html = html + \"<div class = 'cat'>\"",
" html += \"<img src = '\" + val.imageLink + \"'>\"",
"",
" html = html + '<div>' + val + '</div>';",
"",
" html = html + \"</div>\"",
" html += \"</div>\"",
"",
" });",
"",
@ -333,25 +327,23 @@
" });",
"fcces",
"",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>",
""
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well message\">",
" The message will go here",
" </div>",
" </div>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12\">",
" <button id = \"getMessage\" class = \"btn btn-primary\">",
" Get Message",
" </button>",
" </div>",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
@ -362,11 +354,13 @@
"description": [
"Another cool thing we can do is access our user's current location. Every browser has a built in navigator that can give us this information.",
"The navigator will get our user's current longitude and latitude.",
"You will see a prompt to allow or block this site from knowing your current location. The challenge can be completed either way, as long as the code is correct.",
"By selecting allow you will see the text on the output phone change to your latitude and longitude",
"Here's some code that does this:",
"<code>if (navigator.geolocation) {</code>",
"<code>&thinsp;&thinsp;navigator.geolocation.getCurrentPosition(function(position) {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;$(\"#data\").html(\"latitiude\" + position.coords.latitude + \"longitude\" + position.coords.longitude);</code>",
"<code>&thinsp;&thinsp;});</code>",
"<code>&nbsp;&nbsp;navigator.geolocation.getCurrentPosition(function(position) {</code>",
"<code>&nbsp;&nbsp;&nbsp;&nbsp;$(\"#data\").html(\"latitude: \" + position.coords.latitude + \"&lt;br&gt;longitude: \" + position.coords.longitude);</code>",
"<code>&nbsp;&nbsp;});</code>",
"<code>}</code>"
],
"tests": [
@ -375,9 +369,9 @@
"challengeSeed": [
"fccss",
" // Only change code below this line.",
"",
"",
"",
" ",
" ",
" ",
" // Only change code above this line.",
"fcces",
"<div id = \"data\">",

View File

@ -54,9 +54,9 @@
"We are also able to create objects using <code>constructor</code> functions.",
"Here's an example of a constructor function:",
"<code>var Car = function() {</code>",
"<code>&thinsp;&thinsp;this.wheels = 4;</code>",
"<code>&thinsp;&thinsp;this.engines = 1;</code>",
"<code>&thinsp;&thinsp;this.seats = 1;</code>",
"<code>&nbsp;&nbsp;this.wheels = 4;</code>",
"<code>&nbsp;&nbsp;this.engines = 1;</code>",
"<code>&nbsp;&nbsp;this.seats = 1;</code>",
"<code>};</code>",
"Give your <code>myMotorBike</code> object a <code>wheels</code>, <code>engines</code> and <code>seats</code> attribute and set them to numbers.",
"You may be confused by the <code>this</code> keyword here. Don't worry, we will get to that very soon."
@ -189,8 +189,8 @@
"title":"Iterate over Arrays with .map",
"description":[
"The <code>map</code> method is a convenient way to iterate through arrays. Here's an example usage:",
"<code>var timesFour = array.map(function(val){</code>",
"<code>&thinsp;&thinsp;return val*4;</code>",
"<code>var timesFour = oldArray.map(function(val){</code>",
"<code>&nbsp;&nbsp;return val * 4;</code>",
"<code>});</code>",
"",
"The <code>map</code> method will iterate through every element of the array, creating a new array with values that have been modified by the callback function, and return it.",
@ -228,7 +228,7 @@
"<code>reduce</code> has an optional second argument which can be used to set the initial value of the accumulator. If no initial value is specified it will be the first array element and currentVal will start with the second array element.",
"Here is an example of <code>reduce</code> being used to subtract all the values of an array:",
"<code>var singleVal = array.reduce(function(previousVal, currentVal) {</code>",
"<code>&thinsp;&thinsp;return previousVal - currentVal;</code>",
"<code>&nbsp;&nbsp;return previousVal - currentVal;</code>",
"<code>}, 0);</code>",
"Use the <code>reduce</code> method to sum all the values in <code>array</code> and assign it to <code>singleVal</code>."
],
@ -263,7 +263,7 @@
"The following code is an example of using filter to remove array elements that are not even numbers:",
"Note: We omit the second and third arguments since we only need the value",
"<code>array = array.filter(function(val) {</code>",
"<code>&thinsp;&thinsp;return val % 2 === 0;</code>",
"<code>&nbsp;&nbsp;return val % 2 === 0;</code>",
"<code>});</code>",
"Use <code>filter</code> to remove all elements from <code>array</code> that are greater than 5."
],
@ -296,7 +296,7 @@
"Here is an example of using sort with a compare function that will sort the elements from smallest to largest number:",
"<code>var array = [1, 12, 21, 2];</code>",
"<code>array.sort(function(a, b) {</code>",
"<code>&thinsp;&thinsp;return a - b;</code>",
"<code>&nbsp;&nbsp;return a - b;</code>",
"<code>});</code>",
"Use <code>sort</code> to sort <code>array</code> from largest to smallest."
],
@ -330,7 +330,7 @@
"tests": [
"assert.deepEqual(array, [7,6,5,4,3,2,1], 'message: You should reverse the array.');",
"assert(editor.getValue().match(/\\.reverse\\s*\\(\\)/gi), 'message: You should use the <code>reverse</code> method.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), 'message: You should only be using <code>revserse</code> to modify <code>array</code>.');"
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7/gi), 'message: You should only be using <code>reverse</code> to modify <code>array</code>.');"
],
"challengeSeed": [
"var array = [1,2,3,4,5,6,7];",

19
seed/getChallenges.js Normal file
View File

@ -0,0 +1,19 @@
var fs = require('fs');
var path = require('path');
function getFilesFor(dir) {
return fs.readdirSync(path.join(__dirname, '/' + dir));
}
module.exports = function getChallenges() {
try {
return getFilesFor('challenges')
.map(function(file) {
return require('./challenges/' + file);
});
} catch (e) {
console.log('error', e);
return [];
}
};

View File

@ -2,29 +2,23 @@
require('babel/register');
require('dotenv').load();
var fs = require('fs'),
Rx = require('rx'),
var Rx = require('rx'),
_ = require('lodash'),
path = require('path'),
getChallenges = require('./getChallenges'),
app = require('../server/server');
function getFilesFor(dir) {
return fs.readdirSync(path.join(__dirname, '/' + dir));
}
var Challenge = app.models.Challenge;
var challenges = getFilesFor('challenges');
var destroy = Rx.Observable.fromNodeCallback(Challenge.destroyAll, Challenge);
var create = Rx.Observable.fromNodeCallback(Challenge.create, Challenge);
destroy()
.flatMap(function() { return Rx.Observable.from(challenges); })
.flatMap(function(file) {
var challengeSpec = require('./challenges/' + file);
.flatMap(function() { return Rx.Observable.from(getChallenges()); })
.flatMap(function(challengeSpec) {
var order = challengeSpec.order;
var block = challengeSpec.name;
var isBeta = !!challengeSpec.isBeta;
console.log('parsed %s successfully', file);
console.log('parsed %s successfully', block);
// challenge file has no challenges...
if (challengeSpec.challenges.length === 0) {

View File

@ -1,66 +0,0 @@
[
{
"id": "bd7167d8c441cbafaeb5bdef",
"email": "Ada_Gerlach@gmail.com",
"company": "Livestream",
"country": "Singapore",
"city": "Morar berg",
"locale": "Morar berg, Singapore",
"isPaid": true,
"isApproved": true,
"isHighlighted": false,
"state": "South Dakota",
"howToApply": "foofoo foof ooffo http://foo.com/apply",
"position": "Junior Backend Developer (Node.js)",
"logo": "https://s3.amazonaws.com/prod-heroku/greenhouse_job_boards/logos/000/001/189/resized/livestream_logo-rgb_standard-cc718e67ce1a0f6fa400f609bdefe605.png?1429547161",
"description": "Live life one inhalation and one exhalation at a time. May you be healthy. Let the muscles in your neck and shoulders relax. May you be safe. Reflect on the fragility and preciousness of life. Empty your mind; be formless, shapeless like water. May you be at peace. Take a deep breath. You can do what you set out to do; yes, you can. You can do what you set out to do; yes, you can. Watch each breath appear and disappear, just breathing. Give yourself a break. Live life one inhalation and one exhalation at a time. Give yourself a break. Just acknowledge what's there and let be. You can get through this. Open your heart to change, forgiveness and lovingkindness. Love is the first seed of the soul. It will be ok. Impermanence and change is a powerful teacher and teaching. Bring love into your heart, into your breath and into your being. Briefly notice any emotions, thoughts or sensations that may be driving fear and anxiety and let them be. This discomfort will pass. Bring love into your heart, into your breath and into your being. Take a deep breath. Reflect on the fragility and preciousness of life."
},
{
"id": "bd7167d8c442cbafaeb5bdef",
"email": "Ada_Gerlach@gmail.com",
"company": "Adobe",
"country": "Singapore",
"city": "Morar berg",
"locale": "Morar berg, Singapore",
"isPaid": true,
"isApproved": true,
"isHighlighted": false,
"state": "South Dakota",
"howToApply": "foofoo foof ooffo http://foo.com/apply",
"position": "Junior JavaScript Engineer",
"logo": "http://cdn-3.famouslogos.us/images/adobe-logo.jpg",
"description": "Live life one inhalation and one exhalation at a time. May you be healthy. Let the muscles in your neck and shoulders relax. May you be safe. Reflect on the fragility and preciousness of life. Empty your mind; be formless, shapeless like water. May you be at peace. Take a deep breath. You can do what you set out to do; yes, you can. You can do what you set out to do; yes, you can. Watch each breath appear and disappear, just breathing. Give yourself a break. Live life one inhalation and one exhalation at a time. Give yourself a break. Just acknowledge what's there and let be. You can get through this. Open your heart to change, forgiveness and lovingkindness. Love is the first seed of the soul. It will be ok. Impermanence and change is a powerful teacher and teaching. Bring love into your heart, into your breath and into your being. Briefly notice any emotions, thoughts or sensations that may be driving fear and anxiety and let them be. This discomfort will pass. Bring love into your heart, into your breath and into your being. Take a deep breath. Reflect on the fragility and preciousness of life."
},
{
"id": "bd7167d8c443cbafaeb5bdef",
"company": "Bookspan",
"email": "Ada_Gerlach@gmail.com",
"country": "Singapore",
"city": "Morar berg",
"locale": "Morar berg, Singapore",
"isPaid": true,
"isApproved": true,
"isHighlighted": true,
"howToApply": "foofoo foof ooffo http://foo.com/apply",
"state": "South Dakota",
"position": "Full Stack JavaScript Developer (Junior)",
"logo": "https://tm-prod.global.ssl.fastly.net/uploaded/companies/227/small_logo.png?v=db9dbe",
"description": "Live life one inhalation and one exhalation at a time. May you be healthy. Let the muscles in your neck and shoulders relax. May you be safe. Reflect on the fragility and preciousness of life. Empty your mind; be formless, shapeless like water. May you be at peace. Take a deep breath. You can do what you set out to do; yes, you can. You can do what you set out to do; yes, you can. Watch each breath appear and disappear, just breathing. Give yourself a break. Live life one inhalation and one exhalation at a time. Give yourself a break. Just acknowledge what's there and let be. You can get through this. Open your heart to change, forgiveness and lovingkindness. Love is the first seed of the soul. It will be ok. Impermanence and change is a powerful teacher and teaching. Bring love into your heart, into your breath and into your being. Briefly notice any emotions, thoughts or sensations that may be driving fear and anxiety and let them be. This discomfort will pass. Bring love into your heart, into your breath and into your being. Take a deep breath. Reflect on the fragility and preciousness of life."
},
{
"id": "bd7167d8c444cbafaeb5bdef",
"email": "Ada_Gerlach@gmail.com",
"company": "Good Eggs",
"country": "Singapore",
"city": "Morar berg",
"locale": "Morar berg, Singapore",
"isPaid": true,
"isApproved": true,
"isHighlighted": false,
"howToApply": "foofoo foof ooffo http://foo.com/apply",
"state": "South Dakota",
"position": "Full Stack Developer",
"logo": "https://d1qb2nb5cznatu.cloudfront.net/startups/i/72165-64efbd521cdfe3357c811758f5436e7d-medium_jpg.jpg",
"description": "Live life one inhalation and one exhalation at a time. May you be healthy. Let the muscles in your neck and shoulders relax. May you be safe. Reflect on the fragility and preciousness of life. Empty your mind; be formless, shapeless like water. May you be at peace. Take a deep breath. You can do what you set out to do; yes, you can. You can do what you set out to do; yes, you can. Watch each breath appear and disappear, just breathing. Give yourself a break. Live life one inhalation and one exhalation at a time. Give yourself a break. Just acknowledge what's there and let be. You can get through this. Open your heart to change, forgiveness and lovingkindness. Love is the first seed of the soul. It will be ok. Impermanence and change is a powerful teacher and teaching. Bring love into your heart, into your breath and into your being. Briefly notice any emotions, thoughts or sensations that may be driving fear and anxiety and let them be. This discomfort will pass. Bring love into your heart, into your breath and into your being. Take a deep breath. Reflect on the fragility and preciousness of life."
}
]

View File

@ -1,47 +0,0 @@
/**
* Created by nathanleniz on 4/25/15.
*/
require('dotenv').load();
var mongodb = require('mongodb'),
Story = require('../models/Story.js'),
secrets = require('../config/secrets');
mongoose = require('mongoose');
mongoose.connect(secrets.db);
function storyLinkCleanup(cb) {
console.log('headLineCleanup');
var i = 1;
var stream = Story.find({}).skip(0).limit(0).batchSize(20000).stream();
stream.on('data', function (story) {
console.log(i++);
this.pause();
story.storyLink = story.storyLink.
replace(/[^a-z0-9\s]/gi, '').
replace(/\s+/g, ' ').
toLowerCase().
trim();
story.save(function (err) {
if (err) {
console.log('woops');
}
this.resume();
}.bind(this));
})
.on('error', function (err) {
console.error(err);
}).on('close', function () {
console.log('done with set');
stream.destroy();
cb();
});
}
function done() {
console.log('Migration script has completed');
process.exit(0);
}
storyLinkCleanup(done);

112
seed/test-challenges.js Normal file
View File

@ -0,0 +1,112 @@
/* eslint-disable no-eval, no-process-exit */
import _ from 'lodash';
import { Observable } from 'rx';
import tape from 'tape';
import getChallenges from './getChallenges';
function createIsAssert(t, isThing) {
const { assert } = t;
return function() {
const args = [...arguments];
args[0] = isThing(args[0]);
assert.apply(t, args);
};
}
function fillAssert(t) {
const assert = t.assert;
assert.isArray = createIsAssert(t, _.isArray);
assert.isBoolean = createIsAssert(t, _.isBoolean);
assert.isString = createIsAssert(t, _.isString);
assert.isNumber = createIsAssert(t, _.isNumber);
assert.isUndefined = createIsAssert(t, _.isUndefined);
assert.deepEqual = t.deepEqual;
assert.equal = t.equal;
assert.strictEqual = t.equal;
assert.sameMembers = function sameMembers() {
const [ first, second, ...args] = arguments;
assert.apply(
t,
[
_.difference(first, second).length === 0 &&
_.difference(second, first).length === 0
].concat(args)
);
};
assert.includeMembers = function includeMembers() {
const [ first, second, ...args] = arguments;
assert.apply(t, [_.difference(second, first).length === 0].concat(args));
};
assert.match = function match() {
const [value, regex, ...args] = arguments;
assert.apply(t, [regex.test(value)].concat(args));
};
return assert;
}
function createTest({ title, tests = [], solutions = [] }) {
const plan = tests.length;
return Observable.fromCallback(tape)(title)
.doOnNext(t => solutions.length ? t.plan(plan) : t.end())
.flatMap(t => {
if (solutions.length <= 0) {
t.comment('No solutions for ' + title);
return Observable.just({
title,
type: 'missing'
});
}
return Observable.just(t)
.map(fillAssert)
/* eslint-disable no-unused-vars */
// assert is used within the eval
.doOnNext(assert => {
/* eslint-enable no-unused-vars */
solutions.forEach(solution => {
tests.forEach(test => {
try {
eval(solution + ';;' + test);
} catch (e) {
t.fail(e);
}
});
});
})
.map(() => ({ title }));
});
}
Observable.from(getChallenges())
.flatMap(challengeSpec => {
return Observable.from(challengeSpec.challenges);
})
.flatMap(challenge => {
return createTest(challenge);
})
.map(({ title, type }) => {
if (type === 'missing') {
return title;
}
return false;
})
.filter(title => !!title)
.toArray()
.subscribe(
(noSolutions) => {
console.log(
'# These challenges have no solutions\n- [ ] ' +
noSolutions.join('\n- [ ] ')
);
},
err => { throw err; },
() => process.exit(0)
);

View File

@ -1,137 +0,0 @@
/*eslint-disable block-scoped-var */
require('dotenv').load();
var User = require('../models/User.js'),
secrets = require('../config/secrets'),
mongoose = require('mongoose'),
R = require('ramda'),
ziplines = require('./challenges/ziplines.json'),
basejumps = require('./challenges/basejumps.json');
mongoose.connect(secrets.db);
var ziplineIds = ziplines.challenges.map(function(elem) {
return elem.id;
});
var basejumpIds = basejumps.challenges.map(function(elem) {
return elem.id;
});
var ziplineAndBaseJumpIds = R.concat(ziplineIds, basejumpIds);
function userModelAssurity(cb) {
console.log('userModelAssurity');
var i = 1;
var stream = User.find({}).skip(0).limit(0).batchSize(20000).stream();
stream.on('data', function (user) {
console.log(i++);
this.pause();
user.needsMigration = true;
user.save(function (err) {
if (err) {
console.log('woops');
}
this.resume();
}.bind(this));
})
.on('error', function (err) {
console.log(err);
}).on('close', function () {
console.log('done with set');
stream.destroy();
cb();
});
}
function migrateIt() {
console.log('migrateIt');
var dones = 0;
var done = function() {
dones++;
if (dones === 2) {
process.exit(0);
}
if (dones === 1) {
userModelMigration(done);
}
};
console.log('calling userModelAssurity');
userModelAssurity(done);
}
function userModelMigration(cb) {
var i = 1;
var stream = User.find({needsMigration: true}).skip(0).limit(0)
.batchSize(20000).stream();
stream.on('data', function (user) {
console.log(i++);
/*
if (user.challengesHash) {
this.pause();
user.needsMigration = false;
var oldChallenges = Object.keys(user.challengesHash).filter(function (key) {
if (user.challengesHash[key]) {
user.progressTimestamps.push(user.challengesHash[key] * 1000);
}
return user.challengesHash[key];
});
newChallenges.forEach(function (challenge) {
if (oldChallenges.indexOf(challenge.oldNumber) !== -1 && challenge.newId) {
user.completedCoursewares.push({
id: challenge.newId,
completedDate: user.challengesHash[challenge.oldNumber] * 1000
});
}
});
user.completedCoursewares.forEach(function (course) {
var indexOfCourse = user.uncompletedCoursewares.indexOf(course.id) !== -1;
if (indexOfCourse !== -1) {
user.uncompletedCoursewares.splice(indexOfCourse, 1);
}
});
user.completedBonfires.forEach(function (bonfire) {
bonfire.completedDate = bonfire.completedDate * 1000;
user.progressTimestamps.push(bonfire.completedDate);
});
}
*/
user.needsMigration = false;
user.completedChallenges = user.completedChallenges.map(function(elem) {
if (ziplineAndBaseJumpIds.indexOf(elem.id) > 0) {
return ({
id: elem.id,
name: elem.name,
completedWith: elem.completedWith,
completedDate: elem.completedDate,
solution: elem.solution,
githubLink: elem.githubLink,
verified: elem.verified,
challengeType: typeof elem.githubLink === 'boolean' ? 4 : 3
});
} else {
return elem;
}
});
var self = this;
user.save(function (err) {
if (err) {
console.log('woops');
}
self.resume();
});
}).on('error', function (err) {
console.log(err);
}).on('close', function () {
console.log('done with set');
stream.destroy();
cb();
});
}
migrateIt();

View File

@ -35,12 +35,14 @@ const dasherize = utils.dasherize;
const unDasherize = utils.unDasherize;
const getMDNLinks = utils.getMDNLinks;
/*
function makeChallengesUnique(challengeArr) {
// clone and reverse challenges
// then filter by unique id's
// then reverse again
return _.uniq(challengeArr.slice().reverse(), 'id').reverse();
}
*/
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
@ -535,6 +537,11 @@ module.exports = function(app) {
if (completedChallenges.indexOf(challenge.id) !== -1) {
challenge.completed = true;
}
if (typeof challenge.releasedOn !== 'undefined' &&
moment(challenge.releasedOn, 'MMM MMMM DD, YYYY').diff(moment(),
'days') >= -30) {
challenge.markNew = true;
}
return challenge;
})
// group challenges by block | returns a stream of observables
@ -556,7 +563,7 @@ module.exports = function(app) {
dashedName: dasherize(blockArray[0].block),
challenges: blockArray,
completed: completedCount / blockArray.length * 100,
time: blockArray[0] && blockArray[0].time || "???"
time: blockArray[0] && blockArray[0].time || '???'
};
})
.filter(({ name }) => name !== 'Hikes')
@ -579,9 +586,12 @@ module.exports = function(app) {
res.render('challengeMap/show', {
blocks,
daysRunning,
globalCompletedCount: numberWithCommas(
5612952 + (Math.floor((Date.now() - 1446268581061) / 3000))
),
camperCount,
lastCompleted,
title: "A map of all Free Code Camp's Challenges"
title: "A Map to Learn to Code and Become a Software Engineer"
});
},
next

View File

@ -1,7 +1,7 @@
import { defaultProfileImage } from '../../common/utils/constantStrings.json';
const message =
'Learn to Code and Build Projects for Nonprofits';
'Learn to Code and Help Nonprofits';
module.exports = function(app) {
var router = app.loopback.Router();

View File

View File

@ -28,7 +28,6 @@ module.exports = function(app) {
router.get('/pmi-acp-agile-project-managers-form', agileProjectManagersForm);
router.get('/nonprofits', nonprofits);
router.get('/nonprofits-form', nonprofitsForm);
router.get('/our-sponsors', sponsors);
router.get('/unsubscribe/:email', unsubscribe);
router.get('/unsubscribed', unsubscribed);
router.get('/get-started', getStarted);
@ -185,14 +184,14 @@ module.exports = function(app) {
function showLabs(req, res) {
res.render('resources/labs', {
title: 'Projects Built by Free Code Camp Students',
title: 'Projects Built by Free Code Camp Software Engineers',
projects: labs
});
}
function showTestimonials(req, res) {
res.render('resources/stories', {
title: 'Stories from Happy Free Code Camp Campers',
title: 'Testimonials from Happy Free Code Camp Students who got Software Engineer Jobs',
stories: testimonials
});
}
@ -207,15 +206,9 @@ module.exports = function(app) {
});
}
function sponsors(req, res) {
res.render('sponsors/sponsors', {
title: 'The Sponsors who make Free Code Camp Possible'
});
}
function nonprofits(req, res) {
res.render('resources/nonprofits', {
title: 'A guide to our Nonprofit Projects'
title: 'Your Nonprofit Can Get Pro Bono Code'
});
}

View File

@ -109,7 +109,7 @@ module.exports = function(app) {
function hot(req, res) {
return res.render('stories/index', {
title: 'Hot stories currently trending on Camper News',
title: 'Top Stories on Camper News',
page: 'hot'
});
}

View File

@ -128,7 +128,7 @@ module.exports = function(app) {
return res.redirect('/');
}
res.render('account/signin', {
title: 'Free Code Camp Login'
title: 'Sign in to Free Code Camp using a Social Media Account'
});
}
@ -142,7 +142,7 @@ module.exports = function(app) {
return res.redirect('/');
}
res.render('account/email-signin', {
title: 'Sign in to your Free Code Camp Account'
title: 'Sign in to Free Code Camp using your Email Address'
});
}
@ -151,7 +151,7 @@ module.exports = function(app) {
return res.redirect('/');
}
res.render('account/email-signup', {
title: 'Create Your Free Code Camp Account'
title: 'Sign up for Free Code Camp using your Email Address'
});
}
@ -222,7 +222,7 @@ module.exports = function(app) {
});
res.render('account/show', {
title: 'Camper ' + profileUser.username + '\'s portfolio',
title: 'Camper ' + profileUser.username + '\'s Code Portfolio',
username: profileUser.username,
name: profileUser.name,
@ -397,7 +397,7 @@ module.exports = function(app) {
return res.render('account/forgot');
}
res.render('account/reset', {
title: 'Password Reset',
title: 'Reset your Password',
accessToken: req.accessToken.id
});
}

View File

@ -10,27 +10,36 @@ block content
else
img.img-responsive.img-center.border-radius-5(src='https://s3.amazonaws.com/freecodecamp/wide-social-banner.png')
.col-xs-12.col-md-8.col-md-offset-2
h2.text-center
span.text-primary #{camperCount} &thinsp;
| campers have joined our community
br
| since we launched &thinsp;
span.text-primary #{daysRunning} &thinsp;
| days ago.
h2
table.population-table.img-center
tr
td Established:&thinsp;
td
span.text-primary #{daysRunning}&thinsp;
| days ago
tr
td Population:&thinsp;
td
span.text-primary #{camperCount}&thinsp;
| campers
tr
td Completed:&thinsp;
td
span.text-primary #{globalCompletedCount}&thinsp;
| challenges
.spacer
if (user && user.progressTimestamps.length > 5)
#tshirt-notice.col-xs-12.col-md-8.col-md-offset-2.hidden
h2.text-center Get our first-edition t-shirt.
br
span.text-success Only available until Oct 29!
img.thumbnail.img-center.img-responsive(src="http://i.imgur.com/o07uuOL.png")
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;
a(href="https://teespring.com/free-code-camp-shirt-eu" target="_blank") Also ships from Europe
| .
a.button.btn.btn-block.signup-btn(href="https://teespring.com/get-free-code-camp-t-shirt" target="_blank") Get yours
if (user && user.progressTimestamps.length > 100)
#map-notice.col-xs-12.col-md-8.col-md-offset-2.hidden
h2.text-center We have a subreddit
img.thumbnail.img-center.img-responsive(src="http://i.imgur.com/lyd0bfM.jpg")
h4.text-center We welcome you to come ask questions and share your thoughts with our entire open source community.
a.button.btn.btn-block.btn-primary(href="https://reddit.com/r/freecodecamp" target="_blank") Check it out
.button-spacer
.text-center
a#hideTshirtNoticeButton(href='#') Hide this forever
a#hide-map-notice-button(href='#') Hide this
.spacer
.row
.col-xs-12.col-sm-8.col-sm-offset-2
@ -120,6 +129,10 @@ block content
span.capitalize= challenge.type + ': '
span= challenge.title
span.sr-only= " Incomplete"
if challenge.markNew
span.text-danger.small &thinsp; &thinsp;
strong
em NEW
if (challengeBlock.completed === 100)
.button-spacer
@ -131,14 +144,14 @@ block content
var username = !{JSON.stringify(user && user.username || '')};
var lastCompleted = !{JSON.stringify(lastCompleted || false)}
$(document).ready(function () {
if (!localStorage || !localStorage.hideTshirtNotice) {
$("#tshirt-notice").removeClass("hidden");
if (!localStorage || !localStorage.hideRedditNotice) {
$("#map-notice").removeClass("hidden");
}
$("#hideTshirtNoticeButton").on("click", function() {
$("#tshirt-notice").addClass('animated fadeOut');
$("#hide-map-notice-button").on("click", function() {
$("#map-notice").addClass('animated fadeOut');
setTimeout(function() {
$("#tshirt-notice").hide();
$("#map-notice").hide();
}, 1000);
localStorage.hideTshirtNotice = "true";
localStorage.hideRedditNotice = "true";
});
});

View File

@ -108,7 +108,7 @@ block content
i.fa.fa-twitter &thinsp;
= phrase
else
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
#next-challenge.btn.btn-lg.btn-primary.btn-block Go to my next challenge (ctrl + enter)
#reset-modal.modal(tabindex='-1')
.modal-dialog.animated.fadeInUp.fast-animation
.modal-content

View File

@ -98,7 +98,7 @@ block content
if(user)
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
else
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
#next-challenge.btn.btn-lg.btn-primary.btn-block Go to my next challenge (ctrl + enter)
include ../partials/challenge-modals
script.
document.addEventListener('gitter-sidecar-ready', function(e) {

View File

@ -95,7 +95,7 @@ block content
if (user)
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
else
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
#next-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Go to my next challenge (ctrl + enter)
include ../partials/challenge-modals
script.
var MDNlinks = !{JSON.stringify(MDNlinks)};

View File

@ -10,8 +10,12 @@ block content
p.large-p!= step[2]
if step[3]
a.btn.btn-block.btn-primary.challenge-step-btn-action(id='#{index}' href='#{step[3]}' target='_blank') Open link in new tab
.button-spacer
if index + 1 === description.length
.btn.btn-block.btn-primary.challenge-step-btn-finish(id='last' class=step[3] ? 'disabled' : '') Finish challenge
else if index !== 0
.btn.btn-block.btn-primary.challenge-step-btn-next(id='#{index}' class=step[3] ? 'disabled' : '') Go to my next step
.btn.btn-block.btn-warning-ghost.challenge-step-btn-prev(id='#{index - 1}') Go to my previous step
else
.btn.btn-block.btn-primary.challenge-step-btn-next(id='#{index}' class=step[3] ? 'disabled' : '') Go to my next step
#challenge-step-modal.modal(tabindex='-1')

View File

@ -26,17 +26,41 @@ urlset(xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
priority= 0.9
url
loc http://www.freecodecamp.com/coding-bootcamp-cost-calculator
loc http://www.freecodecamp.com/labs
changefreq weekly
lastmod= now
priority= 0.9
url
loc http://www.freecodecamp.com/stories
changefreq weekly
lastmod= now
priority= 0.9
url
loc http://www.freecodecamp.com/twitch
changefreq weekly
lastmod= now
priority= 0.9
url
loc http://www.freecodecamp.com/jobs
changefreq weekly
lastmod= now
priority= 0.9
url
loc http://www.freecodecamp.com/coding-bootcamp-cost-calculator
changefreq monthly
lastmod= now
priority= 0.9
//- User
each user in users
url
loc #{appUrl}/#{user}
lastmod= now
changefreq daily
changefreq weekly
priority= 0.5
each challenge in challenges
@ -44,18 +68,18 @@ urlset(xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
loc #{appUrl}/challenges/#{challenge.replace(/\s/g, '-')}
lastmod= now
changefreq weekly
priority= 0.5
priority= 0.9
each story in stories
url
loc #{appUrl}/news/#{story.replace(/\s/g, '-')}
lastmod= now
changefreq daily
priority= 0.9
changefreq weekly
priority= 0.5
each nonprofit in nonprofits
url
loc #{appUrl}/nonprofits/#{nonprofit.replace(/\s/g, '-')}
lastmod= now
changefreq daily
changefreq weekly
priority= 0.9

View File

@ -1,45 +0,0 @@
var request = require('supertest');
var app = require('../server/server.js');
describe('#ROUTES', function () {
describe('GET /', function () {
it('should return 200 OK', (done) => {
request(app)
.get('/')
.expect(200, done);
});
});
describe('GET /signin', function () {
it('should return 200 OK', (done) => {
request(app)
.get('/signin')
.expect(200, done);
});
});
describe('GET /email-signup', function () {
it('should return 200 OK', (done) => {
request(app)
.get('/email-signup')
.expect(200, done);
});
});
describe('GET /random-url', function () {
it('should return 302', (done) => {
request(app)
.get('/reset')
.expect(302, done);
});
});
describe('GET /camperName', function () {
it('should return 200', (done) => {
request(app)
.get('/terakilobyte')
.expect(200, done);
});
});
});

View File

@ -1,2 +0,0 @@
--reporter spec
--timeout 5000