Merge branch 'staging' into improve-early-challenges

Conflicts:
	seed/challenges/basic-javascript.json
	seed/challenges/bootstrap.json
	seed/challenges/html5-and-css.json
	seed/challenges/object-oriented-and-functional-programming.json
This commit is contained in:
Quincy Larson
2015-10-28 02:20:09 -07:00
33 changed files with 878 additions and 822 deletions

View File

@ -15,7 +15,7 @@ Our campers (students) start by working through our free, self-paced, browser-ba
80% of our campers are over 25, and nearly a fifth of our campers are women. 80% of our campers are over 25, and nearly a fifth of our campers are women.
This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [blog](http://blog.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp). This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [blog](http://medium.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp).
[Join our community here](http://www.freecodecamp.com/signin). [Join our community here](http://www.freecodecamp.com/signin).
@ -54,22 +54,26 @@ The easiest way to get started is to clone the repository:
# Get the latest snapshot # Get the latest snapshot
git clone --depth=1 https://github.com/freecodecamp/freecodecamp.git freecodecamp git clone --depth=1 https://github.com/freecodecamp/freecodecamp.git freecodecamp
# Change directory
cd freecodecamp cd freecodecamp
# Install NPM dependencies # Install NPM dependencies
npm install npm install
# Install Gulp globally
npm install -g gulp
# Install Bower globally
npm install -g bower
# Install Bower dependencies # Install Bower dependencies
bower install bower install
# Create a .env file and populate it with the necessary API keys and secrets: # Create a .env file and populate it with the necessary API keys and secrets:
touch .env touch .env
# Install Gulp globally
npm install -g gulp
``` ```
Edit your `.env` file with the following API keys accordingly (if you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. Edit your `.env` file with the following API keys accordingly. If you only use email login, only the `MONGOHQ_URL`, `SESSION_SECRET`, `MANDRILL_USER` and `MANDRILL_PASSWORD` fields are necessary. Keep in mind if you want to use more services you'll have to get your own API keys for those services. If you only use a subset or no OAuth2 authentication methods, you may want to remove them from ```server/passport-providers.js``` - otherwise the server will complain about missing clientIDs at launch.
``` ```
MONGOHQ_URL='mongodb://localhost:27017/freecodecamp' MONGOHQ_URL='mongodb://localhost:27017/freecodecamp'
@ -107,20 +111,20 @@ DEBUG=true
``` ```
```bash ```bash
# Start the mongo server # Start the mongo server in a seperate terminal
mongod mongod
# Create your mongo database. # Initialize Free Code Camp
# Type "mongo" in your terminal to access the mongo shell # This will seed the database for the first time.
use freecodecamp # This command should only be run once.
# Exit the mongo shell with control + d npm run first-time
# Seed your database with the challenges
node seed/
# start the application # start the application
gulp gulp
``` ```
Now navigate to your browser and open http://localhost:3001
If the app loads, congratulations - you're all set. Otherwise, let us know by opening a GitHub issue and with your error.
License License
------- -------

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
{ {
"className": "ion-speakerphone", "className": "ion-speakerphone",
"content": " Blog ", "content": " Blog ",
"href": "http://blog.freecodecamp.com", "href": "http://medium.freecodecamp.com",
"target": "_blank" "target": "_blank"
}, },
{ {

View File

@ -82,6 +82,10 @@
}, },
"descriptionPt": { "descriptionPt": {
"type": "array" "type": "array"
},
"solutions": {
"type": "array",
"default": []
} }
}, },
"validations": [], "validations": [],

View File

@ -6,6 +6,8 @@
"url": "https://github.com/freecodecamp/freecodecamp.git" "url": "https://github.com/freecodecamp/freecodecamp.git"
}, },
"scripts": { "scripts": {
"first-time": "npm run create-rev && echo '\n\nseeding database\n\n' && node seed && node seed/nonprofits",
"create-rev": "test ! -e server/rev-manifest.json && echo '\n\ncreating manifest\n\n' && touch server/rev-manifest.json && echo '{}' >> server/rev-manifest.json",
"build": "gulp build", "build": "gulp build",
"start": "babel-node server/server.js", "start": "babel-node server/server.js",
"prestart-production": "bower cache clean && bower install && gulp build", "prestart-production": "bower cache clean && bower install && gulp build",
@ -49,6 +51,13 @@
"forever": "~0.14.1", "forever": "~0.14.1",
"frameguard": "^0.2.2", "frameguard": "^0.2.2",
"github-api": "~0.7.0", "github-api": "~0.7.0",
"gulp": "~3.8.8",
"gulp-eslint": "~0.9.0",
"gulp-inject": "~1.0.2",
"gulp-jsonlint": "^1.1.0",
"gulp-nodemon": "^2.0.3",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.0.1",
"gulp-less": "^3.0.3", "gulp-less": "^3.0.3",
"gulp-minify-css": "~0.5.1", "gulp-minify-css": "~0.5.1",
"gulp-reduce-file": "0.0.1", "gulp-reduce-file": "0.0.1",
@ -114,13 +123,6 @@
"browserify": "^10.2.4", "browserify": "^10.2.4",
"chai": "~1.10.0", "chai": "~1.10.0",
"envify": "^3.4.0", "envify": "^3.4.0",
"gulp": "~3.8.8",
"gulp-eslint": "~0.9.0",
"gulp-inject": "~1.0.2",
"gulp-jsonlint": "^1.1.0",
"gulp-nodemon": "^2.0.3",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.0.1",
"istanbul": "^0.3.15", "istanbul": "^0.3.15",
"loopback-explorer": "^1.7.2", "loopback-explorer": "^1.7.2",
"loopback-testing": "^1.1.0", "loopback-testing": "^1.1.0",

View File

@ -57,6 +57,9 @@
"MDNlinks": [ "MDNlinks": [
"RegExp" "RegExp"
], ],
"solutions": [
"var re = /^(?:(?:\\+?1\\s*(?:[.-]\\s*)?)?(?:\\(\\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\\s*\\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\\s*(?:[.-]\\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\\s*(?:[.-]\\s*)?([0-9]{4})$/;\n\nfunction telephoneCheck(str) {\n return !!str.match(re);\n}\n\ntelephoneCheck(\"555-555-5555\");"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -88,13 +91,15 @@
"tests": [ "tests": [
"assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'message: <code>sym([1, 2, 3], [5, 2, 1, 4])</code> should return <code>[3, 5, 4]</code>.');", "assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 5, 4], 'message: <code>sym([1, 2, 3], [5, 2, 1, 4])</code> should return <code>[3, 5, 4]</code>.');",
"assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'message: <code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should return <code>[1, 4, 5]</code>');", "assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'message: <code>sym([1, 2, 5], [2, 3, 5], [3, 4, 5])</code> should return <code>[1, 4, 5]</code>');",
"assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'message: <code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should return <code>[1, 4, 5]</code>.');", "assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'message: <code>sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])</code> should return <code>[1, 4, 5]</code>.');"
"assert.sameMembers(sym([1, 1]), [1], 'message: <code>sym([1, 1])</code> should return <code>[1]</code>.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Array.reduce()", "Array.reduce()",
"Symmetric Difference" "Symmetric Difference"
], ],
"solutions": [
"function sym(args) {\n var index = -1;\n var length = arguments.length;\n var result;\n while (++index < length) {\n var array = arguments[index];\n result = result ? diff(result, array).concat(diff(array, result)) : array;\n }\n return result ? uniq(result) : [];\n}\n\nfunction uniq(arr) {\n var h = Object.create(null);\n var u = [];\n arr.forEach(function(v) {\n if (v in h) return;\n h[v] = true;\n u.push(v);\n });\n return u;\n}\n\nfunction diff(a, b) {\n var h = Object.create(null);\n b.forEach(function(v) {\n h[v] = true; \n });\n return a.filter(function(v) { return !(v in h);});\n}\nsym([1, 2, 3], [5, 2, 1, 4]);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -151,6 +156,9 @@
"MDNlinks": [ "MDNlinks": [
"Global Object" "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", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -205,6 +213,9 @@
"MDNlinks": [ "MDNlinks": [
"Global Array Object" "Global Array Object"
], ],
"solutions": [
"function inventory(arr1, arr2) {\n arr2.forEach(function(item) {\n createOrUpdate(arr1, item);\n });\n // All inventory must be accounted for or you're fired!\n return arr1;\n}\n\nfunction createOrUpdate(arr1, item) {\n var index = -1;\n while (++index < arr1.length) {\n if (arr1[index][1] === item[1]) {\n arr1[index][0] += item[0];\n return;\n }\n if (arr1[index][1] > item[1]) {\n break;\n }\n }\n arr1.splice(index, 0, item);\n}\n\n// Example inventory lists\nvar curInv = [\n [21, 'Bowling Ball'],\n [2, 'Dirty Sock'],\n [1, 'Hair Pin'],\n [5, 'Microphone']\n];\n\nvar newInv = [\n [2, 'Hair Pin'],\n [3, 'Half-Eaten Apple'],\n [67, 'Bowling Ball'],\n [7, 'Toothpaste']\n];\n\ninventory(curInv, newInv);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -246,6 +257,9 @@
"Permutations", "Permutations",
"RegExp" "RegExp"
], ],
"solutions": [
"function permAlone(str) {\n return permutor(str).filter(function(perm) {\n return !perm.match(/(.)\\1/g);\n }).length;\n}\n\nfunction permutor(str) {\n // http://staff.roguecc.edu/JMiller/JavaScript/permute.html\n //permArr: Global array which holds the list of permutations\n //usedChars: Global utility array which holds a list of \"currently-in-use\" characters\n var permArr = [], usedChars = [];\n function permute(input) {\n //convert input into a char array (one element for each character)\n var i, ch, chars = input.split(\"\");\n for (i = 0; i < chars.length; i++) {\n //get and remove character at index \"i\" from char array\n ch = chars.splice(i, 1);\n //add removed character to the end of used characters\n usedChars.push(ch);\n //when there are no more characters left in char array to add, add used chars to list of permutations\n if (chars.length === 0) permArr[permArr.length] = usedChars.join(\"\");\n //send characters (minus the removed one from above) from char array to be permuted\n permute(chars.join(\"\"));\n //add removed character back into char array in original position\n chars.splice(i, 0, ch);\n //remove the last character used off the end of used characters array\n usedChars.pop();\n }\n }\n permute(str);\n return permArr;\n}\n\npermAlone('aab');\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -291,6 +305,9 @@
"String.substr()", "String.substr()",
"parseInt()" "parseInt()"
], ],
"solutions": [
"function friendly(str) {\n var dates = str.map(function(s) {return s.split('-').map(Number);});\n var start = dates[0];\n var end = dates[1];\n if (str[0] === str[1]) {\n return [readable(start)];\n }\n if (start[0] !== end[0]) {\n if (start[0] + 1 === end[0] && start[1] > end[1]) {\n start[0] = undefined;\n end[0] = undefined;\n }\n return dates.map(readable);\n }\n start[0] = undefined;\n end[0] = undefined;\n if (start[1] !== end[1]) {\n return dates.map(readable);\n }\n end[1] = undefined;\n return dates.map(readable);\n}\n\nfunction readable(arr) {\n var ordD = arr[2] + nth(arr[2]);\n if (!arr[1]) {\n return ordD;\n }\n return MONTH[arr[1]] + \" \" + ordD + (!arr[0] ? \"\" : \", \" + arr[0]);\n}\n\nvar MONTH = {1: \"January\",\n 2: \"February\",\n 3: \"March\",\n 4: \"April\",\n 5: \"May\",\n 6: \"June\",\n 7: \"July\",\n 8: \"August\",\n 9: \"September\",\n 10: \"October\",\n 11: \"November\",\n 12: \"December\"};\n\nfunction nth(d) {\n if(d>3 && d<21) return 'th';\n switch (d % 10) {\n case 1: return \"st\";\n case 2: return \"nd\";\n case 3: return \"rd\";\n default: return \"th\";\n }\n} \n\nfriendly(['2015-07-01', '2015-07-04']);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",

View File

@ -28,6 +28,9 @@
"", "",
"meetBonfire(\"You can do this!\");" "meetBonfire(\"You can do this!\");"
], ],
"solutions": [
"function meetBonfire(argument) {\n // Good luck!\n console.log(\"you can read this function's argument in the developer tools\", argument);\n\n return true;\n}\n\n\n\nmeetBonfire(\"You can do this!\");\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -69,6 +72,9 @@
"Array.reverse()", "Array.reverse()",
"Array.join()" "Array.join()"
], ],
"solutions": [
"function reverseString(str) {\n return str.split('').reverse().join(\"\");\n}\n\nreverseString('hello');\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -109,6 +115,9 @@
"MDNlinks": [ "MDNlinks": [
"Arithmetic Operators" "Arithmetic Operators"
], ],
"solutions": [
"function factorialize(num) {\n return num === 1 ? 1 : num * factorialize(num-1);\n}\n\nfactorialize(5);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -159,6 +168,9 @@
"String.replace()", "String.replace()",
"String.toLowerCase()" "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", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -199,6 +211,9 @@
"String.split()", "String.split()",
"String.length" "String.length"
], ],
"solutions": [
"function findLongestWord(str) {\n return str.split(' ').sort(function(a, b) { return b.length - a.length;})[0].length;\n}\n\nfindLongestWord('The quick brown fox jumped over the lazy dog');\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -236,6 +251,9 @@
"MDNlinks": [ "MDNlinks": [
"String.charAt()" "String.charAt()"
], ],
"solutions": [
"function titleCase(str) {\n return str.split(' ').map(function(word) {\n return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();\n }).join(' ');\n}\n\ntitleCase(\"I'm a little tea pot\");\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -274,6 +292,9 @@
"MDNlinks": [ "MDNlinks": [
"Comparison Operators" "Comparison Operators"
], ],
"solutions": [
"function largestOfFour(arr) {\n return arr.map(function(subArr) {\n return Math.max.apply(null, subArr);\n });\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -306,7 +327,7 @@
"tests": [ "tests": [
"assert(end(\"Bastian\", \"n\") === true, 'message: <code>end(\"Bastian\", \"n\")</code> should return true.');", "assert(end(\"Bastian\", \"n\") === true, 'message: <code>end(\"Bastian\", \"n\")</code> should return true.');",
"assert(end(\"Connor\", \"n\") === false, 'message: <code>end(\"Connor\", \"n\")</code> should return false.');", "assert(end(\"Connor\", \"n\") === false, 'message: <code>end(\"Connor\", \"n\")</code> should return false.');",
"assert(end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\") === false, 'message: <code>end(\"Walking on water and developing software from a specification are easy if both are frozen.\", \"specification\")</code> should return false.');", "assert(end(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") === false, '<code>\"Walking on water and developing software from a specification are easy if both are frozen\"&#44; \"specification\"&#41;</code> should return false.');",
"assert(end(\"He has to give me a new name\", \"name\") === true, 'message: <code>end(\"He has to give me a new name\", \"name\")</code> should return true.');", "assert(end(\"He has to give me a new name\", \"name\") === true, 'message: <code>end(\"He has to give me a new name\", \"name\")</code> should return true.');",
"assert(end(\"He has to give me a new name\", \"me\") === true, 'message: <code>end(\"He has to give me a new name\", \"me\")</code> should return true.');", "assert(end(\"He has to give me a new name\", \"me\") === true, 'message: <code>end(\"He has to give me a new name\", \"me\")</code> should return true.');",
"assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: <code>end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")</code> should return false.');" "assert(end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: <code>end(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\")</code> should return false.');"
@ -314,6 +335,9 @@
"MDNlinks": [ "MDNlinks": [
"String.substr()" "String.substr()"
], ],
"solutions": [
"function end(str, target) {\n // \"Never give up and good luck will find you.\"\n // -- Falcor\n return str.substring(str.length-target.length) === target;\n}\n\nend('Bastian', 'n');\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -350,6 +374,9 @@
"MDNlinks": [ "MDNlinks": [
"Global String Object" "Global String Object"
], ],
"solutions": [
"function repeat(str, num) {\n if (num < 0) return '';\n return num === 1 ? str : str + repeat(str, num-1);\n}\n\nrepeat('abc', 3);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -390,6 +417,9 @@
"MDNlinks": [ "MDNlinks": [
"String.slice()" "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", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -427,6 +457,9 @@
"MDNlinks": [ "MDNlinks": [
"Array.push()" "Array.push()"
], ],
"solutions": [
"function chunk(arr, size) {\n var out = [];\n for (var i = 0; i < arr.length; i+=size) {\n out.push(arr.slice(i,i+size));\n }\n return out;\n}\n\nchunk(['a', 'b', 'c', 'd'], 2);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -466,6 +499,9 @@
"Array.slice()", "Array.slice()",
"Array.splice()" "Array.splice()"
], ],
"solutions": [
"function slasher(arr, howMany) {\n // it doesn't always pay to be first\n return arr.slice(howMany);\n}\n\nslasher([1, 2, 3], 2);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -509,6 +545,9 @@
"MDNlinks": [ "MDNlinks": [
"Array.indexOf()" "Array.indexOf()"
], ],
"solutions": [
"function mutation(arr) {\n var hash = Object.create(null);\n arr[0].toLowerCase().split('').forEach(function(c) {\n hash[c] = true;\n });\n return !arr[1].toLowerCase().split('').filter(function(c) {\n return !hash[c];\n }).length;\n}\n\nmutation(['hello', 'hey']);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -547,6 +586,9 @@
"Boolean Objects", "Boolean Objects",
"Array.filter()" "Array.filter()"
], ],
"solutions": [
"function bouncer(arr) {\n // Don't show a false ID to this bouncer.\n return arr.filter(function(e) {return e;});\n}\n\nbouncer([7, 'ate', '', false, 9]);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -586,6 +628,9 @@
"Arguments object", "Arguments object",
"Array.filter()" "Array.filter()"
], ],
"solutions": [
"function destroyer(arr) {\n var hash = Object.create(null);\n [].slice.call(arguments, 1).forEach(function(e) {\n hash[e] = true;\n });\n // Remove all the values\n return arr.filter(function(e) { return !(e in hash);});\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -603,8 +648,9 @@
"id": "a24c1a4622e3c05097f71d67", "id": "a24c1a4622e3c05097f71d67",
"title": "Where do I belong", "title": "Where do I belong",
"description": [ "description": [
"Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", "Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted.",
"For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (0th index), but less than 2 (1st index).", "For example, where([1,2,3,4], 1.5) should return 1 because it is greater than 1 (index 0), but less than 2 (index 1).",
"Likewise, where([20,3,5], 19) should return 2 because it is less than 20 (index 2) and greater than 5 (index 1).",
"Remember to use <a href=\"//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck\" target=\"_blank\">Read-Search-Ask</a> if you get stuck. Write your own code." "Remember to use <a href=\"//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck\" target=\"_blank\">Read-Search-Ask</a> if you get stuck. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
@ -618,12 +664,15 @@
"MDNlinks": [ "MDNlinks": [
"Array.sort()" "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"
],
"tests": [ "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], 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>.');", "assert(where([10, 20, 30, 40, 50], 30) === 2, 'message: <code>where([10, 20, 30, 40, 50], 30)</code> should return <code>2</code>.');",
"assert(where([40, 60], 50) === 1, 'message: <code>where([40, 60,], 50)</code> should return <code>1</code>.');", "assert(where([40, 60], 50) === 1, 'message: <code>where([40, 60,], 50)</code> should return <code>1</code>.');",
"assert(where([5, 3, 20, 3], 3) === 0, 'message: <code>where([5, 3, 20, 3], 3)</code> should return <code>0</code>.');", "assert(where([5, 3, 20, 3], 5) === 2, 'message: <code>where([5, 3, 20, 3], 5)</code> should return <code>2</code>.');",
"assert(where([2, 20, 10], 1) === 0, 'message: <code>where([2, 20, 10], 1)</code> should return <code>0</code>.');", "assert(where([2, 20, 10], 19) === 2, 'message: <code>where([2, 20, 10], 19)</code> should return <code>2</code>.');",
"assert(where([2, 5, 10], 15) === 3, 'message: <code>where([2, 5, 10], 15)</code> should return <code>3</code>.');" "assert(where([2, 5, 10], 15) === 3, 'message: <code>where([2, 5, 10], 15)</code> should return <code>3</code>.');"
], ],
"type": "bonfire", "type": "bonfire",

View File

@ -938,7 +938,7 @@
"description": [ "description": [
"Random numbers are useful for creating random behavior.", "Random numbers are useful for creating random behavior.",
"JavaScript has a <code>Math.random()</code> function that generates a random decimal number.", "JavaScript has a <code>Math.random()</code> function that generates a random decimal number.",
"Change </code>myFunction</code> to return a random number instead of returning <code>0</code>." "Change </code>myFunction</code> to return a random number instead of returning <code>0</code>.",
"Note that you can return a function, just like you would return a variable or value." "Note that you can return a function, just like you would return a variable or value."
], ],
"tests": [ "tests": [
@ -972,7 +972,7 @@
"Note that because we're rounding down, it's impossible to actually get 20.", "Note that because we're rounding down, it's impossible to actually get 20.",
"Putting everything together, this is what our code looks like:", "Putting everything together, this is what our code looks like:",
"<code>Math.floor(Math.random() * 20);</code>", "<code>Math.floor(Math.random() * 20);</code>",
"See how <code>Math.floor</code> takes <code>(Math.random() * 20)</code> as its argument? That's right - you can pass a function to another function as an argument." "See how <code>Math.floor</code> takes <code>(Math.random() * 20)</code> as its argument? That's right - you can pass a function to another function as an argument.",
"Let's use this technique to generate and return a random whole number between 0 and 9." "Let's use this technique to generate and return a random whole number between 0 and 9."
], ],
"tests": [ "tests": [
@ -1003,7 +1003,7 @@
"title": "Generate Random Whole Numbers within a Range", "title": "Generate Random Whole Numbers within a Range",
"description": [ "description": [
"Instead of generating a random number between zero and a given number like we did before, we can generate a random number that falls within a range of two specific numbers.", "Instead of generating a random number between zero and a given number like we did before, we can generate a random number that falls within a range of two specific numbers.",
"To do this, we'll define a minimum number <code>min</code> and a maximum number <code>max</code>." "To do this, we'll define a minimum number <code>min</code> and a maximum number <code>max</code>.",
"Here's the formula we'll use. Take a moment to read and try to understand what this code is doing.", "Here's the formula we'll use. Take a moment to read and try to understand what this code is doing.",
"<code>Math.floor(Math.random() * (max - min + 1)) + min</code>", "<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.", "Define two variables: <code>myMin</code> and </code>myMax</code>, and set them both equal to numbers.",
@ -1186,7 +1186,7 @@
"description": [ "description": [
"You can invert any match by using the uppercase version of the regular expression selector.", "You can invert any match by using the uppercase version of the regular expression selector.",
"For example, <code>\\s</code> will match any whitespace, and <code>\\S</code> will match anything that isn't whitespace.", "For example, <code>\\s</code> will match any whitespace, and <code>\\S</code> will match anything that isn't whitespace.",
"Use <code>/\\S/g</code> to count the number of non-whitespace characters in <code>testString</code>.", "Use <code>/\\S/g</code> to count the number of non-whitespace characters in <code>testString</code>."
], ],
"tests": [ "tests": [
"assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: Use the <code>/\\S/g</code> regular expression to find non-space characters in <code>testString</code>.');", "assert(editor.getValue().match(/\\/\\\\S\\/g/g), 'message: Use the <code>/\\S/g</code> regular expression to find non-space characters in <code>testString</code>.');",

View File

@ -35,7 +35,7 @@
[ [
"http://i.imgur.com/Wzt6Y9Y.gif", "http://i.imgur.com/Wzt6Y9Y.gif",
"A gif showing the process of saving and forking a pen.", "A gif showing the process of saving and forking a pen.",
"Save your pen with the \"Save\" button. Then click the \"Fork\" button. This will create a fork (copy) of your pen that you can experimient with.", "Save your pen with the \"Save\" button. Then click the \"Fork\" button. This will create a fork (copy) of your pen that you can experiment with.",
"" ""
] ]
], ],
@ -68,7 +68,7 @@
"<span class='text-info'>User Story:</span> As a user, I can click different buttons that will take me to the portfolio creator's different social media pages.", "<span class='text-info'>User Story:</span> As a user, I can click different buttons that will take me to the portfolio creator's different social media pages.",
"<span class='text-info'>User Story:</span> As a user, I can see thumbnail images of different projects the portfolio creator has built (if you haven't built any websites before, use placeholders.)", "<span class='text-info'>User Story:</span> As a user, I can see thumbnail images of different projects the portfolio creator has built (if you haven't built any websites before, use placeholders.)",
"<span class='text-info'>Bonus User Story:</span> As a user, I navigate to different sections of the webpage by clicking buttons in the navigation.", "<span class='text-info'>Bonus User Story:</span> As a user, I navigate to different sections of the webpage by clicking buttons in the navigation.",
"Don't worry if you don't have anything to showcase on your portfolio yet - you will build several several apps on the next few CodePen challenges, and can come back and update your portfolio later.", "Don't worry if you don't have anything to showcase on your portfolio yet - you will build several apps on the next few CodePen challenges, and can come back and update your portfolio later.",
"There are many great portfolio templates out there, but for this challenge, you'll need to build a portfolio page yourself. Using Bootstrap will make this much easier for you.", "There are many great portfolio templates out there, but for this challenge, you'll need to build a portfolio page yourself. Using Bootstrap will make this much easier for you.",
"Note that CodePen.io overrides the Window.open() function, so if you want to open windows using jquery, you will need to target invisible anchor elements like this one: <code>&lt;a target='_blank'&gt;</a></code>.", "Note that CodePen.io overrides the Window.open() function, so if you want to open windows using jquery, you will need to target invisible anchor elements like this one: <code>&lt;a target='_blank'&gt;</a></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.", "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

@ -93,14 +93,15 @@
"id": "bad87fee1348bd9acde08812", "id": "bad87fee1348bd9acde08812",
"title": "Make Images Mobile Responsive", "title": "Make Images Mobile Responsive",
"description": [ "description": [
"First, add a new image below the existing one. Set it's <code>src</code> attribute to <code>http://bit.ly/fcc-running-cats</code>.", "First, add a new image below the existing one. Set its <code>src</code> attribute to <code>http://bit.ly/fcc-running-cats</code>.",
"It would be great if this image could be exactly the width of our phone's screen.", "It would be great if this image could be exactly the width of our phone's screen.",
"Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page." "Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page."
], ],
"tests": [ "tests": [
"assert($(\"img\").length > 1, 'You should have a total of two images.')", "assert($(\"img\").length === 2, 'You should have a total of two images.')",
"assert($(\"img\").hasClass(\"img-responsive\"), 'Your new image should have the class <code>img-responsive</code>')", "assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'Your new image should be below your old one and have the class <code>img-responsive</code>.')",
"assert(new RegExp(\"http://bit.ly/fcc-running-cats\", \"gi\").test($(\"img.img-responsive\").attr(\"src\")), 'Add a second image with the <code>src</code> of <code>http&#58;//bit.ly/fcc-running-cats</code>')" "assert($(\"img:eq(1)\").attr(\"src\") === \"http://bit.ly/fcc-running-cats\", 'Your new image should have a <code>src</code> of <code>http&#58;//bit.ly/fcc-running-cats</code>.')",
"assert(editor.match(/<img/g) && editor.match(/<img.*>/g).length === 2 && editor.match(/<img/g).length === 2, 'Make sure your new <code>img</code> element has a closing angle bracket.')"
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
@ -178,8 +179,7 @@
"title": "Center Text with Bootstrap", "title": "Center Text with Bootstrap",
"description": [ "description": [
"Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class <code>text-center</code> to our <code>h2</code> element.", "Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class <code>text-center</code> to our <code>h2</code> element.",
"Remember that you can add several classes to the same element by separating each of them with a space, like this:", "Remember that you can add several classes to the same element by separating each of them with a space, like this: <code>&#60h2 class=\"red-text text-center\"&#62your text&#60/h2&#62</code>."
"<code>&#60h2 class=\"red-text text-center\"&#62your text&#60/h2&#62</code>"
], ],
"tests": [ "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>')"
@ -345,7 +345,7 @@
"id": "bad87fee1348cd8acef08812", "id": "bad87fee1348cd8acef08812",
"title": "Create a Block Element Bootstrap Button", "title": "Create a Block Element Bootstrap Button",
"description": [ "description": [
"Normally, your <code>button</code> elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", "Normally, your <code>button</code> elements are only as wide as the text that they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space and any elements following it will flow onto a \"new line\" below the block.",
"This image illustrates the difference between <code>inline</code> elements and <code>block-level</code> elements:", "This image illustrates the difference between <code>inline</code> elements and <code>block-level</code> elements:",
"<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Click to enlarge\" alt=\"An \"inline\" button is as small as the text it contains. In this image, it's centered. Below it is a \"block-level\" button, which stretches to fill the entire horizontal space.'></a>", "<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Click to enlarge\" alt=\"An \"inline\" button is as small as the text it contains. In this image, it's centered. Below it is a \"block-level\" button, which stretches to fill the entire horizontal space.'></a>",
"Note that these buttons still need the <code>btn</code> class.", "Note that these buttons still need the <code>btn</code> class.",
@ -892,8 +892,7 @@
"<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Click to enlarge\" alt=\"An \"inline\" button is as small as the text it contains. In this image, it's centered. Below it is a \"block-level\" button, which stretches to fill the entire horizontal space.'></a>", "<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Click to enlarge\" alt=\"An \"inline\" button is as small as the text it contains. In this image, it's centered. Below it is a \"block-level\" button, which stretches to fill the entire horizontal space.'></a>",
"By using the <code>span</code> element, you can put several elements together, and even style different parts of the same element differently.", "By using the <code>span</code> element, you can put several elements together, and even style different parts of the same element differently.",
"Nest the word \"love\" in your \"Things cats love\" element below within a <code>span</code> element. Then give that <code>span</code> the class <code>text-danger</code> to make the text red.", "Nest the word \"love\" in your \"Things cats love\" element below within a <code>span</code> element. Then give that <code>span</code> the class <code>text-danger</code> to make the text red.",
"Here's how you would do this with the \"Top 3 things cats hate\" element:", "Here's how you would do this with the \"Top 3 things cats hate\" element: <code>&#60;p&#62;Top 3 things cats &#60;span class = \"text-danger\"&#62;hate&#60;/span&#62;&#60;/p&#62;</code>"
"<code>&#60;p&#62;Top 3 things cats &#60;span class = \"text-danger\"&#62;hate&#60;/span&#62;&#60;/p&#62;</code>"
], ],
"tests": [ "tests": [
"assert($(\"p span\") && $(\"p span\").length > 0, 'Your <code>span</code> element should be inside your <code>p</code> element.')", "assert($(\"p span\") && $(\"p span\").length > 0, 'Your <code>span</code> element should be inside your <code>p</code> element.')",
@ -1909,7 +1908,7 @@
"title": "Add ID Attributes to Bootstrap Elements", "title": "Add ID Attributes to Bootstrap Elements",
"description": [ "description": [
"Recall that in addition to class attributes, you can give each of your elements an <code>id</code> attribute.", "Recall that in addition to class attributes, you can give each of your elements an <code>id</code> attribute.",
"Each id should be unique to a specific element.", "Each id must be unique to a specific element and used only once per page.",
"Let's give a unique id to each of our <code>div</code> elements of class <code>well</code>.", "Let's give a unique id to each of our <code>div</code> elements of class <code>well</code>.",
"Remember that you can give an element an id like this:", "Remember that you can give an element an id like this:",
"<code>&#60;div class=\"well\" id=\"center-well\"&#62;</code>", "<code>&#60;div class=\"well\" id=\"center-well\"&#62;</code>",
@ -2008,7 +2007,7 @@
"title": "Give Each Element a Unique ID", "title": "Give Each Element a Unique ID",
"description": [ "description": [
"We will also want to be able to use jQuery to target each button by its unique id.", "We will also want to be able to use jQuery to target each button by its unique id.",
"Give each of your buttons a unique id, starting with <code>target1</code> and ending with <code>target6</code>." "Give each of your buttons a unique id like, starting with <code>target1</code> and ending with <code>target6</code>."
], ],
"tests": [ "tests": [
"assert($(\"#left-well\").children(\"#target1\") && $(\"#left-well\").children(\"#target1\").length > 0, 'One <code>button</code> element should have the id <code>target1</code>.')", "assert($(\"#left-well\").children(\"#target1\") && $(\"#left-well\").children(\"#target1\").length > 0, 'One <code>button</code> element should have the id <code>target1</code>.')",
@ -2059,7 +2058,7 @@
"title": "Label Bootstrap Buttons", "title": "Label Bootstrap Buttons",
"description": [ "description": [
"Just like we labeled our wells, we want to label our buttons.", "Just like we labeled our wells, we want to label our buttons.",
"Give each of your <code>button</code> elements text that corresponds to its <code>id</code>." "Give each of your <code>button</code> elements text that corresponds to their <code>id</code>."
], ],
"tests": [ "tests": [
"assert(new RegExp(\"#target1\",\"gi\").test($(\"#target1\").text()), 'Give your <code>button</code> element with the id <code>target1</code> the text <code>#target1</code>.')", "assert(new RegExp(\"#target1\",\"gi\").test($(\"#target1\").text()), 'Give your <code>button</code> element with the id <code>target1</code> the text <code>#target1</code>.')",
@ -2116,7 +2115,7 @@
], ],
"tests": [ "tests": [
"assert(editor.match(/<!--/g) && editor.match(/<!--/g).length > 0, 'Start a comment with <code>&#60;!--</code>.')", "assert(editor.match(/<!--/g) && editor.match(/<!--/g).length > 0, 'Start a comment with <code>&#60;!--</code>.')",
"assert(editor.match(/this line/g) && editor.match(/this line/g).length > 0, 'Your comment should have the text <code>You shouldn&#39;t need to modify code below this line</code>')", "assert(editor.match(/this line/g) && editor.match(/this line/g).length > 0, 'Your comment should have the text <code>You shouldn&#39;t need to modify code below this line</code>.')",
"assert(editor.match(/-->.*\\n+.+/g), 'Be sure to close your comment with <code>--&#62;</code>.')" "assert(editor.match(/-->.*\\n+.+/g), 'Be sure to close your comment with <code>--&#62;</code>.')"
], ],
"challengeSeed": [ "challengeSeed": [

View File

@ -390,6 +390,7 @@
"assert(!$(\"h2\").attr(\"style\"), 'Remove the style attribute from your <code>h2</code> element.')", "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($(\"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($(\"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(/<\\/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.')" "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": [ "challengeSeed": [
@ -449,6 +450,7 @@
"tests": [ "tests": [
"assert($(\"h2\").css(\"color\") === \"rgb(255, 0, 0)\", 'Your <code>h2</code> element should be red.')", "assert($(\"h2\").css(\"color\") === \"rgb(255, 0, 0)\", 'Your <code>h2</code> element should be red.')",
"assert($(\"h2\").hasClass(\"red-text\"), 'Your <code>h2</code> element should have the class <code>red-text</code>.')", "assert($(\"h2\").hasClass(\"red-text\"), 'Your <code>h2</code> element should have the class <code>red-text</code>.')",
"assert(editor.match(/\\.red-text\\s*\\{\\s*color:\\s*red;\\s*\\}/g), 'Your stylesheet should declare a <code>red-text</code> class and have its color set to red.')",
"assert($(\"h2\").attr(\"style\") === undefined, 'Do not use inline style declarations like <code>style=\"color&#58; red\"</code> in your <code>h2</code> element.')" "assert($(\"h2\").attr(\"style\") === undefined, 'Do not use inline style declarations like <code>style=\"color&#58; red\"</code> in your <code>h2</code> element.')"
], ],
"challengeSeed": [ "challengeSeed": [

View File

@ -30,6 +30,9 @@
"Math.min()", "Math.min()",
"Array.reduce()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -76,6 +79,9 @@
"Array.indexOf()", "Array.indexOf()",
"Array.concat()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -93,11 +99,25 @@
"id": "a7f4d8f2483413a6ce226cac", "id": "a7f4d8f2483413a6ce226cac",
"title": "Roman Numeral Converter", "title": "Roman Numeral Converter",
"tests": [ "tests": [
"assert.deepEqual(convert(12), \"XII\", 'message: <code>convert(12)</code> should return \"XII\".');",
"assert.deepEqual(convert(5), \"V\", 'message: <code>convert(5)</code> should return \"V\".');", "assert.deepEqual(convert(5), \"V\", 'message: <code>convert(5)</code> should return \"V\".');",
"assert.deepEqual(convert(9), \"IX\", 'message: <code>convert(9)</code> should return \"IX\".');", "assert.deepEqual(convert(9), \"IX\", 'message: <code>convert(9)</code> should return \"IX\".');",
"assert.deepEqual(convert(12), \"XII\", 'message: <code>convert(12)</code> should return \"XII\".');",
"assert.deepEqual(convert(16), \"XVI\", 'message: <code>convert(16)</code> should return \"XVI\".');",
"assert.deepEqual(convert(29), \"XXIX\", 'message: <code>convert(29)</code> should return \"XXIX\".');", "assert.deepEqual(convert(29), \"XXIX\", 'message: <code>convert(29)</code> should return \"XXIX\".');",
"assert.deepEqual(convert(16), \"XVI\", 'message: <code>convert(16)</code> should return \"XVI\".');" "assert.deepEqual(convert(44), \"XLIV\", 'message: <code>convert(44)</code> should return \"XLIV\".');",
"assert.deepEqual(convert(45), \"XLV\", '<code>convert(45)</code> should return \"XLV\"');",
"assert.deepEqual(convert(68), \"LXVIII\", '<code>convert(68)</code> should return \"LXVIII\"');",
"assert.deepEqual(convert(83), \"LXXXIII\", '<code>convert(83)</code> should return \"LXXXIII\"');",
"assert.deepEqual(convert(97), \"XCVII\", '<code>convert(97)</code> should return \"XCVII\"');",
"assert.deepEqual(convert(99), \"XCIX\", '<code>convert(99)</code> should return \"XCIX\"');",
"assert.deepEqual(convert(500), \"D\", '<code>convert(500)</code> should return \"D\"');",
"assert.deepEqual(convert(501), \"DI\", '<code>convert(501)</code> should return \"DI\"');",
"assert.deepEqual(convert(649), \"DCXLIX\", '<code>convert(649)</code> should return \"DCXLIX\"');",
"assert.deepEqual(convert(798), \"DCCXCVIII\", '<code>convert(798)</code> should return \"DCCXCVIII\"');",
"assert.deepEqual(convert(891), \"DCCCXCI\", '<code>convert(891)</code> should return \"DCCCXCI\"');",
"assert.deepEqual(convert(1000), \"M\", '<code>convert(1000)</code> should return \"M\"');",
"assert.deepEqual(convert(1004), \"MIV\", '<code>convert(1004)</code> should return \"MIV\"');",
"assert.deepEqual(convert(1006), \"MVI\", '<code>convert(1006)</code> should return \"MVI\"');"
], ],
"description": [ "description": [
"Convert the given number into a roman numeral.", "Convert the given number into a roman numeral.",
@ -117,6 +137,9 @@
"Array.indexOf()", "Array.indexOf()",
"Array.join()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -148,7 +171,7 @@
"where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });" "where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });"
], ],
"tests": [ "tests": [
"assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: <code>where()</code> should return an array of objects.');", "assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: <code>where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })</code> should return <code>[{ first: \"Tybalt\", last: \"Capulet\" }]</code>.');",
"assert.deepEqual(where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: <code>where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })</code> should return <code>[{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]</code>.');", "assert.deepEqual(where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: <code>where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })</code> should return <code>[{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]</code>.');",
"assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');" "assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');"
], ],
@ -157,6 +180,9 @@
"Object.hasOwnProperty()", "Object.hasOwnProperty()",
"Object.keys()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -176,7 +202,7 @@
"tests": [ "tests": [
"assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: <code>myReplace(\"Let us go to the store\", \"store\", \"mall\")</code> should return \"Let us go to the mall\".');", "assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: <code>myReplace(\"Let us go to the store\", \"store\", \"mall\")</code> should return \"Let us go to the mall\".');",
"assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: <code>myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")</code> should return \"He is Sitting on the couch\".');", "assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: <code>myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")</code> should return \"He is Sitting on the couch\".');",
"assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: <code>myReplace(\"This has a spellngi error\", \"spellingi\", \"spelling\")</code> should return \"This has a spelling error\".');", "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: <code>myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")</code> should return \"This has a spelling error\".');",
"assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: <code>myReplace(\"His name is Tom\", \"Tom\", \"john\")</code> should return \"His name is John\".');", "assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: <code>myReplace(\"His name is Tom\", \"Tom\", \"john\")</code> should return \"His name is John\".');",
"assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: <code>myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")</code> should return \"Let us get back to more Bonfires\".');" "assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: <code>myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")</code> should return \"Let us get back to more Bonfires\".');"
], ],
@ -200,6 +226,9 @@
"String.replace()", "String.replace()",
"Array.join()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -243,6 +272,9 @@
"String.substr()", "String.substr()",
"String.split()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -283,6 +315,9 @@
"Array.push()", "Array.push()",
"String.split()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -321,6 +356,9 @@
"String.charCodeAt()", "String.charCodeAt()",
"String.fromCharCode()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -363,6 +401,9 @@
"MDNlinks": [ "MDNlinks": [
"Boolean Objects" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -403,6 +444,9 @@
"Arguments object", "Arguments object",
"Array.reduce()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -444,6 +488,9 @@
"RegExp", "RegExp",
"HTML Entities" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -483,6 +530,9 @@
"RegExp", "RegExp",
"String.replace()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -523,6 +573,9 @@
"MDNlinks": [ "MDNlinks": [
"Remainder" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -561,6 +614,9 @@
"For Loops", "For Loops",
"Array.push()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -600,6 +656,9 @@
"MDNlinks": [ "MDNlinks": [
"Smallest Common Multiple" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -633,7 +692,10 @@
"assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: <code>find([1, 3, 5, 9], function(num) { return num % 2 === 0; })</code> should return undefined.');" "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: <code>find([1, 3, 5, 9], function(num) { return num % 2 === 0; })</code> should return undefined.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Array.some()" "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"
], ],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
@ -664,15 +726,18 @@
"drop([1, 2, 3], function(n) {return n < 3; });" "drop([1, 2, 3], function(n) {return n < 3; });"
], ],
"tests": [ "tests": [
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'message: <code>drop([1, 2, 3, 4], function(n) {return n>= 3;})</code> should return <code>[3, 4]</code>.');", "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'message: <code>drop([1, 2, 3, 4], function(n) {return n >= 3;})</code> should return <code>[3, 4]</code>.');",
"assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0; }), [1, 2, 3], 'message: <code>drop([1, 2, 3], function(n) {return n > 0; })</code> should return <code>[1, 2, 3]</code>.');", "assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0; }), [1, 2, 3], 'message: <code>drop([1, 2, 3], function(n) {return n > 0; })</code> should return <code>[1, 2, 3]</code>.');",
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: <code>drop([1, 2, 3, 4], function(n) {return n > 5;})</code> should return <code>[]</code>.');", "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: <code>drop([1, 2, 3, 4], function(n) {return n > 5;})</code> should return <code>[]</code>.');",
"assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'message: <code>drop([1, 2, 3, 7, 4], function(n) {return n>= 3})</code> should return <code>[7, 4]</code>.');" "assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'message: <code>drop([1, 2, 3, 7, 4], function(n) {return n > 3})</code> should return <code>[7, 4]</code>.');"
], ],
"MDNlinks": [ "MDNlinks": [
"Arguments object", "Arguments object",
"Array.shift()" "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)"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -710,6 +775,9 @@
"MDNlinks": [ "MDNlinks": [
"Array.isArray()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -746,6 +814,9 @@
"String.charCodeAt()", "String.charCodeAt()",
"String.fromCharCode()" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -763,14 +834,13 @@
"id": "a10d2431ad0c6a099a4b8b52", "id": "a10d2431ad0c6a099a4b8b52",
"title": "Everything Be True", "title": "Everything Be True",
"description": [ "description": [
"Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).", "Check if the predicate (second argument) is truthy on all elements of a collection (first argument).",
"For this, check to see if the property defined in the second argument is present on every element of the collection.",
"Remember, you can access object properties through either dot notation or [] notation.", "Remember, you can access object properties through either dot notation or [] notation.",
"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. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function every(collection, pre) {", "function every(collection, pre) {",
" // Does everyone have one of these?", " // Is everyone being true?",
" return pre;", " return pre;",
"}", "}",
"", "",
@ -778,12 +848,17 @@
], ],
"tests": [ "tests": [
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return true.');", "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return true.');",
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"}), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"})</code> should return false.');", "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return false.');",
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"female\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"}), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"female\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], {\"sex\": \"female\"})</code> should return false.');" "assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\")</code> should return false.');",
"assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: <code>every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\")</code> should return false');",
"assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: <code>every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\")</code> should return true');",
"assert.strictEqual(every([{\"single\": \"yes\"}], \"single\"), true, 'message: <code>every([{\"single\": \"yes\"}], \"single\")</code> should return true');",
"assert.strictEqual(every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: <code>every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\")</code> should return false');",
"assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: <code>every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\")</code> should return false');",
"assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: <code>every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")</code> should return false');"
], ],
"MDNlinks": [ "solutions": [
"Object.hasOwnProperty()", "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"
"Object.getOwnPropertyNames()"
], ],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
@ -828,6 +903,10 @@
"Closures", "Closures",
"Arguments object" "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"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",

View File

@ -8,7 +8,7 @@
"title": "Show the Local Weather", "title": "Show the Local Weather",
"challengeSeed": ["126415127"], "challengeSeed": ["126415127"],
"description": [ "description": [
"<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/AdventureBear/full/yNBJRj' target='_blank'>http://codepen.io/AdventureBear/full/yNBJRj</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/pen/avqvgJ' target='_blank'>http://codepen.io/FreeCodeCamp/pen/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 #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 #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.", "<span class='text-info'>Rule #3:</span> Reverse engineer the example project's functionality, and also feel free to personalize it.",
@ -17,6 +17,7 @@
"<span class='text-info'>Bonus User Story:</span> As a user, I can see an icon depending on the weather.", "<span class='text-info'>Bonus User Story:</span> As a user, I can see an icon depending on the weather.",
"<span class='text-info'>Bonus User Story:</span> As a user, I see a different background image (e.g. snowy mountain, hot desert) depending on the weather.", "<span class='text-info'>Bonus User Story:</span> As a user, I see a different background image (e.g. snowy mountain, hot desert) depending on the weather.",
"<span class='text-info'>Bonus User Story:</span> As a user, I can push a button to toggle between Fahrenheit and Celsius.", "<span class='text-info'>Bonus User Story:</span> As a user, I can push a button to toggle between Fahrenheit and Celsius.",
"We recommend using the <a href='http://openweathermap.org/current#geo' target='_blank'>Open Weather API</a>. This will require creating a free API key. Normally you want to avoid exposing API keys on CodePen, but we haven't been able to find a keyless API for weather.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.", "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.",
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.", "When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
"If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>" "If you'd like immediate feedback on your project from fellow campers, click this button and paste in a link to your CodePen project. <br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"

View File

@ -16,8 +16,7 @@
"This is important because without your <code>document ready function</code>, your code may run before your HTML is rendered, which would cause bugs." "This is important because without your <code>document ready function</code>, your code may run before your HTML is rendered, which would cause bugs."
], ],
"tests": [ "tests": [
"assert(editor.match(/<script>/g), 'Create a <code>script</code> element.')", "assert(editor.match(/<\\/script\\s*>/g) && editor.match(/<script(\\sasync|\\sdefer)*(\\s(charset|src|type)\\s*=\\s*[\"\\']+[^\"\\']*[\"\\']+)*(\\sasync|\\sdefer)*\\s*>/g) && editor.match(/<\\/script\\s*>/g).length === editor.match(/<script(\\sasync|\\sdefer)*(\\s(charset|src|type)\\s*=\\s*[\"\\']+[^\"\\']*[\"\\']+)*(\\sasync|\\sdefer)*\\s*>/g).length, 'Create a <code>script</code> element making sure it is valid and has a closing tag.')",
"assert(editor.match(/<\\/script>/g) && editor.match(/<script/g) && editor.match(/<\\/script>/g).length === editor.match(/<script/g).length, 'Make sure your <code>script</code> element has a closing tag.')",
"assert(editor.match(/\\$\\s*?\\(\\s*?document\\)\\.ready\\s*?\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/g), 'You should add <code>$&#40;document&#41;.ready&#40;function&#40;&#41; {</code> to the beginning of your <code>script</code> element.')", "assert(editor.match(/\\$\\s*?\\(\\s*?document\\)\\.ready\\s*?\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/g), 'You should add <code>$&#40;document&#41;.ready&#40;function&#40;&#41; {</code> to the beginning of your <code>script</code> element.')",
"assert(editor.match(/\\n*?\\s*?\\}\\s*?\\);/g), 'Close your <code>$&#40;document&#41;.ready&#40;function&#40;&#41; {</code> function with <code>}&#41;;</code>')" "assert(editor.match(/\\n*?\\s*?\\}\\s*?\\);/g), 'Close your <code>$&#40;document&#41;.ready&#40;function&#40;&#41; {</code> function with <code>}&#41;;</code>')"
], ],
@ -258,8 +257,10 @@
"title": "Target the same element with multiple jQuery Selectors", "title": "Target the same element with multiple jQuery Selectors",
"description": [ "description": [
"Now you know three ways of targeting elements: by type: <code>$(\"button\")</code>, by class: <code>$(\".btn\")</code>, and by id <code>$(\"#target1\")</code>.", "Now you know three ways of targeting elements: by type: <code>$(\"button\")</code>, by class: <code>$(\".btn\")</code>, and by id <code>$(\"#target1\")</code>.",
"Use each of these jQuery selectors to target your <code>button</code> element with the class <code>btn</code> and the id <code>target1</code>.", "Using each of the above jQuery selectors and the <code>addClass()</code> function:",
"Use the <code>addClass()</code> jQuery function to give the element one new class for each selector: <code>animated</code>, <code>shake</code>, and <code>btn-primary</code>." "Add the <code>animated</code> class to all elements with type <code>button</code>.",
"Add the <code>shake</code> class to all the buttons with class <code>.btn</code>.",
"Add the <code>btn-primary</code> class to the button with id <code>#target1</code>."
], ],
"tests": [ "tests": [
"assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\s*?button\\s*?(?:'|\")/gi), 'Use the <code>$&#40\"button\"&#41</code> selector.')", "assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\s*?button\\s*?(?:'|\")/gi), 'Use the <code>$&#40\"button\"&#41</code> selector.')",

View File

@ -0,0 +1,404 @@
{
"name": "JSON APIs and Ajax",
"order": 10.5,
"time": "30m",
"challenges": [
{
"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.",
"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>.",
"Before we can do this, we need to implement a <code>click event</code> inside of our <code>$(document).ready()</code> function by adding this code:",
"<code>$(\"#getMessage\").on(\"click\", function(){</code>",
"",
"<code>});</code>"
],
"tests": [
"assert(editor.match(/\\$\\s*?\\(\\s*?(?:'|\")\\#getMessage(?:'|\")\\s*?\\)\\s*?\\.on\\s*?\\(\\s*?(?:'|\")click(?:'|\")\\s*?\\,\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/gi), 'Bind the click event to the button with the ID of <code>getMessage</code>')",
"assert(editor.match(/\\n*?\\s*?\\}\\n*?\\s*?\\);/gi) && editor.match(/\\n*?\\s*?\\}\\);/gi).length >= 2, 'Be sure to close your functions with <code>}&#41;;</code>')"
],
"challengeSeed": [
"fccss",
" $(document).ready(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>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bc000000000000000000001",
"title": "Change Text with Click Events",
"description": [
"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>"
],
"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\".')"
],
"challengeSeed": [
"fccss",
" $(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>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bb000000000000000000002",
"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.",
"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>",
"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) && 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.')"
],
"challengeSeed": [
"fccss",
" $(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>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bb000000000000000000003",
"title": "Convert JSON Data to HTML",
"description": [
"Now that we're getting data from a JSON API, let's display it in our HTML.",
"We can use the <code>.map()</code> method to loop through our data and modify our HTML elements.",
"First, let's declare an html variable with <code>var html = \"\";</code>.",
"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;for(var key in val) {</code>",
"<code>&thinsp;&thinsp;&thinsp;&thinsp;html = html + '&lt;div class = \"' + key + '\"&gt;' + val[key] + '&lt;/div&gt;';</code>",
"<code>&thinsp;&thinsp;}</code>",
"<code>&thinsp;&thinsp;html = html + \"&lt;/div&gt;&lt;br/&gt;\"</code>",
"<code>});</code>"
],
"tests": [
"assert(editor.match(/json\\.map/gi), 'The message box should have something in it.')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
"",
" // Only change code below this line.",
"",
"",
"",
"",
"",
"",
"",
"",
"",
" // Only change code above this line.",
"",
" $(\".message\").html(html);",
"",
" });",
" });",
" });",
"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>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bb000000000000000000004",
"title": "Render Images from Data Sources",
"description": [
"In the JSON that we receive from Free Code Camp's Cat Photo API, each object has an attribute called \"imageLink\".",
"When we're looping through these objects, let's check whether an object attribute (key) is <code>imageLink</code>. If it is, instead of outputing the image link, let's render the image.",
"Here's the code that does this:",
"<code>if(key === \"imageLink\") {</code>",
"<code>&thinsp;&thinsp;html = html + '&lt;img class = \"' + key + '\"src = \"' + val[key] + '\"&gt;';</code>",
"<code>} else {</code>",
"<code>&thinsp;&thinsp;html = html + '&lt;div class = \"' + key + '\"&gt;' + val[key] + '&lt;/div&gt;';</code>",
"<code>}</code>"
],
"tests": [
"assert(editor.match(/imageLink/gi), 'You should have accessed the imageLink of each cat object.')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
"",
" var html = \"\";",
"",
" json.map(function(val) {",
"",
" html = html + \"<div class = 'cat'>\"",
"",
" for (var key in val) {",
"",
" // Only change code below this line.",
"",
"",
"",
" // Only change code above this line.",
"",
" }",
"",
" html = html + \"</div>\"",
"",
" });",
"",
" $(\".message\").html(html);",
"",
" });",
" });",
" });",
"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>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bb000000000000000000005",
"title": "Prefilter JSON",
"description": [
"If we don't want to render every cat photo we get from our Free Code Camp's Cat Photo JSON API, we can pre-filter the json before we loop through it.",
"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>});</code>"
],
"tests": [
"assert(editor.match(/filter/gi), 'You should be making use of the .filter method.')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
"",
" $(\"#getMessage\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json?callback=\", function( json ) {",
"",
" var html = \"\";",
"",
" json.map(function(val){",
"",
" val = \"<img src = '\" + val.imageLink + \"'/>\"",
"",
" html = html + \"<div class = 'cat'>\"",
"",
" // Only change code below this line.",
"",
"",
"",
" // Only change code above this line.",
"",
" for(var key in val){",
"",
" html = html + '<div class = \"' + key + '\">' + val[key] + '</div>';",
"",
" }",
"",
" html = html + \"</div>\"",
"",
" });",
"",
" $(\".message\").html(html);",
"",
" });",
" });",
" });",
"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>",
""
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bb000000000000000000006",
"title": "Get Geo-location Data",
"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.",
"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>}</code>"
],
"tests": [
"assert(editor.match(/navigator\\.geolocation\\.getCurrentPosition/gi), 'You should make use of the <code>navigator.geolocation</code> to access the users current location.')"
],
"challengeSeed": [
"fccss",
" // Only change code below this line.",
"",
"",
"",
" // Only change code above this line.",
"fcces",
"<div id = \"data\">",
" <h4>You are here:</h4>",
" ",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
}
]
}

View File

@ -25,7 +25,7 @@
"Complete \"Mongod\"", "Complete \"Mongod\"",
"Complete \"Connect\"", "Complete \"Connect\"",
"Complete \"Find\"", "Complete \"Find\"",
"Complete \"Find Limit\"", "Complete \"Find Project\"",
"Complete \"Insert\"", "Complete \"Insert\"",
"Complete \"Update\"", "Complete \"Update\"",
"Complete \"Remove\"", "Complete \"Remove\"",

View File

@ -182,17 +182,19 @@
"id":"cf1111c1c15feddfaeb7bdef", "id":"cf1111c1c15feddfaeb7bdef",
"title":"Iterate over Arrays with .map", "title":"Iterate over Arrays with .map",
"description":[ "description":[
"The map method is one of the easiest ways to iterate through an array or object there is. Let's use it now.", "The <code>map</code> method is a convenient way to iterate through arrays. Here's an example usage:",
"<code>array = array.map(function(val){</code>", "<code>var timesFour = array.map(function(val){</code>",
"<code>&thinsp;&thinsp;return val+1;</code>", "<code>&thinsp;&thinsp;return val*4;</code>",
"<code>});</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.",
"In our example the callback only uses the value of the array element (the <code>val</code> argument) but your callback can also include arguments for the <code>index</code> and <code>array</code> being acted on.",
"Use the map function to add 3 to every value in the variable <code>array</code>." "Use the map function to add 3 to every value in the variable <code>array</code>."
], ],
"tests":[ "tests":[
"assert.deepEqual(array, [4,5,6,7,8], 'message: You should add three to each value in the array.');", "assert.deepEqual(array, [4,5,6,7,8], 'message: You should add three to each value in the array.');",
"assert(editor.getValue().match(/\\.map\\s*\\(/gi), 'message: You should be making use of the map method.');", "assert(editor.getValue().match(/\\.map\\s*\\(/gi), 'message: You should be making use of the <code>map</code> method.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'message: You should only modify the array with <code>.map</code>.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\]/gi), 'message: You should only modify the array with <code>map</code>.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = [1,2,3,4,5];", "var array = [1,2,3,4,5];",
@ -215,15 +217,18 @@
"id":"cf1111c1c15feddfaeb8bdef", "id":"cf1111c1c15feddfaeb8bdef",
"title":"Condense arrays with .reduce", "title":"Condense arrays with .reduce",
"description":[ "description":[
"Reduce can be useful for condensing an array of numbers into one value.", "The array method <code>reduce</code> is used to iterate through an array and condense it into one value.",
"To use <code>reduce</code> you pass in a callback whose arguments are an accumulator (in this case, <code>previousVal</code>) and the current value (<code>currentVal</code>).",
"<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 if will be the first array element.",
"Here is an example of <code>reduce</code> being used to sum all the values of an array:",
"<code>var singleVal = array.reduce(function(previousVal, currentVal){</code>", "<code>var singleVal = array.reduce(function(previousVal, currentVal){</code>",
"<code>&thinsp;&thinsp;return previousVal+currentVal;</code>", "<code>&thinsp;&thinsp;return previousVal+currentVal;</code>",
"<code>});</code>", "<code>});</code>",
"Use the <code>reduce</code> function to sum all the values in <code>array</code> and assign it to <code>singleVal</code>." "Use the <code>reduce</code> method to sum all the values in <code>array</code> and assign it to <code>singleVal</code>."
], ],
"tests":[ "tests":[
"assert(singleVal == 30, 'message: <code>singleVal</code> should be equal to the sum of all items in the <code>array</code> variable.');", "assert(singleVal == 30, 'message: <code>singleVal</code> should be equal to the sum of all items in the <code>array</code> variable.');",
"assert(editor.getValue().match(/\\.reduce\\s*\\(/gi), 'message: You should have made use of the reduce method.');" "assert(editor.getValue().match(/\\.reduce\\s*\\(/gi), 'message: You should have made use of the <code>reduce</code> method.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = [4,5,6,7,8];", "var array = [4,5,6,7,8];",
@ -248,16 +253,19 @@
"id":"cf1111c1c15feddfaeb9bdef", "id":"cf1111c1c15feddfaeb9bdef",
"title":"Filter Arrays with .filter", "title":"Filter Arrays with .filter",
"description":[ "description":[
"Filter is a useful method that can filter out values that don't match a certain criteria", "The <code>filter</code> method is used to iterate through an array and filter out elements where a given condition is not true.",
"Let's remove all the values greater than five", "<code>filter</code> is passed a callback function which takes the current value (we've called that <code>val</code>) as an argument. It can also use arguments for the <code>index</code> and <code>array</code> being acted on.",
"Any array element for which the callback returns true will be kept and elements that return false will be filtered out.",
"The following code is an example of using filter to remove array elements that are not even numbers:",
"<code>array = array.filter(function(val) {</code>", "<code>array = array.filter(function(val) {</code>",
"<code>&thinsp;&thinsp;return val <= 5;</code>", "<code>&thinsp;&thinsp;return val % 2 === 0;</code>",
"<code>});</code>" "<code>});</code>",
"Use <code>filter</code> to remove all elements from <code>array</code> that are greater than 5."
], ],
"tests":[ "tests":[
"assert.deepEqual(array, [1,2,3,4,5], 'message: You should have removed all the values from the array that are greater than 5.');", "assert.deepEqual(array, [1,2,3,4,5], 'message: You should have removed all the values from the array that are greater than 5.');",
"assert(editor.getValue().match(/array\\.filter\\s*\\(/gi), 'message: You should be using the filter method to remove the values from the array.');", "assert(editor.getValue().match(/array\\.filter\\s*\\(/gi), 'message: You should be using the <code>filter</code> method to remove the values from the array.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'message: You should only be using <code>.filter</code> to modify the contents of the array.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\,4\\,5\\,6\\,7\\,8\\,9\\,10\\]/gi), 'message: You should only be using <code>filter</code> to modify the contents of the array.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = [1,2,3,4,5,6,7,8,9,10];", "var array = [1,2,3,4,5,6,7,8,9,10];",
@ -280,16 +288,20 @@
"id":"cf1111c1c16feddfaeb1bdef", "id":"cf1111c1c16feddfaeb1bdef",
"title": "Sort Arrays with .sort", "title": "Sort Arrays with .sort",
"description":[ "description":[
"You can use the method <code>sort</code> to easily sort the values in the array alphabetically or numerically.", "You can use the method <code>sort</code> to easily sort the values in an array alphabetically or numerically.",
"<code>var array = [1, 3, 2];</code>", "Unlike the previous array methods we have been looking at, <code>sort</code> actually alters the array in place. However, it also returns this sorted array.",
"<code>array = array.sort();</code>", "<code>sort</code> can be passed a compare function as a callback. If no compare function is passed in it will convert the values to strings and sort alphabetically.",
"<code>array</code> is now <code>[1, 2, 3]</code>.", "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>});</code>",
"Use <code>sort</code> to sort <code>array</code> alphabetically." "Use <code>sort</code> to sort <code>array</code> alphabetically."
], ],
"tests":[ "tests":[
"assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'message: You should have sorted the array alphabetically.');", "assert.deepEqual(array, ['alpha', 'beta', 'charlie'], 'message: You should have sorted the array alphabetically.');",
"assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'message: You should only be using <code>.sort</code> to modify the array.');", "assert(editor.getValue().match(/\\[\\'beta\\'\\,\\s\\'alpha\\'\\,\\s'charlie\\'\\];/gi), 'message: You should only be using <code>sort</code> to modify the array.');",
"assert(editor.getValue().match(/\\.sort\\s*\\(\\)/gi), 'message: You should have made use of the sort method.');" "assert(editor.getValue().match(/\\.sort\\s*\\(\\)/gi), 'message: You should have made use of the <code>sort</code> method.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var array = ['beta', 'alpha', 'charlie'];", "var array = ['beta', 'alpha', 'charlie'];",
@ -312,7 +324,8 @@
"id": "cf1111c1c16feddfaeb2bdef", "id": "cf1111c1c16feddfaeb2bdef",
"title": "Reverse Arrays with .reverse", "title": "Reverse Arrays with .reverse",
"description": [ "description": [
"You can use the <code>reverse</code> function to reverse the contents of an array.", "You can use the <code>reverse</code> method to reverse the elements of an array.",
"<code>reverse</code> is another array method that alters the array in place, but it also returns the reversed array.",
"Add a line of code that uses <code>reverse</code> to reverse the <code>array</code> variable." "Add a line of code that uses <code>reverse</code> to reverse the <code>array</code> variable."
], ],
"tests": [ "tests": [
@ -341,12 +354,14 @@
"id": "cf1111c1c16feddfaeb3bdef", "id": "cf1111c1c16feddfaeb3bdef",
"title": "Concatenate Strings with .concat", "title": "Concatenate Strings with .concat",
"description": [ "description": [
"<code>.concat()</code> can be used to merge the contents of two arrays into one.", "<code>concat</code> can be used to merge the contents of two arrays into one.",
"<code>concat</code> takes an array as an argument and returns a new array with the elements of this array concatenated onto the end.",
"Here is an example of <code>concat</code> being used to concatenate <code>otherArray</code> onto the end of <code>array</code>:",
"<code>array = array.concat(otherArray);</code>", "<code>array = array.concat(otherArray);</code>",
"Use <code>.concat()</code> to concatenate <code>concatMe</code> onto the end of <code>array</code> and assign it back to array." "Use <code>.concat()</code> to concatenate <code>concatMe</code> onto the end of <code>array</code> and assign it back to <code>array</code>."
], ],
"tests": [ "tests": [
"assert.deepEqual(array, [1,2,3,4,5,6], 'message: You should concat the two arrays together.');", "assert.deepEqual(array, [1,2,3,4,5,6], 'message: You should concatenate the two arrays together.');",
"assert(editor.getValue().match(/\\.concat\\s*\\(/gi), 'message: You should be using the <code>concat</code> method to merge the two arrays.');", "assert(editor.getValue().match(/\\.concat\\s*\\(/gi), 'message: You should be using the <code>concat</code> method to merge the two arrays.');",
"assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'message: You should only be using <code>concat</code> to modify the arrays.');" "assert(editor.getValue().match(/\\[1\\,2\\,3\\]/gi) && editor.getValue().match(/\\[4\\,5\\,6\\]/gi), 'message: You should only be using <code>concat</code> to modify the arrays.');"
], ],
@ -373,13 +388,14 @@
"id":"cf1111c1c16feddfaeb4bdef", "id":"cf1111c1c16feddfaeb4bdef",
"title":"Split Strings with .split", "title":"Split Strings with .split",
"description":[ "description":[
"You can use the <code>.split()</code> method to split a string into an array.", "You can use the <code>split</code> method to split a string into an array.",
"<code>.split()</code> uses the argument you pass in as a delimiter to determine which points the string should be split at.", "<code>split</code> uses the argument you pass in as a delimiter to determine which points the string should be split at.",
"Here is an example of <code>split</code> being used to split an array at every space character:",
"<code>var array = string.split(' ');</code>", "<code>var array = string.split(' ');</code>",
"Use <code>.split()</code> to create an array of words from <code>string</code> and assign it to <code>array</code>." "Use <code>split</code> to create an array of words from <code>string</code> and assign it to <code>array</code>."
], ],
"tests":[ "tests":[
"assert(/\\.split\\(/gi, 'message: You should use the split method on the string.');", "assert(/\\.split\\(/gi, 'message: You should use the <code>split</code> method on the string.');",
"assert(typeof(array) === 'object' && array.length === 5, 'message: You should split the string by its spaces.');" "assert(typeof(array) === 'object' && array.length === 5, 'message: You should split the string by its spaces.');"
], ],
"challengeSeed":[ "challengeSeed":[
@ -403,24 +419,25 @@
"id":"cf1111c1c16feddfaeb5bdef", "id":"cf1111c1c16feddfaeb5bdef",
"title":"Join Strings with .join", "title":"Join Strings with .join",
"description":[ "description":[
"We can use the <code>.join()</code> method to join each element in an array into a string separated by whatever delimiter you provide as an argument to the join operation.", "We can use the <code>join</code> method to join each element of an array into a string separated by whatever delimiter you provide as an argument.",
"<code>var joinMe = joinMe.join(\" \");</code>", "The following is an example of using <code>join</code> to join all of the elements of an array into a string with all the elements seperated by a space:",
"Use the <code>.join()</code> method to create a string from <code>joinMe</code> with spaces in between each element and assign it back to <code>joinMe</code>." "<code>var joinedString = joinMe.join(\" \");</code>",
"Use the <code>join</code> method to create a string from <code>joinMe</code> with spaces in between each element and assign it to <code>joinedString</code>."
], ],
"tests":[ "tests":[
"assert(typeof(joinMe) === 'string' && joinMe === \"Split me into an array\", 'message: You should join the elements of the array with spaces.');", "assert(typeof(joinedString) === 'string' && joinedString === \"Split me into an array\", 'message: You should join the elements of the array with spaces.');",
"assert(/\\.join\\(/gi, 'message: You should use of the join method on the array.');" "assert(/\\.join\\(/gi, 'message: You should use of the <code>join</code> method on the array.');"
], ],
"challengeSeed":[ "challengeSeed":[
"var joinMe = [\"Split\",\"me\",\"into\",\"an\",\"array\"];", "var joinMe = [\"Split\",\"me\",\"into\",\"an\",\"array\"];",
"", "",
"// Only change code below this line.", "// Only change code below this line.",
"", "",
"joinMe = joinMe;", "var joinedString = joinMe;",
"", "",
"// Only change code above this line.", "// Only change code above this line.",
"", "",
"(function() {return joinMe;})();" "(function() {return joinedString;})();"
], ],
"MDNlinks":[ "MDNlinks":[
"Array.join()" "Array.join()"

View File

@ -39,6 +39,9 @@
"Closures", "Closures",
"Details of the Object Model" "Details of the Object Model"
], ],
"solutions": [
"var Person = function(firstAndLast) {\n\n var firstName, lastName;\n\n function updateName(str) { \n firstName = str.split(\" \")[0];\n lastName = str.split(\" \")[1]; \n }\n\n updateName(firstAndLast);\n\n this.getFirstName = function(){\n return firstName;\n };\n \n this.getLastName = function(){\n return lastName;\n };\n \n this.getFullName = function(){\n return firstName + \" \" + lastName;\n };\n \n this.setFirstName = function(str){\n firstName = str;\n };\n \n\n this.setLastName = function(str){\n lastName = str;\n };\n \n this.setFullName = function(str){\n updateName(str);\n };\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -80,6 +83,9 @@
"MDNlinks": [ "MDNlinks": [
"Math.pow()" "Math.pow()"
], ],
"solutions": [
"function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n var TAU = 2 * Math.PI; \n return arr.map(function(obj) {\n return {\n name: obj.name,\n orbitalPeriod: Math.round(TAU * Math.sqrt(Math.pow(obj.avgAlt+earthRadius, 3)/GM))\n };\n });\n}\n\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);\n"
],
"type": "bonfire", "type": "bonfire",
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
@ -120,6 +126,9 @@
"Array.reduce()" "Array.reduce()"
], ],
"type": "bonfire", "type": "bonfire",
"solutions": [
"function pairwise(arr, arg) {\n var sum = 0;\n arr.forEach(function(e, i, a) {\n if (e != null) { \n var diff = arg-e;\n a[i] = null;\n var dix = a.indexOf(diff);\n if (dix !== -1) {\n sum += dix;\n sum += i;\n a[dix] = null;\n } \n }\n });\n return sum;\n}\n\npairwise([1,4,2,3,0,5], 7);\n"
],
"challengeType": 5, "challengeType": 5,
"nameCn": "", "nameCn": "",
"descriptionCn": [], "descriptionCn": [],

View File

@ -1,55 +1,34 @@
/* eslint-disable no-process-exit */ /* eslint-disable no-process-exit */
require('babel/register'); require('babel/register');
require('dotenv').load(); require('dotenv').load();
var fs = require('fs'), var fs = require('fs'),
Rx = require('rx'),
_ = require('lodash'), _ = require('lodash'),
path = require('path'), path = require('path'),
app = require('../server/server'), app = require('../server/server');
nonprofits = require('./nonprofits.json'),
jobs = require('./jobs.json');
function getFilesFor(dir) { function getFilesFor(dir) {
return fs.readdirSync(path.join(__dirname, '/' + dir)); return fs.readdirSync(path.join(__dirname, '/' + dir));
} }
var Challenge = app.models.Challenge; var Challenge = app.models.Challenge;
var Nonprofit = app.models.Nonprofit;
var Job = app.models.Job;
var counter = 0;
var challenges = getFilesFor('challenges'); var challenges = getFilesFor('challenges');
// plus two accounts for nonprofits and jobs seed. var destroy = Rx.Observable.fromNodeCallback(Challenge.destroyAll, Challenge);
var numberToSave = challenges.length + 1; var create = Rx.Observable.fromNodeCallback(Challenge.create, Challenge);
function completionMonitor() { destroy()
// Increment counter .flatMap(function() { return Rx.Observable.from(challenges); })
counter++; .flatMap(function(file) {
// Exit if all challenges have been checked
if (counter >= numberToSave) {
process.exit(0);
}
// Log where in the seed order we're currently at
console.log('Call: ' + counter + '/' + numberToSave);
}
Challenge.destroyAll(function(err, info) {
if (err) {
throw err;
} else {
console.log('Deleted ', info);
}
challenges.forEach(function(file) {
var challengeSpec = require('./challenges/' + file); var challengeSpec = require('./challenges/' + file);
var order = challengeSpec.order; var order = challengeSpec.order;
var block = challengeSpec.name; var block = challengeSpec.name;
var isBeta = !!challengeSpec.isBeta; var isBeta = !!challengeSpec.isBeta;
console.log('parsed %s successfully', file);
// challenge file has no challenges... // challenge file has no challenges...
if (challengeSpec.challenges.length === 0) { if (challengeSpec.challenges.length === 0) {
console.log('file %s has no challenges', file); return Rx.Observable.just([{ block: 'empty ' + block }]);
completionMonitor();
return;
} }
var challenges = challengeSpec.challenges var challenges = challengeSpec.challenges
@ -73,50 +52,15 @@ Challenge.destroyAll(function(err, info) {
return challenge; return challenge;
}); });
Challenge.create( return create(challenges);
challenges, })
function(err) { .subscribe(
if (err) { function(challenges) {
throw err; console.log('%s successfully saved', challenges[0].block);
} else { },
console.log('Successfully parsed %s', file); function(err) { throw err; },
completionMonitor(err); function() {
} console.log('challenge seed completed');
process.exit(0);
} }
); );
});
});
Nonprofit.destroyAll(function(err, info) {
if (err) {
console.error(err);
} else {
console.log('Deleted ', info);
}
Nonprofit.create(nonprofits, function(err, data) {
if (err) {
throw err;
} else {
console.log('Saved ', data);
}
completionMonitor(err);
console.log('nonprofits');
});
});
Job.destroyAll(function(err, info) {
if (err) {
throw err;
} else {
console.log('Deleted ', info);
}
Job.create(jobs, function(err, data) {
if (err) {
console.log('error: ', err);
} else {
console.log('Saved ', data);
}
console.log('jobs');
completionMonitor(err);
});
});

29
seed/nonprofits.js Normal file
View File

@ -0,0 +1,29 @@
/* eslint-disable no-process-exit */
require('babel/register');
require('dotenv').load();
var Rx = require('rx');
var app = require('../server/server');
var Nonprofits = app.models.Nonprofit;
var nonprofits = require('./nonprofits.json');
var destroy = Rx.Observable.fromNodeCallback(Nonprofits.destroyAll, Nonprofits);
var create = Rx.Observable.fromNodeCallback(Nonprofits.create, Nonprofits);
destroy()
.flatMap(function() {
if (!nonprofits) {
return Rx.Observable.throw(new Error('No nonprofits found'));
}
return create(nonprofits);
})
.subscribe(
function(nonprofits) {
console.log('successfully saved %d nonprofits', nonprofits.length);
},
function(err) { throw err; },
function() {
console.log('nonprofit seed completed');
process.exit(0);
}
);

View File

@ -1,6 +1,5 @@
[ [
{ {
"id": "bd7157d8c441cbafaeb5bdef",
"whatDoesNonprofitDo": "We help the many less-fortunate Jewish families in our community, by providing them with nutritious food and energy to grow, learn, work, and give them hope for a better and brighter future.", "whatDoesNonprofitDo": "We help the many less-fortunate Jewish families in our community, by providing them with nutritious food and energy to grow, learn, work, and give them hope for a better and brighter future.",
"websiteLink": "http://chasdeikaduri.org/", "websiteLink": "http://chasdeikaduri.org/",
"name": "Chasdei Kaduri", "name": "Chasdei Kaduri",
@ -20,7 +19,6 @@
"moneySaved": 60000 "moneySaved": 60000
}, },
{ {
"id": "bd7158d8c464cbafaeb4bdef",
"whatDoesNonprofitDo": "We connect simple technology with last mile communities to reduce poverty.", "whatDoesNonprofitDo": "We connect simple technology with last mile communities to reduce poverty.",
"websiteLink": "http://kopernik.info/", "websiteLink": "http://kopernik.info/",
"name": "Kopernik", "name": "Kopernik",
@ -36,7 +34,6 @@
"moneySaved": 20000 "moneySaved": 20000
}, },
{ {
"id": "bd1326d9c245cbafaeb4bdef",
"whatDoesNonprofitDo": "We distribute biodegradable toothbrushes globally to children in need.", "whatDoesNonprofitDo": "We distribute biodegradable toothbrushes globally to children in need.",
"websiteLink": "http://www.operationbrush.org/", "websiteLink": "http://www.operationbrush.org/",
"name": "Operation Brush", "name": "Operation Brush",
@ -52,7 +49,6 @@
"moneySaved": 20000 "moneySaved": 20000
}, },
{ {
"id": "bd1325d8c464cbafaeb5bdef",
"whatDoesNonprofitDo": "We are the largest roller derby league in the world with around 250 adults and 150 junior skater members plus 500+ volunteers.", "whatDoesNonprofitDo": "We are the largest roller derby league in the world with around 250 adults and 150 junior skater members plus 500+ volunteers.",
"websiteLink": "http://www.rosecityrollers.com/about/our-charities/", "websiteLink": "http://www.rosecityrollers.com/about/our-charities/",
"name": "Rose City Rollers", "name": "Rose City Rollers",
@ -68,7 +64,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1325d8c464cbafaeb6bde1",
"whatDoesNonprofitDo": "We provide urgently needed pediatric heart surgery and follow-up care for indigent children from developing countries", "whatDoesNonprofitDo": "We provide urgently needed pediatric heart surgery and follow-up care for indigent children from developing countries",
"websiteLink": "http://www.saveachildsheart.com/global/young-leadership-program/", "websiteLink": "http://www.saveachildsheart.com/global/young-leadership-program/",
"name": "Save a Child's Heart", "name": "Save a Child's Heart",
@ -84,7 +79,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1225d8c464cbafaeb4bdef",
"whatDoesNonprofitDo": "We empower youth with technology by providing age appropriate resources and education.", "whatDoesNonprofitDo": "We empower youth with technology by providing age appropriate resources and education.",
"websiteLink": "http://savvycyberkids.org/", "websiteLink": "http://savvycyberkids.org/",
"name": "Savvy Cyber Kids", "name": "Savvy Cyber Kids",
@ -100,7 +94,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1325d8c464cbafaeb7bcef",
"whatDoesNonprofitDo": "We bring a new edge to arts and medicine in the Bay Area through powerful live performances of new music to those who feel marginalized by their affliction.", "whatDoesNonprofitDo": "We bring a new edge to arts and medicine in the Bay Area through powerful live performances of new music to those who feel marginalized by their affliction.",
"websiteLink": "http://transcendentpathways.org/", "websiteLink": "http://transcendentpathways.org/",
"name": "Transcendent Pathways", "name": "Transcendent Pathways",
@ -116,7 +109,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1325d8c464cbafaeb8bdef",
"whatDoesNonprofitDo": "We have provide volunteer matching fairs and silent art auctions at events across Canada. Rather than bid money on artwork, participants bid volunteer hours.", "whatDoesNonprofitDo": "We have provide volunteer matching fairs and silent art auctions at events across Canada. Rather than bid money on artwork, participants bid volunteer hours.",
"websiteLink": "http://www.timeraiser.ca/", "websiteLink": "http://www.timeraiser.ca/",
"name": "Timeraiser", "name": "Timeraiser",
@ -132,7 +124,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1325d8c464cbafaeb7bdef",
"whatDoesNonprofitDo": "We focus on raising funds to assist injured homeless animals.", "whatDoesNonprofitDo": "We focus on raising funds to assist injured homeless animals.",
"websiteLink": "http://www.peoplesavinganimals.org/", "websiteLink": "http://www.peoplesavinganimals.org/",
"name": "People Saving Animals", "name": "People Saving Animals",
@ -150,7 +141,6 @@
"moneySaved": 60000 "moneySaved": 60000
}, },
{ {
"id": "bd1325d8c464cbafaeb6bde2",
"whatDoesNonprofitDo": "We preserve Florida's health by regulating septic contractors and reviewing logs of sewage collection and disposal.", "whatDoesNonprofitDo": "We preserve Florida's health by regulating septic contractors and reviewing logs of sewage collection and disposal.",
"websiteLink": "http://www.floridahealth.gov/", "websiteLink": "http://www.floridahealth.gov/",
"name": "Florida Department of Health", "name": "Florida Department of Health",
@ -168,7 +158,6 @@
"moneySaved": 40000 "moneySaved": 40000
}, },
{ {
"id": "bd1325d8c464cbafaeb6bde3",
"whatDoesNonprofitDo": "We strengthen the value of songwriting and independent music in Columbus, Ohio.", "whatDoesNonprofitDo": "We strengthen the value of songwriting and independent music in Columbus, Ohio.",
"websiteLink": "http://columbussongwritersassociation.com", "websiteLink": "http://columbussongwritersassociation.com",
"name": "Columbus Songwriters Association", "name": "Columbus Songwriters Association",
@ -184,7 +173,6 @@
"moneySaved": 20000 "moneySaved": 20000
}, },
{ {
"id": "bd1325d8c464cbafaeb4bbb",
"whatDoesNonprofitDo": "We leverage all the benefits of cycling to support and improve the lives of youth and teens in the Triangle region.", "whatDoesNonprofitDo": "We leverage all the benefits of cycling to support and improve the lives of youth and teens in the Triangle region.",
"websiteLink": "http://www.trianglebikeworks.org", "websiteLink": "http://www.trianglebikeworks.org",
"name": "Triangle Bike Works", "name": "Triangle Bike Works",
@ -200,7 +188,6 @@
"moneySaved": 0 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbafaeb4bccc",
"whatDoesNonprofitDo": "We work to eradicate female genital mutilation in the US and Gambia. We work with survivors and communities.", "whatDoesNonprofitDo": "We work to eradicate female genital mutilation in the US and Gambia. We work with survivors and communities.",
"websiteLink": "http://safehandsforgirls.org/", "websiteLink": "http://safehandsforgirls.org/",
"name": "Safe Hands for Girls", "name": "Safe Hands for Girls",
@ -216,7 +203,6 @@
"moneySaved": 0 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbafaeb4beff",
"whatDoesNonprofitDo": "We're a part of the Department of Psychiatry at Mass General Hospital. We teach an innovative way for helping people that have challenging behaviors.", "whatDoesNonprofitDo": "We're a part of the Department of Psychiatry at Mass General Hospital. We teach an innovative way for helping people that have challenging behaviors.",
"websiteLink": "http://www.thinkkids.org/", "websiteLink": "http://www.thinkkids.org/",
"name": "Think Kids at Massachusetts General Hospital", "name": "Think Kids at Massachusetts General Hospital",
@ -228,11 +214,10 @@
"logoUrl": "http://www.thinkkids.org/wp-content/themes/think-kids/images/logo.png", "logoUrl": "http://www.thinkkids.org/wp-content/themes/think-kids/images/logo.png",
"imageUrl": "http://i.imgur.com/hiGJms5.png", "imageUrl": "http://i.imgur.com/hiGJms5.png",
"estimatedHours": 300, "estimatedHours": 300,
"currentStatus": "open", "currentStatus": "started",
"moneySaved": 0 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbaeaeb4bdef",
"whatDoesNonprofitDo": "We enable, educate, and empower students from rural backgrounds in Uttar Pradesh, India.", "whatDoesNonprofitDo": "We enable, educate, and empower students from rural backgrounds in Uttar Pradesh, India.",
"websiteLink": "http://www.milaan.in/", "websiteLink": "http://www.milaan.in/",
"name": "Milaan", "name": "Milaan",
@ -248,7 +233,6 @@
"moneySaved": 0 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbafaeb4beee",
"whatDoesNonprofitDo": "We're committed to closing the opportunity gap for children in Baltimore City by providing high quality after school and in-school programs.", "whatDoesNonprofitDo": "We're committed to closing the opportunity gap for children in Baltimore City by providing high quality after school and in-school programs.",
"websiteLink": "http://childfirstauthority.org/", "websiteLink": "http://childfirstauthority.org/",
"name": "Child First Authority", "name": "Child First Authority",
@ -260,56 +244,37 @@
"logoUrl": "http://i.imgur.com/YlPsQmN.jpg", "logoUrl": "http://i.imgur.com/YlPsQmN.jpg",
"imageUrl": "http://childfirstauthority.org/wp-content/uploads/2012/09/CFAHEADER7.gif", "imageUrl": "http://childfirstauthority.org/wp-content/uploads/2012/09/CFAHEADER7.gif",
"estimatedHours": 200, "estimatedHours": 200,
"currentStatus": "open", "currentStatus": "started",
"moneySaved": 0 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbafaeb4bdef",
"whatDoesNonprofitDo": "SOLACE Foundation provides drug overdose prevention and awareness training as well as grief support for bereaved families.",
"websiteLink": "https://www.facebook.com/www.solaceorangecounty.org",
"name": "The Solace Foundation of Orange County",
"endUser": "Donors",
"approvedDeliverables": ["Website"],
"projectDescription": "Campers will build a basic website that accepts donations.",
"logoUrl": "http://i.imgur.com/79E3nP0.png",
"imageUrl": "http://i.imgur.com/kCWN1iT.jpg",
"interestedCampers": [],
"confirmedCampers": [],
"estimatedHours": 100
},
{
"id": "bd1325d8c463cbafaeb4bdef",
"whatDoesNonprofitDo": "We are an interdisciplinary team that works towards harmony among humans and nature through three distinct branches: sustainable agriculture, environmental education and applied and appropriate technology; focused in Líbano, Tolima, Colombia.", "whatDoesNonprofitDo": "We are an interdisciplinary team that works towards harmony among humans and nature through three distinct branches: sustainable agriculture, environmental education and applied and appropriate technology; focused in Líbano, Tolima, Colombia.",
"websiteLink": "string", "websiteLink": "",
"name": "QET America", "name": "QET America",
"endUser": "Donors", "endUser": "Donors",
"approvedDeliverables": ["Website"], "approvedDeliverables": ["Website"],
"projectDescription": "Campers will build a multiple language website (English, Spanish) that accepts donations.", "projectDescription": "Campers will build a multiple language website (English, Spanish) that accepts donations.",
"logoUrl": "http://i.imgur.com/jPuiPOy.jpg", "logoUrl": "http://i.imgur.com/jPuiPOy.jpg",
"imageUrl": "http://i.imgur.com/zaaL2pj.jpg", "imageUrl": "http://i.imgur.com/zaaL2pj.jpg",
"interestedCampers": [], "estimatedHours": 100,
"confirmedCampers": [], "currentStatus": "open",
"estimatedHours": 100 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c462cbafaeb4bdef",
"whatDoesNonprofitDo": "1to1 Movement provides free environmental education in schools", "whatDoesNonprofitDo": "1to1 Movement provides free environmental education in schools",
"websiteLink": "http://1to1movement.org/", "websiteLink": "http://1to1movement.org/",
"stakeholderName": "string",
"stakeholderEmail": "string",
"name": "1 to 1 Movement", "name": "1 to 1 Movement",
"endUser": "Pledgers", "endUser": "Pledgers",
"approvedDeliverables": ["Web App"], "approvedDeliverables": ["Web App"],
"projectDescription": "Campers will build a simple, social, data-driven application that allows people to see the impact of their actions. User can make a pledge and track the outcome. Will make use of the D3.js visualization library.", "projectDescription": "Campers will build a simple, social, data-driven application that allows people to see the impact of their actions. User can make a pledge and track the outcome. Will make use of the D3.js visualization library.",
"logoUrl": "http://i.imgur.com/jaqxg0O.png", "logoUrl": "http://i.imgur.com/jaqxg0O.png",
"imageUrl": "http://i.imgur.com/GXSWTZw.jpg", "imageUrl": "http://i.imgur.com/GXSWTZw.jpg",
"interestedCampers": [], "estimatedHours": 300,
"confirmedCampers": [], "currentStatus": "open",
"estimatedHours": 300 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c464cbcfaeb4bdef",
"whatDoesNonprofitDo": "Our missions is to elevate the national dialogue and engage the American people around climate change policy and the promotion of real clean energy solutions in the United States.", "whatDoesNonprofitDo": "Our missions is to elevate the national dialogue and engage the American people around climate change policy and the promotion of real clean energy solutions in the United States.",
"websiteLink": "http://www.usclimateplan.org/", "websiteLink": "http://www.usclimateplan.org/",
"name": "US Climate Plan", "name": "US Climate Plan",
@ -318,24 +283,47 @@
"projectDescription": "Campers will build a basic website for sharing information, feeds from different campaigns websites.", "projectDescription": "Campers will build a basic website for sharing information, feeds from different campaigns websites.",
"logoUrl": "http://i.imgur.com/uAyUiMN.png", "logoUrl": "http://i.imgur.com/uAyUiMN.png",
"imageUrl": "http://i.imgur.com/2Og5tqy.jpg", "imageUrl": "http://i.imgur.com/2Og5tqy.jpg",
"interestedCampers": [], "estimatedHours": 100,
"confirmedCampers": [], "currentStatus": "open",
"estimatedHours": 100 "moneySaved": 0
}, },
{ {
"id": "bd1325d8c461cbafaeb4bdef",
"whatDoesNonprofitDo": "We empower the community through improved literacy.", "whatDoesNonprofitDo": "We empower the community through improved literacy.",
"websiteLink": "http://www.tleliteracy.com/", "websiteLink": "http://www.tleliteracy.com/",
"stakeholderName": "Darlene Brown",
"stakeholderEmail": "string",
"name": "The Learning Exchange", "name": "The Learning Exchange",
"endUser": "string", "endUser": "Community members",
"approvedDeliverables": ["Website"], "approvedDeliverables": ["Website"],
"projectDescription": "Campers will build a simple website to replace essentialskillsquebec.com. Site will host many documents related to the Nine Essential Skills.", "projectDescription": "Campers will build a simple website to replace essentialskillsquebec.com. Site will host many documents related to the Nine Essential Skills.",
"logoUrl": "http://i.imgur.com/jXQY01H.png", "logoUrl": "http://i.imgur.com/jXQY01H.png",
"imageUrl": "http://i.imgur.com/iUXBpeL.jpg", "imageUrl": "http://i.imgur.com/iUXBpeL.jpg",
"interestedCampers": [], "estimatedHours": 100,
"confirmedCampers": [], "currentStatus": "started",
"estimatedHours": 100 "moneySaved": 0
},
{
"whatDoesNonprofitDo": "Options Inc. is an organization that was founded in 1979 to assist adults with disabilities in living and working in the community. We provide transportation to approximately 230 individuals.",
"websiteLink": "www.options-inc.org",
"name": "Options Inc.",
"endUser": "Administrators and Persons with Disabilities",
"approvedDeliverables": ["Web App"],
"projectDescription": "Campers will build a system to store all of Options Inc.'s clients addresses, optimize routes for our 23 vehicles, and schedule their staff for these routes.",
"logoUrl": "http://i.imgur.com/jGWRMuF.jpg",
"imageUrl": "http://i.imgur.com/VUuJJlM.jpg",
"estimatedHours": 300,
"currentStatus": "open",
"moneySaved": 0
},
{
"whatDoesNonprofitDo": "Our goal is to improve addiction treatment and recovery services through targeted outreach, policy development, and direct support services for addicts, their families and health professionals.",
"websiteLink": "http://www.taadas.org/",
"name": "Tennessee Association of Alcohol, Drug, and other Addiction Services",
"endUser": "Administrators and Persons with Disabilities",
"approvedDeliverables": ["Website"],
"projectDescription": "Campers will build a modern, mobile-responsive website.",
"logoUrl": "http://i.imgur.com/kYHgY0F.jpg",
"imageUrl": "http://i.imgur.com/W6L1sGV.jpg",
"estimatedHours": 100,
"currentStatus": "open",
"moneySaved": 0
} }
] ]

View File

@ -1,522 +0,0 @@
{
"name": "JSON APIs and Ajax",
"order": 0.0065,
"challenges": [
{
"id": "bad87fed1348bd9aeca08826",
"title": "Trigger on click Events with jQuery",
"description": [
"With jQuery we are able to get data from APIs via Ajax",
"This data normally comes in the form of JSON",
"Let's get the <code>Get Message</code> button to set the text of a div",
"We will later use this to display the result of out API request",
"<code>$(\"#getMessage\").on(\"click\", function(){</code>",
"<code>&thinsp;&thinsp;$(\".message\").html(\"Here is the message\");</code>",
"<code>});</code>"
],
"tests": [
"assert(editor.match(/\\$\\(\\s?\\\"\\#getMessage\\\"\\s?\\)\\.on\\s?\\(\\s?\\\"click\\\"\\,\\s?function\\s?\\(\\)\\s?\\{/gi), 'You should have bound the click event to the getMessage button')",
"assert(editor.match(/\\$\\(\\s?\\\"\\.message\\\"\\s?\\)\\.html\\(\\s?\\\"Here\\sis\\sthe\\smessage\\\"\\s?\\);/gi), 'You should set te value of the #message box to be the message given in the description')",
"assert(editor.match(/\\}\\);/gi) && editor.match(/\\}\\);/gi).length >= 2, 'Make sure that you close off all of your functions')"
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" ",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <br/>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well Message\">",
" The message will go here",
" </div>",
" </div>",
" <br/>",
" <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"
},
{
"id": "bad87fee1348bd9aebc08726",
"title": "Learn JSON Syntax",
"description": [
"JSON stands for \"JavaScript Object Notation\". It\"s how you create objects in JavaScript.",
"JSON is a series of \"key-value pairs\". Everything on the left of the colon (<code>:</code>) is the \"key\" you use to unlock the \"value\" on the right of the colon."
],
"tests": [
"assert(typeof data != \"undefined\", \"Whoops! It looks like you deleted the <code>data</code> variable!\");",
"assert(typeof getAnId != \"undefined\", \"Whoops! It looks like you deleted the <code>getAnId</code> function!\");",
"assert(data[0]['id'] === getAnId(), \"The duntion getFirstId should return the id of the first element in the array\");"
],
"challengeSeed": [
"fccss",
"var data = [",
" {",
" \"id\": 0,",
" \"imageLink\": \"http://rs611.pbsrc.com/albums/tt194/allypopper423/Funny-Cat-Green-Avacado.jpg~c200\",",
" \"codeNames\": [",
" \"Juggernaut\",",
" \"Mrs. Wallace\",",
" \"Buttercup\"",
" ]",
" },",
" {",
" \"id\": 1,",
" \"imageLink\": \"http://cdn.grumpycats.com/wp-content/uploads/2012/09/GC-Gravatar-copy.png\",",
" \"codeNames\": [",
" \"Oscar\",",
" \"Scrooge\",",
" \"Tyrion\"",
" ]",
" },",
" {",
" \"id\": 2,",
" \"imageLink\": \"http://www.kittenspet.com/wp-content/uploads/2012/08/cat_with_funny_face_3-200x200.jpg\",",
" \"codeNames\": [",
" \"The Doctor\",",
" \"Loki\",",
" \"Joker\"",
" ]",
" }",
"]",
"function getAnId(){",
" return();",
"}",
"fcces"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad87fee1348bd9aeca08826",
"title": "Displaying JSON data in HTML",
"description": [
"JSON stands for \"JavaScript Object Notation\". It\"s how you create objects in JavaScript.",
"JSON is a series of \"key-value pairs\". Everything on the left of the colon (<code>:</code>) is the \"key\" you use to unlock the \"value\" on the right of the colon."
],
"tests": [
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" $(\"#getMessage\").on(\"click\", function(){",
" $(\".message\").html(\"Here is the message\");",
" });",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class = \"row text-center\">",
" <h2>Cat Photo Finder</h2>",
" </div>",
" <br/>",
" <div class = \"row text-center\">",
" <div class = \"col-xs-12 well Message\">",
" The message will go here",
" </div>",
" </div>",
" <br/>",
" <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"
},
{
"id": "bad84fee1348bd9aecc48826",
"title": "Read Data from an Element Using jQuery",
"dashedName": "waypoint-read-data-from-an-element-using-jquery",
"description": [
"Let's make everything roll with <code>rollOut</code>."
],
"tests": [
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" $(\"button\").on(\"click\", function() {",
" $(\"#click-me\").addClass(\"animated shake\");",
" });",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class=\"row\">",
" <div class=\"col-xs-2\">",
" <input type=\"checkbox\" id=\"check-me\">",
" </div>",
" <div class=\"col-xs-10\">",
" <p>#check-me</p>",
" </div>",
" <button class=\"btn btn-block btn-primary\">#click-me</button>",
" <span>Is the checkbox checked?</span>",
" <span id=\"checked-state\"></span>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad84fee1348bd9aecc38826",
"title": "Read Data from an Element Using jQuery",
"dashedName": "waypoint-read-data-from-an-element-using-jquery",
"description": [
"Let's make everything roll with <code>rollOut</code>."
],
"tests": [
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" $(\"button\").on(\"click\", function() {",
" $(\"#click-me\").addClass(\"animated shake\");",
" $(\"#checked-state\").text(\"happy text\");",
" });",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class=\"row\">",
" <div class=\"col-xs-2\">",
" <input type=\"checkbox\" id=\"check-me\">",
" </div>",
" <div class=\"col-xs-10\">",
" <p>#check-me</p>",
" </div>",
" <button class=\"btn btn-block btn-primary\">#click-me</button>",
" <span>Is the checkbox checked?</span>",
" <span id=\"checked-state\"></span>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad84fee1348bd9aecc28826",
"title": "Read Data from an Element Using jQuery",
"dashedName": "waypoint-read-data-from-an-element-using-jquery",
"description": [
"Let's make everything roll with <code>rollOut</code>."
],
"tests": [
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" $(\"button\").on(\"click\", function() {",
" $(\"#click-me\").addClass(\"animated shake\");",
" $(\"#checked-state\").text($(\"#check-me\").prop(\"checked\"));",
" });",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class=\"row\">",
" <div class=\"col-xs-2\">",
" <input type=\"checkbox\" id=\"check-me\">",
" </div>",
" <div class=\"col-xs-10\">",
" <p>#check-me</p>",
" </div>",
" <button class=\"btn btn-block btn-primary\">#click-me</button>",
" <span>Is the checkbox checked?</span>",
" <span id=\"checked-state\"></span>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad84fee1348bd9aecc18826",
"title": "Read Data from an Element Using jQuery",
"dashedName": "waypoint-read-data-from-an-element-using-jquery",
"description": [
],
"tests": [
],
"challengeSeed": [
"fccss",
" $(document).ready(function() {",
" $(\"button\").on(\"click\", function() {",
" $(\"#click-me\").addClass(\"animated shake\");",
" $(\"#checked-state\").text($(\"#check-me\").prop(\"checked\"));",
" });",
" });",
"fcces",
"",
"<!-- You shouldn't need to modify code below this line -->",
"",
"<div class=\"container-fluid\">",
" <div class=\"row\">",
" <div class=\"col-xs-2\">",
" <input type=\"checkbox\" id=\"check-me\">",
" </div>",
" <div class=\"col-xs-10\">",
" <p>#check-me</p>",
" </div>",
" <button class=\"btn btn-block btn-primary\">#click-me</button>",
" <span>Is the checkbox checked?</span>",
" <span id=\"checked-state\"></span>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad87fee1348bd9aecc08826",
"title": "Trigger onHover Events with jQuery",
"dashedName": "waypoint-trigger-onhover-events-with-jquery",
"description": [
],
"tests": [
],
"challengeSeed": [
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad87fee1348bd9aebc08826",
"title": "Get Data from an URL Using jQuery",
"dashedName": "waypoint-get-data-from-a-url-using-jquery",
"description": [
],
"tests": [
],
"challengeSeed": [
"fccss",
"",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
"",
" });",
" });",
"",
" });",
"fcces",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad87fee1348bd9ae9c08826",
"title": "Loop through JSON Data Using jQuery",
"dashedName": "waypoint-loop-through-json-data-using-jquery",
"description": [
],
"tests": [
],
"challengeSeed": [
"fccss",
"",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
"",
" });",
" });",
"",
" });",
"fcces",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad88fee1348bd9ae8c08726",
"title": "Wire AJAX Call into a jQuery Click Event",
"dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event",
"description": [
"<img src=\"https://www.evernote.com/l/AjmAQ5BxGrFGRrWl_j2eSpGZMfrunfse89gB/image.png\">"
],
"tests": [
],
"challengeSeed": [
"fccss",
" var random = function() { return Math.floor(Math.random() * 3) }",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
"",
" });",
" });",
"",
" });",
"fcces",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad88fee1348bd9ae8c08626",
"title": "Wire AJAX Call into a jQuery Click Event",
"dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event",
"description": [
"<img src=\"https://www.evernote.com/l/AjmAQ5BxGrFGRrWl_j2eSpGZMfrunfse89gB/image.png\">"
],
"tests": [
],
"challengeSeed": [
"fccss",
" var random = function() { return Math.floor(Math.random() * 3) }",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
" var kitten = json[random()];",
" });",
" });",
"",
" });",
"fcces",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad88fee1348bd9ae8c08526",
"title": "Wire AJAX Call into a jQuery Click Event",
"dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event",
"description": [
"<img src=\"https://www.evernote.com/l/AjmAQ5BxGrFGRrWl_j2eSpGZMfrunfse89gB/image.png\">"
],
"tests": [
],
"challengeSeed": [
"fccss",
" var random = function() { return Math.floor(Math.random() * 3) }",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
" var kitten = json[random()];",
" $(\"<img src=\"\" + kitten.imageLink + \"\">\").appendTo(\"#output\");",
" });",
" });",
"",
" });",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
},
{
"id": "bad88fee1348bd9ae8c08426",
"title": "Wire AJAX Call into a jQuery Click Event",
"dashedName": "waypoint-wire-ajax-call-into-a-jquery-click-event",
"description": [
"<img src=\"https://www.evernote.com/l/AjmAQ5BxGrFGRrWl_j2eSpGZMfrunfse89gB/image.png\">"
],
"tests": [
],
"challengeSeed": [
"fccss",
" var random = function() { return Math.floor(Math.random() * 3) }",
" $(document).ready(function() {",
"",
" $(\"#cat-button\").on(\"click\", function() {",
" $.getJSON(\"/json/cats.json\", function( json ) {",
" var kitten = json[random()];",
" $(\"<img src=\"\" + kitten.imageLink + \"\">\").appendTo(\"#output\");",
" $(\"<h3>Code name: \" + kitten.codeNames[random()] + \"</h3>\").appendTo(\"#output\");",
" });",
" });",
"",
" });",
"fcces",
"<div class=\"container-fluid\">",
" <button id=\"cat-button\" class=\"btn btn-primary btn-block btn-lg\">#cat-button</button>",
" <div class=\"jumbotron\" id=\"output\">",
" </div>",
"</div>"
],
"challengeType": 0,
"type": "waypoint"
}
]
}

View File

@ -1,4 +1,4 @@
Everything to due with the server Everything to do with the server.
One file that is not tracked here is `rev-manifest.json`. One file that is not tracked here is `rev-manifest.json`.
It is generated at runtime and its contents changes as the contents It is generated at runtime and its contents changes as the contents

View File

@ -72,9 +72,9 @@ module.exports = function(app) {
'Feel free to email us at this address if you have ', 'Feel free to email us at this address if you have ',
'any questions about Free Code Camp.\n', 'any questions about Free Code Camp.\n',
'And if you have a moment, check out our blog: ', 'And if you have a moment, check out our blog: ',
'blog.freecodecamp.com.\n\n', 'medium.freecodecamp.com.\n\n',
'Good luck with the challenges!\n\n', 'Good luck with the challenges!\n\n',
'- the Free Code Camp Volunteer Team' '- the Free Code Camp Team'
].join('') ].join('')
}; };

View File

@ -64,23 +64,6 @@ module.exports = function(app) {
return res.redirect('../nonprofit/' + dashedNameFull); return res.redirect('../nonprofit/' + dashedNameFull);
} }
// We need to create logic that verifies completion.
// Defaulting to false for now.
// var buttonActive = false;
// if (
// req.user &&
// req.user.completedCoursewares.length > 63
// ) {
// var hasShownInterest =
// nonprofit.interestedCampers.filter(function(user) {
// return user.username === req.user.username;
// });
//
// if (hasShownInterest.length === 0) {
// buttonActive = true;
// }
// }
res.render('nonprofits/show', { res.render('nonprofits/show', {
dashedName: dashedNameFull, dashedName: dashedNameFull,
title: nonprofit.name, title: nonprofit.name,

View File

@ -12,13 +12,18 @@ var Rx = require('rx'),
validator = require('validator'), validator = require('validator'),
secrets = require('../../config/secrets'); secrets = require('../../config/secrets');
var foundationDate = 1413298800000; import {
var time48Hours = 172800000; ifNoUser401,
ifNoUserRedirectTo
} from '../utils/middleware';
var unDasherize = utils.unDasherize; const foundationDate = 1413298800000;
var dasherize = utils.dasherize; const time48Hours = 172800000;
var getURLTitle = utils.getURLTitle;
var ifNoUser401 = require('../utils/middleware').ifNoUser401; const unDasherize = utils.unDasherize;
const dasherize = utils.dasherize;
const getURLTitle = utils.getURLTitle;
const sendNonUserToNews = ifNoUserRedirectTo('/news');
function hotRank(timeValue, rank) { function hotRank(timeValue, rank) {
/* /*
@ -62,8 +67,16 @@ module.exports = function(app) {
router.get('/news/hot', hotJSON); router.get('/news/hot', hotJSON);
router.get('/stories/hotStories', hotJSON); router.get('/stories/hotStories', hotJSON);
router.get('/stories/submit', submitNew); router.get(
router.get('/stories/submit/new-story', preSubmit); '/stories/submit',
sendNonUserToNews,
submitNew
);
router.get(
'/stories/submit/new-story',
sendNonUserToNews,
preSubmit
);
router.post('/stories/preliminary', ifNoUser401, newStory); router.post('/stories/preliminary', ifNoUser401, newStory);
router.post('/stories/', ifNoUser401, storySubmission); router.post('/stories/', ifNoUser401, storySubmission);
router.get('/news/', hot); router.get('/news/', hot);
@ -102,17 +115,25 @@ module.exports = function(app) {
} }
function submitNew(req, res) { function submitNew(req, res) {
if (!req.user.isGithubCool) {
req.flash('errors', {
msg: 'You must link GitHub with your account before you can post' +
' on Camper News.'
});
return res.redirect('/news');
}
return res.render('stories/index', { return res.render('stories/index', {
title: 'Submit a new story to Camper News', title: 'Submit a new story to Camper News',
page: 'submit' page: 'submit'
}); });
} }
function preSubmit(req, res, next) { function preSubmit(req, res) {
var data = req.query; var data = req.query;
if (typeof data.url !== 'string') { if (typeof data.url !== 'string') {
req.flash('errors', { msg: 'No URL supplied with story' }); req.flash('errors', { msg: 'No URL supplied with story' });
return next(new TypeError('No URL supplied with story')); return res.redirect('/news');
} }
var cleanedData = cleanData(data.url); var cleanedData = cleanData(data.url);
@ -264,8 +285,11 @@ module.exports = function(app) {
} }
function newStory(req, res, next) { function newStory(req, res, next) {
if (!req.user) { if (!req.user.isGithubCool) {
return next(new Error('Must be logged in')); req.flash('errors', {
msg: 'You must authenticate with Github to post to Camper News'
});
return res.redirect('/news');
} }
var url = req.body.data.url; var url = req.body.data.url;

View File

@ -20,14 +20,17 @@ block content
.spacer .spacer
if (user && user.progressTimestamps.length > 5) if (user && user.progressTimestamps.length > 5)
#tshirt-notice.col-xs-12.col-md-8.col-md-offset-2.hidden #tshirt-notice.col-xs-12.col-md-8.col-md-offset-2.hidden
h2.text-center Get our first-edition t-shirt 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") 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; 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(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 a.button.btn.btn-block.signup-btn(href="https://teespring.com/get-free-code-camp-t-shirt" target="_blank") Get yours
.button-spacer .button-spacer
#hideTshirtNoticeButton.button.btn.btn-block.btn-info Hide this forever .text-center
a#hideTshirtNoticeButton(href='#') Hide this forever
.spacer .spacer
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2 .col-xs-12.col-sm-8.col-sm-offset-2
@ -122,7 +125,7 @@ block content
.button-spacer .button-spacer
.row .row
.col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden
a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends. a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your code portfolio with your friends.
.hidden(id="#{challengeBlock.name}") .hidden(id="#{challengeBlock.name}")
script. script.
var username = !{JSON.stringify(user && user.username || '')}; var username = !{JSON.stringify(user && user.username || '')};

View File

@ -1,12 +1,12 @@
extends ../layout-wide extends ../layout-wide
block content block content
script(type='text/javascript', src='/bower_components/jshint/dist/jshint.js')
script(type='text/javascript', src='/js/lib/codemirror/lib/codemirror.js') script(type='text/javascript', src='/js/lib/codemirror/lib/codemirror.js')
script(type='text/javascript', src='/js/lib/codemirror/addon/edit/closebrackets.js') script(type='text/javascript', src='/js/lib/codemirror/addon/edit/closebrackets.js')
script(type='text/javascript', src='/js/lib/codemirror/addon/edit/matchbrackets.js') script(type='text/javascript', src='/js/lib/codemirror/addon/edit/matchbrackets.js')
script(type='text/javascript', src='/js/lib/codemirror/addon/lint/lint.js') script(type='text/javascript', src='/js/lib/codemirror/addon/lint/lint.js')
script(type='text/javascript', src='/js/lib/codemirror/addon/lint/javascript-lint.js') script(type='text/javascript', src='/js/lib/codemirror/addon/lint/javascript-lint.js')
script(type='text/javascript', src='/bower_components/jshint/dist/jshint.js')
script(type='text/javascript', src='/js/lib/chai/chai.js') script(type='text/javascript', src='/js/lib/chai/chai.js')
link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css')
link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css')
@ -88,8 +88,6 @@ block content
.form-group.codeMirrorView .form-group.codeMirrorView
textarea#codeEditor(autofocus=true, style='display: none;') textarea#codeEditor(autofocus=true, style='display: none;')
script(src=rev('/js', 'commonFramework.js')) script(src=rev('/js', 'commonFramework.js'))
script.
editor.setOption("mode", "javascript");
#complete-courseware-dialog.modal(tabindex='-1') #complete-courseware-dialog.modal(tabindex='-1')
.modal-dialog.animated.fadeIn.fast-animation .modal-dialog.animated.fadeIn.fast-animation

View File

@ -76,6 +76,7 @@ block content
textarea#codeEditor(autofocus=true, style='display: none;') textarea#codeEditor(autofocus=true, style='display: none;')
script(src=rev('/js', 'commonFramework.js')) script(src=rev('/js', 'commonFramework.js'))
script. script.
editor.setOption('lint', false);
editor.setOption("mode", "text/html"); editor.setOption("mode", "text/html");
.col-md-4.col-lg-3 .col-md-4.col-lg-3
.hidden-xs.hidden-sm .hidden-xs.hidden-sm

View File

@ -24,7 +24,7 @@ block content
.big-break .big-break
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2 .col-xs-12.col-sm-8.col-sm-offset-2
a.btn.btn-cta.signup-btn.btn-block(href="/login") Start learning to code (it's free) a.btn.btn-cta.signup-btn.btn-block(href="/signin") Start learning to code (it's free)
.button-spacer .button-spacer
a.btn.btn-cta.btn-success.btn-block(href="/nonprofits") My nonprofit needs coding help a.btn.btn-cta.btn-success.btn-block(href="/nonprofits") My nonprofit needs coding help
h2 As featured in: h2 As featured in:
@ -91,6 +91,6 @@ block content
.big-break .big-break
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2 .col-xs-12.col-sm-8.col-sm-offset-2
a.btn.btn-cta.signup-btn.btn-block(href="/login") Learn to code today (it's free) a.btn.btn-cta.signup-btn.btn-block(href="/signin") Learn to code today (it's free)
script. script.
challengeName = 'Home' challengeName = 'Home'

View File

@ -1,25 +1,25 @@
.fcc-footer .fcc-footer
.col-xs-12.hidden-xs.hidden-sm .col-xs-12.hidden-xs.hidden-sm
a.ion-speakerphone(href='http://blog.freecodecamp.com', target='_blank') &nbsp;Blog&nbsp;&nbsp; a.ion-speakerphone(href='//medium.freecodecamp.com', target='_blank') &nbsp;Blog&nbsp;&nbsp;
a.ion-social-github(href="http://github.com/freecodecamp", target='_blank') &nbsp;GitHub&nbsp;&nbsp; a.ion-social-github(href="//github.com/freecodecamp", target='_blank') &nbsp;GitHub&nbsp;&nbsp;
a.ion-social-twitch-outline(href="/twitch") &thinsp;Twitch&nbsp; a.ion-social-linkedin(href="//www.linkedin.com/edu/school?id=166029", target='_blank') &thinsp;LinkedIn&nbsp;
a.ion-social-linkedin(href="https://www.linkedin.com/edu/school?id=166029", target='_blank') &thinsp;LinkedIn&nbsp; a.ion-social-twitter(href="//twitter.com/freecodecamp", target='_blank') &nbsp;Twitter&nbsp;&nbsp;
a.ion-social-facebook(href="//facebook.com/freecodecamp") &nbsp;Facebook&nbsp;&nbsp; a.ion-social-facebook(href="//facebook.com/freecodecamp") &nbsp;Facebook&nbsp;&nbsp;
a.ion-social-twitter(href="http://twitter.com/freecodecamp", target='_blank') &nbsp;Twitter&nbsp;&nbsp; a.ion-social-twitch-outline(href="//twitch.tv/freecodecamp", target='_blank') &thinsp;Twitch&nbsp;
a.ion-locked(href="//github.com/FreeCodeCamp/freecodecamp/wiki/Free-Code-Camp's-Privacy-Policy") &nbsp;Privacy&nbsp;&nbsp; a.ion-locked(href="//github.com/FreeCodeCamp/freecodecamp/wiki/Free-Code-Camp's-Privacy-Policy") &nbsp;Privacy&nbsp;&nbsp;
.col-xs-12.visible-xs.visible-sm .col-xs-12.visible-xs.visible-sm
a.ion-speakerphone(href='http://blog.freecodecamp.com', target='_blank') a.ion-speakerphone(href='//medium.freecodecamp.com', target='_blank')
span.sr-only Free Code Camp's Blog span.sr-only Free Code Camp's Blog
a.ion-social-github(href="http://github.com/freecodecamp", target='_blank') a.ion-social-github(href="//github.com/freecodecamp", target='_blank')
span.sr-only Free Code Camp on GitHub span.sr-only Free Code Camp on GitHub
a.ion-social-twitch-outline(href="/twitch") a.ion-social-linkedin(href="//www.linkedin.com/edu/school?id=166029", target='_blank')
span.sr-only Free Code Camp Live Pair Programming on Twitch.tv
a.ion-social-linkedin(href="https://www.linkedin.com/edu/school?id=166029", target='_blank')
span.sr-only Free Code Camp LinkedIn Alumni Network span.sr-only Free Code Camp LinkedIn Alumni Network
a.ion-social-facebook(href="//facebook.com/freecodecamp") a.ion-social-twitter(href="//twitter.com/freecodecamp", target='_blank')
span.sr-only Free Code Camp local groups on Facebook
a.ion-social-twitter(href="http://twitter.com/freecodecamp", target='_blank')
span.sr-only Free Code Camp on Twitter span.sr-only Free Code Camp on Twitter
a.ion-social-facebook(href="//facebook.com/freecodecamp", target='_blank')
span.sr-only Free Code Camp local groups on Facebook
a.ion-social-twitch-outline(href="/twitch", target='_blank')
span.sr-only Free Code Camp Live Pair Programming on Twitch.tv
a.ion-locked(href="//github.com/FreeCodeCamp/freecodecamp/wiki/Free-Code-Camp's-Privacy-Policy") a.ion-locked(href="//github.com/FreeCodeCamp/freecodecamp/wiki/Free-Code-Camp's-Privacy-Policy")
span.sr-only Free Code Camp's Privacy Policy span.sr-only Free Code Camp's Privacy Policy

View File

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

View File

@ -60,7 +60,7 @@ script.
"<div class='visible-xs row'>" + "<div class='visible-xs row'>" +
"<div class='visible-xs col-sm-1 col-md-1'>" + "<div class='visible-xs col-sm-1 col-md-1'>" +
"<a href='" + data[i].link + "'>" + "<a href='" + data[i].link + "'>" +
"<img class='mobile-story-image img-responsive' src='" + data[i].author.picture + "'/>" + "<img class='mobile-story-image img-responsive' src='" + (!!data[i].image ? data[i].image : data[i].author.picture) + "'/>" +
"</a>" + "</a>" +
"</div>" + "</div>" +
"<div class='col-xs-12 mobile-story-headline text-center'>" + "<div class='col-xs-12 mobile-story-headline text-center'>" +
@ -76,6 +76,10 @@ script.
"<a href='/" + data[i].author.username + "'>@" + data[i].author.username + "<a href='/" + data[i].author.username + "'>@" + data[i].author.username +
"</a> " + "</a> " +
"</div>" + "</div>" +
"<div class='col-xs-12'>" +
"<br>" +
"<a class='btn btn-no-shadow btn-primary btn-block btn-primary-ghost' href='/news/" + linkedName + "'>more info</a>" +
"</div>" +
"</div>" + "</div>" +
"</div>" + "</div>" +
"<div class='hidden-xs row media-stories'>" + "<div class='hidden-xs row media-stories'>" +
@ -93,6 +97,7 @@ script.
"</a>" + "</a>" +
"</div>" + "</div>" +
"<div class='story-byline col-xs-12 wrappable'>" + "<div class='story-byline col-xs-12 wrappable'>" +
"<a class='btn btn-no-shadow btn-primary btn-xs btn-primary-ghost' href='/news/" + linkedName + "'>more info</a> · " +
rank + (rank > 1 ? " points" : " point") + " · posted " + rank + (rank > 1 ? " points" : " point") + " · posted " +
moment(data[i].timePosted).fromNow() + moment(data[i].timePosted).fromNow() +
" by <a href='/" + data[i].author.username + "'>@" + data[i].author.username + " by <a href='/" + data[i].author.username + "'>@" + data[i].author.username +