diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..ba4e245107
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,2 @@
+We're getting a lot of duplicate issues and bug reports that just aren't reporting actual bugs.
+So, before you submit your issue, please read the [Help I've Found a Bug](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Help-I've-Found-a-Bug) wiki page.
diff --git a/README.md b/README.md
index d62477d7bd..dba5013540 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,8 @@ bower install
# Create a .env file and populate it with the necessary API keys and secrets:
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.
@@ -112,6 +114,11 @@ DEBUG=true
# Start the mongo server
mongod
+# Create your mongo database.
+# Type "mongo" in your terminal to access the mongo shell
+use freecodecamp
+# Exit the mongo shell with control + d
+
# Seed your database with the challenges
node seed/
diff --git a/common/models/User-Identity.js b/common/models/User-Identity.js
index 3b1bcb8750..a6c5241043 100644
--- a/common/models/User-Identity.js
+++ b/common/models/User-Identity.js
@@ -4,12 +4,13 @@ import debugFactory from 'debug';
import {
setProfileFromGithub,
getFirstImageFromProfile,
+ getUsernameFromProvider,
getSocialProvider
} from '../../server/utils/auth';
-const debug = debugFactory('freecc:models:userIdent');
-
const { defaultProfileImage } = require('../utils/constantStrings.json');
+const githubRegex = (/github/i);
+const debug = debugFactory('freecc:models:userIdent');
function createAccessToken(user, ttl, cb) {
if (arguments.length === 2 && typeof ttl === 'function') {
@@ -158,14 +159,13 @@ export default function(UserIdent) {
userChanged = true;
}
- if (!(/github/).test(provider) && profile) {
- debug('setting social', provider, (/github/g).test(provider));
- debug('profile username', profile.username);
- user[provider] = profile.username;
+ if (!githubRegex.test(provider) && profile) {
+ user[provider] = getUsernameFromProvider(provider, profile);
+ userChanged = true;
}
// if user signed in with github refresh their info
- if (/github/.test(provider) && profile && profile._json) {
+ if (githubRegex.test(provider) && profile && profile._json) {
debug("user isn't github cool or username from github is different");
setProfileFromGithub(user, profile, profile._json);
userChanged = true;
diff --git a/gulpfile.js b/gulpfile.js
index 8e1e345716..9cfded3db8 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -19,10 +19,12 @@ var Rx = require('rx'),
sync = require('browser-sync'),
inject = require('gulp-inject'),
+
// css
less = require('gulp-less'),
// lint
+ jsonlint = require('gulp-jsonlint'),
eslint = require('gulp-eslint');
@@ -60,6 +62,11 @@ var paths = {
syncWatch: [
'public/**/*.*'
+ ],
+
+ challenges: [
+ 'seed/challenges/*.json',
+ 'seed/under-construction/*.json'
]
};
@@ -163,12 +170,20 @@ gulp.task('sync', ['serve'], function() {
});
});
-gulp.task('lint', function() {
+gulp.task('lint-js', function() {
return gulp.src(['public/js/lib/**/*'])
.pipe(eslint())
.pipe(eslint.format());
});
+gulp.task('lint-json', function() {
+ return gulp.src(paths.challenges)
+ .pipe(jsonlint())
+ .pipe(jsonlint.reporter());
+});
+
+gulp.task('test-challenges', ['lint-json']);
+
gulp.task('less', function() {
return gulp.src('./public/css/*.less')
.pipe(plumber({ errorHandler: errorHandler }))
@@ -182,6 +197,7 @@ gulp.task('build', ['less']);
gulp.task('watch', ['less', 'serve', 'sync'], function() {
gulp.watch('./public/css/*.less', ['less']);
+ gulp.watch(paths.challenges, ['test-challenges']);
});
gulp.task('default', ['less', 'serve', 'sync', 'watch', 'pack-watch']);
diff --git a/package.json b/package.json
index c4d4b81528..8aa3c12d40 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,7 @@
"lodash": "^3.9.3",
"loopback": "https://github.com/FreeCodeCamp/loopback.git#fix/no-password",
"loopback-boot": "^2.8.0",
- "loopback-component-passport": "^1.5.0",
+ "loopback-component-passport": "https://github.com/FreeCodeCamp/loopback-component-passport.git#feature/flashfailure",
"loopback-connector-mongodb": "^1.10.0",
"lusca": "~1.0.2",
"method-override": "~2.3.0",
@@ -120,6 +120,7 @@
"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",
diff --git a/public/css/main.less b/public/css/main.less
index 82dec41a83..45cd2daed4 100644
--- a/public/css/main.less
+++ b/public/css/main.less
@@ -262,6 +262,10 @@ ul {
font-size: 24px;
}
+.capitalize {
+ text-transform: capitalize;
+}
+
.text-success {
color: @brand-success;
}
@@ -679,9 +683,9 @@ thead {
margin-right: 0px;
padding-left: 10px;
padding-right: 10px;
+ padding-top: 14px;
+ padding-bottom: 12px;
&:hover {
- padding-top: 14px;
- padding-bottom: 14px;
color: #4a2b0f;
background-color: #eee;
text-decoration: none;
diff --git a/public/js/calculator.js b/public/js/calculator.js
index 207611c9e6..9ae06e890a 100644
--- a/public/js/calculator.js
+++ b/public/js/calculator.js
@@ -28,7 +28,7 @@ $(document).ready(function () {
$('#chosen').text('Coming from ' + city.replace(/-/g, ' ').replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}) + ', and making $' + lastYearsIncome.toString().replace(/0000$/, '0,000') + ', your true costs will be:');
- var categoryNames = ['Lost Wages', 'Financing Cost', 'Housing Cost', 'Tuition / Wage Garnishing'];
+ var categoryNames = ['Lost Wages', 'Financing Cost', 'Housing Cost', 'Tuition / Est. Wage Garnishing'];
bootcamps.forEach(function (camp) {
var x0 = 0;
if (camp.cities.indexOf(city) > -1) {
@@ -38,7 +38,7 @@ $(document).ready(function () {
}
camp.mapping = [{
name: camp.name,
- label: 'Tuition / Wage Garnishing',
+ label: 'Tuition / Est. Wage Garnishing',
value: +camp.cost,
x0: x0,
x1: x0 += +camp.cost
diff --git a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js
index 6b004bafe6..89dc0d9dd6 100644
--- a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js
+++ b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js
@@ -198,7 +198,7 @@ codeStorage.isAlive = function() {
return val !== 'null' &&
val !== 'undefined' &&
(val && val.length > 0);
-}
+};
codeStorage.updateStorage = function(){
if(typeof(Storage) !== undefined) {
var value = editor.getValue();
@@ -252,14 +252,18 @@ var allSeeds = '';
editorValue = (codeStorage.isAlive())? codeStorage.getEditorValue() : allSeeds;
-editor.setValue(editorValue);
+editor.setValue(editorValue.replace((/fccss/gi), ''));
+editor.refresh();
var resetEditor = function resetEditor() {
- editor.setValue(allSeeds);
+ editor.setValue(allSeeds.replace((/fccss/gi), ''));
updatePreview();
codeStorage.updateStorage();
};
+
+
+/*
var challengeSeed = challengeSeed || null;
var allSeeds = '';
(function() {
@@ -273,3 +277,4 @@ var allSeeds = '';
}, 200);
})();
})();
+*/
diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js
index 712811c9c1..ddeb9519f4 100644
--- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js
+++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js
@@ -388,3 +388,7 @@ var resetEditor = function resetEditor() {
editor.setValue(allSeeds);
codeStorage.updateStorage();
};
+
+$(document).ready(function(){
+ bonfireExecute();
+});
diff --git a/public/js/main_0.0.3.js b/public/js/main_0.0.3.js
index 3bafc6c8c9..8a72664bbf 100644
--- a/public/js/main_0.0.3.js
+++ b/public/js/main_0.0.3.js
@@ -22,67 +22,6 @@ $(document).ready(function() {
setCSRFToken($('meta[name="csrf-token"]').attr('content'));
- $('#i-want-help').on('click', function() {
- $('#help-modal').modal('hide');
- var editorValue = editor.getValue();
- var currentLocation = window.location.href;
- $.post(
- '/get-help',
- {
- payload: {
- code: editorValue,
- challenge: currentLocation
- }
- },
- function(res) {
- if (res) {
- window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
- }
- }
- );
- });
-
- $('#i-want-help-editorless').on('click', function() {
- $('#help-editorless-modal').modal('hide');
- var currentLocation = window.location.href;
- $.post(
- '/get-help',
- {
- payload: {
- challenge: currentLocation
- }
- },
- function(res) {
- if (res) {
- window.open('https://gitter.im/FreeCodeCamp/Help', '_blank')
- }
- }
- );
- });
-
- $('#report-issue').on('click', function() {
- $('#issue-modal').modal('hide');
- window.open('https://github.com/freecodecamp/freecodecamp/issues/new?&body=Challenge '+ window.location.href +' has an issue. Please describe how to reproduce it, and include links to screenshots if possible.', '_blank')
- });
-
- $('#i-want-to-pair').on('click', function() {
- $('#pair-modal').modal('hide');
- var currentLocation = window.location.href;
- $.post(
- '/get-pair',
- {
- payload: {
- challenge: currentLocation
- }
- },
- function(res) {
- if (res) {
- window.open('https://gitter.im/FreeCodeCamp/LetsPair', '_blank')
- }
- }
- );
- });
-
$('.checklist-element').each(function() {
var checklistElementId = $(this).attr('id');
if(!!localStorage[checklistElementId]) {
@@ -118,41 +57,155 @@ $(document).ready(function() {
$(this).unbind("error").attr("src", "https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png");
});
- $('#completed-courseware').on('click', function() {
- $('#complete-courseware-dialog').modal('show');
- });
+ function reBindModals(){
- $('#completed-courseware-editorless').on('click', function() {
- $('#complete-courseware-editorless-dialog').modal('show');
- });
+ $('.close-modal').unbind('click');
+ $('.close-modal').on('click', function(){
+ setTimeout(function() {
+ $('.close-modal').parent().parent().parent().parent().modal('hide');
+ }, 200);
+ });
- $('#trigger-pair-modal').on('click', function() {
- $('#pair-modal').modal('show');
- });
+ $('#report-issue').unbind('click');
+ $('#report-issue').on('click', function() {
+ $('#issue-modal').modal('hide');
+ window.open('https://github.com/freecodecamp/freecodecamp/issues/new?&body=Challenge '+ window.location.href +' has an issue. Please describe how to reproduce it, and include links to screenshots if possible.', '_blank')
+ });
- $('#trigger-reset-modal').on('click', function() {
- $('#reset-modal').modal('show');
- });
+ $('#completed-courseware').unbind('click');
+ $('#completed-courseware').on('click', function() {
+ $('#complete-courseware-dialog').modal('show');
+ });
- $('#trigger-help-modal').on('click', function() {
- $('#help-modal').modal('show');
- });
+ $('#completed-courseware-editorless').unbind('click');
+ $('#completed-courseware-editorless').on('click', function() {
+ $('#complete-courseware-editorless-dialog').modal('show');
+ });
- $('#trigger-issue-modal').on('click', function() {
- $('#issue-modal').modal('show');
- });
+ $('#trigger-pair-modal').unbind('click');
+ $('#trigger-pair-modal').on('click', function() {
+ $('#pair-modal').modal('show');
+ });
- $('#completed-zipline-or-basejump').on('click', function() {
- $('#complete-zipline-or-basejump-dialog').modal('show');
- });
+ $('#trigger-reset-modal').unbind('click');
+ $('#trigger-reset-modal').on('click', function() {
+ $('#reset-modal').modal('show');
+ });
- $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
- editor.focus();
- });
+ $('#trigger-help-modal').unbind('click');
+ $('#trigger-help-modal').on('click', function() {
+ $('#help-modal').modal('show');
+ });
- $('#complete-challenge-dialog').on('hidden.bs.modal', function() {
- editor.focus();
- });
+ $('#trigger-issue-modal').unbind('click');
+ $('#trigger-issue-modal').on('click', function() {
+ $('#issue-modal').modal('show');
+ });
+
+ $('#completed-zipline-or-basejump').unbind('click');
+ $('#completed-zipline-or-basejump').on('click', function() {
+ $('#complete-zipline-or-basejump-dialog').modal('show');
+ });
+
+ $('#next-courseware-button').unbind('click');
+ $('#next-courseware-button').on('click', function() {
+ $('#next-courseware-button').unbind('click');
+ if ($('.signup-btn-nav').length < 1) {
+ switch (challengeType) {
+ case challengeTypes.HTML_CSS_JQ:
+ case challengeTypes.JAVASCRIPT:
+ case challengeTypes.VIDEO:
+ $.post(
+ '/completed-challenge/',
+ {
+ challengeInfo: {
+ challengeId: challenge_Id,
+ challengeName: challenge_Name
+ }
+ }).success(
+ function(res) {
+ if (res) {
+ window.location.href = '/challenges/next-challenge';
+ }
+ }).fail(
+ function() {
+ window.location.href="/challenges";
+ }
+ );
+ break;
+ case challengeTypes.ZIPLINE:
+ var didCompleteWith = $('#completed-with').val() || null;
+ var publicURL = $('#public-url').val() || null;
+ $.post(
+ '/completed-zipline-or-basejump/',
+ {
+ challengeInfo: {
+ challengeId: challenge_Id,
+ challengeName: challenge_Name,
+ completedWith: didCompleteWith,
+ publicURL: publicURL,
+ challengeType: challengeType
+ }
+ }).success(
+ function() {
+ window.location.href = '/challenges/next-challenge';
+ }).fail(
+ function() {
+ window.location.href = '/challenges';
+ });
+ break;
+ case challengeTypes.BASEJUMP:
+ var didCompleteWith = $('#completed-with').val() || null;
+ var publicURL = $('#public-url').val() || null;
+ var githubURL = $('#github-url').val() || null;
+ $.post(
+ '/completed-zipline-or-basejump/',
+ {
+ challengeInfo: {
+ challengeId: challenge_Id,
+ challengeName: challenge_Name,
+ completedWith: didCompleteWith,
+ publicURL: publicURL,
+ githubURL: githubURL,
+ challengeType: challengeType,
+ verified: false
+ }
+ }).success(function() {
+ window.location.href = '/challenges/next-challenge';
+ }).fail(function() {
+ window.location.replace(window.location.href);
+ });
+ break;
+ case challengeTypes.BONFIRE:
+ window.location.href = '/challenges/next-challenge';
+ default:
+ break;
+ }
+ }
+ });
+
+ $('.next-challenge-button').unbind('click');
+ $('.next-challenge-button').on('click', function() {
+ l = location.pathname.split('/');
+ window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
+ });
+
+ $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
+ editor.focus();
+ });
+
+ $('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
+ editor.focus();
+ });
+ };
+
+
+
+ $(window).resize(function(){
+ reBindModals();
+ });
+
+ reBindModals();
var challengeTypes = {
'HTML_CSS_JQ': '0',
@@ -162,98 +215,6 @@ $(document).ready(function() {
'BASEJUMP': '4',
'BONFIRE': '5'
};
- $('#next-courseware-button').on('click', function() {
- $('#next-courseware-button').unbind('click');
- if ($('.signup-btn-nav').length < 1) {
- switch (challengeType) {
- case challengeTypes.HTML_CSS_JQ:
- case challengeTypes.JAVASCRIPT:
- case challengeTypes.VIDEO:
- $.post(
- '/completed-challenge/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name
- }
- }).success(
- function(res) {
- if (res) {
- window.location.href = '/challenges/next-challenge';
- }
- }).fail(
- function() {
- window.location.href="/challenges";
- }
- );
- break;
- case challengeTypes.ZIPLINE:
- var didCompleteWith = $('#completed-with').val() || null;
- var publicURL = $('#public-url').val() || null;
- $.post(
- '/completed-zipline-or-basejump/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name,
- completedWith: didCompleteWith,
- publicURL: publicURL,
- challengeType: challengeType
- }
- }).success(
- function() {
- window.location.href = '/challenges/next-challenge';
- }).fail(
- function() {
- window.location.href = '/challenges';
- });
- break;
- case challengeTypes.BASEJUMP:
- var didCompleteWith = $('#completed-with').val() || null;
- var publicURL = $('#public-url').val() || null;
- var githubURL = $('#github-url').val() || null;
- $.post(
- '/completed-zipline-or-basejump/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name,
- completedWith: didCompleteWith,
- publicURL: publicURL,
- githubURL: githubURL,
- challengeType: challengeType,
- verified: false
- }
- }).success(function() {
- window.location.href = '/challenges/next-challenge';
- }).fail(function() {
- window.location.replace(window.location.href);
- });
- break;
- case challengeTypes.BONFIRE:
- window.location.href = '/challenges/next-challenge';
- default:
- break;
- }
- }
- });
-
- $('.next-challenge-button').on('click', function() {
- l = location.pathname.split('/');
- window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
- });
-
- // Bonfire instructions functions
- $('#more-info').on('click', function() {
- ga('send', 'event', 'Challenge', 'more-info', challengeName);
- $('#brief-instructions').hide();
- $('#long-instructions').show().removeClass('hide');
-
- });
- $('#less-info').on('click', function() {
- $('#brief-instructions').show();
- $('#long-instructions').hide();
- });
function upvoteHandler(e) {
e.preventDefault();
@@ -356,6 +317,21 @@ $(document).ready(function() {
lockTop();
});
}
+ var execInProgress = false;
+ document.getElementById('scroll-locker').addEventListener('previewUpdateSpy', function(e){
+ if (!execInProgress){
+ execInProgress = true;
+ setTimeout(function(){
+ if($($('.scroll-locker').children()[0]).height()-800 > e.detail){
+ $('.scroll-locker').scrollTop(e.detail);
+ }
+ else {
+ $('.scroll-locker').animate({"scrollTop":$($('.scroll-locker').children()[0]).height()}, 175);
+ }
+ execInProgress = false;
+ }, 750);
+ }
+ }, false);
}
});
diff --git a/public/json/bootcamps.json b/public/json/bootcamps.json
index 41b906c20b..19b016607c 100644
--- a/public/json/bootcamps.json
+++ b/public/json/bootcamps.json
@@ -221,7 +221,28 @@
"cities": [
"portland"
]
-}, {
+},
+ {
+ "name": "Viking Code School",
+ "cost": "18000",
+ "housing": "0",
+ "finance": false,
+ "weeks": "16",
+ "cities": [
+ "online"
+ ]
+ },
+ {
+ "name": "App Academy",
+ "cost": "18000",
+ "housing": "500",
+ "finance": false,
+ "weeks": "12",
+ "cities": [
+ "san-francisco"
+ ]
+ },
+ {
"name": "Turing School",
"cost": "17500",
"housing": "400",
@@ -230,13 +251,4 @@
"cities": [
"denver"
]
-}, {
- "name": "Free Code Camp",
- "cost": "0",
- "housing": "0",
- "finance": false,
- "weeks": "0",
- "cities": [
- "online"
- ]
}]
diff --git a/seed/challenges/automated-testing-and-debugging.json b/seed/challenges/automated-testing-and-debugging.json
index a62368eee0..9cf677a024 100644
--- a/seed/challenges/automated-testing-and-debugging.json
+++ b/seed/challenges/automated-testing-and-debugging.json
@@ -20,7 +20,8 @@
"",
""
],
- "challengeType":1
+ "challengeType":1,
+ "type": "waypoint"
},
{
"id":"cf1111c1c16feddfaeb7bdef",
@@ -46,7 +47,8 @@
"",
""
],
- "challengeType":1
+ "challengeType":1,
+ "type": "waypoint"
}
]
}
diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json
index 6f1cf7b9d4..539ce1d349 100644
--- a/seed/challenges/basic-bonfires.json
+++ b/seed/challenges/basic-bonfires.json
@@ -461,8 +461,8 @@
],
"tests": [
"assert.deepEqual(slasher([1, 2, 3], 2), [3], 'should drop the first two elements');",
- "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'should return all elements when n < 1');",
- "assert.deepEqual(slasher([1, 2, 3], 9), [], 'should return an empty array when n >= array.length');"
+ "assert.deepEqual(slasher([1, 2, 3], 0), [1, 2, 3], 'should return all elements');",
+ "assert.deepEqual(slasher([1, 2, 3], 9), [], 'should return an empty array');"
],
"MDNlinks": [
"Array.slice()",
@@ -506,7 +506,8 @@
"expect(mutation(['Mary', 'Army'])).to.be.true;",
"expect(mutation(['Mary', 'Aarmy'])).to.be.true;",
"expect(mutation(['Alien', 'line'])).to.be.true;",
- "expect(mutation(['floor', 'for'])).to.be.true;"
+ "expect(mutation(['floor', 'for'])).to.be.true;",
+ "expect(mutation(['hello', 'neo'])).to.be.false;"
],
"MDNlinks": [
"Array.indexOf()"
diff --git a/seed/challenges/basic-javascript.json b/seed/challenges/basic-javascript.json
index e68d4ec46d..dbc5eed779 100644
--- a/seed/challenges/basic-javascript.json
+++ b/seed/challenges/basic-javascript.json
@@ -13,7 +13,8 @@
" Click here for cat photos. Things cats love:// This is a comment.
",
"The slash-star-star-slash comment will comment out everything between the /*
and the */
characters:",
"/* This is also a comment */
",
- "Try creating one of each."
+ "Try creating one of each.",
+ "And one more thing you need to notice. Starting at this waypoint in JavaScript related challenges (except AngularJS, all Ziplines, Git, Node.js and Express.js, MongoDB and Full Stack JavaScript Projects) you can see contents of assert()
functions (in some challenges except()
, assert.equal()
and so on) which are used to test your code. It's part of these challenges that you are able to see the tests that are running against your code."
],
"tests":[
"assert(editor.getValue().match(/(\\/\\/)...../g), 'Create a \\/\\/
style comment that contains at least five letters');",
@@ -113,7 +114,7 @@
"description": [
"data structures
have properties
. For example, strings
have a property called .length
that will tell you how many characters are in the string.",
"For example, if we created a variable var firstName = \"Charles\"
, we could find out how long the string \"Charles\" is by using the firstName.length
property.",
- "Use the .length
property to count the number of characters in the lastNameLength
variable."
+ "Use the .length
property to count the number of characters in the lastName
variable."
],
"tests": [
"assert((function(){if(typeof(lastNameLength) !== \"undefined\" && typeof(lastNameLength) === \"number\" && lastNameLength === 8){return(true);}else{return(false);}})(), 'lastNameLength should be equal to eight.');",
@@ -150,7 +151,7 @@
"Bracket notation
is a way to get a character at a specific index
within a string.",
"Computers don't start counting at 1 like humans do. They start at 0.",
"For example, the character at index 0 in the word \"Charles\" is \"C\". So if var firstName = \"Charles\"
, you can get the value of the first letter of the string by using firstName[0]
.",
- "Use bracket notation
to find the first character in a the firstLetterOfLastName
variable.",
+ "Use bracket notation
to find the first character in the firstLetterOfLastName
variable.",
"Try looking at the firstLetterOfFirstName
variable declaration if you get stuck."
],
"tests": [
@@ -216,7 +217,7 @@
"In order to get the last letter of a string, you can subtract one from the string's length.",
"For example, if var firstName = \"Charles\"
, you can get the value of the last letter of the string by using firstName[firstName.length - 1]
.",
"Use bracket notation
to find the last character in the lastName
variable.",
- "Try looking at the lastLetterOfLastName
variable declaration if you get stuck."
+ "Try looking at the lastLetterOfFirstName
variable declaration if you get stuck."
],
"tests": [
"assert(lastLetterOfLastName === \"e\", 'lastLetterOfLastName should be \"e\"');",
@@ -432,9 +433,9 @@
"challengeSeed": [
"//var array = [\"John\", 23];",
"",
- "var myArray = [];",
"// Only change code below this line.",
"",
+ "var myArray = [];",
"",
"// Only change code above this line.",
"// We use this function to show you the value of your variable in your output box.",
@@ -457,9 +458,9 @@
],
"challengeSeed":[
"var ourArray = [[\"the universe\", \"everything\", 42]];",
- "var myArray = [];",
"// Only change code below this line.",
"",
+ "var myArray = [];",
"",
"// Only change code above this line.",
"// We use this function to show you the value of your variable in your output box.",
@@ -496,7 +497,7 @@
"// Only change code above this line.",
"// We use this function to show you the value of your variable in your output box.",
"// You'll learn about functions soon.",
- "if(typeof(myArray) !== \"undefined\" && typeof(data) !== \"undefined\"){(function(y,z){return('myArray = ' + JSON.stringify(y) + ', data = ' + JSON.stringify(z));})(myArray, data);}"
+ "if(typeof(myArray) !== \"undefined\" && typeof(myData) !== \"undefined\"){(function(y,z){return('myArray = ' + JSON.stringify(y) + ', myData = ' + JSON.stringify(z));})(myArray, myData);}"
],
"type": "waypoint",
"challengeType": 1
@@ -606,7 +607,7 @@
"Take the myArray array and shift()
the first value off of it."
],
"tests": [
- "assert((function(d){if(d[0] == 23 && d[1][0] == 'dog' && d[1][1] == 3 && d[2] == undefined){return(true);}else{return(false);}})(myArray), 'myArray should only have the first two values left([\"John\", 23])');",
+ "assert((function(d){if(d[0] == 23 && d[1][0] == 'dog' && d[1][1] == 3 && d[2] == undefined){return(true);}else{return(false);}})(myArray), 'myArray should only have the last two values left([23, [\"dog\", 3]])');",
"assert((function(d){if(d === 'John' && typeof(myRemoved) === 'string'){return(true);}else{return(false);}})(myRemoved), 'myRemoved should contain \"John\"');"
],
"challengeSeed": [
@@ -634,7 +635,7 @@
"difficulty": "9.9818",
"description": [
"Now that we've learned how to shift
things from the start of the array, we need to learn how to unshift
stuff back to the start",
- "Let's take the code we had last time and unshift
this value to the end: \"Paul\"
"
+ "Let's take the code we had last time and unshift
this value to the start: \"Paul\"
"
],
"tests": [
"assert((function(d){if(d[0].toLowerCase() == 'paul' && d[1] == 23 && d[2][0] != undefined && d[2][0] == 'dog' && d[2][1] != undefined && d[2][1] == 3){return(true);}else{return(false);}})(myArray), 'myArray should now have [\"Paul\", 23, [\"dog\", 3]])');"
@@ -643,7 +644,7 @@
"var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];",
"ourArray.shift();",
"ourArray.unshift([\"happy\", \"joy\"]);",
- "// ourArray now equals [[\"happy\", \"joy\"], \"Stimpson\", \"J\"]",
+ "// ourArray now equals [[\"happy\", \"joy\"], \"J\", [\"cat\"]]",
"",
"var myArray = [\"John\", 23, [\"dog\", 3]];",
"myArray.shift();",
@@ -670,8 +671,8 @@
"function functionName (a, b) {
",
" return(a + b);
",
"}
",
- "We can \"call\" our function like this: functionName();
, and it will run and return it's return
value to us.",
- "Create and call a function called myFunction
."
+ "We can \"call\" our function like this: functionName();
, and it will run and return its return
value to us.",
+ "Create and call a function called myFunction
that returns the sum of a and b."
],
"tests":[
"assert((function(){if(typeof(f) !== \"undefined\" && typeof(f) === \"number\" && f === a + b && editor.getValue().match(/return/gi).length >= 1 && editor.getValue().match(/a/gi).length >= 1 && editor.getValue().match(/b/gi).length >= 1 && editor.getValue().match(/\\+/gi).length >= 1){return(true);}else{return(false);}})(), 'Your function should return the value of a + b');"
@@ -684,9 +685,9 @@
" return a - b;",
"};",
"",
- "//Don't modify above this line",
- "//Create a function called myFunction that returns the value of a plus b.",
- " // Only change code below this line.",
+ "// Don't modify above this line",
+ "// Create a function called myFunction that returns the value of a plus b.",
+ "// Only change code below this line.",
"",
"",
"",
@@ -755,11 +756,11 @@
"title": "Manipulate JavaScript Objects",
"difficulty":"9.9823",
"description":[
- "There are many ways to add and add and remove properties from objects.",
+ "There are many ways to add and remove properties from objects.",
"For example, we can add properties to objects like this:",
"myObject.myProperty = \"myValue\";
",
"We can also delete them like this:",
- "delete(myObject.myProperty);
",
+ "delete myObject.myProperty;
",
"Let's add the property \"bark\", and delete the property \"tails\"."
],
"tests":[
@@ -774,8 +775,8 @@
"// \"friends\": [\"everything!\"]",
"// };",
"",
- "// ourDog.bark(\"arf!\");",
- "// delete(ourDog.tails);",
+ "// ourDog.bark = \"arf!\";",
+ "// delete ourDog.tails;",
"",
"var myDog = {",
" \"name\": \"Camper\",",
@@ -818,6 +819,10 @@
"assert.deepEqual(myArray, [0,1,2,3,4], 'myArray should equal [0,1,2,3,4]');"
],
"challengeSeed":[
+ "ourArray = [];",
+ "for(var i = 0; i < 5; i++){",
+ " ourArray.push(i);",
+ "}",
"var myArray = [];",
"//Push the numbers zero through four to myArray using a \"for loop\" like above.",
"",
@@ -832,14 +837,14 @@
"difficulty":"9.9825",
"description":[
"You can run the same code multiple times by using a loop.",
- "Another type of JavaScript loop is called a \"while loop\" because it runs \"while\" something is true, and stops once that something is no longer true.",
+ "Another type of JavaScript loop is called a \"while loop\", because it runs \"while\" something is true and stops once that something is no longer true.",
"var ourArray = [];
",
"var i = 0;
",
"while(i < 5) {
",
" ourArray.push(i);
",
" i++;
",
"}
",
- "Let's try getting a for loop to work by pushing values to an array."
+ "Let's try getting a while loop to work by pushing values to an array."
],
"tests":[
"assert(editor.getValue().match(/while/g), 'You should be using a while loop for this.');",
@@ -859,7 +864,7 @@
"title": "Generate Random Fractions with JavaScript",
"difficulty":"9.9827",
"description":[
- "Random numbers are useful for creating random behaviours and games.",
+ "Random numbers are useful for creating random behavior.",
"JavaScript has a Math.random()
function that generates a random decimal number.",
"Use Math.random()
to get myFunction
to return a random number."
],
@@ -889,17 +894,17 @@
"title": "Generate Random Whole Numbers with JavaScript",
"difficulty":"9.9828",
"description":[
- "It's great that we can create random decimal numbers, but it's even more useful if we lot more useful to generate a random whole number.",
- "To achieve this we can multiply the random number by ten and use the Math.floor()
to convert the decimal number to a whole number",
- "This technique gives us a whole number between zero and nine",
+ "It's great that we can create random decimal numbers, but it's even more useful if we use it to generate a random whole number.",
+ "To achieve this we can multiply the random number by ten and use the Math.floor()
to convert the decimal number to a whole number.",
+ "This technique gives us a whole number between zero and nine.",
"Example:",
"Math.floor(Math.random()*10);
",
- "Let's give this technique a go now"
+ "Let's give this technique a go now."
],
"tests":[
"assert(typeof(myFunction()) === \"number\", 'The result of myFunction should be a number');",
"assert(editor.getValue().match(/Math.random/g), 'You should be using Math.random to create a random number');",
- "assert(!(''+myFunction()).match(/\\./g), 'You should have multiplied the result of Math.random but 10 to make it a number that\\'s greater then zero');",
+ "assert(!(''+myFunction()).match(/\\./g), 'You should have multiplied the result of Math.random by 10 to make it a number that\\'s greater than zero');",
"assert(editor.getValue().match(/Math.floor/g), 'You should use Math.floor to remove the decimal part of the number');"
],
"challengeSeed":[
@@ -935,7 +940,7 @@
],
"challengeSeed":[
"var min = 0;",
- "var max = 12;",
+ "var max = 9;",
"function myFunction() {",
" // Make myFunction return a random number between zero and nine instead of a decimal",
" // Only change code below this line.",
@@ -956,16 +961,16 @@
"difficulty":"9.983",
"description":[
"We can use if statements in JavaScript to only execute code if a certain condition is met.",
- "if statements require some sort of boolean condition evaluate.",
+ "if statements require some sort of boolean condition to evaluate.",
"Example:",
- " if (1 == 2) {
",
+ " if (1 === 2) {
",
" return(true);
",
"}
",
"else {
",
" return(false);
",
"}
",
"Let's use if
and else
statements to make a coin-flip game.",
- "Create an if-else statement
to return heads
if the flip var is zero and to return tails
if it's not."
+ "Create an if-else statement
to return heads
if the flip var is zero, or else return tails
if it's not."
],
"tests":[
"assert((function(){if(myFunction() === \"heads\" || myFunction() === \"tails\"){return(true);}else{return(false);}})(), 'myFunction should either return heads or tails');",
@@ -975,7 +980,7 @@
"challengeSeed":[
"function myFunction(){",
" var flip = Math.floor(Math.random() * (1 - 0 + 1)) + 0;",
- " // Create and if else statement here to return \"heads\" if flip is 0. Otherwise return \"tails\".",
+ " // Create an if-else statement here to return \"heads\" if flip is 0. Otherwise return \"tails\".",
"",
" // Only change code below this line.",
"",
@@ -1002,7 +1007,7 @@
"g
means that we want to search the entire string for this pattern.",
"i
means that we want to ignore the case (uppercase or lowercase) when searching for the pattern.",
"Regular expressions
are usually surrounded by /
symbols.",
- "Let's try selecting all the occurances of the word and
in the string George Boole and Alan Turing went to the shop and got some milk
. We can do this by replacing the +
part of our regular expression with the word and
."
+ "Let's try selecting all the occurrences of the word and
in the string George Boole and Alan Turing went to the shop and got some milk
. We can do this by replacing the +
part of our regular expression with the word and
."
],
"tests":[
"assert(test==2, 'Your regular expression
should find two occurrences of the word and
');",
@@ -1036,11 +1041,11 @@
],
"tests":[
"assert(test === 2, 'Your RegEx should have found two numbers in the testString');",
- "assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'You should be using the following expression /\\d+/gi to find the numbers in the testString');"
+ "assert(editor.getValue().match(/\\/\\\\d\\+\\//gi), 'You should be using the following expression /\\\\d+/gi to find the numbers in the testString');"
],
"challengeSeed":[
"var test = (function() {",
- " var testString = \"There's 3 cats but 4 dogs.\";",
+ " var testString = \"There are 3 cats but 4 dogs.\";",
"",
" // Only change code below this line.",
"",
@@ -1066,7 +1071,7 @@
],
"tests":[
"assert(test === 7, 'Your RegEx should have found seven spaces in the testString
.');",
- "assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'You should be using the following expression /\\s+/gi to find the spaces in the testString
.');"
+ "assert(editor.getValue().match(/\\/\\\\s\\+\\//gi), 'You should be using the following expression /\\\\s+/gi to find the spaces in the testString
.');"
],
"challengeSeed":[
"var test = (function(){",
@@ -1093,12 +1098,12 @@
"You can invert any match by using the uppercase version of the selector \\s
versus \\S
for example."
],
"tests":[
- "assert(test === 36, 'Your RegEx should have found seven spaces in the testString
.');",
- "assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'You should be using the following expression /\\+S/gi
to find the spaces in the testString
.');"
+ "assert(test === 49, 'Your RegEx should have found forty nine non-space characters in the testString
.');",
+ "assert(editor.getValue().match(/\\/\\\\S\\/gi/gi), 'You should be using the following expression /\\\\S/gi
to find non-space characters in the testString
.');"
],
"challengeSeed":[
"var test = (function(){",
- " var testString = \"How many spaces are there in this sentence?\";",
+ " var testString = \"How many non-space characters are there in this sentence?\";",
"",
" // Only change code below this line.",
"",
@@ -1274,7 +1279,7 @@
"Now that our slots will each generate random numbers, we need to check whether they've all returned the same number.",
"If they have, we should notify our user that they've won.",
"Otherwise, we should return null
, which is a JavaScript data structure that means nothing.",
- "If all three numbers match, we should change the value of win to the number that we have three of or leave it as null.",
+ "If all three numbers match, we should return the number that we have in three of slots or leave it as null
.",
"Let's create an if statement
with multiple conditions in order to check whether all numbers are equal.",
"if(slotOne !== slotTwo || slotTwo !== slotThree){
",
" return(null);
",
@@ -1604,7 +1609,7 @@
"Set up all three slots like this, then click the \"Go\" button to play the slot machine."
],
"tests":[
- "assert(editor.match(/\\$\\(\\$\\(\\'\\.slot\\'\\)\\[\\d\\]\\)\\.html\\(\\'\\\\'\\);/gi) && editor.match(/\\$\\(\\$\\(\\'\\.slot\\'\\)\\[\\d\\]\\)\\.html\\(\\'\\
\\'\\);/gi).length >= 3, 'Use the provided code three times. One for each slot')",
+ "assert((editor.match(/\\$\\(\\$\\(\\'\\.slot\\'\\)\\[\\d\\]\\)\\.html\\(\\'\\
\\'\\);/gi) && editor.match(/\\$\\(\\$\\(\\'\\.slot\\'\\)\\[\\d\\]\\)\\.html\\(\\'\\
\\'\\);/gi).length >= 3) || (editor.match(/\\$\\(\\$\\(\\\"\\.slot\\\"\\)\\[\\d\\]\\)\\.html\\(\\'\\
\\'\\);/gi) && editor.match(/\\$\\(\\$\\(\\\"\\.slot\\\"\\)\\[\\d\\]\\)\\.html\\(\\'\\
\\'\\);/gi).length >= 3), 'Use the provided code three times. One for each slot')",
"assert(editor.match(/slotOne/gi) && editor.match(/slotOne/gi).length >= 7, 'You should have used the slotOne value at least once')",
"assert(editor.match(/slotTwo/gi) && editor.match(/slotTwo/gi).length >= 8, 'You should have used the slotTwo value at least once')",
"assert(editor.match(/slotThree/gi) && editor.match(/slotThree/gi).length >= 7, 'You should have used the slotThree value at least once')"
diff --git a/seed/challenges/basic-ziplines.json b/seed/challenges/basic-ziplines.json
index 6f7d3989ab..d97d049b80 100644
--- a/seed/challenges/basic-ziplines.json
+++ b/seed/challenges/basic-ziplines.json
@@ -45,14 +45,15 @@
"Rule #1: Don't look at the example project's code on CodePen. Figure it out for yourself.",
"Rule #2: You may use whichever libraries or APIs you need.",
"Rule #3: Reverse engineer the example project's functionality, and also feel free to personalize it.",
+ "Hint: If you don't want to start from scratch, you can fork this simple Bootstrap portfolio template on CodePen: http://codepen.io/FreeCodeCamp/pen/mJNqQj.",
"Here are the user stories you must enable, and optional bonus user stories:",
"User Story: As a user, I can access all of the portfolio webpage's content just by scrolling.",
"User Story: As a user, I can click different buttons that will take me to the portfolio creator's different social media pages.",
- "User Story: As a user, I can see thumbnail images of different projects the portfolio creator has built (if you don't haven't built any websites before, use placeholders.)",
+ "User Story: 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.)",
"Bonus User Story: 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.",
"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:
<a target='_blank'&rt;.",
+ "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:
elements have a closing tag.')"
@@ -700,7 +700,7 @@
"description": [
"Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a <a target='_blank'>
.",
"Remember to use Read-Search-Ask 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.",
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.
Click here then add your link to your tweet's text"
diff --git a/seed/challenges/bootstrap.json b/seed/challenges/bootstrap.json
index a58be9f38b..5f5d0ff63e 100644
--- a/seed/challenges/bootstrap.json
+++ b/seed/challenges/bootstrap.json
@@ -133,7 +133,7 @@
"",
" ",
+ "
",
"",
"
",
@@ -176,8 +176,8 @@
"title": "Center Text with Bootstrap",
"difficulty": 2.03,
"description": [
- "Now that we're using Bootstrap, we can center our heading elements to make them look better. All we need to do is add the class
text-center
to our h1
and h2
elements.",
- "Remember that you can add several classes to the same element by separating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>
."
+ "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 text-center
to our h2
element.",
+ "Remember that you can add several classes to the same element by separating each of them with a space, like this: <h2 class=\"red-text text-center\">your text</h2>
."
],
"tests": [
"assert($(\"h2\").hasClass(\"text-center\"), 'Your h2
element should be centered by applying the class text-center
')"
@@ -347,7 +347,7 @@
"description": [
"Normally, your button
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.",
"This image illustrates the difference between inline
elements and block-level
elements:",
- "",
+ "
",
"Note that these buttons still need the
btn
class.",
"Add Bootstrap's btn-block
class to your Bootstrap button."
],
@@ -614,7 +614,7 @@
"Note that these buttons still need the btn
and btn-block
classes."
],
"tests": [
- "assert(new RegExp(\"delete\",\"gi\").test($(\"button\").text()), 'Create a new button
element with the text \"delete\".')",
+ "assert(new RegExp(\"Delete\",\"gi\").test($(\"button\").text()), 'Create a new button
element with the text \"Delete\".')",
"assert($(\"button.btn-block.btn\").length > 2, 'All of your Bootstrap buttons should have the btn
and btn-block
classes.')",
"assert($(\"button\").hasClass(\"btn-danger\"), 'Your new button should have the class btn-danger
.')",
"assert(editor.match(/<\\/button>/g) && editor.match(/div
element.",
"Here's a diagram of how Bootstrap's 12-column grid layout works:",
- "",
+ "
",
"Note that in this illustration, the
col-md-*
class is being used. Here, md
means medium, and *
is a number specifying how many columns wide the element should be. In this case, the column width of an element on a medium-sized screen, such as a laptop, is being specified.",
"In the Cat Photo App that we're building, we'll use col-xs-*
, where xs
means extra small (like an extra-small mobile phone screen), and *
is the number of columns specifying how many columns wide the element should be.",
"Put the Like
, Info
and Delete
buttons side-by-side by nesting all three of them within one <div class=\"row\">
element, then each of them within a <div class=\"col-xs-4\">
element.",
@@ -795,7 +795,7 @@
"We can clean up our code and make our Cat Photo App look more conventional by using Bootstrap's built-in styles instead of the custom styles we created earlier.",
"Don't worry - there will be plenty of time to customize our CSS later.",
"Delete the .red-text
, p
, and .smaller-image
CSS declarations from your style
element so that the only declarations left in your style
element are h2
and thick-green-border
.",
- "Then Delete the p
element that contains a dead link. Then remove the red-text
class from your h2
element and replace it with the text-primary
Bootstrap class.",
+ "Then delete the p
element that contains a dead link. Then remove the red-text
class from your h2
element and replace it with the text-primary
Bootstrap class.",
"Finally, remove the \"smaller-image\" class from your first img
element and replace it with the img-responsive
class."
],
"tests": [
@@ -893,9 +893,9 @@
"title": "Use Spans for Inline Elements",
"difficulty": 2.105,
"description": [
- "You can use use spans to create inline elements. Remember when we used the btn-block
class to make the button grow fill the entire row?",
+ "You can use spans to create inline elements. Remember when we used the btn-block
class to make the button fill the entire row?",
"This image illustrates the difference between inline
elements and block-level
elements:",
- "",
+ "
",
"By using the
span
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 span
element. Then give that span
the class text-danger
to make the text red.",
"Here's how you would do this with the \"Top 3 things cats hate\" element: <p>Top 3 things cats <span class = \"text-danger\">hate</span></p>
"
@@ -997,7 +997,7 @@
"We will make a simple heading for our Cat Photo App by putting them in the same row.",
"Remember, Bootstrap uses a responsive grid system, which makes it easy to put elements into rows and specify each element's relative width. Most of Bootstrap's classes can be applied to a div
element.",
"Here's a diagram of how Bootstrap's 12-column grid layout works:",
- "",
+ "
",
"Note that in this illustration, the
col-md-*
class is being used. Here, md
means medium, and *
is a number specifying how many columns wide the element should be. In this case, the column width of an element on a medium-sized screen, such as a laptop, is being specified.",
"In the Cat Photo App that we're building, we'll use col-xs-*
, where xs
means extra small (like an extra-small mobile phone screen), and *
is the number of columns specifying how many columns wide the element should be.",
"Nest your first image and your h2
element within a single <div class=\"row\">
element. Nest your h2
text within a <div class=\"col-xs-8\">
and your image in a <div class=\"col-xs-4\">
so that they are on the same line.",
@@ -1532,7 +1532,7 @@
"difficulty": 2.17,
"description": [
"Now let's get your form input
and your submission button
on the same line. We'll do this the same way we have previously: by using a div
element with the class row
, and other div
elements within it using the col-xs-*
class.",
- "Nest both your form's text input
and submit button
within a div
with the class row
. Nest your form's text input
within a div with the class of \"col-xs-7\". Nest your form's submit button
in a div
with the class col-xs-5
.",
+ "Nest both your form's text input
and submit button
within a div
with the class row
. Nest your form's text input
within a div with the class of col-xs-7
. Nest your form's submit button
in a div
with the class col-xs-5
.",
"This is the last challenge we'll do for our Cat Photo App for now. We hope you've enjoyed learning Font Awesome, Bootstrap, and responsive design!"
],
"tests": [
@@ -1769,8 +1769,8 @@
"Nest one div
element with the class well
within each of your col-xs-6
div
elements."
],
"tests": [
- "assert($(\"div\").length > 4, 'Add two div
elements inside your div class=\"well\">
element both with the class col-xs-6
')",
- "assert($(\"div.col-xs-6\").children(\"div.well\").length > 1, 'Nest both of your div class=\"col-xs-6\"
elements within your div class=\"row\"
element.')",
+ "assert($(\"div\").length > 4, 'Add a div
element with the class well
inside each of your div class=\"col-xs-6\"> elements
')",
+ "assert($(\"div.col-xs-6 div.well\").length > 1, 'Nest both of your div class=\"col-xs-6\"
elements within your div class=\"row\"
element.')",
"assert(editor.match(/<\\/div>/g) && editor.match(/
how-to-npm
with this command: npm install -g git-it
",
+ "Install git-it
with this command: npm install -g git-it
",
"Now start the tutorial by running git-it
.",
"Note that you can resize the c9.io's windows by dragging their borders.",
"Make sure that you are always in your project's \"workspace\" directory. You can always navigate back to this directory by running this command: cd ~/workspace
.",
diff --git a/seed/challenges/html5-and-css.json b/seed/challenges/html5-and-css.json
index b7a82a256c..e55619b87b 100644
--- a/seed/challenges/html5-and-css.json
+++ b/seed/challenges/html5-and-css.json
@@ -428,8 +428,12 @@
"description": [
"Create a CSS class called red-text
and apply it to your h2
element.",
"Classes are reusable styles that can be added to HTML elements.",
- "Here's the anatomy of a CSS class:",
- "<style>
",
+ " .blue-text {
",
+ " color: blue;
",
+ " }
",
+ "</style>
",
"You can see that we've created a CSS class called blue-text
within the <style>
tag.",
"You can apply a class to an HTML element like this: <h2 class=\"blue-text\">CatPhotoApp</h2>
.",
"Note that in your CSS style
element, classes should start with a period. In your HTML elements' class declarations, classes shouldn't start with a period.",
@@ -749,13 +753,13 @@
"title": "Add Images to your Website",
"difficulty": 1.17,
"description": [
- "You can add images to your website by using the img
element, and point to an specific image's URL using the src
attribute.",
- "An example of this would be <img src=\"www.your-image-source.com/your-image.jpg\">
. Note that in most cases, img
elements are self-closing.",
+ "You can add images to your website by using the img
element, and point to a specific image's URL using the src
attribute.",
+ "An example of this would be <img src=\"http://www.your-image-source.com/your-image.jpg\">
. Note that in most cases, img
elements are self-closing.",
"Try it with this image: https://bit.ly/fcc-relaxing-cat
."
],
"tests": [
"assert($(\"img\").length > 0, 'Your page should have an image element.')",
- "assert(new RegExp(\"\\/\\/bit.ly\\/fcc-relaxing-cat\", \"gi\").test($(\"img\").attr(\"src\")), 'Your image should have have a src
attribute that points to the kitten image.')"
+ "assert(new RegExp(\"\\/\\/bit.ly\\/fcc-relaxing-cat\", \"gi\").test($(\"img\").attr(\"src\")), 'Your image should have a src
attribute that points to the kitten image.')"
],
"challengeSeed": [
"",
@@ -1056,13 +1060,13 @@
"description": [
"a
elements, also known as anchor
elements, are used to link to content outside of the current page.",
"Here's a diagram of an a
element. In this case, the a
element is used in the middle of a paragraph element, which means the link will appear in the middle of a sentence.",
- "<p>Here's a <a href=\"http://freecodecamp.com\"> link to Free Code Camp</a> for you to follow.</p>
.",
"Create an a
element that links to http://catphotoapp.com
and has \"cat photos\" as its anchor text
."
],
"tests": [
"assert((/cat photos/gi).test($(\"a\").text()), 'Your a
element should have the anchor text
of \"cat photos\"')",
- "assert(/http:\\/\\/catphotoapp\\.com/gi.test($(\"a\").attr(\"href\")), 'You need an a
element that links to http://catphotoapp.com.')",
+ "assert(/http:\\/\\/catphotoapp\\.com/gi.test($(\"a\").attr(\"href\")), 'You need an a
element that links to http://catphotoapp.com
.')",
"assert(editor.match(/<\\/a>/g) && editor.match(/<\\/a>/g).length === editor.match(/a
element has a closing tag.')"
],
"challengeSeed": [
@@ -1126,7 +1130,7 @@
"difficulty": 1.23,
"description": [
"Again, here's a diagram of an a
element for your reference:",
- "
",
+ "
",
"Here's an example: <p>Here's a <a href=\"http://freecodecamp.com\"> link to Free Code Camp</a> for you to follow.</p>
.",
"Nesting
just means putting one element inside of another element.",
"Now nest your a
element within a new p
element so that the surrounding paragraph says \"click here for cat photos\", but where only \"cat photos\" is a link, and the rest of the text is rest is plain text."
@@ -3117,7 +3121,7 @@
"difficulty": 1.46,
"description": [
"Now let's start fresh and talk about CSS inheritance.",
- "Every HTML page has body
element.",
+ "Every HTML page has a body
element.",
"We can prove that the body
element exists here by giving it a background-color
of black.",
"We can do this by adding body { background-color: black; }
to our style
element."
],
@@ -3235,7 +3239,8 @@
"Our \"pink-text\" class overrode our body
element's CSS declaration!",
"We just proved that our classes will override the body
element's CSS. So the next logical question is, what can we do to override our pink-text
class?",
"Create an additional CSS class called blue-text
that gives an element the color blue. Make sure it's below your pink-text
class declaration.",
- "Apply the blue-text
class to your h1
element in addition to your pink-text
class, and let's see which one wins."
+ "Apply the blue-text
class to your h1
element in addition to your pink-text
class, and let's see which one wins.",
+ "Applying multiple class attributes to a HTML element is done with a space between them like this: class=\"class1 class2\"
"
],
"tests": [
"assert($(\"h1\").hasClass(\"pink-text\"), 'Your h1
element should have the class pink-text
.')",
@@ -3280,12 +3285,14 @@
"Let's override your pink-text
and blue-text
classes, and make your h1
element orange, by giving the h1
element an id and then styling that id.",
"Give your h1
element the id
attribute of orange-text
. Remember, id styles look like this: <h1 id=\"orange-text\">
",
"Leave the blue-text
and pink-text
classes on your h1
element.",
- "Create a CSS declaration for your orange-text
id in your style
element. Here's and example of what this looks like: #brown-text { color: brown; }
"
+ "Create a CSS declaration for your orange-text
id in your style
element. Here's an example of what this looks like: #brown-text { color: brown; }
"
],
"tests": [
"assert($(\"h1\").hasClass(\"pink-text\"), 'Your h1
element should have the class pink-text
.')",
"assert($(\"h1\").hasClass(\"blue-text\"), 'Your h1
element should have the class blue-text
.')",
"assert($(\"h1\").attr(\"id\") === \"orange-text\", 'Give your h1
element the id of orange-text
.')",
+ "assert(editor.match(/#orange-text\\s*{/gi), 'Create a CSS declaration for your orange-text
id')",
+ "assert(!editor.match(//gi), 'Do not give your h1
any style
attributes.')",
"assert($(\"h1\").css(\"color\") === \"rgb(255, 165, 0)\", 'Your h1
element should be orange.')"
],
"challengeSeed": [
@@ -3387,7 +3394,7 @@
"assert($(\"h1\").hasClass(\"blue-text\"), 'Your h1
element should have the class blue-text
.')",
"assert($(\"h1\").attr(\"id\") === \"orange-text\", 'Your h1
element should have the id of orange-text
.')",
"assert(editor.match(/ 0, 'Your h1
element should have the inline style of color: white
.')",
- "assert(editor.match(/pink.*\\!important/gi) && editor.match(/pink.*\\!important;/gi).length > 0, 'Your pink-text
class should have the !important
keyword to override all other declarations.')",
+ "assert(editor.match(/pink.*\\!important;/gi), 'Your pink-text
class should have the !important
keyword to override all other declarations.')",
"assert($(\"h1\").css(\"color\") === \"rgb(255, 192, 203)\", 'Your h1
element should be pink.')"
],
"challengeSeed": [
@@ -3431,7 +3438,7 @@
"description": [
"Did you know there are other ways to represent colors in CSS? One of these ways is called hexadecimal code, or hex code
for short.",
"Decimal
means the numbers zero through nine - the numbers that people use in everyday life. Hexadecimal
includes these 10 numbers, plus the letters A, B, C, D, E and F. This means that Hexidecimal has a total of 16 possible values, instead of the 10 possible values that our normal base-10 number system gives us.",
- "With CSS, we use 6 hexidecimal number to represent colors. For example, #000000
is the lowest possible value, and it represents the color black.",
+ "With CSS, we use 6 hexadecimal numbers to represent colors. For example, #000000
is the lowest possible value, and it represents the color black.",
"Replace the word black
in our body
element's background-color with its hex code
representation, #000000
. "
],
"tests": [
@@ -3749,7 +3756,7 @@
"description": [
"Another way you can represent colors in CSS is by using rgb
values.",
"RGB values look like this: rgb(0, 0, 0)
for black and rgb(255, 255, 255)
for white.",
- "Instead of using six hexadecimal digits like you do with hex code, with rbg
you specify the brightness of each color with a number between 0 and 255.",
+ "Instead of using six hexadecimal digits like you do with hex code, with rgb
you specify the brightness of each color with a number between 0 and 255.",
"If you do the math, 16 times 16 is 256 total values. So rgb
, which starts counting from zero, has the exact same number of possible values as hex code.",
"Let's replace the hex code in our body
element's background color with the RGB value for black: rgb(0, 0, 0)
"
],
diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json
index 0a0c57f85c..6317353902 100644
--- a/seed/challenges/intermediate-ziplines.json
+++ b/seed/challenges/intermediate-ziplines.json
@@ -138,9 +138,9 @@
"id": "bd7158d8c442eddfaeb5bd1c",
"title": "Build a Simon Game",
"difficulty": 1.07,
- "challengeSeed": ["126415123"],
+ "challengeSeed": ["137213633"],
"description": [
- "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/dting/full/KpJXZV/.",
+ "Objective: Build a CodePen.io app that successfully reverse-engineers this: http://codepen.io/dting/full/QbRyqq/.",
"Rule #1: Don't look at the example project's code on CodePen. Figure it out for yourself.",
"Rule #2: You may use whichever libraries or APIs you need.",
"Rule #3: Reverse engineer the example project's functionality, and also feel free to personalize it.",
diff --git a/seed/challenges/jquery.json b/seed/challenges/jquery.json
index d6a6fa0fb0..93cc8899b2 100644
--- a/seed/challenges/jquery.json
+++ b/seed/challenges/jquery.json
@@ -17,7 +17,7 @@
"assert(editor.match(/