From b574bed0a1d4abe7e3697a59ee1c4f1aa1108688 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 11 May 2015 13:43:12 -0700 Subject: [PATCH 01/81] start integrating html css coursewares --- controllers/challengeMap.js | 2 +- controllers/courseware.js | 4 - seed_data/coursewares.json | 1514 +++++++++++++++-- seed_data/future-coursewares.json | 2589 +---------------------------- 4 files changed, 1412 insertions(+), 2697 deletions(-) diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index e10c7ab409..be7cc20eb9 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -43,7 +43,7 @@ module.exports = { coursewareList = resources.allCoursewareNames(); completedCoursewareList = noDuplicatedCoursewares; waypoints = coursewareList.filter(function(challenge) { - if (challenge.challengeType === 2) { return challenge } + if (challenge.challengeType === 2 || challenge.challengeType === 0) { return challenge } }); ziplines = coursewareList.filter(function(challenge) { if (challenge.challengeType === 3) { return challenge } diff --git a/controllers/courseware.js b/controllers/courseware.js index 267f09d6e5..fbab4b69bc 100644 --- a/controllers/courseware.js +++ b/controllers/courseware.js @@ -28,9 +28,6 @@ exports.returnNextCourseware = function(req, res, next) { if (!req.user) { return res.redirect('../challenges/learn-how-free-code-camp-works'); } - if (req.user.finishedWaypoints && req.user.uncompletedBonfires.length > 0) { - return res.redirect('../bonfires') - } var completed = req.user.completedCoursewares.map(function (elem) { return elem._id; @@ -46,7 +43,6 @@ exports.returnNextCourseware = function(req, res, next) { var uncompletedCoursewares = req.user.uncompletedCoursewares[0]; - var displayedCoursewares = Courseware.find({'_id': uncompletedCoursewares}); displayedCoursewares.exec(function(err, courseware) { if (err) { diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 724af142fb..e27ab751f7 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -2,7 +2,7 @@ { "_id": "bd7124d8c441eddfaeb5bdef", "name": "Learn how Free Code Camp Works", - "difficulty": 0.01, + "difficulty": 0.001, "challengeSeed": "125407438", "description": [ "Watch this 1-minute video, or simply read this summary:", @@ -20,7 +20,7 @@ { "_id": "bd7125d8c441eddfaeb5bd0f", "name": "Join Our Chat Room", - "difficulty": 0.02, + "difficulty": 0.002, "challengeSeed": "124555254", "description": [ "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", @@ -40,7 +40,7 @@ { "_id": "bd7125d8c441eddfaeb5bdff", "name": "Preview our Challenge Map", - "difficulty": 0.03, + "difficulty": 0.003, "challengeSeed": "125407437", "description": [ "Before you start learning how to code, we'd like to introduce you to a few things.", @@ -55,7 +55,7 @@ { "_id": "bd7125d8c441eddfaeb5bd1f", "name": "Browse our Field Guide", - "difficulty": 0.04, + "difficulty": 0.004, "challengeSeed": "125407435", "description": [ "Free Code Camp has an up-to-date field guide that will answer your many questions.", @@ -70,7 +70,7 @@ { "_id": "bd7125d8c441eddfaeb5bd2f", "name": "Customize your Portfolio Page", - "difficulty": 0.05, + "difficulty": 0.005, "challengeSeed": "125407433", "description": [ "You and all your fellow campers have portfolio pages.", @@ -87,7 +87,7 @@ { "_id": "bd7126d8c441eddfaeb5bd3f", "name": "Try Camper News", - "difficulty": 0.06, + "difficulty": 0.006, "challengeSeed": "124553410", "description": [ "Camper News is the best place for our campers to share and discuss helpful links.", @@ -106,7 +106,7 @@ { "_id": "bd7126d8c441eddfaeb5bd3e", "name": "Meet Other Campers in your City", - "difficulty": 0.065, + "difficulty": 0.007, "challengeSeed": "127358841", "description": [ "One of the best ways to stay motivated when learning to code is to hang out with other campers.", @@ -124,7 +124,7 @@ { "_id": "bd7137d8c441eddfaeb5bdef", "name": "Get Help the Hacker Way with RSAP", - "difficulty": 0.07, + "difficulty": 0.008, "challengeSeed": "125407432", "description": [ "Let's cover one last thing before you start working through our lessons: how to get help.", @@ -140,140 +140,1446 @@ "tests": [] }, { - "_id": "bd7127d8c441eddfaeb5bdef", - "name": "Build a Landing Page with HTML", - "difficulty": 0.08, - "challengeSeed": "125671867", + "_id": "bd7123c8c441eddfaeb5bdef", + "name": "Use HTML Elements", + "difficulty": 0.0085, "description": [ - "Now it's time for us to start our actual coding lessons. We've curated a series of free, self-paced, browser-based lessons from providers like Codecademy and Stanford University.", - "These lessons will cover a lot of ground quickly, and will hold your hand throughout the process. Don't try to memorize everything - you'll spend more than a thousand hours practicing these later, and you can always look things up. Just keep moving.", - "If you've learned HTML and CSS before, these next few Waypoints will be a valuable review. If you haven't learned HTML or CSS before, you're in for a treat!", - "This Codecademy will quickly cover HTML, CSS and even Responsive Design with Bootstrap.", - "If you don't already have a Codecademy account, create one here: http://www.codecademy.com.", - "Go to http://www.codecademy.com/en/skills/make-a-website/topics/html-elements and complete the section.", - "Once you're done, mark this Waypoint complete and move on the next Waypoint." + "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", + "Awesome. Now you can read the rest of this challenge's instructions.", + "You can edit code in the text editor we've embedded into this web page.", + "Do you see the code in the text editor that says <h1>Hello</h1>? That's an HTML element.", + "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", + "Once you've completed the challenge, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", + "To enable the \"Go to my next challenge\" button on this exercise, change the h1 tag's text to say \"Hello World\" instead of \"Hello\"." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" + ], + "challengeSeed": [ + "

Hello

" + ], + "challengeType": 0 }, { - "_id": "bd7128d8c441eddfaeb5bdef", - "name": "Style Text with CSS", - "difficulty": 0.09, - "challengeSeed": "125671735", + "_id": "bad87fee1348bd9aedf0887a", + "name": "Use the h2 Element", + "difficulty": 0.010, "description": [ - "Cascading Style Sheets (CSS) is what gives HTML it's style.", - "Now let's learn how to style HTML elements, such as headlines and body text, using CSS.", - "Go to http://www.codecademy.com/skills/make-a-website/topics/css-properties-text and complete the section." + "Add an h2 tag that says \"Cat Photo App\" to make a second HTML element below the \"Hello World\" h1 element.", + "The h2 element you enter will create an h2 element on the website.", + "This element tells the browser how to render the text that it contains.", + "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert.isTrue((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text()), 'Your h2 element should have the text \"Cat Photo App\"')", + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" + ], + "challengeSeed": [ + "

hello world

" + ], + "challengeType": 0 }, { - "_id": "bd8129d8c441ecdfaeb5bdef", - "name": "Space Out with CSS", - "difficulty": 0.10, - "challengeSeed": "125671732", + "_id": "bad87fee1348bd9aedf08801", + "name": "Use the P Element", + "difficulty": 0.011, "description": [ - "There are several ways to control spacing between elements using CSS. Let's learn about padding, margins, and more.", - "Go to http://www.codecademy.com/skills/make-a-website/topics/css-properties-box and complete the section." + "Create a p element below the h2 element, and give it the text \"Hello Paragraph\".", + "p elements are the preferred element for normal-sized paragraph text on websites.", + "You can create a p element like so: <p>I'm a p tag!</p>" ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your p element should have the text \"Hello Paragraph\"')" + ], + "challengeSeed": [ + "

Hello World

", + "

Cat Photo App

" + ], + "challengeType": 0 }, { - "_id": "bd8129d8c441eddfaeb5bdef", - "name": "Design a Layout with HTML", - "difficulty": 0.11, - "challengeSeed": "125671731", + "_id": "bad87fee1348bd9aeaf08801", + "name": "Add a Line Break to Visually Separate Elements", + "difficulty": 0.012, "description": [ - "Now let's apply the HTML and CSS we've learned toward making a proper layout.", - "We'll learn the difference between block elements and inline elements. We'll also learn the difference between absolute position and relative positioning.", - "Go to http://www.codecademy.com/skills/make-a-website/topics/css-properties-layout and complete the section." + "Add a line break between the <h2> and <p> elements.", + "You can create an line break element with <br/>.", + "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?", + "You'll encounter other self-closing element tags soon." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert(($('br').length > 0), 'You should have a br element between your h2 and p elements.')" + ], + "challengeSeed": [ + "

Hello World

", + "

Cat Photo App

", + "

Hello Paragraph

" + ], + "challengeType": 0 }, { - "_id": "bd8129d8c441eddfaeb5bdee", - "name": "Design Responsively with Bootstrap", - "difficulty": 0.12, - "challengeSeed": "125671730", + "_id": "bad87fee1348bd9aedf08802", + "name": "Uncomment HTML", + "difficulty": 0.013, "description": [ - "Responsive Design is the practice of building web applications that look good on any screen size - whether it's a phone or a big screen TV.", - "Bootstrap is a CSS library that was created by Twitter. It's by far the most popular responsive design framework. It's websites like Newsweek, Free Code Camp, and, of course, Twitter.", - "Go to http://www.codecademy.com/skills/make-a-website/topics/bootstrap-components and complete the section." + "Uncomment the h1, h2 and p elements.", + "Commenting is a way that you can leave comments within your code without affecting the code itself.", + "Commenting is also a convenient way to make code inactive without having to delete it entirely.", + "You can start a comment with <!-- and end a comment with -->." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert(($('h1').length > 0), 'The h1 element should not commented. It should be visible in the browser.')", + "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", + "assert(($('p').length > 0), 'The p element should not commented. It should be visible in the browser.')" + ], + "challengeSeed": [ + "" + ], + "challengeType": 0 }, { - "_id": "bd7112d8c441eddfaeb5bded", - "name": "Get Started with jQuery", - "difficulty": 0.13, - "challengeSeed": "125671865", + "_id": "bad87fee1348bd9aedf08804", + "name": "Comment out HTML", + "difficulty": 0.014, "description": [ - "jQuery is a powerful library built in JavaScript for manipulating HTML elements.", - "It's a lot easier to use than JavaScript itself, so we'll learn it first.", - "It's also extremely popular with employers, so we're going to learn it well.", - "Codecademy has an excellent free course that will walk us through the basics of jQuery.", - "Go to http://www.codecademy.com/courses/web-beginner-en-bay3D/0/1 and complete the first section." + "Comment out the h1 element and the p element, but leave the h2 element uncommented.", + "Remember that in order to start a comment, you need to use <!-- and to end a comment, you need to use -->.", + "Here you'll need to end the comment before the h2 element begins." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert(($('h1').length == 0), 'The h1 element should be commented. It should not be visible in the browser.')", + "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", + "assert(($('p').length == 0), 'The p element should be commented. It should not be visible in the browser.')" + ], + "challengeSeed": [ + "" + ], + "challengeType": 0 }, { - "_id": "bd7113d8c441eddfaeb5bdef", - "name": "Write Functions with jQuery", - "difficulty": 0.14, - "challengeSeed": "125658029", + "_id": "bad87fee1348bd9aedf08833", + "name": "Use Lorem Ipsum Text as a Placeholder", + "difficulty": 0.015, "description": [ - "Now we're ready to write your first jQuery functions.", - "Functions are little sub-programs. You can call a function and ask it to do something. Then it will return an answer.", - "First, you'll learn about one of the most important jQuery functions of all: $(document).ready().", - "Go to http://www.codecademy.com/courses/web-beginner-en-GfjC6/0/1 and complete the second section." + "Change the text in the p element to use the first few words of lorem ipsum text.", + "Web developers use lorem ipsum as placeholder text. It's called lorem ipsum text because it's those are the first two words of a passage by Cicero of Ancient Rome.", + "Lorem ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", + "Here are the first 25 words of Lorem Ipsum text, which you can copy and paste into the right position: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert.isTrue((/Lorem(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your p element should contain the first few words of the famous Lorem Ipsum text.')" + ], + "challengeSeed": [ + "

Hello World

", + "", + "

Cat Photo App

", + "", + "
", + "", + "

Hello Paragraph

" + ], + "challengeType": 0 }, { - "_id": "bd7114d8c441eddfaeb5bdef", - "name": "Harness Dynamic HTML", - "difficulty": 0.15, - "challengeSeed": "125658028", + "_id": "bad87fed1348bd9aedf08833", + "name": "Delete HTML Elements", + "difficulty": 0.016, "description": [ - "Did you know that you can create HTML elements using jQuery?", - "Let's learn some more advanced ways to use jQuery to manipulate the DOM.", - "Go to http://www.codecademy.com/courses/web-beginner-en-v6phg/0/1 and complete the third section." + "Delete the h1 and br elements so we can simplify our view.", + "Our phone doesn't have much space, for HTML elements.", + "Let's remove the unnecessary elements so we can start building our cat photo app." ], - "challengeType": 2, - "tests": [] + "tests": [ + "assert(($('h1').length == 0), 'Delete the h1 element.')", + "assert(($('h2').length > 0), 'Leave the h2 element on the page.')", + "assert(($('br').length == 0), 'Delete the br element.')", + "assert(($('p').length > 0), 'Leave the p element on the page.')" + ], + "challengeSeed": [ + "

Hello World

", + "", + "

Cat Photo App

", + "", + "
", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 }, { - "_id": "bd7115d8c441eddfaeb5bdef", - "name": "Listen for jQuery Events", - "difficulty": 0.16, - "challengeSeed": "125658027", + "_id": "bad87fee1348bd9aedf08803", + "name": "Change the Color of Text", + "difficulty": 0.017, "description": [ - "jQuery can listen for events, such as clicking a button, and respond to them.", - "Here we'll learn how to use the jQuery click() function to respond to events in the browser.", - "Go to http://www.codecademy.com/courses/web-beginner-en-JwhI1/0/1 and complete the fourth section." + "Change the h2 element's style so that its text color is red.", + "We can do this by changing the style of the h2 element.", + "The style responsible for the color of an element's text is the \"color\" style.", + "Here's how you would set the h2 element's text color to blue: <h2 style=\"color: blue\">cat photo app<h2>" ], - "challengeType": 2, - "tests": [] + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" + ], + "challengeSeed": [ + "

hello world

", + "

cat photo app

", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 }, { - "_id": "bd7116d8c441eddfaeb5bdef", - "name": "Trigger jQuery Effects", - "difficulty": 0.17, - "challengeSeed": "125658025", + "_id": "bad87fee1348bd9aedf08805", + "name": "Create a Style Tag for CSS", + "difficulty": 0.018, "description": [ - "We can use jQuery to do all kinds of visual effects and transitions.", - "Let's explore some of the fun ways we can manipulate DOM elements with jQuery.", - "Go to http://www.codecademy.com/courses/web-beginner-en-jtFIC/0/1 and complete the fifth section." + "Create a style tag and write the CSS to make all h2 elements blue.", + "With CSS, there are hundreds of CSS attributes that you can use to change the way an element looks on a web page.", + "When you entered <h2 style=\"color: red\">hello html<h2>, you were giving that individual h2 element an inline style", + "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", + "At the top of your code, create a style tag like this: <style></style>", + "Inside that style element, you can create a global style for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2: {color: red;}</style>", + "Note that it's important to have an opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of the element's styles." ], - "challengeType": 2, - "tests": [] + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(0, 0, 255)');" + ], + "challengeSeed": [ + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aecf08806", + "name": "Use a CSS Class to Style an Element", + "difficulty": 0.0185, + "description": [ + "Create a CSS class called .red-text and apply it to the h2 element.", + "Classes are reusable styles that can be added to HTML elements.", + "Classes always start with a period. You can see that we've created a CSS class called .blue-text within the <style> tag.", + "You can follow that pattern to make a .red-text class, which you can attach to HTML elements by using the class=\"class\" within the relevant element's opening tag." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aeff08806", + "name": "Use a CSS Class to Style Multiple Elements", + "difficulty": 0.019, + "description": [ + "Apply the \"red-text\" class to the h1, h2 and p elements.", + "Remember that you can attach classes to HTML elements by using the class=\"class\" within the relevant element's opening tag." + ], + "tests": [ + "expect($('h1')).to.have.class('red-text');", + "expect($('h2')).to.have.class('red-text');", + "expect($('p')).to.have.class('red-text');", + "expect($('h1')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('p')).to.have.css('color', 'rgb(255, 0, 0)');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08806", + "name": "Change the Font Size of an Element", + "difficulty": 0.020, + "description": [ + "Set the font size of all p elements to 16 pixels", + "Font size is controlled by the font-size CSS attribute.", + "We've already set the font-size attribute for all h2 elements. See if you can figure out how to give all p elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for h1." + ], + "tests": [ + "expect($('p')).to.have.css('font-size', '16px');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08807", + "name": "Import a Google Font", + "difficulty": 0.021, + "description": [ + "Apply the font-family of Lobster to all h1 elements.", + "The first line of code in your text editor is a call to Google that grabs a font called Lobster and loads it into your HTML.", + "You'll notice that we've already applied the font-family of Lobster to all h2 elements. Now you should also apply it to all h1 elements." + ], + "tests": [ + "expect($('h1')).to.have.css('font-family', 'Lobster');" + ], + "challengeSeed": [ + "", + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08808", + "name": "Specify How Fonts Should Degrade", + "difficulty": 0.022, + "description": [ + "Make all h2 elements use Lobster as their font family, but degrade to the Serif font when the Lobster font isn't available.", + "We commented out our call to Google Fonts, and now our lobter isn't available.", + "You can leave Lobster as the font, and have it degrade to a different font if that font isn't available.", + "There are several default fonts that are availble in all browsers. These include Monospace, Serif and Sans-Serif. See if you can set the h2 elements to use Lobster and degrade to monospace." + ], + "tests": [ + "expect($('h2')).to.have.css('font-family').match(/serif/i);", + "expect($('h2')).to.have.css('font-family').match(/lobster/i);" + ], + "challengeSeed": [ + "", + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08809", + "name": "Using Important to Override Styles", + "difficulty": 0.023, + "description": [ + "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", + "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", + "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", + "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", + "Look at the example in the editor's style tag to see how you can use !important.", + "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." + ], + "tests": [ + "expect($('h2')).to.have.class('urgently-red');", + "expect($('h2')).to.have.class('blue-text');", + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08810", + "name": "Use Hex Codes for Precise Colors", + "difficulty": 0.024, + "description": [ + "Change the hex code in the \"red-text\" class to hex code for the color red.", + "Hexadecimal (hex) code is a popular way of specifying color in CSS.", + "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", + "The six hex code correspond to red-red-green-green-blue-blue.", + "You can change these six values to make more than 16 million colors!", + "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", + "Now figure out how to make the bright green in the \"red-text\" class into a bright red." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9bedf08810", + "name": "Use Shortened 3 Digit Hex Codes", + "difficulty": 0.025, + "description": [ + "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", + "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08811", + "name": "Use RGB Codes for Precise Colors", + "difficulty": 0.026, + "description": [ + "Change the RGB code to be red.", + "Another way to represent color in CSS is with RGB, or red-green-blue notation.", + "For each of the three colors, you specify a value between 0 and 256.", + "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", + "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08812", + "name": "Add an Image to your Website", + "difficulty": 0.027, + "description": [ + "Use an img element to add the image http://bit.ly/cutegraycat to your website.", + "You can add images to your website by using the img element.", + "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.", + "Try it with this image: http://bit.ly/cutegraycat." + ], + "tests": [ + "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9acdf08812", + "name": "Specify an Image Size TEST", + "difficulty": 0.028, + "description": [ + "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", + "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", + "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", + "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('narrow-image');", + "expect($('img')).to.have.css('width', 200px)" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9bedf08813", + "name": "Add a Border Around an Element", + "difficulty": 0.029, + "description": [ + "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", + "CSS Borders have attributes like style, color and width.", + "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", + "expect($('img')).to.have.css('border-width', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08814", + "name": "Add Rounded Corners with a Border Radius", + "difficulty": 0.030, + "description": [ + "Give your cat photo a border radius of 10 pixels.", + "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", + "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-radius', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08815", + "name": "Make an Image Circular with a Border Radius", + "difficulty": 0.031, + "description": [ + "Give your cat photo a border-radius of 50%.", + "In addition to pixels, you can also specify a border-radius of a percentage." + ], + "tests": [ + "expect($('img')).to.have.css('border-radius', '50%');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08816", + "name": "Use an Anchor Tag to Link to an External Page", + "difficulty": 0.033, + "description": [ + "Create an anchor tag hyperlink that links to freecodecamp.com", + "" + ], + "tests": [ + "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08817", + "name": "Make Named Anchors using the Hash Symbol", + "difficulty": 0.034, + "description": [ + "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", + "Sometimes you want to add anchor elements to your website before you know where they will link.", + "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", + "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." + ], + "tests": [ + "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This named anchor leads nowhere", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08820", + "name": "Turn an Image into a Link", + "difficulty": 0.035, + "description": [ + "Wrap the gray cat's image with an anchor tag that leads nowhere.", + "You can make elements into links by wrapping them in an anchor tag.", + "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", + "Wrap your gray cat's photo in an anchor tag", + "Use the hash symbol as the anchor tag's href." + ], + "tests": [ + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08818", + "name": "Add Alt Text to an image", + "difficulty": 0.036, + "description": [ + "Add the alt text \"a photo of a cute gray cat\" to our cat photo", + "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", + "In short, every image should have alt text!", + "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." + ], + "tests": [ + "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "\"a", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad88fee1348bd9aedf08825", + "name": "Adjusting the Padding of an Element", + "difficulty": 0.037, + "description": [ + "Change the padding of the green box to match that of the red box.", + "An element's padding controls the amount of space between an element and its border.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", + "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08822", + "name": "Adjust the Margin of an Element", + "difficulty": 0.038, + "description": [ + "Change the margin of the green box to match that of the red box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", + "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08823", + "name": "Add a Negative Margin to an Element", + "difficulty": 0.039, + "description": [ + "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "If you set an element's margin to a negative value, the element will grow larger.", + "Try to set the margin to a negative value like the one for the red box." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '-15px')" + ], + "challengeSeed": [ + "", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08824", + "name": "Add Different Padding to Each Side of an Element TEST", + "difficulty": 0.040, + "description": [ + "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has different padding on each of its sides.", + "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding-bottom', '20px')", + "expect($('.green-box')).to.have.css('padding-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1248bd9aedf08824", + "name": "Add Different a Margin to Each Side of an Element TEST", + "difficulty": 0.041, + "description": [ + "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", + "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08826", + "name": "Use Clockwise Notation to Specify an Element's Padding", + "difficulty": 0.042, + "description": [ + "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9acde08812", + "name": "Use Bootstrap for Responsive Images", + "difficulty": 0.043, + "description": [ + "Add the img-responsive Bootstrap class to the image.", + "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", + "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", + "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", + "Now all you need to do is add the img-responsive class to your image." + ], + "tests": [ + "expect($('img')).to.have.class('img-responsive');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd8acde08812", + "name": "Center Text with Bootstrap", + "difficulty": 0.044, + "description": [ + "Add Bootstrap's text-center class to your h2 element.", + "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", + "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." + ], + "tests": [ + "expect($('h2')).to.have.class('text-center');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348cd8acde08812", + "name": "Create a Button", + "difficulty": 0.045, + "description": [ + "Create a button with the text \"Delete\" using the HTML button element.", + "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." + ], + "tests": [ + "expect((/delete/gi).test($('button').text())).to.be.true;" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348cd8acdf08812", + "name": "Create a Bootstrap Button", + "difficulty": 0.046, + "description": [ + "Apply the Bootstrap's btn class to both of your buttons.", + "Bootstrap has its own button styles, which look much better than the plain HTML ones." + ], + "tests": [ + "expect($('.btn').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348cd8acef08812", + "name": "Create a Block Element Bootstrap Button", + "difficulty": 0.047, + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348cd8acef08811", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty": 0.048, + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348cd8acef08813", + "name": "Color a Bootstrap Button with Button Info", + "difficulty": 0.049, + "description": [ + "Add Bootstrap's btn-primary class to both of your buttons.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", + "Note that these buttons still need the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-primary').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348ce8acef08814", + "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", + "difficulty": 0.050, + "description": [ + "Change the \"Delete\" button from btn-primary to btn-danger.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", + "Note that this button still needs the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-danger').length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad88fee1348ce8acef08815", + "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", + "difficulty": 0.051, + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad89fee1348ce8acef08816", + "name": "Wrap Side By Side Elements in a Bootstrap Row", + "difficulty": 0.052, + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08813", + "name": "Add Alt Text to an Image TEST", + "difficulty": 0.053, + "description": [ + "Add the alt text \"A picture of a gray cat\" to the image.", + "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", + "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." + ], + "tests": [ + "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 }, { "_id": "bd7123d8c441eddfaeb5bdef", diff --git a/seed_data/future-coursewares.json b/seed_data/future-coursewares.json index badb123236..0967ef424b 100644 --- a/seed_data/future-coursewares.json +++ b/seed_data/future-coursewares.json @@ -1,2588 +1 @@ -[ - { - "_id" : "bd7123d8c441eddfaeb5bdef", - "name": "Learn how Free Code Camp Works", - "difficulty": 0.00, - "description": [ - "Watch this 90 second video, or simply read this summary:", - "Welcome to Free Code Camp. We're a community of busy people learning to code.", - "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And the best way to stay motivated is to code with friends.", - "To maximize accessibility, all our challenges are self-paced, browser-based, and free.", - "All of us start with the same 100 hours of interactive coding challenges. These cover Computer Science and databases. They also cover in-demand JavaScript tools like jQuery, Node.js and MongoDB.", - "Once we have a basic understanding of web development, we'll spend another 900 hours putting that theory into practice. We'll build full stack solutions for nonprofits.", - "By the end of this process, we'll be good at coding. We'll have a portfolio of apps with happy users to prove it. We'll also have an alumni network of fellow coders and nonprofits ready to serve as references.", - "If you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", - "Also, for every pure coding job, there are at least 5 additional jobs that require some coding skills. So even if you decide not to pursue coding as a career, you'll still walk away with a valuable job skill.", - "There are 3 keys to succeeding in our community: do the challenges, make friends, and find a routine.", - "Now it's time to join our chatroom. Click the \"Go to my next challenge\" button to move on to your next challenge." - ], - "tests": [ - "" - ], - "challengeSeed": [ - "114486344" - ], - "challengeType" : 2 - }, - { - "_id": "bd7123c8c441eddfaeb5bdef", - "name": "Meet Booleans", - "difficulty": "0.001", - "description": [ - "Return true" - ], - "tests": [ - "expect(welcomeToBooleans()).to.be.a(\"boolean\");", - "expect(welcomeToBooleans()).to.be.true;" - ], - "challengeSeed": [ - "function welcomeToBooleans() {\n // Good luck!\n return false;\n}\n\nwelcomeToBooleans();" - ], - "challengeType": 1 - }, - { - "_id" : "bd7123c8c441eddfaeb5bdef", - "name": "Start our Challenges", - "difficulty": "0.002", - "description": [ - "Welcome to Free Code Camp's first challenge! Click on the button below for further instructions.", - "Awesome. Now you can read the rest of this challenge's instructions.", - "You can edit code in the text editor we've embedded into this web page.", - "Do you see the code in the text editor that says <h1>hello</h1>? That's an HTML element.", - "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", - "Once you've completed the challenge, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", - "To enable the \"Go to my next challenge\" button on this exercise, change the h1 tag's text to say \"Hello World\" instead of \"Hello\"." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" - ], - "challengeSeed": [ - "

Hello

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf0887a", - "name": "Use the h2 Element", - "difficulty" : "0.01", - "description": [ - "Add an h2 tag that says \"cat photo app\" to make a second HTML element below the \"hello world\" h1 element.", - "The h2 element you enter will create an h2 element on the website.", - "This element tells the browser how to render the text that it contains.", - "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;", - "expect((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text())).to.be.true;" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08801", - "name": "Use the P Element", - "difficulty" : "0.02", - "description": [ - "Create a p element below the h2 element, and give it the text \"hello paragraph\".", - "p elements are the preferred element for normal-sized paragraph text on websites.", - "You can create a p element like so: <p>I'm a p tag!</p>" - ], - "tests": [ - "expect((/hello(\\s)+paragraph/gi).test($('p').text())).to.be.true;" - ], - "challengeSeed": [ - "

hello world

", - "

hello html

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aeaf08801", - "name": "Add a Line Break to Visually Separate Elements", - "difficulty" : "0.03", - "description": [ - "Add a line break between the <h2> and <p> elements.", - "You can create an line break element with <br/>.", - "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?" - ], - "tests": [ - "expect($('br')).to.exist;" - ], - "challengeSeed": [ - "

hello world

", - "

hello html

", - "

hello paragraph

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08802", - "name": "Uncomment HTML", - "difficulty" : "0.04", - "description": [ - "Uncomment the h1, h2 and p elements.", - "Commenting is a way that you can leave comments within your code without affecting the code itself.", - "Commenting is also a convenient way to make code inactive without having to delete it entirely.", - "You can start a comment with <!-- and end a comment with -->." - ], - "tests": [ - "expect((/hello(\\s)+world/gi).test($('h1').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08809", - "name": "Using Important to Override Styles", - "difficulty" : "0.14", - "description": [ - "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", - "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", - "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", - "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", - "Look at the example in the editor's style tag to see how you can use !important.", - "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." - ], - "tests": [ - "expect($('h2')).to.have.class('urgently-red');", - "expect($('h2')).to.have.class('blue-text');", - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08810", - "name": "Use Hex Codes for Precise Colors", - "difficulty" : "0.15", - "description": [ - "Change the hex code in the \"red-text\" class to hex code for the color red.", - "Hexadecimal (hex) code is a popular way of specifying color in CSS.", - "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", - "The six hex code correspond to red-red-green-green-blue-blue.", - "You can change these six values to make more than 16 million colors!", - "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", - "Now figure out how to make the bright green in the \"red-text\" class into a bright red." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08810", - "name": "Use Shortened 3 Digit Hex Codes", - "difficulty" : "0.16", - "description": [ - "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", - "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08811", - "name": "Use RGB Codes for Precise Colors", - "difficulty" : "0.17", - "description": [ - "Change the RGB code to be red.", - "Another way to represent color in CSS is with RGB, or red-green-blue notation.", - "For each of the three colors, you specify a value between 0 and 256.", - "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", - "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08812", - "name": "Add an Image to your Website", - "difficulty" : "0.18", - "description": [ - "Use an img element to add the image http://bit.ly/cutegraycat to your website.", - "You can add images to your website by using the img element.", - "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.", - "Try it with this image: http://bit.ly/cutegraycat." - ], - "tests": [ - "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size TEST", - "difficulty" : "0.19", - "description": [ - "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", - "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", - "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", - "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('narrow-image');", - "expect($('img')).to.have.css('width', 200px)" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08813", - "name": "Add a Border Around an Element", - "difficulty" : "0.20", - "description": [ - "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", - "CSS Borders have attributes like style, color and width.", - "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", - "expect($('img')).to.have.css('border-width', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08814", - "name": "Add Rounded Corners with a Border Radius", - "difficulty" : "0.21", - "description": [ - "Give your cat photo a border radius of 10 pixels.", - "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", - "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-radius', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08815", - "name": "Make an Image Circular with a Border Radius", - "difficulty" : "0.22", - "description": [ - "Give your cat photo a border-radius of 50%.", - "In addition to pixels, you can also specify a border-radius of a percentage." - ], - "tests": [ - "expect($('img')).to.have.css('border-radius', '50%');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08816", - "name": "Use an Anchor Tag to Link to an External Page", - "difficulty" : "0.23", - "description": [ - "Create an anchor tag hyperlink that links to freecodecamp.com", - "" - ], - "tests": [ - "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08817", - "name": "Make Named Anchors using the Hash Symbol", - "difficulty" : "0.24", - "description": [ - "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", - "Sometimes you want to add anchor elements to your website before you know where they will link.", - "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", - "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." - ], - "tests": [ - "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This named anchor leads nowhere", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08820", - "name": "Turn an Image into a Link", - "difficulty" : "0.25", - "description": [ - "Wrap the gray cat's image with an anchor tag that leads nowhere.", - "You can make elements into links by wrapping them in an anchor tag.", - "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", - "Wrap your gray cat's photo in an anchor tag", - "Use the hash symbol as the anchor tag's href." - ], - "tests": [ - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08818", - "name": "Add Alt Text to an image", - "difficulty" : "0.26", - "description": [ - "Add the alt text \"a photo of a cute gray cat\" to our cat photo", - "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", - "In short, every image should have alt text!", - "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." - ], - "tests": [ - "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "\"a", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348bd9aedf08825", - "name": "Adjusting the Padding of an Element", - "difficulty" : "0.27", - "description": [ - "Change the padding of the green box to match that of the red box.", - "An element's padding controls the amount of space between an element and its border.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", - "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08822", - "name": "Adjust the Margin of an Element", - "difficulty" : "0.28", - "description": [ - "Change the margin of the green box to match that of the red box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", - "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08823", - "name": "Add a Negative Margin to an Element", - "difficulty" : "0.29", - "description": [ - "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "If you set an element's margin to a negative value, the element will grow larger.", - "Try to set the margin to a negative value like the one for the red box." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '-15px')" - ], - "challengeSeed": [ - "", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08824", - "name": "Add Different Padding to Each Side of an Element TEST", - "difficulty" : "0.30", - "description": [ - "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has different padding on each of its sides.", - "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding-bottom', '20px')", - "expect($('.green-box')).to.have.css('padding-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1248bd9aedf08824", - "name": "Add Different a Margin to Each Side of an Element TEST", - "difficulty" : "0.31", - "description": [ - "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", - "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08826", - "name": "Use Clockwise Notation to Specify an Element's Padding", - "difficulty" : "0.32", - "description": [ - "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", - "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", - "You can also use this notation for margins!" - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acde08812", - "name": "Use Bootstrap for Responsive Images", - "difficulty" : "0.33", - "description": [ - "Add the img-responsive Bootstrap class to the image.", - "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", - "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", - "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", - "Now all you need to do is add the img-responsive class to your image." - ], - "tests": [ - "expect($('img')).to.have.class('img-responsive');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd8acde08812", - "name": "Center Text with Bootstrap", - "difficulty" : "0.34", - "description": [ - "Add Bootstrap's text-center class to your h2 element.", - "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." - ], - "tests": [ - "expect($('h2')).to.have.class('text-center');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acde08812", - "name": "Create a Button", - "difficulty" : "0.35", - "description": [ - "Create a button with the text \"Delete\" using the HTML button element.", - "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." - ], - "tests": [ - "expect((/delete/gi).test($('button').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acdf08812", - "name": "Create a Bootstrap Button", - "difficulty" : "0.36", - "description": [ - "Apply the Bootstrap's btn class to both of your buttons.", - "Bootstrap has its own button styles, which look much better than the plain HTML ones." - ], - "tests": [ - "expect($('.btn').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Create a Block Element Bootstrap Button", - "difficulty" : "0.37", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.38", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.39", - "description": [ - "Add Bootstrap's btn-primary class to both of your buttons.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", - "Note that these buttons still need the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-primary').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348ce8acef08812", - "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", - "difficulty" : "0.40", - "description": [ - "Change the \"Delete\" button from btn-primary to btn-danger.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", - "Note that this button still needs the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-danger').length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348ce8acef08812", - "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", - "difficulty" : "0.41", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad89fee1348ce8acef08812", - "name": "Wrap Side By Side Elements in a Bootstrap Row", - "difficulty" : "0.42", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08813", - "name": "Add Alt Text to an Image TEST", - "difficulty" : "0.43", - "description": [ - "Add the alt text \"A picture of a gray cat\" to the image.", - "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", - "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." - ], - "tests": [ - "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08827", - "name": "Create an Bulleted Unordered List", - "difficulty" : "0.44", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08828", - "name": "Created a Numbered Ordered List", - "difficulty" : "0.45", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08829", - "name": "Create a Text Field", - "difficulty" : "0.46", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08830", - "name": "Use HTML5 to Make a Field Required", - "difficulty" : "0.47", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08831", - "name": "Use HTML5 to Specify an Input Type", - "difficulty" : "0.49", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08832", - "name": "Create a Text Area", - "difficulty" : "0.50", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08834", - "name": "Create a Set of Radio Buttons", - "difficulty" : "0.51", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08835", - "name": "Create a Set of Checkboxes", - "difficulty" : "0.52", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08836", - "name": "Create a HTML Form", - "difficulty" : "0.53", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08841", - "name": "Change the background of element", - "difficulty" : "0.54", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08842", - "name": "Make an element translucent", - "difficulty" : "0.55", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08844", - "name": "Add a Drop Shadow", - "difficulty" : "0.56", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08845", - "name": "Make a Navbar", - "difficulty" : "0.57", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08847", - "name": "Add a Logo to a Navbar", - "difficulty" : "0.58", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08848", - "name": "Make a Footer", - "difficulty" : "0.59", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08849", - "name": "Use Icons as Links", - "difficulty" : "0.60", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08850", - "name": "Add Hover Effects to Icons", - "difficulty" : "0.61", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08851", - "name": "Add Depth to a Page with a Well", - "difficulty" : "0.62", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08852", - "name": "Add an ID to a Button", - "difficulty" : "0.52", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08853", - "name": "Fire a Modal by Clicking a Button", - "difficulty" : "0.63", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08854", - "name": "Style a Modal with a Header", - "difficulty" : "0.64", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08855", - "name": "Style a Modal with a Body", - "difficulty" : "0.65", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08856", - "name": "Make a Modal Dismissable", - "difficulty" : "0.66", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08857", - "name": "Create an Accordian Menu", - "difficulty" : "0.67", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08863", - "name": "Add a Gradient to a Button", - "difficulty" : "0.68", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08864", - "name": "Adjust the Line Height of Text", - "difficulty" : "0.69", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08866", - "name": "", - "difficulty" : "0.70", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08867", - "name": "", - "difficulty" : "0.71", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08868", - "name": "", - "difficulty" : "0.711", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08869", - "name": "", - "difficulty" : "0.712", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08870", - "name": "", - "difficulty" : "0.713", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08871", - "name": "", - "difficulty" : "0.714", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08872", - "name": "", - "difficulty" : "0.72", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08873", - "name": "", - "difficulty" : "0.73", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08874", - "name": "", - "difficulty" : "0.74", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08875", - "name": "", - "difficulty" : "0.75", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08876", - "name": "", - "difficulty" : "0.76", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08877", - "name": "", - "difficulty" : "0.77", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08878", - "name": "", - "difficulty" : "0.78", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08879", - "name": "", - "difficulty" : "0.79", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08880", - "name": "", - "difficulty" : "0.80", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08881", - "name": "", - "difficulty" : "0.81", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08882", - "name": "", - "difficulty" : "0.82", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08883", - "name": "", - "difficulty" : "0.83", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08884", - "name": "", - "difficulty" : "0.84", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08885", - "name": "", - "difficulty" : "0.85", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08886", - "name": "", - "difficulty" : "0.86", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08887", - "name": "", - "difficulty" : "0.87", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08888", - "name": "", - "difficulty" : "0.88", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08889", - "name": "", - "difficulty" : "0.89", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08890", - "name": "", - "difficulty" : "0.90", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08891", - "name": "", - "difficulty" : "0.91", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08892", - "name": "", - "difficulty" : "0.92", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08893", - "name": "", - "difficulty" : "0.93", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08894", - "name": "", - "difficulty" : "0.94", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08895", - "name": "", - "difficulty" : "0.95", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08896", - "name": "", - "difficulty" : "0.96", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08897", - "name": "", - "difficulty" : "0.97", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08898", - "name": "", - "difficulty" : "0.98", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08899", - "name": "", - "difficulty" : "0.99", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08100", - "name": "", - "difficulty" : "1.00", - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0 - } - -] +{} From da9ac03a341510cd95a72d5cd5714c386ea2a8e7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 11 May 2015 13:58:59 -0700 Subject: [PATCH 02/81] created a chai test for css attributes --- seed_data/coursewares.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index e27ab751f7..a260ea7af5 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -333,11 +333,11 @@ "Here's how you would set the h2 element's text color to blue: <h2 style=\"color: blue\">cat photo app<h2>" ], "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" ], "challengeSeed": [ - "

hello world

", - "

cat photo app

", + "

Cat Photo App

", + "", "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" ], "challengeType": 0 From 2091f65dfdb4a7df31f9b25428b1284e0509ea51 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 11 May 2015 14:27:29 -0700 Subject: [PATCH 03/81] more courseware improvements --- seed_data/coursewares.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index a260ea7af5..027ac56e6e 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -347,21 +347,22 @@ "name": "Create a Style Tag for CSS", "difficulty": 0.018, "description": [ - "Create a style tag and write the CSS to make all h2 elements blue.", + "Create remove your h2 element's style tag and write the CSS to make all h2 elements blue.", "With CSS, there are hundreds of CSS attributes that you can use to change the way an element looks on a web page.", - "When you entered <h2 style=\"color: red\">hello html<h2>, you were giving that individual h2 element an inline style", + "When you entered <h2 style=\"color: red\">Cat Photo App<h2>, you were giving that individual h2 element an inline style", "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", "At the top of your code, create a style tag like this: <style></style>", "Inside that style element, you can create a global style for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2: {color: red;}</style>", "Note that it's important to have an opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of the element's styles." ], "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(0, 0, 255)');" + "assert($('h2').css('color') === 'rgb(0, 0, 255)', 'Your h2 element should be blue.')", + "assert(!$('h2').attr('style'), 'You should remove the style attribute from your h2 element.')" ], "challengeSeed": [ - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" ], "challengeType": 0 }, From 4d0017a4d45542c8ffd9f15956c0b5515a8c92e0 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 11 May 2015 23:40:04 -0700 Subject: [PATCH 04/81] bower install jshint and build more coursewares --- bower.json | 3 +- seed_data/coursewares.json | 156 +++++++++++++++++++++----------- views/bonfire/show.jade | 2 +- views/coursewares/showHTML.jade | 2 +- views/coursewares/showJS.jade | 2 +- 5 files changed, 107 insertions(+), 58 deletions(-) diff --git a/bower.json b/bower.json index 0d92dd37c2..cd8cfd5cf3 100644 --- a/bower.json +++ b/bower.json @@ -25,6 +25,7 @@ "font-awesome": "~4.3.0", "moment": "~2.10.2", "angular-bootstrap": "~0.13.0", - "ramda": "~0.13.0" + "ramda": "~0.13.0", + "jshint": "~2.7.0" } } diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 027ac56e6e..2a9a2e9288 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -277,13 +277,14 @@ "name": "Use Lorem Ipsum Text as a Placeholder", "difficulty": 0.015, "description": [ - "Change the text in the p element to use the first few words of lorem ipsum text.", - "Web developers use lorem ipsum as placeholder text. It's called lorem ipsum text because it's those are the first two words of a passage by Cicero of Ancient Rome.", - "Lorem ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", - "Here are the first 25 words of Lorem Ipsum text, which you can copy and paste into the right position: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + "Change the text in the p element to use the first few words of Kitty Ipsum text.", + "Web developers traditionally use Lorem Ipsum as placeholder text. It's called Lorem Ipsum text because those are the first two words of a famous passage by Cicero of Ancient Rome.", + "Lorem Ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", + "Well, 5 centuries is long enough. Since we're building a cat photo app, let's use something called Kitty Ipsum!", + "Here are the first few words of Kitty Ipsum text, which you can copy and paste into the right position: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff." ], "tests": [ - "assert.isTrue((/Lorem(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your p element should contain the first few words of the famous Lorem Ipsum text.')" + "assert.isTrue((/Kitty(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your p element should contain the first few words of the famous Kitty Ipsum text.')" ], "challengeSeed": [ "

Hello World

", @@ -352,7 +353,7 @@ "When you entered <h2 style=\"color: red\">Cat Photo App<h2>, you were giving that individual h2 element an inline style", "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", "At the top of your code, create a style tag like this: <style></style>", - "Inside that style element, you can create a global style for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2: {color: red;}</style>", + "Inside that style element, you can create a global style for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>", "Note that it's important to have an opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of the element's styles." ], "tests": [ @@ -373,40 +374,42 @@ "description": [ "Create a CSS class called .red-text and apply it to the h2 element.", "Classes are reusable styles that can be added to HTML elements.", + "Here's the anatomy of a CSS class:", + "", "Classes always start with a period. You can see that we've created a CSS class called .blue-text within the <style> tag.", - "You can follow that pattern to make a .red-text class, which you can attach to HTML elements by using the class=\"class\" within the relevant element's opening tag." + "You can apply a class to an element like this: <h2 class=\"blue-text\">Cat Photo App<h2>", + "Instead of creating a new Style tag, try removing the h2 style declaration from the existing style element, and replace it with the class declaration for \".red-text\"." ], "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')" ], "challengeSeed": [ "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "", + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" ], "challengeType": 0 }, { - "_id": "bad87fee1348bd9aeff08806", + "_id": "bad87fee1348bd9aefe08806", "name": "Use a CSS Class to Style Multiple Elements", "difficulty": 0.019, "description": [ - "Apply the \"red-text\" class to the h1, h2 and p elements.", + "Apply the \"red-text\" class to the h2 and p elements.", "Remember that you can attach classes to HTML elements by using the class=\"class\" within the relevant element's opening tag." ], "tests": [ - "expect($('h1')).to.have.class('red-text');", - "expect($('h2')).to.have.class('red-text');", - "expect($('p')).to.have.class('red-text');", - "expect($('h1')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('p')).to.have.css('color', 'rgb(255, 0, 0)');" + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')", + "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('p').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')" ], "challengeSeed": [ "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "", + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" ], "challengeType": 0 }, @@ -426,23 +430,54 @@ "difficulty": 0.020, "description": [ "Set the font size of all p elements to 16 pixels", - "Font size is controlled by the font-size CSS attribute.", - "We've already set the font-size attribute for all h2 elements. See if you can figure out how to give all p elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for h1." + "Font size is controlled by the font-size CSS attribute, like this: h1 { font-size: 30px; }.", + "First, create a second p element with the following Kitty Ipsum text: Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.", + "See if you can figure out how to give both of your p elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for your .red-text class." ], "tests": [ - "expect($('p')).to.have.css('font-size', '16px');" + "assert($('p').length > 1, 'You need 2 p elements with Kitty Ipsum text.')", + "assert($('p').css('font-size') === '16px', 'Your p elements should have be 16px font.')" ], "challengeSeed": [ "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aede08807", + "name": "Set the Font of an Element", + "difficulty": 0.0205, + "description": [ + "Make all p elements use the \"Monospace\" font.", + "You can set an element's font by using the font-family attribute.", + "For example, if you wanted to set your h2 element's font \"San-serif\", you would use the following CSS: h2 { font-family: 'San-serif'; }" + ], + "tests": [ + "assert($('p').css('font-family').match(/monospace/i, 'Your p elements should use the font \"Monospace\".')" + ], + "challengeSeed": [ + "", + "", + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, @@ -451,29 +486,31 @@ "name": "Import a Google Font", "difficulty": 0.021, "description": [ - "Apply the font-family of Lobster to all h1 elements.", - "The first line of code in your text editor is a call to Google that grabs a font called Lobster and loads it into your HTML.", - "You'll notice that we've already applied the font-family of Lobster to all h2 elements. Now you should also apply it to all h1 elements." + "Apply the font-family of Lobster to your h2 element.", + "First, you'll need to make a call to Google to grab the \"Lobster\" font and loads it into your HTML.", + "Copy and paste this into your code editor above your style element:", + "<link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>", + "Now you can set \"Lobster\" as a font-family attribute." ], "tests": [ - "expect($('h1')).to.have.css('font-family', 'Lobster');" + "assert($('h2').css('font-family').match(/lobster/i', 'Your h2 element should use the font \"Lobster\".')" ], "challengeSeed": [ - "", "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, @@ -482,26 +519,37 @@ "name": "Specify How Fonts Should Degrade", "difficulty": 0.022, "description": [ - "Make all h2 elements use Lobster as their font family, but degrade to the Serif font when the Lobster font isn't available.", - "We commented out our call to Google Fonts, and now our lobter isn't available.", + "Make all h2 elements use \"Lobster\" as their font family, but degrade to the \"Monospace\" font when the Lobster font isn't available.", + "Commented out your call to Google Fonts, so that our \"Lobter\" isn't available.", "You can leave Lobster as the font, and have it degrade to a different font if that font isn't available.", - "There are several default fonts that are availble in all browsers. These include Monospace, Serif and Sans-Serif. See if you can set the h2 elements to use Lobster and degrade to monospace." + "For example, if you prefer \"Helvetica\", but want to degrade to \"Sans-Serif\" when Helvetica isn't available, you can do use this style: <p { font-family: \"Helvetica\", \"Sans-Serif\"; } >", + "There are several default fonts that are available in all browsers. These include \"Monospace\", \"Serif\" and \"Sans-Serif\". See if you can set the h2 elements to use \"Lobster\" and degrade to \"Monospace\"." ], "tests": [ - "expect($('h2')).to.have.css('font-family').match(/serif/i);", - "expect($('h2')).to.have.css('font-family').match(/lobster/i);" + "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')", + "assert($('h2').css('font-family').match(/monospace/i), 'Your h2 element should degrade to the font \"Monospace\" when \"Lobster\" is not available.')" ], "challengeSeed": [ - "", + "", "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, diff --git a/views/bonfire/show.jade b/views/bonfire/show.jade index 9a28e530c2..1383241a9d 100644 --- a/views/bonfire/show.jade +++ b/views/bonfire/show.jade @@ -6,7 +6,7 @@ block content 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/javascript-lint.js') - script(type='text/javascript', src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(type='text/javascript', src='/bower_components/jshint/dist/jshint.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/addon/lint/lint.css') diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 6349650804..2ca19662a0 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -5,7 +5,7 @@ block content script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') script(src='/js/lib/codemirror/addon/lint/lint.js') script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') - script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(src='/bower_components/jshint/dist/jshint.js') script(src='/js/lib/chai/chai.js') script(src='/js/lib/chai/chai-jquery.js') link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index b55d8ad4d9..7e87587f93 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -5,7 +5,7 @@ block content script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') script(src='/js/lib/codemirror/addon/lint/lint.js') script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') - script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(src='/bower_components/jshint/dist/jshint.js') script(src='/js/lib/chai/chai.js') link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') From d2044eca06df9c0222e0a534fd829d057a30b9dc Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 12 May 2015 15:36:41 -0700 Subject: [PATCH 05/81] add some additional coursewares to front end curriculum --- seed_data/coursewares.json | 48 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 2a9a2e9288..614ae432d3 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -345,7 +345,7 @@ }, { "_id": "bad87fee1348bd9aedf08805", - "name": "Create a Style Tag for CSS", + "name": "Use CSS Selectors to Style Elements", "difficulty": 0.018, "description": [ "Create remove your h2 element's style tag and write the CSS to make all h2 elements blue.", @@ -353,7 +353,7 @@ "When you entered <h2 style=\"color: red\">Cat Photo App<h2>, you were giving that individual h2 element an inline style", "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", "At the top of your code, create a style tag like this: <style></style>", - "Inside that style element, you can create a global style for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>", + "Inside that style element, you can create a css selector for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>", "Note that it's important to have an opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of the element's styles." ], "tests": [ @@ -408,8 +408,8 @@ "tests": [ "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')", - "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", - "assert($('p').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')" + "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your p element should be red.')", + "assert($('p').hasClass('red-text'), 'You p element should have the class \"red-text\".')" ], "challengeSeed": [ "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, From 3ecf56d9fd30ed221a612896a4b45317500959e4 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 12 May 2015 17:09:13 -0700 Subject: [PATCH 06/81] finish courseware 29 --- seed_data/coursewares.json | 224 +++++++++++++++---------------------- 1 file changed, 91 insertions(+), 133 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 614ae432d3..d8e5f428e4 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -567,8 +567,8 @@ "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." ], "tests": [ - "assert($('h2').hasClass('blue-text'), 'You h2 element should have the class \"blue-text\".')", - "assert($('h2').hasClass('urgently-red'), 'You h2 element should have the class \"urgently-red\".')", + "assert($('h2').hasClass('blue-text'), 'Your h2 element should have the class \"blue-text\".')", + "assert($('h2').hasClass('urgently-red'), 'Your h2 element should have the class \"urgently-red\".')", "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" ], "challengeSeed": [ @@ -595,143 +595,81 @@ ], "challengeType": 0 }, - { - "_id": "bad87fee1348bd9aedf08810", - "name": "Use Hex Codes for Precise Colors", - "difficulty": 0.024, - "description": [ - "Change the hex code in the \"red-text\" class to hex code for the color red.", - "Hexadecimal (hex) code is a popular way of specifying color in CSS.", - "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", - "The six hex code correspond to red-red-green-green-blue-blue.", - "You can change these six values to make more than 16 million colors!", - "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", - "Now figure out how to make the bright green in the \"red-text\" class into a bright red." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9bedf08810", - "name": "Use Shortened 3 Digit Hex Codes", - "difficulty": 0.025, - "description": [ - "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", - "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9aedf08811", - "name": "Use RGB Codes for Precise Colors", - "difficulty": 0.026, - "description": [ - "Change the RGB code to be red.", - "Another way to represent color in CSS is with RGB, or red-green-blue notation.", - "For each of the three colors, you specify a value between 0 and 256.", - "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", - "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, + { "_id": "bad87fee1348bd9aedf08812", "name": "Add an Image to your Website", "difficulty": 0.027, "description": [ - "Use an img element to add the image http://bit.ly/cutegraycat to your website.", + "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", "You can add images to your website by using the img element.", "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.", "Try it with this image: http://bit.ly/cutegraycat." ], "tests": [ - "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" + "assert($('img').length > 0, 'Your webpage should have an image element.')", + "assert(!!$('img').attr('src'), 'Your image should have have a src attribute that points to the kitten image.')" ], "challengeSeed": [ + "", "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + "

Cat Photo App

", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, { "_id": "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size TEST", + "name": "Specify an Image Size", "difficulty": 0.028, "description": [ - "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", - "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", + "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", - "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." + "Create a class called smaller-image and added it to the image element. Change the width to 100 pixels." ], "tests": [ - "expect($('img')).to.have.class('narrow-image');", - "expect($('img')).to.have.css('width', 200px)" + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').width() === 100, 'Your image should be 100 pixels wide.')" ], "challengeSeed": [ + "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" + "", + "

Cat Photo App

", + "", + "", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, @@ -740,35 +678,43 @@ "name": "Add a Border Around an Element", "difficulty": 0.029, "description": [ - "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", + "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border around your cat photo.", "CSS Borders have attributes like style, color and width.", "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." ], "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", - "expect($('img')).to.have.css('border-width', '10px');" + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", + "assert($('img').css('border-left-color') === 'rgb(0,128,0)', 'This test is broken. Sorry. Your image should have a green border.')", + "assert(parseInt($('img').css('border-left-width')) > 8, 'Your image should have a border with a width of 10 pixels.')" ], "challengeSeed": [ + "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" + "", + "

Cat Photo App

", + "", + "", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, @@ -782,30 +728,42 @@ "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." ], "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-radius', '10px');" + "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", + "assert(parseInt($('img').css('border-top-left-radius')) > 8, 'Your image should have a border radius of 10 pixels')" ], "challengeSeed": [ + "", "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" + "", + "

Cat Photo App

", + "", + "", + "", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "

Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

" ], "challengeType": 0 }, From e8e538b1fa0823e430f132ed7926df7aa8999e20 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 12 May 2015 19:44:40 -0700 Subject: [PATCH 07/81] add additional coursewares --- seed_data/coursewares.json | 229 ++++++++++++++++++++++++++----------- 1 file changed, 164 insertions(+), 65 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index d8e5f428e4..cb0394a2cb 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -181,15 +181,15 @@ }, { "_id": "bad87fee1348bd9aedf08801", - "name": "Use the P Element", + "name": "Use the Paragraph Element", "difficulty": 0.011, "description": [ - "Create a p element below the h2 element, and give it the text \"Hello Paragraph\".", - "p elements are the preferred element for normal-sized paragraph text on websites.", - "You can create a p element like so: <p>I'm a p tag!</p>" + "Create a paragraph element below the h2 element, and give it the text \"Hello Paragraph\".", + "Paragraph elements are the preferred element for normal-sized paragraph text on websites.", + "You can create a paragraph element like so: <p>I'm a p tag!</p>" ], "tests": [ - "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your p element should have the text \"Hello Paragraph\"')" + "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your paragraph element should have the text \"Hello Paragraph\"')" ], "challengeSeed": [ "

Hello World

", @@ -208,7 +208,7 @@ "You'll encounter other self-closing element tags soon." ], "tests": [ - "assert(($('br').length > 0), 'You should have a br element between your h2 and p elements.')" + "assert(($('br').length > 0), 'You should have a br element between your h2 and paragraph elements.')" ], "challengeSeed": [ "

Hello World

", @@ -230,7 +230,7 @@ "tests": [ "assert(($('h1').length > 0), 'The h1 element should not commented. It should be visible in the browser.')", "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", - "assert(($('p').length > 0), 'The p element should not commented. It should be visible in the browser.')" + "assert(($('p').length > 0), 'The paragraph element should not commented. It should be visible in the browser.')" ], "challengeSeed": [ "", + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08809", + "name": "Using Important to Override Styles", + "difficulty" : "0.14", + "description": [ + "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", + "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", + "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", + "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", + "Look at the example in the editor's style tag to see how you can use !important.", + "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." + ], + "tests": [ + "expect($('h2')).to.have.class('urgently-red');", + "expect($('h2')).to.have.class('blue-text');", + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08810", + "name": "Use Hex Codes for Precise Colors", + "difficulty" : "0.15", + "description": [ + "Change the hex code in the \"red-text\" class to hex code for the color red.", + "Hexadecimal (hex) code is a popular way of specifying color in CSS.", + "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", + "The six hex code correspond to red-red-green-green-blue-blue.", + "You can change these six values to make more than 16 million colors!", + "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", + "Now figure out how to make the bright green in the \"red-text\" class into a bright red." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9bedf08810", + "name": "Use Shortened 3 Digit Hex Codes", + "difficulty" : "0.16", + "description": [ + "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", + "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08811", + "name": "Use RGB Codes for Precise Colors", + "difficulty" : "0.17", + "description": [ + "Change the RGB code to be red.", + "Another way to represent color in CSS is with RGB, or red-green-blue notation.", + "For each of the three colors, you specify a value between 0 and 256.", + "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", + "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." + ], + "tests": [ + "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", + "expect($('h2')).to.have.class('red-text');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08812", + "name": "Add an Image to your Website", + "difficulty" : "0.18", + "description": [ + "Use an img element to add the image http://bit.ly/cutegraycat to your website.", + "You can add images to your website by using the img element.", + "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.", + "Try it with this image: http://bit.ly/cutegraycat." + ], + "tests": [ + "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" + ], + "challengeSeed": [ + "", + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9acdf08812", + "name": "Specify an Image Size TEST", + "difficulty" : "0.19", + "description": [ + "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", + "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", + "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", + "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('narrow-image');", + "expect($('img')).to.have.css('width', 200px)" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9bedf08813", + "name": "Add a Border Around an Element", + "difficulty" : "0.20", + "description": [ + "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", + "CSS Borders have attributes like style, color and width.", + "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", + "expect($('img')).to.have.css('border-width', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08814", + "name": "Add Rounded Corners with a Border Radius", + "difficulty" : "0.21", + "description": [ + "Give your cat photo a border radius of 10 pixels.", + "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", + "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." + ], + "tests": [ + "expect($('img')).to.have.class('thick-green-border');", + "expect($('img')).to.have.css('border-radius', '10px');" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08815", + "name": "Make an Image Circular with a Border Radius", + "difficulty" : "0.22", + "description": [ + "Give your cat photo a border-radius of 50%.", + "In addition to pixels, you can also specify a border-radius of a percentage." + ], + "tests": [ + "expect($('img')).to.have.css('border-radius', '50%');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08816", + "name": "Use an Anchor Tag to Link to an External Page", + "difficulty" : "0.23", + "description": [ + "Create an anchor tag hyperlink that links to freecodecamp.com", + "" + ], + "tests": [ + "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08817", + "name": "Make Named Anchors using the Hash Symbol", + "difficulty" : "0.24", + "description": [ + "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", + "Sometimes you want to add anchor elements to your website before you know where they will link.", + "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", + "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." + ], + "tests": [ + "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "", + "
", + "This named anchor leads nowhere", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08820", + "name": "Turn an Image into a Link", + "difficulty" : "0.25", + "description": [ + "Wrap the gray cat's image with an anchor tag that leads nowhere.", + "You can make elements into links by wrapping them in an anchor tag.", + "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", + "Wrap your gray cat's photo in an anchor tag", + "Use the hash symbol as the anchor tag's href." + ], + "tests": [ + "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08818", + "name": "Add Alt Text to an image", + "difficulty" : "0.26", + "description": [ + "Add the alt text \"a photo of a cute gray cat\" to our cat photo", + "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", + "In short, every image should have alt text!", + "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." + ], + "tests": [ + "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "\"a", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad88fee1348bd9aedf08825", + "name": "Adjusting the Padding of an Element", + "difficulty" : "0.27", + "description": [ + "Change the padding of the green box to match that of the red box.", + "An element's padding controls the amount of space between an element and its border.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", + "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08822", + "name": "Adjust the Margin of an Element", + "difficulty" : "0.28", + "description": [ + "Change the margin of the green box to match that of the red box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", + "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '20px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08823", + "name": "Add a Negative Margin to an Element", + "difficulty" : "0.29", + "description": [ + "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "If you set an element's margin to a negative value, the element will grow larger.", + "Try to set the margin to a negative value like the one for the red box." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '-15px')" + ], + "challengeSeed": [ + "", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08824", + "name": "Add Different Padding to Each Side of an Element TEST", + "difficulty" : "0.30", + "description": [ + "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has different padding on each of its sides.", + "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding-bottom', '20px')", + "expect($('.green-box')).to.have.css('padding-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1248bd9aedf08824", + "name": "Add Different a Margin to Each Side of an Element TEST", + "difficulty" : "0.31", + "description": [ + "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", + "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9aedf08826", + "name": "Use Clockwise Notation to Specify an Element's Padding", + "difficulty" : "0.32", + "description": [ + "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
margin
", + "", + "
", + "
padding
", + "
padding
", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd9acde08812", + "name": "Use Bootstrap for Responsive Images", + "difficulty" : "0.33", + "description": [ + "Add the img-responsive Bootstrap class to the image.", + "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", + "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", + "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", + "Now all you need to do is add the img-responsive class to your image." + ], + "tests": [ + "expect($('img')).to.have.class('img-responsive');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "This is a link to Google", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348bd8acde08812", + "name": "Center Text with Bootstrap", + "difficulty" : "0.34", + "description": [ + "Add Bootstrap's text-center class to your h2 element.", + "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", + "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." + ], + "tests": [ + "expect($('h2')).to.have.class('text-center');" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acde08812", + "name": "Create a Button", + "difficulty" : "0.35", + "description": [ + "Create a button with the text \"Delete\" using the HTML button element.", + "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." + ], + "tests": [ + "expect((/delete/gi).test($('button').text())).to.be.true;" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acdf08812", + "name": "Create a Bootstrap Button", + "difficulty" : "0.36", + "description": [ + "Apply the Bootstrap's btn class to both of your buttons.", + "Bootstrap has its own button styles, which look much better than the plain HTML ones." + ], + "tests": [ + "expect($('.btn').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Create a Block Element Bootstrap Button", + "difficulty" : "0.37", + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty" : "0.38", + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "expect($('.btn-block').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348cd8acef08812", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty" : "0.39", + "description": [ + "Add Bootstrap's btn-primary class to both of your buttons.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", + "Note that these buttons still need the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-primary').length).to.eql(2);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad87fee1348ce8acef08812", + "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", + "difficulty" : "0.40", + "description": [ + "Change the \"Delete\" button from btn-primary to btn-danger.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", + "Note that this button still needs the btn and btn-block classes." + ], + "tests": [ + "expect($('.btn-danger').length).to.eql(1);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad88fee1348ce8acef08812", + "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", + "difficulty" : "0.41", + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + + { + "_id" : "bad89fee1348ce8acef08812", + "name": "Wrap Side By Side Elements in a Bootstrap Row", + "difficulty" : "0.42", + "description": [ + "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "expect($('.row').length).to.eql(2);", + "expect($('.col-xs-12').length).to.eql(4);" + ], + "challengeSeed": [ + "", + "

cat photo app

", + "", + "
", + "
", + "
", + " ", + "
", + "
", + " ", + "
", + "
", + "", + "
", + "" + ], + "challengeType": 0 + }, + { + "_id" : "bad87fee1348bd9aedf08813", + "name": "Add Alt Text to an Image TEST", + "difficulty" : "0.43", + "description": [ + "Add the alt text \"A picture of a gray cat\" to the image.", + "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", + "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." + ], + "tests": [ + "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" + ], + "challengeSeed": [ + "", + "

hello world

", + "

cat photo app

", + "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", + "" + ], + "challengeType": 0 + } +] From 2d981d833cf9ba190e60b8b01b9f6853faec7811 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Fri, 15 May 2015 23:34:20 -0700 Subject: [PATCH 11/81] additional work on courseware --- controllers/resources.js | 2 +- seed_data/coursewares.json | 264 +++++++++++++++++++++++++------------ 2 files changed, 178 insertions(+), 88 deletions(-) diff --git a/controllers/resources.js b/controllers/resources.js index 6f2000457a..efa1cba29f 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -158,7 +158,7 @@ module.exports = { }, catPhotoSubmit: function catPhotoSubmit(req, res) { - res.send('Success! You have submitted your cat photo.') + res.send('Success! You have submitted your cat photo. Return to your website by typing any letter into your code editor.') }, nonprofits: function nonprofits(req, res) { diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index bd9604b9f1..23d8f7ba2e 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -1262,7 +1262,7 @@ "" ], "tests": [ - "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"type a cat photo URL here\".')" + "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"enter cat photo URL\".')" ], "challengeSeed": [ "", @@ -1510,58 +1510,136 @@ "completionMessage": "" }, - { - "_id" : "bad87fee1348bd9aedf08831", - "name": "Use HTML5 to Specify an Input Type", - "difficulty" : 0.043, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08832", - "name": "Create a Text Area", - "difficulty" : 0.044, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - { "_id" : "bad87fee1348bd9aedf08834", "name": "Create a Set of Radio Buttons", - "difficulty" : 0.045, + "difficulty" : 0.043, "description": [ - "", + "Add to your form a pair of radio buttons with the options of \"indoor\" and \"outdoor\".", + "You can use radio buttons for questions that can only have only one answer.", "" ], "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" + "assert($('input[type=\"radio\"').length > 1, 'Your webpage should have two radio button elements.')" ], "challengeSeed": [ - "

hello world

" + "", + "", + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + " ", + "
" + ], + "challengeType": 0, + "completionMessage": "" + }, + + { + "_id" : "bad87fee1348bd9aede08835", + "name": "Check a Radio Button by Default", + "difficulty" : 0.044, + "description": [ + "Clean up your form by adding linebreaks between form elements, then set one of your radio buttons to checked by default.", + "" + ], + "tests": [ + "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')" + ], + "challengeSeed": [ + "", + "", + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + " Indoor", + " Outdoor", + " ", + "
" ], "challengeType": 0, "completionMessage": "" @@ -1570,36 +1648,67 @@ { "_id" : "bad87fee1348bd9aedf08835", "name": "Create a Set of Checkboxes", - "difficulty" : 0.046, + "difficulty" : 0.045, "description": [ - "", - "" + "Create a set of three checkboxes." ], "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" + "assert($('input[type=\"checkbox\"').length > 2, 'Your webpage should have three checkbox elements.')" ], "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08836", - "name": "Create a HTML Form", - "difficulty" : 0.047, - "description": [ + "", + "", + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " Indoor", + " Outdoor", + "
", + " ", + "
" ], "challengeType": 0, "completionMessage": "" @@ -1624,25 +1733,6 @@ "completionMessage": "" }, - { - "_id" : "bad87fee1348bd9aedf08842", - "name": "Make an element translucent", - "difficulty" : 0.049, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - { "_id" : "bad87fee1348bd9aedf08844", "name": "Add a Drop Shadow", From a90e84f7d55a8868d7f978f0dc6e40bfffcfffd6 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 16 May 2015 11:19:28 -0700 Subject: [PATCH 12/81] add further coursewares --- seed_data/coursewares.json | 945 +++++++++++++++++++++---------------- 1 file changed, 549 insertions(+), 396 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 23d8f7ba2e..a24e83bc37 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -1449,7 +1449,7 @@ "name": "Use HTML5 to Make a Field Required", "difficulty" : 0.042, "description": [ - "", + "Make it required for your user to input text into your form before being able to submit it.", "" ], "tests": [ @@ -1516,11 +1516,11 @@ "difficulty" : 0.043, "description": [ "Add to your form a pair of radio buttons with the options of \"indoor\" and \"outdoor\".", - "You can use radio buttons for questions that can only have only one answer.", - "" + "You can use radio buttons for questions that can only have only one answer." ], "tests": [ - "assert($('input[type=\"radio\"').length > 1, 'Your webpage should have two radio button elements.')" + "assert($('input[type=\"radio\"').length > 1, 'Your webpage should have two radio button elements.')", + "assert($('label').length > 1, 'Each of your two radio button elements should be wrapped in a label element.')" ], "challengeSeed": [ "", @@ -1577,83 +1577,156 @@ "completionMessage": "" }, - { - "_id" : "bad87fee1348bd9aede08835", - "name": "Check a Radio Button by Default", - "difficulty" : 0.044, - "description": [ - "Clean up your form by adding linebreaks between form elements, then set one of your radio buttons to checked by default.", - "" - ], - "tests": [ - "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')" - ], - "challengeSeed": [ - "", - "", - "", - "

Cat Photo App

", - "", - "

Click here for cat photos.

", - "", - "", - "", - "

Things cats love:

", - "
    ", - "
  • cat nip
  • ", - "
  • laser pointers
  • ", - "
  • lasagna
  • ", - "
", - "

Top 3 things cats hate:

", - "
    ", - "
  1. flea treatment
  2. ", - "
  3. thunder
  4. ", - "
  5. other cats
  6. ", - "
", - "
", - " ", - " Indoor", - " Outdoor", - " ", - "
" - ], - "challengeType": 0, - "completionMessage": "" - }, - { "_id" : "bad87fee1348bd9aedf08835", "name": "Create a Set of Checkboxes", - "difficulty" : 0.045, + "difficulty" : 0.044, "description": [ "Create a set of three checkboxes." ], "tests": [ - "assert($('input[type=\"checkbox\"').length > 2, 'Your webpage should have three checkbox elements.')" + "assert($('input[type=\"checkbox\"').length > 2, 'Your webpage should have three checkbox elements.')", + "assert($('label').length > 2, 'Each of your three checkbox elements should be wrapped in a label element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + " ", + " ", + " ", + "
" + ], + "challengeType": 0, + "completionMessage": "" + }, + + { + "_id" : "bad87fee1348bd9aede08835", + "name": "Clean up your form using Linebreaks", + "difficulty" : 0.045, + "description": [ + "Clean up your form by adding linebreaks between form elements", + "" + ], + "tests": [ + "assert($('br').length > 2, 'Your webpage should use at least 3 line breaks to visually separate your form elements.')" + ], + "challengeSeed": [ + "", + "", + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "
" + ], + "challengeType": 0, + "completionMessage": "" + }, + + { + "_id" : "bad87fee1348bd9aedd08835", + "name": "Check a Radio Button and Checkbox by Default", + "difficulty" : 0.046, + "description": [ + "Set one of your radio buttons and one of your checkboxes to be checked by default.", + "" + ], + "tests": [ + "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')", + "assert($('input[type=\"checkbox\"').prop('checked'), 'One of the checkboxes on your form should be checked by default.')" ], "challengeSeed": [ "", @@ -1704,8 +1777,12 @@ "
", " ", "
", - " Indoor", - " Outdoor", + " ", + " ", + "
", + " ", + " ", + " ", "
", " ", "
" @@ -1714,328 +1791,537 @@ "completionMessage": "" }, - { - "_id" : "bad87fee1348bd9aedf08841", - "name": "Change the background of element", - "difficulty" : 0.048, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08844", - "name": "Add a Drop Shadow", - "difficulty" : 0.050, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08863", - "name": "Add a Gradient to a Button", - "difficulty" : 0.051, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08864", - "name": "Adjust the Line Height of Text", - "difficulty" : 0.052, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - - - { "_id": "bad87fee1348bd9acde08812", "name": "Use Bootstrap for Responsive Images", - "difficulty": 0.999, + "difficulty": 0.047, "description": [ - "Add the img-responsive Bootstrap class to the image.", + "Add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to the image.", "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", "Now all you need to do is add the img-responsive class to your image." ], "tests": [ - "expect($('img')).to.have.class('img-responsive');" + "assert($('img').hasClass('img-responsive'), 'Your new image should have the class \"img-responsive\"')", + "assert($('img').length > 1, 'You should add an image with the src of \"http://bit.ly/fcc-kittens2\"')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "This is a link to Google", - "
" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad87fee1348bd8acde08812", "name": "Center Text with Bootstrap", - "difficulty": 0.999, + "difficulty": 0.048, "description": [ "Add Bootstrap's text-center class to your h2 element.", "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." + "Note 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>." ], "tests": [ - "expect($('h2')).to.have.class('text-center');" + "assert($('h2').hasClass('text-center'), 'Your h2 element should be centered by applying the class \"text-center\"')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
" - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348cd8acde08812", - "name": "Create a Button", - "difficulty": 0.999, - "description": [ - "Create a button with the text \"Delete\" using the HTML button element.", - "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." - ], - "tests": [ - "expect((/delete/gi).test($('button').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, + { "_id": "bad87fee1348cd8acdf08812", "name": "Create a Bootstrap Button", - "difficulty": 0.999, + "difficulty": 0.049, "description": [ - "Apply the Bootstrap's btn class to both of your buttons.", + "Create a new button below your large kitten photo with the class \"btn\" and the text of \"like this photo\".", "Bootstrap has its own button styles, which look much better than the plain HTML ones." ], "tests": [ - "expect($('.btn').length).to.eql(2);" + "assert($('.btn').length > 0, 'your new button should have the class \"btn\".')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "", - "
", - "" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08812", "name": "Create a Block Element Bootstrap Button", - "difficulty": 0.999, + "difficulty": 0.050, "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", + "Add Bootstrap's btn-block class to your Bootstrap button.", "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", "Note that these buttons still need the btn class." ], "tests": [ - "expect($('.btn-block').length).to.eql(2);" + "assert($('.btn-block').length > 0, 'your new button should have the class \"btn-block\".')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "", - "
", - "" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08811", "name": "Color a Bootstrap Button with Button Primary", - "difficulty": 0.999, + "difficulty": 0.051, "description": [ "Add Bootstrap's btn-block class to both of your buttons.", "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", "Note that these buttons still need the btn class." ], "tests": [ - "expect($('.btn-block').length).to.eql(2);" + "assert($('.btn-primary').length > 0, 'your new button should have the class \"btn-primary\".')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "", - "
", - "" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08813", "name": "Color a Bootstrap Button with Button Info", - "difficulty": 0.999, + "difficulty": 0.052, "description": [ - "Add Bootstrap's btn-primary class to both of your buttons.", + "Create a new block-level Bootstrap button below your \"like this photo\" button with the text \"more info about this photo\", and add Bootstrap's btn-info class to it.", "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", "Note that these buttons still need the btn and btn-block classes." ], "tests": [ - "expect($('.btn-primary').length).to.eql(2);" + "assert($('.btn-info').length > 0, 'your new button should have the class \"btn-info\".')", + "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "", - "
", - "" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad87fee1348ce8acef08814", "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", - "difficulty": 0.999, + "difficulty": 0.053, "description": [ "Change the \"Delete\" button from btn-primary to btn-danger.", "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", "Note that this button still needs the btn and btn-block classes." ], "tests": [ - "expect($('.btn-danger').length).to.eql(1);" + "assert($('.btn-danger').length > 0, 'your new button should have the class \"btn-danger\".')", + "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" ], "challengeSeed": [ + "", "", - "

cat photo app

", - "", - "
", - "", - "
", - "" + "", + "

Cat Photo App

", + "", + "

Click here for cat photos.

", + "", + "", + "", + "", + "", + "", + "

Things cats love:

", + "
    ", + "
  • cat nip
  • ", + "
  • laser pointers
  • ", + "
  • lasagna
  • ", + "
", + "

Top 3 things cats hate:

", + "
    ", + "
  1. flea treatment
  2. ", + "
  3. thunder
  4. ", + "
  5. other cats
  6. ", + "
", + "
", + " ", + "
", + " ", + " ", + "
", + " ", + " ", + " ", + "
", + " ", + "
" ], "challengeType": 0 }, { "_id": "bad88fee1348ce8acef08815", "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", - "difficulty": 0.999, + "difficulty": 0.054, "description": [ "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", "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.", @@ -2074,7 +2360,7 @@ { "_id": "bad89fee1348ce8acef08816", "name": "Wrap Side By Side Elements in a Bootstrap Row", - "difficulty": 0.999, + "difficulty": 0.055, "description": [ "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", "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.", @@ -2113,7 +2399,7 @@ { "_id" : "bad87fee1348bd9aedf08845", "name": "Make a Navbar", - "difficulty" : 0.999, + "difficulty" : 0.056, "description": [ "", "" @@ -2132,7 +2418,7 @@ { "_id" : "bad87fee1348bd9aedf08847", "name": "Add a Logo to a Navbar", - "difficulty" : 0.999, + "difficulty" : 0.057, "description": [ "", "" @@ -2151,7 +2437,7 @@ { "_id" : "bad87fee1348bd9aedf08848", "name": "Make a Footer", - "difficulty" : 0.999, + "difficulty" : 0.058, "description": [ "", "" @@ -2170,26 +2456,7 @@ { "_id" : "bad87fee1348bd9aedf08849", "name": "Use Icons as Links", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08850", - "name": "Add Hover Effects to Icons", - "difficulty" : 0.999, + "difficulty" : 0.059, "description": [ "", "" @@ -2208,121 +2475,7 @@ { "_id" : "bad87fee1348bd9aedf08851", "name": "Add Depth to a Page with a Well", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08852", - "name": "Add an ID to a Button", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08853", - "name": "Fire a Modal by Clicking a Button", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08854", - "name": "Style a Modal with a Header", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08855", - "name": "Style a Modal with a Body", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08856", - "name": "Make a Modal Dismissable", - "difficulty" : 0.999, - "description": [ - "", - "" - ], - "tests": [ - "expect($('h1')).to.have.class('text-center');", - "expect($('h1')).to.have.text('hello world');" - ], - "challengeSeed": [ - "

hello world

" - ], - "challengeType": 0, - "completionMessage": "" - }, - - { - "_id" : "bad87fee1348bd9aedf08857", - "name": "Create an Accordian Menu", - "difficulty" : 0.999, + "difficulty" : 0.060, "description": [ "", "" From a635c87a498a4e6836cda4f7965f9dcebb86123c Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 16 May 2015 23:53:31 -0700 Subject: [PATCH 13/81] add bootstrap coursewares --- seed_data/coursewares.json | 1013 ++++++++++++++++++++++++++++-------- 1 file changed, 790 insertions(+), 223 deletions(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index a24e83bc37..937751adc9 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -165,13 +165,13 @@ "name": "Use the h2 Element", "difficulty": 0.010, "description": [ - "Add an h2 tag that says \"Cat Photo App\" to make a second HTML element below the \"Hello World\" h1 element.", + "Add an h2 tag that says \"CatPhotoApp\" to make a second HTML element below the \"Hello World\" h1 element.", "The h2 element you enter will create an h2 element on the website.", "This element tells the browser how to render the text that it contains.", "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." ], "tests": [ - "assert.isTrue((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text()), 'Your h2 element should have the text \"Cat Photo App\"')", + "assert.isTrue((/cat(\\s)+photo(\\s)+app/gi).test($('h2').text()), 'Your h2 element should have the text \"CatPhotoApp\"')", "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" ], "challengeSeed": [ @@ -193,7 +193,7 @@ ], "challengeSeed": [ "

Hello World

", - "

Cat Photo App

" + "

CatPhotoApp

" ], "challengeType": 0 }, @@ -212,7 +212,7 @@ ], "challengeSeed": [ "

Hello World

", - "

Cat Photo App

", + "

CatPhotoApp

", "

Hello Paragraph

" ], "challengeType": 0 @@ -236,7 +236,7 @@ "", - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08809", - "name": "Using Important to Override Styles", - "difficulty" : "0.14", - "description": [ - "Apply both the \"blue-text\" and \"urgently-red\" classes to all h2 elements, but use !important to ensure the element is rendered as being red.", - "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", - "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", - "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", - "Look at the example in the editor's style tag to see how you can use !important.", - "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." - ], - "tests": [ - "expect($('h2')).to.have.class('urgently-red');", - "expect($('h2')).to.have.class('blue-text');", - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08810", - "name": "Use Hex Codes for Precise Colors", - "difficulty" : "0.15", - "description": [ - "Change the hex code in the \"red-text\" class to hex code for the color red.", - "Hexadecimal (hex) code is a popular way of specifying color in CSS.", - "Hex code is called \"hex\" because each digit has 16 possible values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f", - "The six hex code correspond to red-red-green-green-blue-blue.", - "You can change these six values to make more than 16 million colors!", - "The higher the value in a field, the more intense its color. For example, #000000 is black, #ffffff is white, and #00ff00 is bright green. You can also get less intense colors by using values lower than f. For example, #00f000 with the second green digit set to 0 is a light green, and #00f900 is a slightly brighter green", - "Now figure out how to make the bright green in the \"red-text\" class into a bright red." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08810", - "name": "Use Shortened 3 Digit Hex Codes", - "difficulty" : "0.16", - "description": [ - "Change the hex code in the \"red-text\" class to the shortened 3-digit hex code for the color red.", - "You can also shorten the 6-digit color hex code to a 3-digit code. For example, #00ff00 becomes #0f0. This is less precise, but equally effective." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08811", - "name": "Use RGB Codes for Precise Colors", - "difficulty" : "0.17", - "description": [ - "Change the RGB code to be red.", - "Another way to represent color in CSS is with RGB, or red-green-blue notation.", - "For each of the three colors, you specify a value between 0 and 256.", - "For example, black is rgb(0, 0, 0), white is rgb(255, 255, 255), bright green is rgb(0, 255, 0). You can also get less intense colors by using values lower than 255. For example, light green is rgb(0, 123, 0).", - "If you think about it, this is just as precise as using hex code, because 16 times 16 is 256. In practice, most developers use hex code since it's faster to say out loud and to type." - ], - "tests": [ - "expect($('h2')).to.have.css('color', 'rgb(255, 0, 0)');", - "expect($('h2')).to.have.class('red-text');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08812", - "name": "Add an Image to your Website", - "difficulty" : "0.18", - "description": [ - "Use an img element to add the image http://bit.ly/cutegraycat to your website.", - "You can add images to your website by using the img element.", - "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.", - "Try it with this image: http://bit.ly/cutegraycat." - ], - "tests": [ - "expect($('img').attr('src')).to.equal('http://bit.ly/cutegraycat');" - ], - "challengeSeed": [ - "", - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size TEST", - "difficulty" : "0.19", - "description": [ - "Create a class called narrow-image and use it to resize the image so that it's only 200 pixels wide", - "Uh-oh, our image is too big to fit on a mobile phone. As a result, our user will need to scroll horizontally to view the image. But we can fix this by specifying an image size.", - "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", - "Create a class called narrow-image and added it to the image element. Change the width to 200 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('narrow-image');", - "expect($('img')).to.have.css('width', 200px)" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9bedf08813", - "name": "Add a Border Around an Element", - "difficulty" : "0.20", - "description": [ - "Create a class called \"thick-green-border\" that puts a 5-pixel-wide black border around your cat photo.", - "CSS Borders have attributes like style, color and width.", - "We've created an example border around your h1 element. See if you can add a 10-pixel-wide green border around your cat photo." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-color', 'rgb(0,255,0)'));", - "expect($('img')).to.have.css('border-width', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08814", - "name": "Add Rounded Corners with a Border Radius", - "difficulty" : "0.21", - "description": [ - "Give your cat photo a border radius of 10 pixels.", - "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", - "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." - ], - "tests": [ - "expect($('img')).to.have.class('thick-green-border');", - "expect($('img')).to.have.css('border-radius', '10px');" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08815", - "name": "Make an Image Circular with a Border Radius", - "difficulty" : "0.22", - "description": [ - "Give your cat photo a border-radius of 50%.", - "In addition to pixels, you can also specify a border-radius of a percentage." - ], - "tests": [ - "expect($('img')).to.have.css('border-radius', '50%');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08816", - "name": "Use an Anchor Tag to Link to an External Page", - "difficulty" : "0.23", - "description": [ - "Create an anchor tag hyperlink that links to freecodecamp.com", - "" - ], - "tests": [ - "expect((/free(\\s+)?code(\\s+)?camp(\\s+)?/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /freecodecamp\\.com/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08817", - "name": "Make Named Anchors using the Hash Symbol", - "difficulty" : "0.24", - "description": [ - "Use the hash symbol(#) to turn the link to the bottom of the page into a named anchor.", - "Sometimes you want to add anchor elements to your website before you know where they will link.", - "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", - "Replace the href in the link to freecodecamp.com with a hash symbol to turn it into a named anchor." - ], - "tests": [ - "expect((/this link leads nowhere/gi).test($('a').text())).to.be.true;", - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "", - "
", - "This named anchor leads nowhere", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08820", - "name": "Turn an Image into a Link", - "difficulty" : "0.25", - "description": [ - "Wrap the gray cat's image with an anchor tag that leads nowhere.", - "You can make elements into links by wrapping them in an anchor tag.", - "Check out the example snow-colored cat's photo. When you hover over it with your cursor, you'll see the finger pointer you usually see when you hover over a link. The photo is now a link.", - "Wrap your gray cat's photo in an anchor tag", - "Use the hash symbol as the anchor tag's href." - ], - "tests": [ - "expect($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08818", - "name": "Add Alt Text to an image", - "difficulty" : "0.26", - "description": [ - "Add the alt text \"a photo of a cute gray cat\" to our cat photo", - "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", - "In short, every image should have alt text!", - "You can add alt text right in the image tag, like we've done here with the \"cute white cat\" image." - ], - "tests": [ - "expect($('img').filter(function(){ return /cat/gi.test(this.alt) }).length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "\"a", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348bd9aedf08825", - "name": "Adjusting the Padding of an Element", - "difficulty" : "0.27", - "description": [ - "Change the padding of the green box to match that of the red box.", - "An element's padding controls the amount of space between an element and its border.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", - "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08822", - "name": "Adjust the Margin of an Element", - "difficulty" : "0.28", - "description": [ - "Change the margin of the green box to match that of the red box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", - "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '20px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08823", - "name": "Add a Negative Margin to an Element", - "difficulty" : "0.29", - "description": [ - "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "If you set an element's margin to a negative value, the element will grow larger.", - "Try to set the margin to a negative value like the one for the red box." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '-15px')" - ], - "challengeSeed": [ - "", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08824", - "name": "Add Different Padding to Each Side of an Element TEST", - "difficulty" : "0.30", - "description": [ - "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has different padding on each of its sides.", - "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding-bottom', '20px')", - "expect($('.green-box')).to.have.css('padding-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1248bd9aedf08824", - "name": "Add Different a Margin to Each Side of an Element TEST", - "difficulty" : "0.31", - "description": [ - "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", - "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9aedf08826", - "name": "Use Clockwise Notation to Specify an Element's Padding", - "difficulty" : "0.32", - "description": [ - "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", - "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", - "You can also use this notation for margins!" - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
margin
", - "", - "
", - "
padding
", - "
padding
", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd9acde08812", - "name": "Use Bootstrap for Responsive Images", - "difficulty" : "0.33", - "description": [ - "Add the img-responsive Bootstrap class to the image.", - "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", - "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", - "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", - "Now all you need to do is add the img-responsive class to your image." - ], - "tests": [ - "expect($('img')).to.have.class('img-responsive');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "This is a link to Google", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348bd8acde08812", - "name": "Center Text with Bootstrap", - "difficulty" : "0.34", - "description": [ - "Add Bootstrap's text-center class to your h2 element.", - "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note that you can add several classes to the same element by seperating each of them with a space, like this: <h2 class=\"text-red text-center\">your text</h2>." - ], - "tests": [ - "expect($('h2')).to.have.class('text-center');" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acde08812", - "name": "Create a Button", - "difficulty" : "0.35", - "description": [ - "Create a button with the text \"Delete\" using the HTML button element.", - "HTML has special elements that function like links, but look like buttons. Let's creating a default HTML button." - ], - "tests": [ - "expect((/delete/gi).test($('button').text())).to.be.true;" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acdf08812", - "name": "Create a Bootstrap Button", - "difficulty" : "0.36", - "description": [ - "Apply the Bootstrap's btn class to both of your buttons.", - "Bootstrap has its own button styles, which look much better than the plain HTML ones." - ], - "tests": [ - "expect($('.btn').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Create a Block Element Bootstrap Button", - "difficulty" : "0.37", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.38", - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "expect($('.btn-block').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348cd8acef08812", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty" : "0.39", - "description": [ - "Add Bootstrap's btn-primary class to both of your buttons.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", - "Note that these buttons still need the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-primary').length).to.eql(2);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad87fee1348ce8acef08812", - "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", - "difficulty" : "0.40", - "description": [ - "Change the \"Delete\" button from btn-primary to btn-danger.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", - "Note that this button still needs the btn and btn-block classes." - ], - "tests": [ - "expect($('.btn-danger').length).to.eql(1);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad88fee1348ce8acef08812", - "name": "Use the Bootstrap Grid to Put Two Elements Side By Side", - "difficulty" : "0.41", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - - { - "_id" : "bad89fee1348ce8acef08812", - "name": "Wrap Side By Side Elements in a Bootstrap Row", - "difficulty" : "0.42", - "description": [ - "Put the \"Like\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"row\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "expect($('.row').length).to.eql(2);", - "expect($('.col-xs-12').length).to.eql(4);" - ], - "challengeSeed": [ - "", - "

cat photo app

", - "", - "
", - "
", - "
", - " ", - "
", - "
", - " ", - "
", - "
", - "", - "
", - "" - ], - "challengeType": 0 - }, - { - "_id" : "bad87fee1348bd9aedf08813", - "name": "Add Alt Text to an Image TEST", - "difficulty" : "0.43", - "description": [ - "Add the alt text \"A picture of a gray cat\" to the image.", - "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", - "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." - ], - "tests": [ - "expect((/cat/gi).test($('img').attr('alt')).to.be.true;" - ], - "challengeSeed": [ - "", - "

hello world

", - "

cat photo app

", - "

lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

", - "" - ], - "challengeType": 0 - } -] diff --git a/seed_data/challenges/basics.json b/seed_data/challenges/basics.json new file mode 100644 index 0000000000..16134aa92f --- /dev/null +++ b/seed_data/challenges/basics.json @@ -0,0 +1,59 @@ +{ + "name": "basics", + "order" : 0.001, + "challenges": [ + { + "_id": "bd7126d8c441eddfaeb5bd3e", + "name": "Meet Other Campers in your City", + "difficulty": 0.065, + "challengeSeed": "127358841", + "description": [ + "One of the best ways to stay motivated when learning to code is to hang out with other campers.", + "Slack and Camper News are great ways to communicate with other campers, but there's no substitute for meeting people in-person.", + "The easiest way to meet other campers in your city is to join your city's Facebook Group. Click here to view our growing list of local groups.", + "Click the link to your city, then, once Facebook loads, click \"Join group\".", + "Our local groups are new, so if you don't see your city on this list, you should follow the directions to create a Facebook group for your city.", + "If you don't have a Facebook account, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.", + "Our groups allow you to create events, coordinate those events, and share photos from the events afterward.", + "Whether you're hosting a study group, pair programming at your local library, or going to a weekend hackathon, your city's group will help you make it happen." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7137d8c441eddfaeb5bdef", + "name": "Get Help the Hacker Way with RSAP", + "difficulty": 0.07, + "challengeSeed": "125407432", + "description": [ + "Let's cover one last thing before you start working through our lessons: how to get help.", + "Any time you get stuck or don't know what to do next, follow this simple algorithm (procedure): RSAP (Read, Search, Ask, Post).", + "First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", + "Next, S - Search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.", + "Then, if you still haven't found an answer to your question, A - Ask your friends. If you have trouble, you can ask your fellow campers. We have a special chat room specifically for getting help with tools you learn through these Free Code Camp Challenges. Go to https://freecode.slack.com/messages/help/. Keep this chat open while you work on the remaining challenges.", + "Finally, P - Post on Stack Overflow. Before you attempt to do this, read Stack Overflow's guide to asking good questions: http://stackoverflow.com/help/how-to-ask.", + "Here's our detailed field guide on getting help: http://freecodecamp.com/field-guide/how-do-i-get-help-when-i-get-stuck.", + "Now you have a clear algorithm to follow when you need help! Let's start coding! Move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7127d8c441eddfaeb5bdef", + "name": "Build a Landing Page with HTML", + "difficulty": 0.08, + "challengeSeed": "125671867", + "description": [ + "Now it's time for us to start our actual coding lessons. We've curated a series of free, self-paced, browser-based lessons from providers like Codecademy and Stanford University.", + "These lessons will cover a lot of ground quickly, and will hold your hand throughout the process. Don't try to memorize everything - you'll spend more than a thousand hours practicing these later, and you can always look things up. Just keep moving.", + "If you've learned HTML and CSS before, these next few Waypoints will be a valuable review. If you haven't learned HTML or CSS before, you're in for a treat!", + "This Codecademy will quickly cover HTML, CSS and even Responsive Design with Bootstrap.", + "If you don't already have a Codecademy account, create one here: http://www.codecademy.com.", + "Go to http://www.codecademy.com/en/skills/make-a-website/topics/html-elements and complete the section.", + "Once you're done, mark this Waypoint complete and move on the next Waypoint." + ], + "challengeType": 2, + "tests": [] + } + ] +} \ No newline at end of file diff --git a/seed_data/challenges/prepwork.json b/seed_data/challenges/prepwork.json new file mode 100644 index 0000000000..3049d6c31a --- /dev/null +++ b/seed_data/challenges/prepwork.json @@ -0,0 +1,55 @@ +[ + { + "_id": "bd7124d8c441eddfaeb5bdef", + "name": "Learn how Free Code Camp Works", + "difficulty": 0.01, + "challengeSeed": "125407438", + "description": [ + "Watch this 1-minute video, or simply read this summary:", + "Welcome to Free Code Camp. We're a community of busy people learning to code by building projects for nonprofits.", + "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And to stay motivated, you just need to:
  1. make friends with people who code
  2. code a little every day
    1. ", + "All our challenges are
      1. free
      2. self-paced
      3. browser-based
      ", + "We'll spend
      1. 200 hours learning tools like HTML, CSS, JavaScript, Node.js and databases
      2. 600 hours building practice projects
      3. 800 hours building full stack solutions for nonprofits
      ", + "By the end, we'll
      1. be good at coding
      2. have the portfolio of apps with happy users to prove it
      ", + "Once you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", + "Now it's time to join our chat room. Click the \"I've completed this challenge\" button to move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bd0f", + "name": "Join Our Chat Room", + "difficulty": 0.02, + "challengeSeed": "124555254", + "description": [ + "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", + "Make sure your Free Code Camp account includes your email address. You can do this here: http://freecodecamp.com/account.", + "Click this link, which will email you an invite to Free Code Camp's Slack chat room: http://freecodecamp.com/api/slack.", + "Now check your email and click the link in the email from Slack", + "Complete the sign up process, then update your biographical information and upload an image. A picture of your face works best. This is how people will see you in the chat room, so put your best foot forward.", + "Now enter the general chat room and introduce yourself to our chat room by typing: \"hello world!\".", + "Note that you're expected to follow our Code of Conduct: http://freecodecamp.com/field-guide/what-is-the-free-code-camp-code-of-conduct?", + "Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", + "Keep the chat room open while you work through the other challenges. That way you ask for help if you get stuck on a challenge. You can also socialize when you feel like taking a break.", + "You can also access this chat room by clicking the \"Chat\" button in the upper right hand corner." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bdff", + "name": "Preview our Challenge Map", + "difficulty": 0.03, + "challengeSeed": "125407437", + "description": [ + "Before you start learning how to code, we'd like to introduce you to a few things.", + "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", + "You should complete all these challenges in order.", + "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", + "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." + ], + "challengeType": 2, + "tests": [] + } +] \ No newline at end of file diff --git a/seed_data/seed.js b/seed_data/seed.js index 95c35b328f..fc87f56d02 100644 --- a/seed_data/seed.js +++ b/seed_data/seed.js @@ -1,96 +1,78 @@ require('dotenv').load(); -var Bonfire = require('../models/Bonfire.js'), - Courseware = require('../models/Courseware.js'), - FieldGuide = require('../models/FieldGuide.js'), - Nonprofit = require('../models/Nonprofit.js'), - mongoose = require('mongoose'), - secrets = require('../config/secrets'), - coursewares = require('./coursewares.json'), - fieldGuides = require('./field-guides.json'), - nonprofits = require('./nonprofits.json'), - bonfires = require('./bonfires.json'); +var Challenge = require('../models/Challenge.js'), + FieldGuide = require('../models/FieldGuide.js'), + Nonprofit = require('../models/Nonprofit.js'), + mongoose = require('mongoose'), + secrets = require('../config/secrets'), + fieldGuides = require('./field-guides.json'), + nonprofits = require('./nonprofits.json'), + fs = require('fs'); mongoose.connect(secrets.db); +var challenges = fs.readdirSync(__dirname + '/challenges'); var counter = 0; -var offerings = 4; +var offerings = 3; var CompletionMonitor = function() { - counter++; - console.log('call ' + counter); + counter++; + console.log('call ' + counter); - if (counter < offerings) { - return; - } else { - process.exit(0); - } + if (counter < offerings) { + return; + } else { + process.exit(0); + } }; - -Bonfire.remove({}, function(err, data) { - if (err) { - console.error(err); - } else { - console.log('Deleted ', data); - } - Bonfire.create(bonfires, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); +Challenge.remove({}, function(err, data) { + if (err) { + console.err(err); + } else { + console.log('Deleted ', data); + } + challenges.forEach(function (file) { + Challenge.create(require('./challenges/' + file), function (err, data) { + if (err) { + console.log(err); + } else { + console.log('Successfully parsed %s', file); + } }); - console.log('bonfires'); + }); }); - -Courseware.remove({}, function(err, data) { - if (err) { - console.error(err); - } else { - console.log('Deleted ', data); - } - Courseware.create(coursewares, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('coursewares'); -}); - +/* FieldGuide.remove({}, function(err, data) { + if (err) { + console.error(err); + } else { + console.log('Deleted ', data); + } + FieldGuide.create(fieldGuides, function(err, data) { if (err) { - console.error(err); + console.log(err); } else { - console.log('Deleted ', data); + console.log('Saved ', data); } - FieldGuide.create(fieldGuides, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('field guides'); + CompletionMonitor(); + }); + console.log('field guides'); }); Nonprofit.remove({}, function(err, data) { + if (err) { + console.error(err); + } else { + console.log('Deleted ', data); + } + Nonprofit.create(nonprofits, function(err, data) { if (err) { - console.error(err); + console.log(err); } else { - console.log('Deleted ', data); + console.log('Saved ', data); } - Nonprofit.create(nonprofits, function(err, data) { - if (err) { - console.log(err); - } else { - console.log('Saved ', data); - } - CompletionMonitor(); - }); - console.log('nonprofits'); + CompletionMonitor(); + }); + console.log('nonprofits'); }); +*/ From 51257be6a44fe951db9ff09a5633e37d44d767bc Mon Sep 17 00:00:00 2001 From: Sage Elliott Date: Mon, 18 May 2015 21:25:22 -0700 Subject: [PATCH 20/81] fix typo on line 97 of coursewwares.json --- seed_data/coursewares.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index fffdab5fbb..fa0c2ecea1 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -94,7 +94,7 @@ "Click \"News\" in the upper right hand corner.", "You'll see a variety of links that have been submitted. Click on the \"Discuss\" button under one of them.", "You can upvote links. This will push the link up the rankings of hot links.", - "You an also comment on a link. If someone responds to your comment, you'll get an email notification so you can come back and respond to them.", + "You can also comment on a link. If someone responds to your comment, you'll get an email notification so you can come back and respond to them.", "You can also submit links. You can modify the link's headline and also leave an initial comment about the link.", "You can view the portfolio pages of any camper who has posted links or comments on Camper News. Just click on their photo.", "When you submit a link, you'll get a point. You will also get a point each time someone upvotes your link.", From 45d4954a433881508f7f0460a3a21a539ea503e8 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 18 May 2015 22:25:48 -0700 Subject: [PATCH 21/81] fix script tag importing issue in coursewares --- .../js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js | 4 ++-- seed_data/coursewares.json | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js index f91de93e29..192083f0a2 100644 --- a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js +++ b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js @@ -107,11 +107,11 @@ var tests = tests || []; var allSeeds = ''; (function() { challengeSeed.forEach(function(elem) { - allSeeds += elem + '\n'; + allSeeds += elem.replace(/fccss/g, '') + '\n'; }); + editor.setValue(allSeeds); })(); -editor.setValue(allSeeds); function doLinting () { editor.operation(function () { diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 39b5a14978..0cbce3b770 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -3420,14 +3420,15 @@ ], "tests": [ "assert($('#target').hasClass('disabled'), 'The button with the ID of \"target\" should continue to have the \"disabled\" class.')", - "assert($('#target').attr('disabled', true), 'Enable the button with the ID of \"target\" by using jQuery.')" + "assert(!!$('#target[disabled]'), 'Enable the button with the ID of \"target\" by using jQuery.')", + "expect($('#target')).to.exist()" ], "challengeSeed": [ - "", + "fcces", "" ], "challengeType": 0 From ad248a4830c0f398348ac4fdd1b7fd3c9243503d Mon Sep 17 00:00:00 2001 From: phoenixstormcrow Date: Mon, 18 May 2015 22:36:27 -0700 Subject: [PATCH 22/81] Added MDN links to bonfire 19: Diff Two Arrays Fixes FreeCodeCamp/freecodecamp#374 --- seed_data/bonfires.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 04116d840b..65452f1ce3 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -316,7 +316,8 @@ "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" - ] + ], + "MDNlinks" : ["String.slice()", "Array.filter()", "Array.indexOf()", "String.concat()"] }, { "_id": "a7f4d8f2483413a6ce226cac", From e659d8c7fa567d7569e5255e5cbab4b1dca4584d Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Tue, 19 May 2015 01:57:55 -0700 Subject: [PATCH 23/81] factor challenges and bonfires into smaller json files --- models/Bonfire.js | 2 +- models/Courseware.js | 1 - seed_data/bonfires.json | 501 ++++- seed_data/challenges/basejumps.json | 176 ++ seed_data/challenges/basic-html5-and-css.json | 1626 +++++++++++++++++ seed_data/challenges/basic-javascript.json | 167 ++ seed_data/challenges/basics.json | 59 - seed_data/challenges/bonfires.json | 1166 ++++++++++++ seed_data/challenges/bootstrap.json | 1575 ++++++++++++++++ seed_data/challenges/computer-science.json | 86 + .../challenges/full-stack-javascript.json | 155 ++ .../getting-set-for-free-code-camp.json | 146 ++ .../challenges/jquery-ajax-and-json.json | 283 +++ seed_data/challenges/prepwork.json | 55 - seed_data/challenges/ziplines.json | 197 ++ seed_data/coursewares.json | 259 +-- 16 files changed, 6080 insertions(+), 374 deletions(-) create mode 100644 seed_data/challenges/basejumps.json create mode 100644 seed_data/challenges/basic-html5-and-css.json create mode 100644 seed_data/challenges/basic-javascript.json delete mode 100644 seed_data/challenges/basics.json create mode 100644 seed_data/challenges/bonfires.json create mode 100644 seed_data/challenges/bootstrap.json create mode 100644 seed_data/challenges/computer-science.json create mode 100644 seed_data/challenges/full-stack-javascript.json create mode 100644 seed_data/challenges/getting-set-for-free-code-camp.json create mode 100644 seed_data/challenges/jquery-ajax-and-json.json delete mode 100644 seed_data/challenges/prepwork.json create mode 100644 seed_data/challenges/ziplines.json diff --git a/models/Bonfire.js b/models/Bonfire.js index 8c0c4599ed..fdfebb3291 100644 --- a/models/Bonfire.js +++ b/models/Bonfire.js @@ -15,7 +15,7 @@ var bonfireSchema = new mongoose.Schema({ difficulty: String, description: Array, tests: Array, - challengeSeed: String, + challengeSeed: Array, MDNlinks: [String] }); diff --git a/models/Courseware.js b/models/Courseware.js index 64309a6540..d760acdfd3 100644 --- a/models/Courseware.js +++ b/models/Courseware.js @@ -15,7 +15,6 @@ var coursewareSchema = new mongoose.Schema({ description: Array, tests: Array, challengeSeed: Array, - completionMessage: String, // Congratulations! You've finished our HTML and CSS track! challengeType: Number // 0 = html, 1 = javascript only, 2 = video, 3 = zipline, 4 = basejump }); diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 5ac7923de5..7b0f310987 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -14,7 +14,18 @@ "expect(meetBonfire()).to.be.a(\"boolean\");", "expect(meetBonfire()).to.be.true;" ], - "challengeSeed": "function meetBonfire(argument) {\n // Good luck!\n console.log(\"you can read this function's argument in the developer tools\", argument);\n\n return false;\n}\n\n\n\nmeetBonfire(\"You can do this!\");" + "challengeSeed": [ + "function meetBonfire(argument) {", + " // Good luck!", + " console.log(\"you can read this function's argument in the developer tools\", argument);", + "", + " return false;", + "}", + "", + "", + "", + "meetBonfire(\"You can do this!\");" + ] }, { "_id": "a202eed8fc186c8434cb6d61", @@ -31,8 +42,14 @@ "You may need to turn the string into an array before you can reverse it.", "Your result must be a string." ], - "challengeSeed": "function reverseString(str) {\n return str;\n}\n\nreverseString('hello');", - "MDNlinks" : ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] + "challengeSeed": [ + "function reverseString(str) {", + " return str;", + "}", + "", + "reverseString('hello');" + ], + "MDNlinks": ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] }, { "_id": "a302f7aae1aa3152a5b413bc", @@ -50,8 +67,14 @@ "Factorials are often represented with the shorthand notation n!", "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f" ], - "challengeSeed": "function factorialize(num) {\n return num;\n}\n\nfactorialize(5);", - "MDNlinks" : ["Arithmetic Operators"] + "challengeSeed": [ + "function factorialize(num) {", + " return num;", + "}", + "", + "factorialize(5);" + ], + "MDNlinks": ["Arithmetic Operators"] }, { "_id": "aaa48de84e1ecc7c742e1124", @@ -72,8 +95,17 @@ "assert.deepEqual(palindrome(\"never odd or even\"), true);", "assert.deepEqual(palindrome(\"nope\"), false);" ], - "challengeSeed": "function palindrome(str) {\n // Good luck!\n return true;\n}\n\n\n\npalindrome(\"eye\");", - "MDNlinks" : ["String.replace()", "String.toLowerCase()"] + "challengeSeed": [ + "function palindrome(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "palindrome(\"eye\");" + ], + "MDNlinks": ["String.replace()", "String.toLowerCase()"] }, { "_id": "a26cbbe9ad8655a977e1ceb5", @@ -83,7 +115,13 @@ "Return the length of the longest word in the provided sentence.", "Your response should be a number." ], - "challengeSeed": "function findLongestWord(str) {\n return str.length;\n}\n\nfindLongestWord('The quick brown fox jumped over the lazy dog');", + "challengeSeed": [ + "function findLongestWord(str) {", + " return str.length;", + "}", + "", + "findLongestWord('The quick brown fox jumped over the lazy dog');" + ], "tests": [ "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.be.a('Number');", "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.equal(6);", @@ -91,7 +129,7 @@ "expect(findLongestWord('Google do a barrel roll')).to.equal(6);", "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);" ], - "MDNlinks" : ["String.split()", "String.length"] + "MDNlinks": ["String.split()", "String.length"] }, { "_id": "ab6137d4e35944e21037b769", @@ -101,14 +139,20 @@ "Return the provided string with the first letter of each word capitalized.", "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'." ], - "challengeSeed": "function titleCase(str) {\n return str;\n}\n\ntitleCase(\"I'm a little tea pot\");", + "challengeSeed": [ + "function titleCase(str) {", + " return str;", + "}", + "", + "titleCase(\"I'm a little tea pot\");" + ], "tests": [ "expect(titleCase(\"I'm a little tea pot\")).to.be.a('String');", "expect(titleCase(\"I'm a little tea pot\")).to.equal(\"I'm A Little Tea Pot\");", "expect(titleCase(\"sHoRt AnD sToUt\")).to.equal(\"Short And Stout\");", "expect(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")).to.equal(\"Here Is My Handle Here Is My Spout\");" ], - "MDNlinks" : ["String.charAt()"] + "MDNlinks": ["String.charAt()"] }, { "_id": "a789b3483989747d63b0e427", @@ -119,13 +163,20 @@ "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays." ], - "challengeSeed": "function largestOfFour(arr) {\n // You can do this!\n return arr;\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);", + "challengeSeed": [ + "function largestOfFour(arr) {", + " // You can do this!", + " return arr;", + "}", + "", + "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" + ], "tests": [ "expect(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).to.be.a('array');", "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", "assert(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]).should.eql([9,35,97,1000000]));" ], - "MDNlinks" : ["Comparison Operators"] + "MDNlinks": ["Comparison Operators"] }, { "_id": "acda2fb1324d9b0fa741e6b5", @@ -135,13 +186,21 @@ "Check if a string (first argument) ends with the given target string (second argument)." ], - "challengeSeed": "function end(str, target) {\n // \"Never give up and good luck will find you.\"\n // -- Falcor\n return str;\n}\n\nend('Bastian', 'n');", + "challengeSeed": [ + "function end(str, target) {", + " // \"Never give up and good luck will find you.\"", + " // -- Falcor", + " return str;", + "}", + "", + "end('Bastian', 'n');" + ], "tests": [ "assert.strictEqual(end('Bastian', 'n'), true, 'should equal true if target equals end of string');", "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", "assert.strictEqual(end('If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing', 'mountain'), false, 'should equal false if target does not equal end of string');" ], - "MDNlinks" : ["String.substr()"] + "MDNlinks": ["String.substr()"] }, { "_id": "afcc8d540bea9ea2669306b6", @@ -150,13 +209,20 @@ "description": [ "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number." ], - "challengeSeed": "function repeat(str, num) {\n // repeat after me\n return str;\n}\n\nrepeat('abc', 3);", + "challengeSeed": [ + "function repeat(str, num) {", + " // repeat after me", + " return str;", + "}", + "", + "repeat('abc', 3);" + ], "tests": [ "assert.strictEqual(repeat('*', 3), '***', 'should repeat a string n times');", "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", "assert.strictEqual(repeat('abc', -2), '', 'should return an empty string for negative numbers');" ], - "MDNlinks" : ["Global String Object"] + "MDNlinks": ["Global String Object"] }, { "_id": "ac6993d51946422351508a41", @@ -166,13 +232,20 @@ "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", "Note that the three dots at the end add to the string length." ], - "challengeSeed":"function truncate(str, num) {\n // Clear out that junk in your trunk\n return str;\n}\n\ntruncate('A-tisket a-tasket A green and yellow basket', 11);", + "challengeSeed": [ + "function truncate(str, num) {", + " // Clear out that junk in your trunk", + " return str;", + "}", + "", + "truncate('A-tisket a-tasket A green and yellow basket', 11);" + ], "tests": [ "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" ], - "MDNlinks" : ["String.slice()"] + "MDNlinks": ["String.slice()"] }, { "_id": "a9bd25c716030ec90084d8a1", @@ -181,13 +254,20 @@ "description": [ "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array." ], - "challengeSeed": "function chunk(arr, size) {\n // Break it up.\n return arr;\n}\n\nchunk(['a', 'b', 'c', 'd'], 2);", + "challengeSeed": [ + "function chunk(arr, size) {", + " // Break it up.", + " return arr;", + "}", + "", + "chunk(['a', 'b', 'c', 'd'], 2);" + ], "tests": [ "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" ], - "MDNlinks" : ["Array.push()"] + "MDNlinks": ["Array.push()"] }, { "_id": "ab31c21b530c0dafa9e241ee", @@ -196,13 +276,20 @@ "description": [ "Return the remaining elements of an array after chopping off n elements from the head." ], - "challengeSeed": "function slasher(arr, howMany) {\n // it doesn't always pay to be first\n return arr;\n}\n\nslasher([1, 2, 3], 2);", + "challengeSeed": [ + "function slasher(arr, howMany) {", + " // it doesn't always pay to be first", + " return arr;", + "}", + "", + "slasher([1, 2, 3], 2);" + ], "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');" ], - "MDNlinks" : ["Array.slice()", "Array.splice()"] + "MDNlinks": ["Array.slice()", "Array.splice()"] }, { "_id": "af2170cad53daa0770fabdea", @@ -214,7 +301,13 @@ "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'." ], - "challengeSeed": "function mutation(arr) {\n return arr;\n}\n\nmutation(['hello', 'hey']);", + "challengeSeed": [ + "function mutation(arr) {", + " return arr;", + "}", + "", + "mutation(['hello', 'hey']);" + ], "tests": [ "expect(mutation(['hello', 'hey'])).to.be.false;", "expect(mutation(['hello', 'Hello'])).to.be.true;", @@ -222,7 +315,7 @@ "expect(mutation(['Mary', 'Army'])).to.be.true;", "expect(mutation(['Alien', 'line'])).to.be.true;" ], - "MDNlinks" : ["Array.sort()"] + "MDNlinks": ["Array.sort()"] }, { "_id": "adf08ec01beb4f99fc7a68f2", @@ -232,13 +325,20 @@ "Remove all falsey values from an array.", "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN." ], - "challengeSeed": "function bouncer(arr) {\n // Don't show a false ID to this bouncer.\n return arr;\n}\n\nbouncer([7, 'ate', '', false, 9]);", + "challengeSeed": [ + "function bouncer(arr) {", + " // Don't show a false ID to this bouncer.", + " return arr;", + "}", + "", + "bouncer([7, 'ate', '', false, 9]);" + ], "tests": [ "assert.deepEqual(bouncer([7, 'ate', '', false, 9]), [7, 'ate', 9], 'should remove falsey values');", "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", "assert.deepEqual(bouncer([false, null, 0]), [], 'should return empty array if all elements are falsey');" ], - "MDNlinks" : ["Boolean Objects", "Array.filter()"] + "MDNlinks": ["Boolean Objects", "Array.filter()"] }, { "_id":"a8e512fbe388ac2f9198f0fa", @@ -247,12 +347,20 @@ "description":[ "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument)." ], - "challengeSeed":"function where(collection, source) {\n var arr = [];\n // What's in a name?\n return arr;\n}\n\nwhere([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });", + "challengeSeed": [ + "function where(collection, source) {", + " var arr = [];", + " // What's in a name?", + " return arr;", + "}", + "", + "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" + ], "tests":[ "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" ], - "MDNlinks" : ["Global Object", "Object.hasOwnProperty()", "Object.keys()"] + "MDNlinks": ["Global Object", "Object.hasOwnProperty()", "Object.keys()"] }, { "_id":"a39963a4c10bc8b4d4f06d7e", @@ -261,12 +369,19 @@ "description":[ "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments." ], - "challengeSeed": "function destroyer(arr) {\n // Remove all the values\n return arr;\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);", + "challengeSeed": [ + "function destroyer(arr) {", + " // Remove all the values", + " return arr;", + "}", + "", + "destroyer([1, 2, 3, 1, 2, 3], 2, 3);" + ], "tests": [ "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" ], - "MDNlinks" : ["Arguments object","Array.filter()"] + "MDNlinks": ["Arguments object","Array.filter()"] }, { "_id": "a24c1a4622e3c05097f71d67", @@ -276,7 +391,14 @@ "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", "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)." ], - "challengeSeed": "function where(arr, num) {\n // Find my place in this sorted array.\n return num;\n}\n\nwhere([40, 60], 50);", + "challengeSeed": [ + "function where(arr, num) {", + " // Find my place in this sorted array.", + " return num;", + "}", + "", + "where([40, 60], 50);" + ], "tests": [ "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" @@ -290,7 +412,13 @@ "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", "The lowest number will not always come first." ], - "challengeSeed": "function sumAll(arr) {\n return(1);\n}\n\nsumAll([1, 4]);", + "challengeSeed": [ + "function sumAll(arr) {", + " return(1);", + "}", + "", + "sumAll([1, 4]);" + ], "tests": [ "expect(sumAll([1, 4])).to.be.a('Number');", "expect(sumAll([1, 4])).to.equal(10);", @@ -298,7 +426,7 @@ "expect(sumAll([5, 10])).to.equal(45);", "expect(sumAll([10, 5])).to.equal(45);" ], - "MDNlinks" : ["Math.max()", "Math.min()", "Array.reduce()"] + "MDNlinks": ["Math.max()", "Math.min()", "Array.reduce()"] }, { "_id": "a5de63ebea8dbee56860f4f2", @@ -307,7 +435,15 @@ "description": [ "Compare two arrays and return a new array with any items not found in both of the original arrays." ], - "challengeSeed": "function diff(arr1, arr2) {\n var newArr = [];\n // Same, same; but different.\n return newArr;\n}\n\ndiff([1, 2, 3, 5], [1, 2, 3, 4, 5]);", + "challengeSeed": [ + "function diff(arr1, arr2) {", + " var newArr = [];", + " // Same, same; but different.", + " return newArr;", + "}", + "", + "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" + ], "tests": [ "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", @@ -333,8 +469,14 @@ "Convert the number be a roman numeral.", "All roman numerals answers should be provided in upper-case." ], - "challengeSeed": "function convert(num) {\n return num;\n}\n\nconvert(36);", - "MDNlinks" : ["Array.splice()", "Array.indexOf()", "Array.join()"] + "challengeSeed": [ + "function convert(num) {", + " return num;", + "}", + "", + "convert(36);" + ], + "MDNlinks": ["Array.splice()", "Array.indexOf()", "Array.join()"] }, { "_id": "a0b5010f579e69b815e7c5d6", @@ -354,8 +496,14 @@ "Third argument is what you will be replacing the second argument with (after).", "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'" ], - "challengeSeed": "function replace(str, before, after) {\n return str;\n}\n\nreplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");", - "MDNlinks" : ["Array.splice()", "String.replace()", "Array.join()"] + "challengeSeed": [ + "function replace(str, before, after) {", + " return str;", + "}", + "", + "replace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" + ], + "MDNlinks": ["Array.splice()", "String.replace()", "Array.join()"] }, { "_id": "aa7697ea2477d1316795783b", @@ -373,8 +521,14 @@ "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", "If a word begins with a vowel you just add \"way\" to the end." ], - "challengeSeed": "function translate(str) {\n return str;\n}\n\ntranslate(\"consonant\");", - "MDNlinks" : ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] + "challengeSeed": [ + "function translate(str) {", + " return str;", + "}", + "", + "translate(\"consonant\");" + ], + "MDNlinks": ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] }, { "_id": "afd15382cdfb22c9efe8b7de", @@ -390,8 +544,14 @@ "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", "Return the provided character as the first element in each array." ], - "challengeSeed": "function pair(str) {\n return str;\n}\n\npair(\"GCG\");", - "MDNlinks" : ["Array.push()", "String.split()"] + "challengeSeed": [ + "function pair(str) {", + " return str;", + "}", + "", + "pair(\"GCG\");" + ], + "MDNlinks": ["Array.push()", "String.split()"] }, { "_id": "af7588ade1100bde429baf20", @@ -401,14 +561,20 @@ "Find the missing letter in the passed letter range and return it.", "If all letters are present in the range, return undefined." ], - "challengeSeed": "function fearNotLetter(str) {\n return str;\n}\n\nfearNotLetter('abce');", + "challengeSeed": [ + "function fearNotLetter(str) {", + " return str;", + "}", + "", + "fearNotLetter('abce');" + ], "tests": [ "expect(fearNotLetter('abce')).to.equal('d');", "expect(fearNotLetter('bcd')).to.be.undefined;", "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", "expect(fearNotLetter('yz')).to.be.undefined;" ], - "MDNlinks" : ["String.charCodeAt()"] + "MDNlinks": ["String.charCodeAt()"] }, { "_id": "a77dbc43c33f39daa4429b4f", @@ -418,7 +584,14 @@ "Check if a value is classified as a boolean primitive. Return true or false.", "Boolean primitives are true and false." ], - "challengeSeed": "function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return bool;\n}\n\nboo(null);", + "challengeSeed": [ + "function boo(bool) {", + " // What is the new fad diet for ghost developers? The Boolean.", + " return bool;", + "}", + "", + "boo(null);" + ], "tests": [ "assert.strictEqual(boo(true), true);", "assert.strictEqual(boo(false), true);", @@ -429,7 +602,7 @@ "assert.strictEqual(boo(NaN), false);", "assert.strictEqual(boo('a'), false);" ], - "MDNlinks" : ["Boolean Objects"] + "MDNlinks": ["Boolean Objects"] }, { "_id": "a105e963526e7de52b219be9", @@ -441,7 +614,13 @@ "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", "Check the assertion tests for examples." ], - "challengeSeed": "function unite(arr1, arr2, arr3) {\n return arr1;\n}\n\nunite([1, 2, 3], [5, 2, 1, 4], [2, 1]);", + "challengeSeed": [ + "function unite(arr1, arr2, arr3) {", + " return arr1;", + "}", + "", + "unite([1, 2, 3], [5, 2, 1, 4], [2, 1]);" + ], "tests": [ "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" @@ -454,12 +633,19 @@ "description": [ "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities." ], - "challengeSeed": "function convert(str) {\n // :)\n return str;\n}\n\nconvert('Dolce & Gabbana');", + "challengeSeed": [ + "function convert(str) {", + " // :)", + " return str;", + "}", + "", + "convert('Dolce & Gabbana');" + ], "tests": [ "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" ], - "MDNlinks" : ["RegExp"] + "MDNlinks": ["RegExp"] }, { "_id": "a103376db3ba46b2d50db289", @@ -468,14 +654,22 @@ "description": [ "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes." ], - "challengeSeed": "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n return str;\n}\n\nspinalCase('This Is Spinal Tap');", + "challengeSeed": [ + "function spinalCase(str) {", + " // \"It's such a fine line between stupid, and clever.\"", + " // --David St. Hubbins", + " return str;", + "}", + "", + "spinalCase('This Is Spinal Tap');" + ], "tests": [ "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" ], - "MDNlinks" : ["RegExp", "String.replace()"] + "MDNlinks": ["RegExp", "String.replace()"] }, { "_id": "a5229172f011153519423690", @@ -486,7 +680,13 @@ "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3." ], - "challengeSeed": "function sumFibs(num) {\n return num;\n}\n\nsumFibs(4);", + "challengeSeed": [ + "function sumFibs(num) {", + " return num;", + "}", + "", + "sumFibs(4);" + ], "tests": [ "expect(sumFibs(1)).to.be.a('number');", "expect(sumFibs(1000)).to.equal(1785);", @@ -495,7 +695,7 @@ "expect(sumFibs(75024)).to.equal(60696);", "expect(sumFibs(75025)).to.equal(135721);" ], - "MDNlinks" : ["Remainder"] + "MDNlinks": ["Remainder"] }, { "_id": "a3bfc1673c0526e06d3ac698", @@ -506,7 +706,13 @@ "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", "The provided number may not be a prime." ], - "challengeSeed": "function sumPrimes(num) {\n return num;\n}\n\nsumPrimes(10);", + "challengeSeed": [ + "function sumPrimes(num) {", + " return num;", + "}", + "", + "sumPrimes(10);" + ], "tests": [ "expect(sumPrimes(10)).to.be.a('number');", "expect(sumPrimes(10)).to.equal(17);", @@ -521,7 +727,14 @@ "Find the smallest number that is evenly divisible by all numbers in the provided range.", "The range will be an array of two numbers that will not necessarily be in numerical order." ], - "challengeSeed": "function smallestCommons(arr) {\n return arr;\n}\n\n\nsmallestCommons([1,5]);", + "challengeSeed": [ + "function smallestCommons(arr) {", + " return arr;", + "}", + "", + "", + "smallestCommons([1,5]);" + ], "tests": [ "expect(smallestCommons([1,5])).to.be.a('number');", "expect(smallestCommons([1,5])).to.equal(60);", @@ -536,12 +749,19 @@ "description": [ "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument)." ], - "challengeSeed": "function find(arr, func) {\n var num = 0;\n return num;\n}\n\nfind([1, 2, 3, 4], function(num){ return num % 2 === 0; });", + "challengeSeed": [ + "function find(arr, func) {", + " var num = 0;", + " return num;", + "}", + "", + "find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" + ], "tests": [ "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" ], - "MDNlinks" : ["Array.some()"] + "MDNlinks": ["Array.some()"] }, { "_id": "a5deed1811a43193f9f1c841", @@ -550,13 +770,20 @@ "description": [ "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true." ], - "challengeSeed": "function drop(arr, func) {\n // Drop them elements.\n return arr;\n}\n\ndrop([1, 2, 3], function(n) {return n < 3; });", + "challengeSeed": [ + "function drop(arr, func) {", + " // Drop them elements.", + " return arr;", + "}", + "", + "drop([1, 2, 3], function(n) {return n < 3; });" + ], "tests": [ "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);" ], - "MDNlinks" : ["Arguments object", "Array.shift()"] + "MDNlinks": ["Arguments object", "Array.shift()"] }, { "_id": "ab306dbdcc907c7ddfc30830", @@ -565,13 +792,20 @@ "description": [ "Flatten a nested array. You must account for varying levels of nesting." ], - "challengeSeed": "function steamroller(arr) {\n // I'm a steamroller, baby\n return arr;\n}\n\nsteamroller([1, [2], [3, [[4]]]]);", + "challengeSeed": [ + "function steamroller(arr) {", + " // I'm a steamroller, baby", + " return arr;", + "}", + "", + "steamroller([1, [2], [3, [[4]]]]);" + ], "tests": [ "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');" ], - "MDNlinks" : ["Array.isArray()"] + "MDNlinks": ["Array.isArray()"] }, { "_id": "a8d97bd4c764e91f9d2bda01", @@ -581,12 +815,19 @@ "Return an English translated sentence of the passed binary string.", "The binary string will be space separated." ], - "challengeSeed": "function binaryAgent(str) {\n return str;\n}\n\nbinaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');", + "challengeSeed": [ + "function binaryAgent(str) {", + " return str;", + "}", + "", + "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" + ], "tests": [ "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" ], - "MDNlinks" : ["String.charCodeAt()", "String.fromCharCode()"] + "MDNlinks": ["String.charCodeAt()", "String.fromCharCode()" + ] }, { "_id" : "a3f503de51cfab748ff001aa", @@ -597,7 +838,13 @@ "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!" ], - "challengeSeed": "function pairwise(arr, arg) {\n return arg;\n}\n\npairwise([1,4,2,3,0,5], 7);", + "challengeSeed": [ + "function pairwise(arr, arg) {", + " return arg;", + "}", + "", + "pairwise([1,4,2,3,0,5], 7);" + ], "tests": [ "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", @@ -615,12 +862,19 @@ "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." ], - "challengeSeed": "function every(collection, pre) {\n // Does everyone have one of these?\n return pre;\n}\n\nevery([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');", + "challengeSeed": [ + "function every(collection, pre) {", + " // Does everyone have one of these?", + " return pre;", + "}", + "", + "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" + ], "tests": [ "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" ], - "MDNlinks" : ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"] + "MDNlinks": ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"] }, { "_id": "a97fd23d9b809dac9921074f", @@ -631,7 +885,13 @@ "For example, add(2, 3) should return 5, and add(2) should return a function that is waiting for an argument so that var sum2And = add(2); return sum2And(3); // 5", "If either argument isn't a valid number, return undefined." ], - "challengeSeed": "function add() {\n return false;\n}\n\nadd(2,3);", + "challengeSeed": [ + "function add() {", + " return false;", + "}", + "", + "add(2,3);" + ], "tests": [ "expect(add(2, 3)).to.equal(5);", "expect(add(2)(3)).to.equal(5);", @@ -651,7 +911,14 @@ "All functions that take an argument have an arity of 1, and the argument will be a string.", "These methods must be the only available means for interacting with the object." ], - "challengeSeed": "var Person = function(firstAndLast) {\n return firstAndLast;\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();", + "challengeSeed": [ + "var Person = function(firstAndLast) {", + " return firstAndLast;", + "};", + "", + "var bob = new Person('Bob Ross');", + "bob.getFullName();" + ], "tests": [ "expect(Object.keys(bob).length).to.eql(6);", "expect(bob instanceof Person).to.be.true;", @@ -668,7 +935,7 @@ "expect(bob.getFullName()).to.eql('George Carlin');", "bob.setFullName('Bob Ross');" ], - "MDNlinks" : ["Closures", "Details of the Object Model"] + "MDNlinks": ["Closures", "Details of the Object Model"] }, { "_id": "af4afb223120f7348cdfc9fd", @@ -681,12 +948,20 @@ "The values should be rounded to the nearest whole number. The body being orbited is Earth.", "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418" ], - "challengeSeed": "function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n return arr;\n}\n\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);", + "challengeSeed": [ + "function orbitalPeriod(arr) {", + " var GM = 398600.4418;", + " var earthRadius = 6367.4447;", + " return arr;", + "}", + "", + "orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);" + ], "tests": [ "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" ], - "MDNlinks" : ["Math.pow()"] + "MDNlinks": ["Math.pow()"] }, { "_id": "aff0395860f5d3034dc0bfc9", @@ -722,7 +997,16 @@ "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" ], - "challengeSeed": "function telephoneCheck(str) {\n // Good luck!\n return true;\n}\n\n\n\ntelephoneCheck(\"555-555-5555\");" + "challengeSeed": [ + "function telephoneCheck(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "telephoneCheck(\"555-555-5555\");" + ] }, { "_id": "a3f503de51cf954ede28891d", @@ -732,7 +1016,13 @@ "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both." ], - "challengeSeed": "function sym(args) {\n return arguments;\n}\n\nsym([1, 2, 3], [5, 2, 1, 4]);", + "challengeSeed": [ + "function sym(args) {", + " return arguments;", + "}", + "", + "sym([1, 2, 3], [5, 2, 1, 4]);" + ], "tests": [ "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", @@ -747,7 +1037,26 @@ "description": [ "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order." ], - "challengeSeed": "function drawer(price, cash, cid) {\n var change;\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]]);", + "challengeSeed": [ + "function drawer(price, cash, cid) {", + " var change;", + " // Here is your change, ma'am.", + " return change;", + "}", + "", + "// Example cash-in-drawer array:", + "// [['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]]", + "", + "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" + ], "tests": [ "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", @@ -765,7 +1074,29 @@ "description": [ "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order." ], - "challengeSeed": "function inventory(arr1, arr2) {\n // All inventory must be accounted for or you're fired!\n return arr1;\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);", + "challengeSeed": [ + "function inventory(arr1, arr2) {", + " // All inventory must be accounted for or you're fired!", + " return arr1;", + "}", + "", + "// Example inventory lists", + "var curInv = [", + " [21, 'Bowling Ball'],", + " [2, 'Dirty Sock'],", + " [1, 'Hair Pin'],", + " [5, 'Microphone']", + "];", + "", + "var newInv = [", + " [2, 'Hair Pin'],", + " [3, 'Half-Eaten Apple'],", + " [67, 'Bowling Ball'],", + " [7, 'Toothpaste']", + "];", + "", + "inventory(curInv, newInv);" + ], "tests": [ "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", @@ -783,7 +1114,13 @@ "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating." ], - "challengeSeed": "function permAlone(str) {\n return str;\n}\n\npermAlone('aab');", + "challengeSeed": [ + "function permAlone(str) {", + " return str;", + "}", + "", + "permAlone('aab');" + ], "tests": [ "expect(permAlone('aab')).to.be.a.number;", "expect(permAlone('aab')).to.equal(2);", @@ -805,7 +1142,13 @@ "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", "Input date is formatted as YYYY-MM-DD" ], - "challengeSeed": "function friendly(str) {\n return str;\n}\n\nfriendly(['2015-07-01', '2015-07-04']);", + "challengeSeed": [ + "function friendly(str) {", + " return str;", + "}", + "", + "friendly(['2015-07-01', '2015-07-04']);" + ], "tests": [ "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", @@ -814,6 +1157,6 @@ "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" ], - "MDNlinks" : ["String.split()", "String.substr()", "parseInt()"] + "MDNlinks": ["String.split()", "String.substr()", "parseInt()"] } ] diff --git a/seed_data/challenges/basejumps.json b/seed_data/challenges/basejumps.json new file mode 100644 index 0000000000..95ec8505f8 --- /dev/null +++ b/seed_data/challenges/basejumps.json @@ -0,0 +1,176 @@ +{ + "name": "Basejumps", + "order" : 0.010, + "challenges": [ + { + "_id": "bd7158d8c443eddfaeb5bcef", + "name": "Get Set for Basejumps", + "difficulty": 2.00, + "challengeSeed": "126433451", + "description": [ + "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.", + "We'll build our Basejumps on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "If you don't already have Cloud 9 account, create one now at http://c9.io.", + "Now let's get your development environment ready for a new Angular-Fullstack application provided by Yeoman.", + "Open up http://c9.io and sign in to your account.", + "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", + "Give your workspace a name.", + "Choose Node.js in the selection area below the name field.", + "Click the Create button.", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", + "Click the \"Start Editing\" button.", + "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", + "Never run this command on your local machine. But in your Cloud 9 terminal window, run: rm -rf * && echo \"export NODE_PATH=$NODE_PATH:/home/ubuntu/.nvm/v0.10.35/lib/node_modules\" >> ~/.bashrc && source ~/.bashrc && npm install -g yo grunt grunt-cli generator-angular-fullstack && yo angular-fullstack", + "Yeoman will prompt you to answer some questions. Answer them like this:", + "What would you like to write scripts with? JavaScript", + "What would you like to write markup with? HTML", + "What would you like to write stylesheets with? CSS", + "What Angular router would you like to use? ngRoute", + "Would you like to include Bootstrap? Yes", + "Would you like to include UI Bootstrap? Yes", + "Would you like to use MongoDB with Mongoose for data modeling? Yes", + "Would you scaffold out an authentication boilerplate? Yes", + "Would you like to include additional oAuth strategies? Twitter", + "Would you like to use socket.io? No", + "May bower anonymously report usage statistics to improve the tool over time? (Y/n) Y", + "You may get an error similar to ERR! EEXIST, open ‘/home/ubuntu/.npm. This is caused when Cloud9 runs out of memory and kills an install. If you get this, simply re-run this process with the command yo angular-fullstack. You will then be asked a few questions regarding the re-install. Answer them as follows:", + "Existing .yo-rc configuration found, would you like to use it? (Y/n) Y", + "Overwrite client/favicon.ico? (Ynaxdh) Y", + "To finish the installation run the commands: bower install && npm install", + "To start MongoDB, run the following commands in your terminal: mkdir data && echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest \"$@\"' > mongod && chmod a+x mongod && ./mongod", + "You will want to open up a new terminal to work from by clicking on the + icon and select New Terminal", + "Start the application by running the following command in your new terminal window: grunt serve", + "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", + "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", + "Create a new Github repository by signing in to http://github.com and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", + "Enter a project name, then click the \"Create Repository\" button.", + "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", + "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to Github.", + "Check back on your Github profile to verify the changes were successfully pushed up to Github.", + "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.", + "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c hotkey to shut down these processes.", + "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login. At this point, the terminal will prompt you to log in to Heroku from the command line.", + "Now run yo angular-fullstack:heroku. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", + "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab.", + "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace directory by running cd ~/workspace. Then you can this code to stage the changes to your changes and commit them: git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." + ], + "challengeType": 4, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdef", + "name": "Basejump: Build a Voting App", + "difficulty": 2.01, + "challengeSeed": "123488494", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://voteplex.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an authenticated user, I can keep my polls and come back later to access them.", + "User Story: As an authenticated user, I can share my polls with my friends.", + "User Story: As an authenticated user, I can see the aggregate results of my polls.", + "User Story: As an authenticated user, I can delete polls that I decide I don't want anymore.", + "User Story: As an authenticated user, I can create a poll with any number of possible items.", + "Bonus User Story: As an unauthenticated user, I can see everyone's polls, but I can't vote on anything.", + "Bonus User Story: As an unauthenticated or authenticated user, I can see the results of polls in chart form. (This could be implemented using Chart.js or Google Charts.)", + "Bonus User Story: As an authenticated user, if I don't like the options on a poll, I can create a new option.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

      Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdff", + "name": "Basejump: Build a Nightlife Coordination App", + "difficulty": 2.02, + "challengeSeed": "123488494", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://sociallife.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an unauthenticated user, I can view all bars in my area.", + "User Story: As an authenticated user, I can add myself to a bar to indicate I am going there tonight.", + "User Story: As an authenticated user, I can remove myself from a bar if I no longer want to go there.", + "Bonus User Story: As an unauthenticated user, when I login I should not have to search again.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

      Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bd0e", + "name": "Basejump: Chart the Stock Market", + "difficulty": 2.03, + "challengeSeed": "123488494", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockjump.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As a user, I can view a graph displaying the recent trend lines for each added stock.", + "User Story: As a user, I can add new stocks by their symbol name.", + "User Story: As a user, I can remove stocks.", + "Bonus User Story: As a user, I can see changes in real-time when any other user adds or removes a stock.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

      Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bd0f", + "name": "Basejump: Manage a Book Trading Club", + "difficulty": 2.04, + "challengeSeed": "123488494", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookoutpost.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an authenticated user, I can view all books posted by every user.", + "User Story: As an authenticated user, I can add a new book.", + "User Story: As an authenticated user, I can update my settings to store my full name, city, and state.", + "Bonus User Story: As an authenticated user, I can propose a trade and wait for the other user to accept the trade.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

      Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [] + }, + { + "_id": "bd7158d8c443eddfaeb5bdee", + "name": "Basejump: Build a Pinterest Clone", + "difficulty": 2.05, + "challengeSeed": "123488494", + "description": [ + "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://linkterest.herokuapp.com/ and deploy it to Heroku.", + "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", + "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", + "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Here are the specific User Stories you should implement for this Basejump:", + "User Story: As an unauthenticated user, I can login with Twitter.", + "User Story: As an authenticated user, I can link to images.", + "User Story: As an authenticated user, I can delete images that I've linked to.", + "User Story: As an authenticated user, I can see a Pinterest-style wall of all the images I've linked to.", + "User Story: As an unauthenticated user, I can browse other users' walls of images.", + "User Story: As an unauthenticated user, I can see everyone's polls, but not be able to vote.", + "Bonus User Story: As an authenticated user, if I upload an image that is broken, it will be replaced by a placeholder image. (can use jQuery broken image detection)", + "Hint: Masonry.js is a library that allows for Pinterest-style image grids.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

      Click here then add your link to your tweet's text" + ], + "challengeType": 4, + "tests": [] + } + ] +} diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json new file mode 100644 index 0000000000..274d64485b --- /dev/null +++ b/seed_data/challenges/basic-html5-and-css.json @@ -0,0 +1,1626 @@ +{ + "name": "Basic HTML5 and CSS", + "order" : 0.002, + "challenges": [ + { + "_id": "bd7123c8c441eddfaeb5bdef", + "name": "Use HTML Elements", + "difficulty": 0.0085, + "description": [ + "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", + "Awesome. Now you can read the rest of this challenge's instructions.", + "You can edit code in your text editor, which we've embedded into this web page.", + "Do you see the code in your text editor that says <h1>Hello</h1>? That's an HTML element.", + "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", + "Once you've completed each challenge, and all its tests are passing, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", + "To enable the \"Go to my next challenge\" button on this exercise, change your h1 tag's text to say \"Hello World\" instead of \"Hello\"." + ], + "tests": [ + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" + ], + "challengeSeed": [ + "

      Hello

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf0887a", + "name": "Use the h2 Element", + "difficulty": 0.010, + "description": [ + "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", + "The h2 element you enter will create an h2 element on the website.", + "This element tells the browser how to render the text that it contains.", + "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." + ], + "tests": [ + "assert.isTrue((/cat(\\s)?photo(\\s)?app/gi).test($('h2').text()), 'Your h2 element should have the text \"CatPhotoApp\"')", + "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" + ], + "challengeSeed": [ + "

      Hello World

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08801", + "name": "Use the Paragraph Element", + "difficulty": 0.011, + "description": [ + "Create a paragraph element below the h2 element, and give it the text \"Hello Paragraph\".", + "Paragraph elements are the preferred element for normal-sized paragraph text on websites.", + "You can create a paragraph element like so: <p>I'm a p tag!</p>" + ], + "tests": [ + "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your paragraph element should have the text \"Hello Paragraph\"')" + ], + "challengeSeed": [ + "

      Hello World

      ", + "

      CatPhotoApp

      " + ] + }, + { + "_id": "bad87fee1348bd9aeaf08801", + "name": "Add a Line Break to Visually Separate Elements", + "difficulty": 0.012, + "description": [ + "Add a line break between the <h2> and <p> elements.", + "You can create an line break element with <br/>.", + "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?", + "You'll encounter other self-closing element tags soon." + ], + "tests": [ + "assert(($('br').length > 0), 'You should have a br element between your h2 and paragraph elements.')" + ], + "challengeSeed": [ + "

      Hello World

      ", + "

      CatPhotoApp

      ", + "

      Hello Paragraph

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08802", + "name": "Uncomment HTML", + "difficulty": 0.013, + "description": [ + "Uncomment the h1, h2 and p elements.", + "Commenting is a way that you can leave comments within your code without affecting the code itself.", + "Commenting is also a convenient way to make code inactive without having to delete it entirely.", + "You can start a comment with <!-- and end a comment with -->." + ], + "tests": [ + "assert(($('h1').length > 0), 'The h1 element should not commented. It should be visible in the browser.')", + "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", + "assert(($('p').length > 0), 'The paragraph element should not commented. It should be visible in the browser.')" + ], + "challengeSeed": [ + "" + ] + }, + { + "_id": "bad87fee1348bd9aedf08804", + "name": "Comment out HTML", + "difficulty": 0.014, + "description": [ + "Comment out the h1 element and the p element, but leave the h2 element uncommented.", + "Remember that in order to start a comment, you need to use <!-- and to end a comment, you need to use -->.", + "Here you'll need to end the comment before the h2 element begins." + ], + "tests": [ + "assert(($('h1').length == 0), 'The h1 element should be commented. It should not be visible in the browser.')", + "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", + "assert(($('p').length == 0), 'The paragraph element should be commented. It should not be visible in the browser.')" + ], + "challengeSeed": [ + "" + ] + }, + { + "_id": "bad87fee1348bd9aedf08833", + "name": "Use Lorem Ipsum Text as a Placeholder", + "difficulty": 0.015, + "description": [ + "Change the text in the p element to use the first few words of Kitty Ipsum text.", + "Web developers traditionally use Lorem Ipsum as placeholder text. It's called Lorem Ipsum text because those are the first two words of a famous passage by Cicero of Ancient Rome.", + "Lorem Ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", + "Well, 5 centuries is long enough. Since we're building a CatPhotoApp, let's use something called Kitty Ipsum!", + "Here are the first few words of Kitty Ipsum text, which you can copy and paste into the right position: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff." + ], + "tests": [ + "assert.isTrue((/Kitty(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your paragraph element should contain the first few words of the famous Kitty Ipsum text.')" + ], + "challengeSeed": [ + "

      Hello World

      ", + "", + "

      CatPhotoApp

      ", + "", + "
      ", + "", + "

      Hello Paragraph

      " + ] + }, + { + "_id": "bad87fed1348bd9aedf08833", + "name": "Delete HTML Elements", + "difficulty": 0.016, + "description": [ + "Delete the h1 and br elements so we can simplify our view.", + "Our phone doesn't have much space, for HTML elements.", + "Let's remove the unnecessary elements so we can start building our CatPhotoApp." + ], + "tests": [ + "assert(($('h1').length == 0), 'Delete the h1 element.')", + "assert(($('h2').length > 0), 'Leave the h2 element on the page.')", + "assert(($('br').length == 0), 'Delete the br element.')", + "assert(($('p').length > 0), 'Leave the paragraph element on the page.')" + ], + "challengeSeed": [ + "

      Hello World

      ", + "", + "

      CatPhotoApp

      ", + "", + "
      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08803", + "name": "Change the Color of Text", + "difficulty": 0.017, + "description": [ + "Change the h2 element's style so that its text color is red.", + "We can do this by changing the style of the h2 element.", + "The style that is responsible for the color of an element's text is the \"color\" style.", + "Here's how you would set your h2 element's text color to blue: <h2 style=\"color: blue\">CatPhotoApp<h2>" + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" + ], + "challengeSeed": [ + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08805", + "name": "Use CSS Selectors to Style Elements", + "difficulty": 0.018, + "description": [ + "Delete your h2 element's style tag and write the CSS to make all h2 elements blue.", + "With CSS, there are hundreds of CSS attributes that you can use to change the way an element looks on a web page.", + "When you entered <h2 style=\"color: red\">CatPhotoApp<h2>, you were giving that individual h2 element an inline style", + "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", + "At the top of your code, create a style tag like this: <style></style>", + "Inside that style element, you can create a css selector for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>", + "Note that it's important to have opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(0, 0, 255)', 'Your h2 element should be blue.')", + "assert(!$('h2').attr('style'), 'You should remove the style attribute from your h2 element.')" + ], + "challengeSeed": [ + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aecf08806", + "name": "Use a CSS Class to Style an Element", + "difficulty": 0.019, + "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:", + "a diagram of how style tags are composed, which is also described in detail on the following lines.", + "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.", + "Instead of creating a new Style tag, try removing the h2 style declaration from the existing style element, and replace it with the class declaration for \".red-text\"." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')" + ], + "challengeSeed": [ + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aefe08806", + "name": "Use a CSS Class to Style Multiple Elements", + "difficulty": 0.020, + "description": [ + "Apply the \"red-text\" class to the h2 and p elements.", + "Remember that you can attach classes to HTML elements by using the class=\"class\" within the relevant element's opening tag." + ], + "tests": [ + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", + "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')", + "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your paragraph element should be red.')", + "assert($('p').hasClass('red-text'), 'You paragraph element should have the class \"red-text\".')" + ], + "challengeSeed": [ + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08806", + "name": "Change the Font Size of an Element", + "difficulty": 0.021, + "description": [ + "Create a second p element. Then set the font size of all p elements to 16 pixels.", + "Font size is controlled by the font-size CSS attribute, like this: h1 { font-size: 30px; }.", + "First, create a second paragraph element with the following Kitty Ipsum text: Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.", + "See if you can figure out how to give both of your paragraph elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for your \"red-text\" class." + ], + "tests": [ + "assert($('p').length > 1, 'You need 2 paragraph elements with Kitty Ipsum text.')", + "assert($('p').css('font-size') === '16px', 'Your paragraph elements should have the font-size of 16px.')" + ], + "challengeSeed": [ + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      " + ] + }, + { + "_id": "bad87fee1348bd9aede08807", + "name": "Set the Font Family of an Element", + "difficulty": 0.022, + "description": [ + "Make all paragraph elements use the \"Monospace\" font.", + "You can set an element's font by using the font-family attribute.", + "For example, if you wanted to set your h2 element's font to \"San-serif\", you would use the following CSS: h2 { font-family: 'San-serif'; }" + ], + "tests": [ + "assert($('p').css('font-family').match(/monospace/i), 'Your paragraph elements should use the font \"Monospace\".')" + ], + "challengeSeed": [ + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08807", + "name": "Import a Google Font", + "difficulty": 0.023, + "description": [ + "Apply the font-family of \"Lobster\" to your h2 element.", + "First, you'll need to make a call to Google to grab the \"Lobster\" font and load it into your HTML.", + "Copy the following code snippet and paste it into your code editor above your style element:", + "<link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>", + "Now you can set \"Lobster\" as a font-family attribute on your h2 element." + ], + "tests": [ + "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')" + ], + "challengeSeed": [ + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08808", + "name": "Specify How Fonts Should Degrade", + "difficulty": 0.024, + "description": [ + "Make all your h2 elements use \"Lobster\" as their font family, but degrade to the \"Monospace\" font when the \"Lobster\" font isn't available.", + "You can leave \"Lobster\" your h2 element's font-family, and have it \"degrade\" to a different font when \"Lobster\" isn't available.", + "For example, if you wanted an element to use the \"Helvetica\" font, but also degrade to the \"Sans-Serif\" font when \"Helvetica\" wasn't available, you could do use this CSS style: p { font-family: \"Helvetica\", \"Sans-Serif\"; }.", + "There are several default fonts that are available in all browsers. These include \"Monospace\", \"Serif\" and \"Sans-Serif\". See if you can set your h2 elements to use \"Lobster\" and degrade to \"Monospace\".", + "Now try commenting out your call to Google Fonts, so that the \"Lobster\" font isn't available. Notice how it degrades to the \"Monospace\" font." + ], + "tests": [ + "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')", + "assert($('h2').css('font-family').match(/monospace/i), 'Your h2 element should degrade to the font \"Monospace\" when \"Lobster\" is not available.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08809", + "name": "Using Important to Override Styles", + "difficulty": 0.025, + "description": [ + "Create a \"blue-text\" class that gives an element the font-color of blue. Also create a \"urgently-red\" class that give an element the font-color of red, but use !important to ensure the element is rendered as being red. Apply both classes to your h2 element.", + "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", + "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", + "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", + "In case you're curious, this is the priority hierarchy for element styles: !important > inline style > css class selector > css selector. That is, !important trumps all other styles, and inline styles trump style tag declarations.", + "Here's an example of a CSS style that uses !important: <style> .urgently-blue { color: blue !important; } </style>.", + "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." + ], + "tests": [ + "assert($('h2').hasClass('blue-text'), 'Your h2 element should have the class \"blue-text\".')", + "assert($('h2').hasClass('urgently-red'), 'Your h2 element should have the class \"urgently-red\".')", + "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + + { + "_id": "bad87fee1348bd9aedf08812", + "name": "Add an Image to your Website", + "difficulty": 0.026, + "description": [ + "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", + "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.", + "Try it with this image: http://bit.ly/fcc-kittens." + ], + "tests": [ + "assert($('img').length > 0, 'Your webpage should have an image element.')", + "assert(!!$('img').attr('src'), 'Your image should have have a src attribute that points to the kitten image.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9acdf08812", + "name": "Specify an Image Size", + "difficulty": 0.027, + "description": [ + "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", + "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", + "For example, if we wanted to create a CSS class called \"larger-image\" that gave HTML elements a width of 500 pixels, we'd use: <style> .larger-image { width: 500px; } </style>." + ], + "tests": [ + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').width() === 100, 'Your image should be 100 pixels wide.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9bedf08813", + "name": "Add a Border Around an Element", + "difficulty": 0.028, + "description": [ + "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border around an HTML element, and apply it to your cat photo.", + "CSS borders have attributes like style, color and width.", + "For example, if we wanted to create a red, 5 pixel border around an HTML element, we could use this class: <style> .thin-red-border { border-color: red; border-width: 5px; border-style: solid; } </style>." + ], + "tests": [ + "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", + "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", + "assert(parseInt($('img').css('border-left-width')) > 8, 'Your image should have a border with a width of 10 pixels.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08814", + "name": "Add Rounded Corners with a Border Radius", + "difficulty": 0.029, + "description": [ + "Give your cat photo a border radius of 10 pixels.", + "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", + "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." + ], + "tests": [ + "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", + "assert(parseInt($('img').css('border-top-left-radius')) > 8, 'Your image should have a border radius of 10 pixels')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08815", + "name": "Make an Image Circular with a Border Radius", + "difficulty": 0.030, + "description": [ + "Give your cat photo a border-radius of 50%.", + "In addition to pixels, you can also specify a border-radius using a percentage." + ], + "tests": [ + "assert(parseInt($('img').css('border-top-left-radius')) > 48, 'Your image should have a border radius of 50 percent, making it perfectly circular.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08816", + "name": "Use an Anchor Tag to Link to an External Page", + "difficulty": 0.031, + "description": [ + "Create an anchor element that links to http://catphotoapp.com and has \"cat photos\" as its anchor text (link text).", + "Here's a diagram of an anchor tag. In this case, it's used in the middle of a paragraph element, which means your link will appear in the middle of your sentence.", + "a diagram of how anchor tags are composed with the same text as on the following line", + "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>" + ], + "tests": [ + "assert((/photo/gi).test($('a').text()), 'You need an anchor element that links to \"catphotoapp.com\".')", + "assert($('a').filter(function(index) { return /photo/gi.test($('a')[index]); }).length === 1, 'Your anchor element should have the anchor text of \"See my cat photos\"')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aede08817", + "name": "Wrap an Anchor Element within a Paragraph", + "difficulty": 0.032, + "description": [ + "Now wrap your anchor element within a paragraph element so that the surrounding paragraph says \"click here for cat photos\", but where only \"cat photos\" is a link - the rest is plain text.", + "Again, here's a diagram of an anchor tag for your reference:", + "a diagram of how anchor tags are composed with the same text as on the following line", + "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>" + ], + "tests": [ + "assert((/photo/gi).test($('a').text()), 'You need an anchor element that links to \"catphotoapp.com\".')", + "assert($('a').filter(function(index) { return /photo/gi.test($('a')[index]); }).length === 1, 'Your anchor element should have the anchor text of \"See my cat photos\"')", + "assert($('a').parent().is('p'), 'Your anchor element should be wrapped within a paragraph element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "cat photos", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + + { + "_id": "bad87fee1348bd9aedf08817", + "name": "Make Dead Links using the Hash Symbol", + "difficulty": 0.033, + "description": [ + "Use the hash symbol(#) to turn your anchor element's link into a dead link.", + "Sometimes you want to add anchor elements to your website before you know where they will link.", + "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", + "Replace your anchor element's href attribute with a hash symbol to turn it into a dead link." + ], + "tests": [ + "assert($('a').attr('href') === '#', 'Your anchor element should be a dead link with a href attribute set to \"#\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08820", + "name": "Turn an Image into a Link", + "difficulty": 0.034, + "description": [ + "Wrap your img element inside an anchor element with a dead link.", + "You can make elements into links by wrapping them in an anchor tag.", + "Wrap your image in an anchor tag. Here's an example: <a href='#'><img src='http://bit.ly/fcc-kittens2'></a>", + "Remember to use the hash symbol as your anchor tag's href property in order to turn it into a dead link.", + "Once you've done this, hover over your image with your cursor. Your cursor's normal pointer should become the link clicking pointer. The photo is now a link." + ], + "tests": [ + "assert($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length > 1, 'Wrap your image element inside an anchor element that has its href attribute set to \"#\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08818", + "name": "Add Alt Text to an image", + "difficulty": 0.035, + "description": [ + "Add the alt text \"A cute orange cat lying on its back\" to our cat photo", + "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", + "In short, every image should have alt text!", + "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", + "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." + ], + "tests": [ + "assert($('img').filter(function(){ return /cat/gi.test(this.alt) }).length > 0, 'Your image element should have an alt attribute set to \"A cute orange cat lying on its back\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08827", + "name": "Create a Bulleted Unordered List", + "difficulty" : 0.036, + "description": [ + "Replace the paragraph elements with an unordered list of three things that cats love.", + "HTML has a special element for creating unordered lists, or bullet point-style lists.", + "Unordered lists start with a <ul> element. Then they contain some number of <li> elements.", + "For example: <ul><li>milk</li><li>cheese</li><ul> would create a bulleted list of \"milk\" and \"cheese\"." + ], + "tests": [ + "assert($('ul').length > 0, 'Create a ul element.')", + "assert($('li').length > 2, 'Add three li elements to your ul element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

      ", + "

      Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08828", + "name": "Create an Ordered List", + "difficulty" : 0.037, + "description": [ + "Create an ordered list of the the top 3 things cats hate the most.", + "HTML has a special element for creating ordered lists, or numbered-style lists.", + "Ordered lists start with a <ol> element. Then they contain some number of <li> elements.", + "For example: <ol><li>hydrogen</li><li>helium</li><ol> would create a numbered list of \"hydrogen\" and \"helium\"." + ], + "tests": [ + "assert($('ul').length > 0, 'You should have an ul element on your webpage.')", + "assert($('ol').length > 0, 'You should have an ol element on your webpage.')", + "assert($('li').length > 5, 'You should have three li elements on within your ul element.')", + "assert($('li').length > 5, 'You should have three li elements on within your ol element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08829", + "name": "Create a Text Field", + "difficulty" : 0.038, + "description": [ + "Now we'll create a web form. Create a text field under your lists.", + "Text inputs are a convenient way to get input from your user.", + "You can create one like this: <input type='text'>" + ], + "tests": [ + "assert($('input[type=\"text\"').length > 0, 'Your webpage should have an text field input element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08830", + "name": "Add Placeholder Text to a Text Field", + "difficulty" : 0.039, + "description": [ + "Add the placeholder text \"type a cat photo URL here\" to your text field.", + "Placeholder text will appear in your text field before your user has inputed anything.", + "For example: <input type='text' placeholder='this is placeholder text'>" + ], + "tests": [ + "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"cat photo URL\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "" + ] + }, + + { + "_id" : "bad87fee1348bd9aede08830", + "name": "Create a basic Form Element", + "difficulty" : 0.040, + "description": [ + "Wrap your text field in a <form> element. Add the action=\"/submit-cat-photo\" attribute to this form element.", + "You can build web forms that actually submit data to a server using nothing more than pure HTML. You can do this by specifying an action on your form element.", + "For example: <form action=\"/url-where-you-want-to-submit-form-data\"></form>" + ], + "tests": [ + "assert($('form').length > 0, 'Wrap your text input element within a form element.')", + "assert($('form').attr('action'), 'Your form element should have an action attribute.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "" + ] + }, + + { + "_id" : "bad87fee1348bd9aedd08830", + "name": "Add a Submit Button to a Form", + "difficulty" : 0.041, + "description": [ + "Add a submit button to your form field.", + "Let's add a submit button to your form. Clicking this button will send the date from your form to the URL you specified with your form's action attribute.", + "Here's an example submit button: <button type='submit'>this button submits the form</button>" + ], + "tests": [ + "assert($('button').length > 0, 'Your form should have a button inside it.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedc08830", + "name": "Use HTML5 to Make a Field Required", + "difficulty" : 0.042, + "description": [ + "Make it required for your user to input text into your form before being able to submit it.", + "You can require your user to complete specific form fields before they will be able to submit your form.", + "For example, if you wanted to make a text input field required, you can just add the word \"required\" within your input element use: <input type='text' required>" + ], + "tests": [ + "assert($('input').prop('required'), 'Your text field have the property of being required.')", + "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"cat photo URL\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08834", + "name": "Create a Set of Radio Buttons", + "difficulty" : 0.043, + "description": [ + "Add to your form a pair of radio buttons that are wrapped in label elements and share a name attribute, with the options of \"indoor\" and \"outdoor\".", + "You can use radio buttons for questions where you want the user to only give you one answer.", + "Radio buttons are a type of input.", + "Radio buttons should be wrapped within label elements.", + "All related radio buttons should have the same name attribute.", + "Here's an example of a radio button: <label><input type='radio' name='indoor-outdoor'> Indoor</label>" + ], + "tests": [ + "assert($('input[type=\"radio\"').length > 1, 'Your webpage should have two radio button elements.')", + "assert($('input[type=\"radio\"').attr('name'), 'Both of your radio button should have name attributes with the same value.')", + "assert($('label').length > 1, 'Each of your two radio button elements should be wrapped in a label element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08835", + "name": "Create a Set of Checkboxes", + "difficulty" : 0.044, + "description": [ + "Add to your form a set of three checkbox elements that are wrapped in label elements and share the same name attribute.", + "Forms commonly use checkbox elements for questions that may have more than one answer.", + "For example: <label><input type='checkbox' name='personality'> Loving</label>" + ], + "tests": [ + "assert($('input[type=\"checkbox\"').length > 2, 'Your webpage should have three checkbox elements.')", + "assert($('label').length > 2, 'Each of your three checkbox elements should be wrapped in a label element.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aede08835", + "name": "Clean up your form using Linebreaks", + "difficulty" : 0.045, + "description": [ + "Clean up your form by adding linebreaks between form elements.", + "Remember that you can create a linebreak element by using the code: <br>" + ], + "tests": [ + "assert($('br').length > 1, 'Add at least 2 line breaks to visually separate your form elements.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedd08835", + "name": "Check Radio Buttons and Checkboxes by Default", + "difficulty" : 0.046, + "description": [ + "Set one of your radio buttons and one of your checkboxes to be checked by default.", + "" + ], + "tests": [ + "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')", + "assert($('input[type=\"checkbox\"').prop('checked'), 'One of the checkboxes on your form should be checked by default.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + } + ] +} diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json new file mode 100644 index 0000000000..7f33bd5bbc --- /dev/null +++ b/seed_data/challenges/basic-javascript.json @@ -0,0 +1,167 @@ +{ + "name": "Basic JavaScript", + "order" : 0.006, + "challenges": [ + { + "_id": "bd7129d8c441eddfaeb5bdef", + "name": "Build an Adventure Game", + "difficulty": 0.24, + "challengeSeed": "114604814", + "description": [ + "Now that you understand some Computer Science fundamentals, let's focus on programming JavaScript!", + "We're going to work through Codecademy's famous interactive JavaScript course.", + "This course will teach us some JavaScript fundamentals while guiding us through the process of building interesting web apps, all within Codecademy's learner-friendly environment!", + "Go to http://www.codecademy.com/courses/getting-started-v2/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-x9DnD/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7130d8c441eddfaeb5bdef", + "name": "Build Rock Paper Scissors", + "difficulty": 0.25, + "challengeSeed": "114604815", + "description": [ + "Now we'll learn how JavaScript functions work, and use them to build a simple Rock Paper Scissors game.", + "Go to http://www.codecademy.com/courses/javascript-beginner-en-6LzGd/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-Bthev-mskY8/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7131d8c441eddfaeb5bdef", + "name": "Learn JavaScript For Loops", + "difficulty": 0.26, + "challengeSeed": "114614220", + "description": [ + "Let's learn more about the loops that make virtually all programs possible - the \"For Loop\" and \"While Loop\". First, we'll learn the For Loop.", + "Go to http://www.codecademy.com/courses/javascript-beginner-en-NhsaT/0/1web and complete both the both For and While loop section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-XEDZA/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7132d8c441eddfaeb5bdef", + "name": "Learn JavaScript While Loops", + "difficulty": 0.27, + "challengeSeed": "114612889", + "description": [ + "Go to http://www.codecademy.com/courses/javascript-beginner-en-ASGIv/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-mrTNH-6VIZ9/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7133d8c441eddfaeb5bdef", + "name": "Learn Control Flow", + "difficulty": 0.28, + "challengeSeed": "114612888", + "description": [ + "Much of human reasoning can be broken down into what we call Boolean Logic. Lucky for us, computers can think the same way! Let's learn how to instruct our computers by writing \"If Statements\" and \"Else Statements\".", + "We'll also learn some advanced \"Control Flow\" principals, such as ways we can exit loops early.", + "Go to http://www.codecademy.com/courses/javascript-beginner-en-qDwp0/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-ZA2rb/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7134d8c441eddfaeb5bdef", + "name": "Build a Contact List", + "difficulty": 0.29, + "challengeSeed": "114612887", + "description": [ + "Up to this point, you've been working mostly with strings and numbers. Now we're going to learn more complicated data structures, like \"Arrays\" and \"Objects\".", + "Go to http://www.codecademy.com/courses/javascript-beginner-en-9Sgpi/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-3bmfN/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7135d8c441eddfaeb5bdef", + "name": "Build an Address Book", + "difficulty": 0.30, + "challengeSeed": "114612885", + "description": [ + "Let's learn more about objects.", + "Go to http://www.codecademy.com/courses/spencer-sandbox/0/1 and complete the section.", + "Be sure to also complete this section: http://www.codecademy.com/courses/building-an-address-book/0/1?curriculum_id=506324b3a7dffd00020bf661." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7136d8c441eddfaeb5bdef", + "name": "Build a Cash Register", + "difficulty": 0.31, + "challengeSeed": "114612882", + "description": [ + "In this final Codecademy section, we'll learn even more about JavaScript objects.", + "Go to http://www.codecademy.com/courses/objects-ii/0/1 and complete this section.", + "Be sure to also complete the final section: http://www.codecademy.com/courses/close-the-super-makert/0/1." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7118d8c441eddfaeb5bdef", + "name": "Discover Chrome's DevTools", + "difficulty": 0.32, + "challengeSeed": "110752743", + "description": [ + "It's time to learn the most powerful tool your browser has - the Development Tools!", + "If you aren't already using Chrome, you'll want to download it here: http://www.google.com/chrome/. While it's true that Firefox has a tool called Firebug that is very similar to Chrome's DevTools, we will use Chrome for this challenge.", + "Note that this course, jointly produced by Google and Code School, is technologically impressive, but occasionally buggy. If you encounter a bug, just ignore it and keep going.", + "Go to http://discover-devtools.codeschool.com and complete this short course." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7138d8c441eddfaeb5bdef", + "name": "Learn Regular Expressions", + "difficulty": 0.33, + "challengeSeed": "112547802", + "description": [ + "You can use a Regular Expression, or \"Regex\", to select specific types of characters in text.", + "Check out http://www.regexr.com. It's a Regular Expression Sandbox.", + "Now go to http://www.regexone.com and complete the tutorial and exercises 1 - 6.", + "Note that you can click \"continue\" to move on to the next step as soon as all the tasks have green check marks beside them. You can often do this just by using the wildcard \"dot\" operator, but try to use the techniques that each lesson recommends." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7139d8c441eddfaeb5bdef", + "name": "Pair Program on Bonfires", + "difficulty": 0.44, + "challengeSeed": "119657641", + "description": [ + "OK, we're finally ready to start pair programming!", + "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", + "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", + "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", + "We have a special chat room for people ready to pair program. Go to our Slack chatroom and navigate to the #letspair channel and type \"Hello Pair Programmers!\"", + "If someone is available, they will be your \"pair\" - the person you pair programming with.", + "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", + "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", + "Add them as a new contact in Screen Hero, then click the monitor-looking button to attempt to share your screen with them.", + "Once the Screen Hero session starts, your screen's margins will glow orange. You are now sharing your screen.", + "Your pair will have their own cursor, and will be able to type text on his or her and keyboard.", + "Now it's time to tackle our Bonfires.", + "Go to http://freecodecamp.com/bonfires and start working through our Bonfire challenges.", + "Once you you finish pair programming, end the session in Screen Hero session.", + "Congratulations! You have completed your first pair programming session.", + "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", + "Mark this challenge as complete and move on to the Bonfires." + ], + "challengeType": 2, + "tests": [] + } + ] +} diff --git a/seed_data/challenges/basics.json b/seed_data/challenges/basics.json deleted file mode 100644 index 16134aa92f..0000000000 --- a/seed_data/challenges/basics.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "basics", - "order" : 0.001, - "challenges": [ - { - "_id": "bd7126d8c441eddfaeb5bd3e", - "name": "Meet Other Campers in your City", - "difficulty": 0.065, - "challengeSeed": "127358841", - "description": [ - "One of the best ways to stay motivated when learning to code is to hang out with other campers.", - "Slack and Camper News are great ways to communicate with other campers, but there's no substitute for meeting people in-person.", - "The easiest way to meet other campers in your city is to join your city's Facebook Group. Click here to view our growing list of local groups.", - "Click the link to your city, then, once Facebook loads, click \"Join group\".", - "Our local groups are new, so if you don't see your city on this list, you should follow the directions to create a Facebook group for your city.", - "If you don't have a Facebook account, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.", - "Our groups allow you to create events, coordinate those events, and share photos from the events afterward.", - "Whether you're hosting a study group, pair programming at your local library, or going to a weekend hackathon, your city's group will help you make it happen." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7137d8c441eddfaeb5bdef", - "name": "Get Help the Hacker Way with RSAP", - "difficulty": 0.07, - "challengeSeed": "125407432", - "description": [ - "Let's cover one last thing before you start working through our lessons: how to get help.", - "Any time you get stuck or don't know what to do next, follow this simple algorithm (procedure): RSAP (Read, Search, Ask, Post).", - "First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", - "Next, S - Search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.", - "Then, if you still haven't found an answer to your question, A - Ask your friends. If you have trouble, you can ask your fellow campers. We have a special chat room specifically for getting help with tools you learn through these Free Code Camp Challenges. Go to https://freecode.slack.com/messages/help/. Keep this chat open while you work on the remaining challenges.", - "Finally, P - Post on Stack Overflow. Before you attempt to do this, read Stack Overflow's guide to asking good questions: http://stackoverflow.com/help/how-to-ask.", - "Here's our detailed field guide on getting help: http://freecodecamp.com/field-guide/how-do-i-get-help-when-i-get-stuck.", - "Now you have a clear algorithm to follow when you need help! Let's start coding! Move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7127d8c441eddfaeb5bdef", - "name": "Build a Landing Page with HTML", - "difficulty": 0.08, - "challengeSeed": "125671867", - "description": [ - "Now it's time for us to start our actual coding lessons. We've curated a series of free, self-paced, browser-based lessons from providers like Codecademy and Stanford University.", - "These lessons will cover a lot of ground quickly, and will hold your hand throughout the process. Don't try to memorize everything - you'll spend more than a thousand hours practicing these later, and you can always look things up. Just keep moving.", - "If you've learned HTML and CSS before, these next few Waypoints will be a valuable review. If you haven't learned HTML or CSS before, you're in for a treat!", - "This Codecademy will quickly cover HTML, CSS and even Responsive Design with Bootstrap.", - "If you don't already have a Codecademy account, create one here: http://www.codecademy.com.", - "Go to http://www.codecademy.com/en/skills/make-a-website/topics/html-elements and complete the section.", - "Once you're done, mark this Waypoint complete and move on the next Waypoint." - ], - "challengeType": 2, - "tests": [] - } - ] -} \ No newline at end of file diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json new file mode 100644 index 0000000000..ad9d6c4b4e --- /dev/null +++ b/seed_data/challenges/bonfires.json @@ -0,0 +1,1166 @@ +{ + "name": "Bonfires", + "order" : 0.007, + "challenges": [ + { + "_id": "ad7123c8c441eddfaeb5bdef", + "name": "Meet Bonfire", + "difficulty": "0", + "description": [ + "Click the button below for further instructions.", + "Your goal is to fix the failing test.", + "First, run all the tests by clicking \"Run code\" or by pressing Control + Enter", + "The failing test is in red. Fix the code so that all tests pass. Then you can move on to the next Bonfire.", + "Make this function return true no matter what." + ], + "tests": [ + "expect(meetBonfire()).to.be.a(\"boolean\");", + "expect(meetBonfire()).to.be.true;" + ], + "challengeSeed": [ + "function meetBonfire(argument) {", + " // Good luck!", + " console.log(\"you can read this function's argument in the developer tools\", argument);", + "", + " return false;", + "}", + "", + "", + "", + "meetBonfire(\"You can do this!\");" + ] + }, + { + "_id": "a202eed8fc186c8434cb6d61", + "name": "Reverse a String", + "difficulty": "1.01", + "tests": [ + "expect(reverseString('hello')).to.be.a('String');", + "expect(reverseString('hello')).to.equal('olleh');", + "expect(reverseString('Howdy')).to.equal('ydwoH');", + "expect(reverseString('Greetings from Earth')).to.equal('htraE morf sgniteerG');" + ], + "description": [ + "Reverse the provided string.", + "You may need to turn the string into an array before you can reverse it.", + "Your result must be a string." + ], + "challengeSeed": [ + "function reverseString(str) {", + " return str;", + "}", + "", + "reverseString('hello');" + ], + "MDNlinks": ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] + }, + { + "_id": "a302f7aae1aa3152a5b413bc", + "name": "Factorialize a Number", + "tests": [ + "expect(factorialize(5)).to.be.a(\"Number\");", + "expect(factorialize(5)).to.equal(120);", + "expect(factorialize(10)).to.equal(3628800);", + "expect(factorialize(20)).to.equal(2432902008176640000);" + ], + "difficulty": "1.02", + "description": [ + "Return the factorial of the provided integer.", + "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.", + "Factorials are often represented with the shorthand notation n!", + "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f" + ], + "challengeSeed": [ + "function factorialize(num) {", + " return num;", + "}", + "", + "factorialize(5);" + ], + "MDNlinks": ["Arithmetic Operators"] + }, + { + "_id": "aaa48de84e1ecc7c742e1124", + "name": "Check for Palindromes", + "difficulty": "1.03", + "description": [ + "Return true if the given string is a palindrome. Otherwise, return false.", + "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.", + "You'll need to remove punctuation and turn everything lower case in order to check for palindromes.", + "We'll pass strings with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others." + ], + "tests": [ + "expect(palindrome(\"eye\")).to.be.a(\"boolean\");", + "assert.deepEqual(palindrome(\"eye\"), true);", + "assert.deepEqual(palindrome(\"race car\"), true);", + "assert.deepEqual(palindrome(\"not a palindrome\"), false);", + "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", + "assert.deepEqual(palindrome(\"never odd or even\"), true);", + "assert.deepEqual(palindrome(\"nope\"), false);" + ], + "challengeSeed": [ + "function palindrome(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "palindrome(\"eye\");" + ], + "MDNlinks": ["String.replace()", "String.toLowerCase()"] + }, + { + "_id": "a26cbbe9ad8655a977e1ceb5", + "name": "Find the Longest Word in a String", + "difficulty": "1.04", + "description": [ + "Return the length of the longest word in the provided sentence.", + "Your response should be a number." + ], + "challengeSeed": [ + "function findLongestWord(str) {", + " return str.length;", + "}", + "", + "findLongestWord('The quick brown fox jumped over the lazy dog');" + ], + "tests": [ + "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.be.a('Number');", + "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.equal(6);", + "expect(findLongestWord('May the force be with you')).to.equal(5);", + "expect(findLongestWord('Google do a barrel roll')).to.equal(6);", + "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);" + ], + "MDNlinks": ["String.split()", "String.length"] + }, + { + "_id": "ab6137d4e35944e21037b769", + "name": "Title Case a Sentence", + "difficulty": "1.05", + "description": [ + "Return the provided string with the first letter of each word capitalized.", + "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'." + ], + "challengeSeed": [ + "function titleCase(str) {", + " return str;", + "}", + "", + "titleCase(\"I'm a little tea pot\");" + ], + "tests": [ + "expect(titleCase(\"I'm a little tea pot\")).to.be.a('String');", + "expect(titleCase(\"I'm a little tea pot\")).to.equal(\"I'm A Little Tea Pot\");", + "expect(titleCase(\"sHoRt AnD sToUt\")).to.equal(\"Short And Stout\");", + "expect(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")).to.equal(\"Here Is My Handle Here Is My Spout\");" + ], + "MDNlinks": ["String.charAt()"] + }, + { + "_id": "a789b3483989747d63b0e427", + "name": "Return Largest Numbers in Arrays", + "difficulty": "1.06", + "description": [ + "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", + "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", + "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays." + ], + "challengeSeed": [ + "function largestOfFour(arr) {", + " // You can do this!", + " return arr;", + "}", + "", + "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" + ], + "tests": [ + "expect(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).to.be.a('array');", + "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", + "assert(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]).should.eql([9,35,97,1000000]));" + ], + "MDNlinks": ["Comparison Operators"] + }, + { + "_id": "acda2fb1324d9b0fa741e6b5", + "name": "Confirm the Ending", + "difficulty": "1.07", + "description": [ + "Check if a string (first argument) ends with the given target string (second argument)." + ], + + "challengeSeed": [ + "function end(str, target) {", + " // \"Never give up and good luck will find you.\"", + " // -- Falcor", + " return str;", + "}", + "", + "end('Bastian', 'n');" + ], + "tests": [ + "assert.strictEqual(end('Bastian', 'n'), true, 'should equal true if target equals end of string');", + "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", + "assert.strictEqual(end('If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing', 'mountain'), false, 'should equal false if target does not equal end of string');" + ], + "MDNlinks": ["String.substr()"] + }, + { + "_id": "afcc8d540bea9ea2669306b6", + "name": "Repeat a string repeat a string", + "difficulty": "1.08", + "description": [ + "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number." + ], + "challengeSeed": [ + "function repeat(str, num) {", + " // repeat after me", + " return str;", + "}", + "", + "repeat('abc', 3);" + ], + "tests": [ + "assert.strictEqual(repeat('*', 3), '***', 'should repeat a string n times');", + "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", + "assert.strictEqual(repeat('abc', -2), '', 'should return an empty string for negative numbers');" + ], + "MDNlinks": ["Global String Object"] + }, + { + "_id": "ac6993d51946422351508a41", + "name": "Truncate a string", + "difficulty": "1.09", + "description": [ + "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", + "Note that the three dots at the end add to the string length." + ], + "challengeSeed": [ + "function truncate(str, num) {", + " // Clear out that junk in your trunk", + " return str;", + "}", + "", + "truncate('A-tisket a-tasket A green and yellow basket', 11);" + ], + "tests": [ + "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", + "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", + "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" + ], + "MDNlinks": ["String.slice()"] + }, + { + "_id": "a9bd25c716030ec90084d8a1", + "name": "Chunky Monkey", + "difficulty": "1.10", + "description": [ + "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array." + ], + "challengeSeed": [ + "function chunk(arr, size) {", + " // Break it up.", + " return arr;", + "}", + "", + "chunk(['a', 'b', 'c', 'd'], 2);" + ], + "tests": [ + "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", + "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" + ], + "MDNlinks": ["Array.push()"] + }, + { + "_id": "ab31c21b530c0dafa9e241ee", + "name": "Slasher Flick", + "difficulty": "1.11", + "description": [ + "Return the remaining elements of an array after chopping off n elements from the head." + ], + "challengeSeed": [ + "function slasher(arr, howMany) {", + " // it doesn't always pay to be first", + " return arr;", + "}", + "", + "slasher([1, 2, 3], 2);" + ], + "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');" + ], + "MDNlinks": ["Array.slice()", "Array.splice()"] + }, + { + "_id": "af2170cad53daa0770fabdea", + "name": "Mutations", + "difficulty": "1.12", + "description": [ + "Return true if the string in the first element of the array contains the letters of the string in the second element of the array.", + "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", + "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", + "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'." + ], + "challengeSeed": [ + "function mutation(arr) {", + " return arr;", + "}", + "", + "mutation(['hello', 'hey']);" + ], + "tests": [ + "expect(mutation(['hello', 'hey'])).to.be.false;", + "expect(mutation(['hello', 'Hello'])).to.be.true;", + "expect(mutation(['zyxwvutsrqponmlkjihgfedcba', 'qrstu'])).to.be.true;", + "expect(mutation(['Mary', 'Army'])).to.be.true;", + "expect(mutation(['Alien', 'line'])).to.be.true;" + ], + "MDNlinks": ["Array.sort()"] + }, + { + "_id": "adf08ec01beb4f99fc7a68f2", + "name": "Falsey Bouncer", + "difficulty": "1.50", + "description": [ + "Remove all falsey values from an array.", + "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN." + ], + "challengeSeed": [ + "function bouncer(arr) {", + " // Don't show a false ID to this bouncer.", + " return arr;", + "}", + "", + "bouncer([7, 'ate', '', false, 9]);" + ], + "tests": [ + "assert.deepEqual(bouncer([7, 'ate', '', false, 9]), [7, 'ate', 9], 'should remove falsey values');", + "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", + "assert.deepEqual(bouncer([false, null, 0]), [], 'should return empty array if all elements are falsey');" + ], + "MDNlinks": ["Boolean Objects", "Array.filter()"] + }, + { + "_id":"a8e512fbe388ac2f9198f0fa", + "name":"Where art thou", + "difficulty":"1.55", + "description":[ + "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument)." + ], + "challengeSeed": [ + "function where(collection, source) {", + " var arr = [];", + " // What's in a name?", + " return arr;", + "}", + "", + "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" + ], + "tests":[ + "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", + "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" + ], + "MDNlinks": ["Global Object", "Object.hasOwnProperty()", "Object.keys()"] + }, + { + "_id":"a39963a4c10bc8b4d4f06d7e", + "name":"Seek and Destroy", + "difficulty":"1.60", + "description":[ + "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments." + ], + "challengeSeed": [ + "function destroyer(arr) {", + " // Remove all the values", + " return arr;", + "}", + "", + "destroyer([1, 2, 3, 1, 2, 3], 2, 3);" + ], + "tests": [ + "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" + ], + "MDNlinks": ["Arguments object","Array.filter()"] + }, + { + "_id": "a24c1a4622e3c05097f71d67", + "name": "Where do I belong", + "difficulty": "1.61", + "description": [ + "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", + "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)." + ], + "challengeSeed": [ + "function where(arr, num) {", + " // Find my place in this sorted array.", + " return num;", + "}", + "", + "where([40, 60], 50);" + ], + "tests": [ + "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", + "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" + ] + }, + { + "_id": "a3566b1109230028080c9345", + "name": "Sum All Numbers in a Range", + "difficulty": "2.00", + "description": [ + "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", + "The lowest number will not always come first." + ], + "challengeSeed": [ + "function sumAll(arr) {", + " return(1);", + "}", + "", + "sumAll([1, 4]);" + ], + "tests": [ + "expect(sumAll([1, 4])).to.be.a('Number');", + "expect(sumAll([1, 4])).to.equal(10);", + "expect(sumAll([4, 1])).to.equal(10);", + "expect(sumAll([5, 10])).to.equal(45);", + "expect(sumAll([10, 5])).to.equal(45);" + ], + "MDNlinks": ["Math.max()", "Math.min()", "Array.reduce()"] + }, + { + "_id": "a5de63ebea8dbee56860f4f2", + "name": "Diff Two Arrays", + "difficulty": "2.01", + "description": [ + "Compare two arrays and return a new array with any items not found in both of the original arrays." + ], + "challengeSeed": [ + "function diff(arr1, arr2) {", + " var newArr = [];", + " // Same, same; but different.", + " return newArr;", + "}", + "", + "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" + ], + "tests": [ + "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", + "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", + "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", + "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", + "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", + "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", + "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" + ] + }, + { + "_id": "a7f4d8f2483413a6ce226cac", + "name": "Roman Numeral Converter", + "tests": [ + "expect(convert(12)).to.equal(\"XII\");", + "expect(convert(5)).to.equal(\"V\");", + "expect(convert(9)).to.equal(\"IX\");", + "expect(convert(29)).to.equal(\"XXIX\");", + "expect(convert(16)).to.equal(\"XVI\");" + ], + "difficulty": "2.02", + "description": [ + "Convert the number be a roman numeral.", + "All roman numerals answers should be provided in upper-case." + ], + "challengeSeed": [ + "function convert(num) {", + " return num;", + "}", + "", + "convert(36);" + ], + "MDNlinks": ["Array.splice()", "Array.indexOf()", "Array.join()"] + }, + { + "_id": "a0b5010f579e69b815e7c5d6", + "name": "Search and Replace", + "tests": [ + "expect(replace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", + "expect(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", + "expect(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\")).to.equal(\"This has a spelling error\");", + "expect(replace(\"His name is Tom\", \"Tom\", \"john\")).to.equal(\"His name is John\");", + "expect(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")).to.equal(\"Let us get back to more Bonfires\");" + ], + "difficulty": "2.03", + "description": [ + "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", + "First argument is the sentence the perform the search and replace on.", + "Second argument is the word that you will be replacing (before).", + "Third argument is what you will be replacing the second argument with (after).", + "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'" + ], + "challengeSeed": [ + "function replace(str, before, after) {", + " return str;", + "}", + "", + "replace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" + ], + "MDNlinks": ["Array.splice()", "String.replace()", "Array.join()"] + }, + { + "_id": "aa7697ea2477d1316795783b", + "name": "Pig Latin", + "tests": [ + "expect(translate(\"california\")).to.equal(\"aliforniacay\");", + "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", + "expect(translate(\"glove\")).to.equal(\"oveglay\");", + "expect(translate(\"algorithm\")).to.equal(\"algorithmway\");", + "expect(translate(\"eight\")).to.equal(\"eightway\");" + ], + "difficulty": "2.04", + "description": [ + "Translate the provided string to pig latin.", + "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", + "If a word begins with a vowel you just add \"way\" to the end." + ], + "challengeSeed": [ + "function translate(str) {", + " return str;", + "}", + "", + "translate(\"consonant\");" + ], + "MDNlinks": ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] + }, + { + "_id": "afd15382cdfb22c9efe8b7de", + "name": "DNA Pairing", + "tests": [ + "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'should return the dna pair');", + "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'should return the dna pair');", + "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'should return the dna pair');" + ], + "difficulty": "2.05", + "description": [ + "The DNA strand is missing the pairing element. Match each character with the missing element and return the results as a 2d array.", + "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", + "Return the provided character as the first element in each array." + ], + "challengeSeed": [ + "function pair(str) {", + " return str;", + "}", + "", + "pair(\"GCG\");" + ], + "MDNlinks": ["Array.push()", "String.split()"] + }, + { + "_id": "af7588ade1100bde429baf20", + "name" : "Missing letters", + "difficulty": "2.05", + "description" : [ + "Find the missing letter in the passed letter range and return it.", + "If all letters are present in the range, return undefined." + ], + "challengeSeed": [ + "function fearNotLetter(str) {", + " return str;", + "}", + "", + "fearNotLetter('abce');" + ], + "tests": [ + "expect(fearNotLetter('abce')).to.equal('d');", + "expect(fearNotLetter('bcd')).to.be.undefined;", + "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", + "expect(fearNotLetter('yz')).to.be.undefined;" + ], + "MDNlinks": ["String.charCodeAt()"] + }, + { + "_id": "a77dbc43c33f39daa4429b4f", + "name": "Boo who", + "difficulty": "2.06", + "description": [ + "Check if a value is classified as a boolean primitive. Return true or false.", + "Boolean primitives are true and false." + ], + "challengeSeed": [ + "function boo(bool) {", + " // What is the new fad diet for ghost developers? The Boolean.", + " return bool;", + "}", + "", + "boo(null);" + ], + "tests": [ + "assert.strictEqual(boo(true), true);", + "assert.strictEqual(boo(false), true);", + "assert.strictEqual(boo([1, 2, 3]), false);", + "assert.strictEqual(boo([].slice), false);", + "assert.strictEqual(boo({ 'a': 1 }), false);", + "assert.strictEqual(boo(1), false);", + "assert.strictEqual(boo(NaN), false);", + "assert.strictEqual(boo('a'), false);" + ], + "MDNlinks": ["Boolean Objects"] + }, + { + "_id": "a105e963526e7de52b219be9", + "name": "Sorted Union", + "difficulty": "2.07", + "description": [ + "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", + "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.", + "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", + "Check the assertion tests for examples." + ], + "challengeSeed": [ + "function unite(arr1, arr2, arr3) {", + " return arr1;", + "}", + "", + "unite([1, 2, 3], [5, 2, 1, 4], [2, 1]);" + ], + "tests": [ + "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", + "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" + ] + }, + { + "_id": "a6b0bb188d873cb2c8729495", + "name": "Convert HTML Entities", + "difficulty": "2.07", + "description": [ + "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities." + ], + "challengeSeed": [ + "function convert(str) {", + " // :)", + " return str;", + "}", + "", + "convert('Dolce & Gabbana');" + ], + "tests": [ + "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", + "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" + ], + "MDNlinks": ["RegExp"] + }, + { + "_id": "a103376db3ba46b2d50db289", + "name": "Spinal Tap Case", + "difficulty": "2.08", + "description": [ + "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes." + ], + "challengeSeed": [ + "function spinalCase(str) {", + " // \"It's such a fine line between stupid, and clever.\"", + " // --David St. Hubbins", + " return str;", + "}", + "", + "spinalCase('This Is Spinal Tap');" + ], + "tests": [ + "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", + "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", + "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", + "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" + ], + "MDNlinks": ["RegExp", "String.replace()"] + }, + { + "_id": "a5229172f011153519423690", + "name": "Sum All Odd Fibonacci Numbers", + "difficulty": "2.09", + "description": [ + "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", + "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", + "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3." + ], + "challengeSeed": [ + "function sumFibs(num) {", + " return num;", + "}", + "", + "sumFibs(4);" + ], + "tests": [ + "expect(sumFibs(1)).to.be.a('number');", + "expect(sumFibs(1000)).to.equal(1785);", + "expect(sumFibs(4000000)).to.equal(4613732);", + "expect(sumFibs(4)).to.equal(5);", + "expect(sumFibs(75024)).to.equal(60696);", + "expect(sumFibs(75025)).to.equal(135721);" + ], + "MDNlinks": ["Remainder"] + }, + { + "_id": "a3bfc1673c0526e06d3ac698", + "name": "Sum All Primes", + "difficulty": "2.10", + "description": [ + "Sum all the prime numbers up to and including the provided number.", + "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", + "The provided number may not be a prime." + ], + "challengeSeed": [ + "function sumPrimes(num) {", + " return num;", + "}", + "", + "sumPrimes(10);" + ], + "tests": [ + "expect(sumPrimes(10)).to.be.a('number');", + "expect(sumPrimes(10)).to.equal(17);", + "expect(sumPrimes(977)).to.equal(73156);" + ] + }, + { + "_id": "ae9defd7acaf69703ab432ea", + "name": "Smallest Common Multiple", + "difficulty": "2.11", + "description": [ + "Find the smallest number that is evenly divisible by all numbers in the provided range.", + "The range will be an array of two numbers that will not necessarily be in numerical order." + ], + "challengeSeed": [ + "function smallestCommons(arr) {", + " return arr;", + "}", + "", + "", + "smallestCommons([1,5]);" + ], + "tests": [ + "expect(smallestCommons([1,5])).to.be.a('number');", + "expect(smallestCommons([1,5])).to.equal(60);", + "expect(smallestCommons([5,1])).to.equal(60);", + "(smallestCommons([1,13])).should.equal(360360);" + ] + }, + { + "_id": "a6e40f1041b06c996f7b2406", + "name": "Finders Keepers", + "difficulty": "2.12", + "description": [ + "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument)." + ], + "challengeSeed": [ + "function find(arr, func) {", + " var num = 0;", + " return num;", + "}", + "", + "find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" + ], + "tests": [ + "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", + "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" + ], + "MDNlinks": ["Array.some()"] + }, + { + "_id": "a5deed1811a43193f9f1c841", + "name": "Drop it like it's hot", + "difficulty": "2.13", + "description": [ + "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true." + ], + "challengeSeed": [ + "function drop(arr, func) {", + " // Drop them elements.", + " return arr;", + "}", + "", + "drop([1, 2, 3], function(n) {return n < 3; });" + ], + "tests": [ + "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", + "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", + "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);" + ], + "MDNlinks": ["Arguments object", "Array.shift()"] + }, + { + "_id": "ab306dbdcc907c7ddfc30830", + "name": "Steamroller", + "difficulty": "2.14", + "description": [ + "Flatten a nested array. You must account for varying levels of nesting." + ], + "challengeSeed": [ + "function steamroller(arr) {", + " // I'm a steamroller, baby", + " return arr;", + "}", + "", + "steamroller([1, [2], [3, [[4]]]]);" + ], + "tests": [ + "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", + "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", + "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');" + ], + "MDNlinks": ["Array.isArray()"] + }, + { + "_id": "a8d97bd4c764e91f9d2bda01", + "name": "Binary Agents", + "difficulty": "2.15", + "description": [ + "Return an English translated sentence of the passed binary string.", + "The binary string will be space separated." + ], + "challengeSeed": [ + "function binaryAgent(str) {", + " return str;", + "}", + "", + "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" + ], + "tests": [ + "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", + "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" + ], + "MDNlinks": ["String.charCodeAt()", "String.fromCharCode()" + ] + }, + { + "_id" : "a3f503de51cfab748ff001aa", + "name": "Pairwise", + "difficulty": "2.16", + "description": [ + "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", + "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", + "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!" + ], + "challengeSeed": [ + "function pairwise(arr, arg) {", + " return arg;", + "}", + "", + "pairwise([1,4,2,3,0,5], 7);" + ], + "tests": [ + "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", + "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", + "expect(pairwise([1,1,1], 2)).to.equal(1);", + "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", + "expect(pairwise([], 100)).to.equal(0);" + ] + }, + { + "_id": "a10d2431ad0c6a099a4b8b52", + "name": "Everything Be True", + "difficulty": "2.21", + "description": [ + "Check if the predicate (second argument) returns truthy (defined) for 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." + ], + "challengeSeed": [ + "function every(collection, pre) {", + " // Does everyone have one of these?", + " return pre;", + "}", + "", + "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" + ], + "tests": [ + "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", + "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" + ], + "MDNlinks": ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"] + }, + { + "_id": "a97fd23d9b809dac9921074f", + "name": "Arguments Optional", + "difficulty": "2.22", + "description": [ + "Create a function that sums two arguments together. If only one argument is provided, return a function that expects one additional argument and will return the sum.", + "For example, add(2, 3) should return 5, and add(2) should return a function that is waiting for an argument so that var sum2And = add(2); return sum2And(3); // 5", + "If either argument isn't a valid number, return undefined." + ], + "challengeSeed": [ + "function add() {", + " return false;", + "}", + "", + "add(2,3);" + ], + "tests": [ + "expect(add(2, 3)).to.equal(5);", + "expect(add(2)(3)).to.equal(5);", + "expect(add('http://bit.ly/IqT6zt')).to.be.undefined;", + "expect(add(2, '3')).to.be.undefined;", + "expect(add(2)([3])).to.be.undefined;" + ], + "MDNlinks": ["Global Function Object", "Arguments object"] + }, + { + "_id": "a2f1d72d9b908d0bd72bb9f6", + "name": "Make a Person", + "difficulty": "3.12", + "description": [ + "Fill in the object constructor with the methods specified in the tests.", + "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", + "All functions that take an argument have an arity of 1, and the argument will be a string.", + "These methods must be the only available means for interacting with the object." + ], + "challengeSeed": [ + "var Person = function(firstAndLast) {", + " return firstAndLast;", + "};", + "", + "var bob = new Person('Bob Ross');", + "bob.getFullName();" + ], + "tests": [ + "expect(Object.keys(bob).length).to.eql(6);", + "expect(bob instanceof Person).to.be.true;", + "expect(bob.firstName).to.be.undefined();", + "expect(bob.lastName).to.be.undefined();", + "expect(bob.getFirstName()).to.eql('Bob');", + "expect(bob.getLastName()).to.eql('Ross');", + "expect(bob.getFullName()).to.eql('Bob Ross');", + "bob.setFirstName('Happy');", + "expect(bob.getFirstName()).to.eql('Happy');", + "bob.setLastName('Trees');", + "expect(bob.getLastName()).to.eql('Trees');", + "bob.setFullName('George Carlin');", + "expect(bob.getFullName()).to.eql('George Carlin');", + "bob.setFullName('Bob Ross');" + ], + "MDNlinks": ["Closures", "Details of the Object Model"] + }, + { + "_id": "af4afb223120f7348cdfc9fd", + "name": "Map the Debris", + "difficulty": "3.50", + "description": [ + "Return a new array that transforms the element's average altitude into their orbital periods.", + "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", + "You can read about orbital periods on wikipedia.", + "The values should be rounded to the nearest whole number. The body being orbited is Earth.", + "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418" + ], + "challengeSeed": [ + "function orbitalPeriod(arr) {", + " var GM = 398600.4418;", + " var earthRadius = 6367.4447;", + " return arr;", + "}", + "", + "orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);" + ], + "tests": [ + "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", + "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" + ], + "MDNlinks": ["Math.pow()"] + }, + { + "_id": "aff0395860f5d3034dc0bfc9", + "name": "Validate US Telephone Numbers", + "difficulty": "4.01", + "description": [ + "Return true if the passed string is a valid US phone number", + "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", + "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", + "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false." + ], + "tests": [ + "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", + "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", + "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", + "assert.deepEqual(telephoneCheck(\"55555555\"), false);", + "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", + "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", + "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" + ], + "challengeSeed": [ + "function telephoneCheck(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "telephoneCheck(\"555-555-5555\");" + ] + }, + { + "_id": "a3f503de51cf954ede28891d", + "name": "Symmetric Difference", + "difficulty": "4.02", + "description": [ + "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", + "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both." + ], + "challengeSeed": [ + "function sym(args) {", + " return arguments;", + "}", + "", + "sym([1, 2, 3], [5, 2, 1, 4]);" + ], + "tests": [ + "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", + "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", + "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", + "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" + ] + }, + { + "_id": "aa2e6f85cab2ab736c9a9b24", + "name": "Cash Register", + "difficulty": "4.03", + "description": [ + "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order." + ], + "challengeSeed": [ + "function drawer(price, cash, cid) {", + " var change;", + " // Here is your change, ma'am.", + " return change;", + "}", + "", + "// Example cash-in-drawer array:", + "// [['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]]", + "", + "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" + ], + "tests": [ + "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", + "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" + ] + }, + { + "_id": "a56138aff60341a09ed6c480", + "name": "Inventory Update", + "difficulty": "4.04", + "description": [ + "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order." + ], + "challengeSeed": [ + "function inventory(arr1, arr2) {", + " // All inventory must be accounted for or you're fired!", + " return arr1;", + "}", + "", + "// Example inventory lists", + "var curInv = [", + " [21, 'Bowling Ball'],", + " [2, 'Dirty Sock'],", + " [1, 'Hair Pin'],", + " [5, 'Microphone']", + "];", + "", + "var newInv = [", + " [2, 'Hair Pin'],", + " [3, 'Half-Eaten Apple'],", + " [67, 'Bowling Ball'],", + " [7, 'Toothpaste']", + "];", + "", + "inventory(curInv, newInv);" + ], + "tests": [ + "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", + "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", + "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" + ] + }, + { + "_id": "a7bf700cd123b9a54eef01d5", + "name": "No repeats please", + "difficulty": "4.05", + "description": [ + "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", + "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating." + ], + "challengeSeed": [ + "function permAlone(str) {", + " return str;", + "}", + "", + "permAlone('aab');" + ], + "tests": [ + "expect(permAlone('aab')).to.be.a.number;", + "expect(permAlone('aab')).to.equal(2);", + "expect(permAlone('aaa')).to.equal(0);", + "expect(permAlone('aabb')).to.equal(8);", + "expect(permAlone('abcdefa')).to.equal(3600);", + "expect(permAlone('abfdefa')).to.equal(2640);", + "expect(permAlone('zzzzzzzz')).to.equal(0);" + ] + }, + { + "_id": "a19f0fbe1872186acd434d5a", + "name": "Friendly Date Ranges", + "difficulty": "4.06", + "description": [ + "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", + "It must not show any redundant information in the date range.", + "For example, if the year and month are the same then only the day range should be displayed.", + "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", + "Input date is formatted as YYYY-MM-DD" + ], + "challengeSeed": [ + "function friendly(str) {", + " return str;", + "}", + "", + "friendly(['2015-07-01', '2015-07-04']);" + ], + "tests": [ + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th, 2016']);", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" + ], + "MDNlinks": ["String.split()", "String.substr()", "parseInt()"] + } + ] +} diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json new file mode 100644 index 0000000000..5c86dce808 --- /dev/null +++ b/seed_data/challenges/bootstrap.json @@ -0,0 +1,1575 @@ +{ + "name": "Bootstrap", + "order" : 0.003, + "challenges": [ + { + "_id": "bad87fee1348bd9acde08812", + "name": "Use Bootstrap for Responsive Images", + "difficulty": 0.047, + "description": [ + "Add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to the image.", + "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", + "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", + "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", + "Now all you need to do is add the img-responsive class to your image." + ], + "tests": [ + "assert($('img').hasClass('img-responsive'), 'Your new image should have the class \"img-responsive\"')", + "assert($('img').length > 1, 'You should add an image with the src of \"http://bit.ly/fcc-kittens2\"')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad87fee1348bd8acde08812", + "name": "Center Text with Bootstrap", + "difficulty": 0.048, + "description": [ + "Add Bootstrap's text-center class to your h2 element.", + "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", + "Note 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>." + ], + "tests": [ + "assert($('h2').hasClass('text-center'), 'Your h2 element should be centered by applying the class \"text-center\"')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id": "bad87fee1348cd8acdf08812", + "name": "Create a Bootstrap Button", + "difficulty": 0.049, + "description": [ + "Create a new button below your large kitten photo with the class \"btn\" and the text of \"like this photo\".", + "Bootstrap has its own button styles, which look much better than the plain HTML ones." + ], + "tests": [ + "assert($('.btn').length > 0, 'your new button should have the class \"btn\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad87fee1348cd8acef08812", + "name": "Create a Block Element Bootstrap Button", + "difficulty": 0.050, + "description": [ + "Add Bootstrap's btn-block class to your Bootstrap button.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "assert($('.btn-block').length > 0, 'your new button should have the class \"btn-block\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad87fee1348cd8acef08811", + "name": "Color a Bootstrap Button with Button Primary", + "difficulty": 0.051, + "description": [ + "Add Bootstrap's btn-block class to both of your buttons.", + "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", + "Note that these buttons still need the btn class." + ], + "tests": [ + "assert($('.btn-primary').length > 0, 'your new button should have the class \"btn-primary\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad87fee1348cd8acef08813", + "name": "Color a Bootstrap Button with Button Info", + "difficulty": 0.052, + "description": [ + "Create a new block-level Bootstrap button below your \"like\" button with the text \"Info\", and add Bootstrap's btn-info class to it.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", + "Note that these buttons still need the btn and btn-block classes." + ], + "tests": [ + "assert($('.btn-info').length > 0, 'your new button should have the class \"btn-info\".')", + "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad87fee1348ce8acef08814", + "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", + "difficulty": 0.053, + "description": [ + "Create a button with the text \"delete\" and give it the class btn-danger.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", + "Note that this button still needs the btn and btn-block classes." + ], + "tests": [ + "assert($('.btn-danger').length > 0, 'Your new button should have the class \"btn-danger\".')", + "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + { + "_id": "bad88fee1348ce8acef08815", + "name": "Use the Bootstrap Grid to Put Elements Side By Side", + "difficulty": 0.054, + "description": [ + "Put the \"like\", \"Info\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"col-xs-4\"> element.", + "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.", + "The row class is applied to a div, and the buttons themselves can be nested within it." + ], + "tests": [ + "assert($('.row').length > 0, 'Your new button should be wrapped within a div with the class \"row\".')", + "assert($('.col-xs-4').length > 2, 'Each of your bootstrap buttons should be wrapped in a div with the class \"col-xs-4\".')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "", + "", + "", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedf08845", + "name": "Use Bootstrap Text Primary Class instead of Custom CSS", + "difficulty" : 0.055, + "description": [ + "Delete the following from your style tag: .red-text, p, .smaller-image. Delete the p element with the dead link. Remove your red-text class from your h2 element and instead apply the text-primary Bootstrap class. Replace the smaller-image class on your top image with the img-responsive class." + ], + "tests": [ + "assert(!$('h2').hasClass('red-text'), 'You h2 element should no longer have the class \"red-text\".')", + "assert($('h2').hasClass('text-primary'), 'You h2 element should now have the class \"text-primary\".')", + "assert(!$('p').css('font-family').match(/monospace/i), 'Your paragraph elements should no longer use the font \"Monospace\".')", + "assert($('.img-responsive').length > 1, 'Remove the \"smaller-image\" class from your top image and replace it with the \"img-responsive\" class.')" + ], + "challengeSeed": [ + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "

      Click here for cat photos.

      ", + "", + "", + "", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aede08845", + "name": "Create a Custom Heading", + "difficulty" : 0.056, + "description": [ + "Wrap your first image and your h2 element in a <div class='row'> element. Wrap your h2 text in a <div class='col-xs-8'> and your image in a <div class='col-xs-4'> so that they are on the same line." + ], + "tests": [ + "assert($('.row').length > 1, 'Your h2 and top image elements should both be wrapped together within a div with the class \"row\".')", + "assert($('.col-xs-4').length > 3, 'Wrap your top image inside a div with the class \"col-xs-4\".')", + "assert($('.col-xs-8').length > 0, 'Wrap your h2 element inside a div with the class \"col-xs-8\".')" + ], + "challengeSeed": [ + "", + "", + "", + "", + "

      CatPhotoApp

      ", + "", + "", + "", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedd08845", + "name": "Add Font Awesome Icons to our Buttons", + "difficulty" : 0.057, + "description": [ + "Use Font Awesome to add a \"like\" icon to your like button.", + "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." + ], + "tests": [ + "assert($('.fa-thumbs-up').length > 0, 'You should add a <i class=\"fa fa-thumbs-up\"><i> within your like button element.')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedc08845", + "name": "Add Font Awesome Icons all of our Buttons", + "difficulty" : 0.058, + "description": [ + "Use Font Awesome to add a \"info-circle\" icon to your info button and a \"trash\" button to your delete button.", + "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." + ], + "tests": [ + "assert($('.fa-trash').length > 0, 'You should add a <i class=\"fa fa-trash\"><i> within your like button element.')", + "assert($('.fa-info-circle').length > 0, 'You should add a <i class=\"fa fa-info-circle\"><i> within your like button element.')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aedb08845", + "name": "Use Bootstrap to Responsively Style a Radio Buttons", + "difficulty" : 0.059, + "description": [ + "Wrap all of your radio buttons in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-6'> element." + ], + "tests": [ + "assert($('.row').length > 2, 'Wrap your all of your radio buttons inside one div with the class \"row\".')", + "assert($('.col-xs-6').length > 3, 'Wrap each of your radio buttons inside its own div with the class \"col-xs-6\".')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + " ", + " ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aeda08845", + "name": "Use Bootstrap to Responsively Style Checkboxes", + "difficulty" : 0.060, + "description": [ + "Wrap all your checkboxes in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-4'> element." + ], + "tests": [ + "assert($('.row').length > 3, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", + "assert($('.col-xs-4').length > 6, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + " ", + " ", + " ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aed908845", + "name": "Style a Text Input with the Bootstrap Form Control Class", + "difficulty" : 0.061, + "description": [ + "Give your form's text input field in a class of \"form-control\". Give your form's submit button the classes \"btn btn-primary\" and give it the Font Awesome icon of \"fa-paper-plane\"." + ], + "tests": [ + "assert($('.btn-primary').length > 1, 'Give your form's submit button the classes \"btn btn-primary\".')", + "assert($('.fa-paper-plane').length > 0, 'You should add a <i class=\"fa fa-paper-plane\"><i> within your submit button element.')", + "assert($('.form-control').length > 0, 'Give your form's text input field in a class of \"form-control\".')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id" : "bad87fee1348bd9aec908845", + "name": "Line up Form Elements Responsively with Bootstrap", + "difficulty" : 0.062, + "description": [ + "Wrap both your form's text input field and submit button within a div with the class \"row\". Wrap your form's text input field within a div with the class of \"col-xs-7\". Wrap your form's submit button the in a div with the class \"col-xs-5\"." + ], + "tests": [ + "assert($('.row').length > 4, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", + "assert($('.col-xs-5').length > 0, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')", + "assert($('.col-xs-7').length > 0, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')" + ], + "challengeSeed": [ + "", + "", + "", + "
      ", + "
      ", + "

      CatPhotoApp

      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "

      Things cats love:

      ", + "
        ", + "
      • cat nip
      • ", + "
      • laser pointers
      • ", + "
      • lasagna
      • ", + "
      ", + "

      Top 3 things cats hate:

      ", + "
        ", + "
      1. flea treatment
      2. ", + "
      3. thunder
      4. ", + "
      5. other cats
      6. ", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + " ", + "
      ", + "
      ", + "
      ", + " ", + " ", + "
      " + ] + }, + + { + "_id": "bad88fee1348bd9aedf08825", + "name": "Adjusting the Padding of an Element", + "difficulty": 0.064, + "description": [ + "Change the padding of the green box to match that of the red box.", + "An element's padding controls the amount of space between an element and its border.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", + "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding', '20px')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08822", + "name": "Adjust the Margin of an Element", + "difficulty": 0.065, + "description": [ + "Change the margin of the green box to match that of the red box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", + "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '20px')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08823", + "name": "Add a Negative Margin to an Element", + "difficulty": 0.066, + "description": [ + "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "If you set an element's margin to a negative value, the element will grow larger.", + "Try to set the margin to a negative value like the one for the red box." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin', '-15px')" + ], + "challengeSeed": [ + "", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08824", + "name": "Add Different Padding to Each Side of an Element TEST", + "difficulty": 0.067, + "description": [ + "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has different padding on each of its sides.", + "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('padding-bottom', '20px')", + "expect($('.green-box')).to.have.css('padding-left', '40px')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + { + "_id": "bad87fee1248bd9aedf08824", + "name": "Add Different a Margin to Each Side of an Element TEST", + "difficulty": 0.068, + "description": [ + "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", + "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + { + "_id": "bad87fee1348bd9aedf08826", + "name": "Use Clockwise Notation to Specify an Element's Padding", + "difficulty": 0.069, + "description": [ + "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "expect($('.green-box')).to.have.css('margin-bottom', '20px')", + "expect($('.green-box')).to.have.css('margin-left', '40px')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ] + }, + + { + "_id": "bad87fee1348bd9aede08826", + "name": "Use Hex Codes for Precise Colors", + "difficulty": 0.070, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aedd08826", + "name": "Use Shortened Hex Codes for Colors", + "difficulty": 0.071, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + } + ] +} diff --git a/seed_data/challenges/computer-science.json b/seed_data/challenges/computer-science.json new file mode 100644 index 0000000000..50c0b873a5 --- /dev/null +++ b/seed_data/challenges/computer-science.json @@ -0,0 +1,86 @@ +{ + "name": "Computer Science", + "order" : 0.005, + "challenges": [ + { + "_id": "bd7123d8c441eddfaeb5bdef", + "name": "Learn Basic Computer Science", + "difficulty": 0.90, + "challengeSeed": "114628241", + "description": [ + "Stanford has an excellent free online Computer Science curriculum. This interactive course uses a modified version of JavaScript. It will cover a lot of concepts quickly.", + "Note that Harvard also has an excellent introduction to computer science course called CS50, but it takes more than 100 hours to complete, and doesn't use JavaScript.", + "Despite being completely self-paced, Stanford's CS101 course is broken up into weeks. Each of the following challenges will address one of those weeks.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z54/z1/ and complete the first week's course work." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd8124d8c441eddfaeb5bdef", + "name": "Learn Loops", + "difficulty": 0.19, + "challengeSeed": "114597348", + "description": [ + "Now let's tackle week 2 of Stanford's Intro to Computer Science course.", + "This will introduce us to loops, a fundamental feature of every programming language.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z100/a7a70ce6e4724c58862ee6007284face/ and complete Week 2." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd8125d8c441eddfaeb5bdef", + "name": "Learn Computer Hardware", + "difficulty": 0.20, + "challengeSeed": "114597347", + "description": [ + "Week 3 of Stanford's Intro to Computer Science covers computer hardware and explains Moore's law of exponential growth in the price-performance of processors.", + "This challenge will also give you an understanding of how bits and bytes work.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z143/z101/ and complete Week 3." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd8126d8c441eddfaeb5bdef", + "name": "Learn Computer Networking", + "difficulty": 0.21, + "challengeSeed": "114604811", + "description": [ + "Now that you've learned about computer hardware, it's time to learn about the software that runs on top of it.", + "Particularly important, you will learn about networks and TCP/IP - the protocol that powers the internet.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z187/z144/ and complete Week 4." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd8127d8c441eddfaeb5bdef", + "name": "Learn Boolean Logic", + "difficulty": 0.22, + "challengeSeed": "114604812", + "description": [ + "Now we'll do some more table exercises and learn boolean logic.", + "We'll also learn the difference between digital data and analog data.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z208/z188/ and complete Week 5." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd8128d8c441eddfaeb5bdef", + "name": "Learn Computer Security", + "difficulty": 0.23, + "challengeSeed": "114604813", + "description": [ + "We're almost done with Stanford's Introduction to Computer Science course!", + "We'll learn about one of the most important inventions of the 20th century - spreadsheets.", + "We'll also learn about Computer Security and some of the more common vulnerabilities software systems have.", + "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z229/z213/ and complete Week 6, the final week of the course." + ], + "challengeType": 2, + "tests": [] + } + ] +} diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json new file mode 100644 index 0000000000..c1491ce793 --- /dev/null +++ b/seed_data/challenges/full-stack-javascript.json @@ -0,0 +1,155 @@ +{ + "name": "Full Stack JavaScript", + "order" : 0.008, + "challenges": [ + { + "_id": "bd7154d8c441eddfaeb5bdef", + "name": "Get Started with Angular.js", + "difficulty": 0.34, + "challengeSeed": "114684726", + "description": [ + "Code School has a short, free Angular.js course. This will give us a quick tour of Angular.js's mechanics and features.", + "In this course, we'll build a virtual shop entirely in Angular.js.", + "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/1/section/1/video/1 and complete the section." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7155d8c441eddfaeb5bdef", + "name": "Apply Angular.js Directives", + "difficulty": 0.35, + "challengeSeed": "114684727", + "description": [ + "Directives serve as markers in your HTML. When Angular.js compiles your HTML, it will can alter the behavior of DOM elements based on the directives you've used.", + "Let's learn how these powerful directives work, and how to use them to make your web apps more dynamic", + "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/2/section/1/video/1 and complete the section." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7156d8c441eddfaeb5bdef", + "name": "Power Forms with Angular.js", + "difficulty": 0.36, + "challengeSeed": "114684729", + "description": [ + "One area where Angular.js really shines is its powerful web forms.", + "Learn how to create reactive Angular.js forms, including real-time form validation.", + "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/3/section/1/video/1 and complete the section." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7157d8c441eddfaeb5bdef", + "name": "Customize Angular.js Directives", + "difficulty": 0.37, + "challengeSeed": "114685062", + "description": [ + "Now we'll learn how to modify existing Angular.js directives, and even build directives of your own.", + "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/4/section/1/video/1 and complete the section." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7158d8c441eddfaeb5bdef", + "name": "Create Angular.js Services", + "difficulty": 0.38, + "challengeSeed": "114685060", + "description": [ + "Services are functions that you can use and reuse throughout your Angular.js app to get things done.", + "We'll learn how to use services in this final Code School Angular.js challenge.", + "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/5/section/1/video/1 and complete the section." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7153d8c441eddfaeb5bd0f", + "name": "Manage Packages with NPM", + "difficulty": 0.39, + "challengeSeed": "126433450", + "description": [ + "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "If you don't already have Cloud 9 account, create one now at http://c9.io.", + "Open up http://c9.io and sign in to your account.", + "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", + "Give your workspace a name.", + "Choose Node.js in the selection area below the name field", + "Click the Create button", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Click the \"Start Editing\" button.", + "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", + "Run this command: sudo npm install how-to-npm -g", + "Now start this tutorial by running how-to-npm", + "Note that you can resize the c9.io's windows by dragging their borders.", + "Follow the directions and work through all of the the tutorial's steps before moving on." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7153d8c441eddfaeb5bdff", + "name": "Start a Node.js Server", + "difficulty": 0.40, + "challengeSeed": "126411561", + "description": [ + "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "If you don't already have Cloud 9 account, create one now at http://c9.io.", + "Open up http://c9.io and sign in to your account.", + "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", + "Give your workspace a name.", + "Choose Node.js in the selection area below the name field", + "Click the Create button", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Click the \"Start Editing\" button.", + "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", + "Run this command: sudo npm install learnyounode -g", + "Now start this tutorial by running learnyounode", + "Note that you can resize the c9.io's windows by dragging their borders.", + "Follow the directions and work through all of the the tutorial's steps before moving on." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7153d8c441eddfaeb5bd1f", + "name": "Build Web Apps with Express.js", + "difficulty": 0.41, + "challengeSeed": "126411559", + "description": [ + "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "If you don't already have Cloud 9 account, create one now at http://c9.io.", + "Open up http://c9.io and sign in to your account.", + "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", + "Give your workspace a name.", + "Choose Node.js in the selection area below the name field", + "Click the Create button", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Click the \"Start Editing\" button.", + "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", + "Run this command: git clone http://github.com/reddock/fcc_express && chmod 744 fcc_express/setup.sh && fcc_express/setup.sh && source ~/.profile", + "Now start this tutorial by running expressworks", + "Note that you can resize the c9.io's windows by dragging their borders.", + "Follow the directions and work through all of the the tutorial's steps before moving on." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7140d8c441eddfaeb5bdef", + "name": "Manage Source Code with Git", + "difficulty": 0.43, + "challengeSeed": "114635309", + "description": [ + "Version Control Systems like Git ensure that, no matter how you experiment with your code, you can always roll back your app to a stable previous state.", + "Git is also a great way to share and contribute to open source software.", + "Go to https://www.codeschool.com/courses/try-git and complete this short interactive course." + ], + "challengeType": 2, + "tests": [] + } + ] +} diff --git a/seed_data/challenges/getting-set-for-free-code-camp.json b/seed_data/challenges/getting-set-for-free-code-camp.json new file mode 100644 index 0000000000..92c5cc6f8b --- /dev/null +++ b/seed_data/challenges/getting-set-for-free-code-camp.json @@ -0,0 +1,146 @@ +{ + "name": "Getting Set for Free Code Camp", + "order" : 0.001, + "challenges": [ + { + "_id": "bd7124d8c441eddfaeb5bdef", + "name": "Learn how Free Code Camp Works", + "difficulty": 0.001, + "challengeSeed": "125407438", + "description": [ + "Watch this 1-minute video, or simply read this summary:", + "Welcome to Free Code Camp. We're a community of busy people learning to code by building projects for nonprofits.", + "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And to stay motivated, you just need to:
      1. make friends with people who code
      2. code a little every day
        1. ", + "All our challenges are
          1. free
          2. self-paced
          3. browser-based
          ", + "We'll spend
          1. 200 hours learning tools like HTML, CSS, JavaScript, Node.js and databases
          2. 600 hours building practice projects
          3. 800 hours building full stack solutions for nonprofits
          ", + "By the end, we'll
          1. be good at coding
          2. have the portfolio of apps with happy users to prove it
          ", + "Once you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", + "Now it's time to join our chat room. Click the \"I've completed this challenge\" button to move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bd0f", + "name": "Join Our Chat Room", + "difficulty": 0.002, + "challengeSeed": "124555254", + "description": [ + "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", + "Make sure your Free Code Camp account includes your email address. Please note that the email address you use will be invisible to the public, but Slack will make it visible to other campers in our slack chat rooms. You can do this here: http://freecodecamp.com/account.", + "Click this link, which will email you an invite to Free Code Camp's Slack chat rooms: http://freecodecamp.com/api/slack.", + "Now check your email and click the link in the email from Slack.", + "Complete the sign up process, then update your biographical information and upload an image. A picture of your face works best. This is how people will see you in our chat rooms, so put your best foot forward.", + "Now enter the General chat room and introduce yourself to our chat room by typing: \"Hello world!\".", + "Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", + "Keep the chat room open while you work through the other challenges. That way you ask for help if you get stuck on a challenge. You can also socialize when you feel like taking a break.", + "You can also access this chat room by clicking the \"Chat\" button in the upper right hand corner.", + "In order to keep our community a friendly and positive place to learn to code, please read and follow our Code of Conduct: http://freecodecamp.com/field-guide/what-is-the-free-code-camp-code-of-conduct?" + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bdff", + "name": "Preview our Challenge Map", + "difficulty": 0.003, + "challengeSeed": "125407437", + "description": [ + "Before you start learning how to code, we'd like to introduce you to a few things.", + "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", + "You should complete all these challenges in order.", + "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", + "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bd1f", + "name": "Browse our Field Guide", + "difficulty": 0.004, + "challengeSeed": "125407435", + "description": [ + "Free Code Camp has an up-to-date field guide that will answer your many questions.", + "Click the \"Field Guide\" button in the upper right hand corner.", + "You can browse the field guide at your convenience. Most of its articles take less than 1 minute to read.", + "When you click the Field Guide button, it will always take you back to whichever article you were last reading.", + "Read a few field guide articles, then move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7125d8c441eddfaeb5bd2f", + "name": "Customize your Portfolio Page", + "difficulty": 0.005, + "challengeSeed": "125407433", + "description": [ + "You and all your fellow campers have portfolio pages.", + "To see your portfolio page, click your picture in the upper right hand corner.", + "Your portfolio page will automatically show off your progress through Free Code Camp.", + "Click the \"Update my portfolio page or manage my account\" button", + "You can link to your Github, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", + "Be sure to click the \"Update my Bio\" or \"Update my Social Links\" button to save this new information to your portfolio page.", + "Once you're happy with your portfolio page, you can move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7126d8c441eddfaeb5bd3f", + "name": "Try Camper News", + "difficulty": 0.006, + "challengeSeed": "124553410", + "description": [ + "Camper News is the best place for our campers to share and discuss helpful links.", + "Click \"News\" in the upper right hand corner.", + "You'll see a variety of links that have been submitted. Click on the \"Discuss\" button under one of them.", + "You can upvote links. This will push the link up the rankings of hot links.", + "You an also comment on a link. If someone responds to your comment, you'll get an email notification so you can come back and respond to them.", + "You can also submit links. You can modify the link's headline and also leave an initial comment about the link.", + "You can view the portfolio pages of any camper who has posted links or comments on Camper News. Just click on their photo.", + "When you submit a link, you'll get a point. You will also get a point each time someone upvotes your link.", + "Now that you've learned how to use Camper News, let's move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7126d8c441eddfaeb5bd3e", + "name": "Meet Other Campers in your City", + "difficulty": 0.007, + "challengeSeed": "127358841", + "description": [ + "One of the best ways to stay motivated when learning to code is to hang out with other campers.", + "Slack and Camper News are great ways to communicate with other campers, but there's no substitute for meeting people in-person.", + "The easiest way to meet other campers in your city is to join your city's Facebook Group. Click here to view our growing list of local groups.", + "Click the link to your city, then, once Facebook loads, click \"Join group\".", + "Our local groups are new, so if you don't see your city on this list, you should follow the directions to create a Facebook group for your city.", + "If you don't have a Facebook account, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.", + "Our groups allow you to create events, coordinate those events, and share photos from the events afterward.", + "Whether you're hosting a study group, pair programming at your local library, or going to a weekend hackathon, your city's group will help you make it happen." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7137d8c441eddfaeb5bdef", + "name": "Get Help the Hacker Way with RSAP", + "difficulty": 0.008, + "challengeSeed": "125407432", + "description": [ + "Let's cover one last thing before you start working through our lessons: how to get help.", + "Any time you get stuck or don't know what to do next, follow this simple algorithm (procedure): RSAP (Read, Search, Ask, Post).", + "First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", + "Next, S - Search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.", + "Then, if you still haven't found an answer to your question, A - Ask your friends. If you have trouble, you can ask your fellow campers. We have a special chat room specifically for getting help with tools you learn through these Free Code Camp Challenges. Go to https://freecode.slack.com/messages/help/. Keep this chat open while you work on the remaining challenges.", + "Finally, P - Post on Stack Overflow. Before you attempt to do this, read Stack Overflow's guide to asking good questions: http://stackoverflow.com/help/how-to-ask.", + "Here's our detailed field guide on getting help: http://freecodecamp.com/field-guide/how-do-i-get-help-when-i-get-stuck.", + "Now you have a clear algorithm to follow when you need help! Let's start coding! Move on to your next challenge." + ], + "challengeType": 2, + "tests": [] + } + ] +} diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json new file mode 100644 index 0000000000..8a51f9ddbb --- /dev/null +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -0,0 +1,283 @@ +{ + "name": "jQuery Ajax and JSON", + "order" : 0.004, + "challenges": [ + { + "_id": "bad87fee1348bd9acdd08826", + "name": "Learn how Script Tags and Document Ready Work", + "difficulty": 0.072, + "description": [ + "Test" + ], + "tests": [ + "assert($('#target').hasClass('disabled'), 'The button with the ID of \"target\" should continue to have the \"disabled\" class.')", + "assert(!!$('#target[disabled]'), 'Enable the button with the ID of \"target\" by using jQuery.')", + "expect($('#target')).to.exist()" + ], + "challengeSeed": [ + "fccss", + " $(document).ready(function() {", + " $('#target').attr('disabled', true)", + " });", + "fcces", + "" + ] + }, + + { + "_id": "bad87fee1348bd9aedc08826", + "name": "Target Elements by Selectors Using jQuery", + "difficulty": 0.073, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aedb08826", + "name": "Target Elements by Class Using jQuery", + "difficulty": 0.074, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aeda08826", + "name": "Target an element by ID Using jQuery", + "difficulty": 0.075, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed908826", + "name": "Change the CSS of an Element Using jQuery", + "difficulty": 0.076, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed808826", + "name": "Disable an Element Using jQuery", + "difficulty": 0.077, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed708826", + "name": "Remove an Element Using jQuery", + "difficulty": 0.078, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed608826", + "name": "Move an Element Using jQuery", + "difficulty": 0.079, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed508826", + "name": "Clone an Element Using jQuery", + "difficulty": 0.080, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed408826", + "name": "Animate an Element Using jQuery", + "difficulty": 0.081, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed308826", + "name": "Target the Parent of an Element Using jQuery", + "difficulty": 0.082, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed208826", + "name": "Target the Children of an Element Using jQuery", + "difficulty": 0.083, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + + { + "_id": "bad87fee1348bd9aed108826", + "name": "Target a Specific Child of an Element Using jQuery", + "difficulty": 0.084, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aed008826", + "name": "Target Even Numbered Elements Using jQuery", + "difficulty": 0.085, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aecc08826", + "name": "Read Data from an Element Using jQuery", + "difficulty": 0.086, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9aebc08826", + "name": "Get Data from an URL Using jQuery", + "difficulty": 0.087, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9ae9c08826", + "name": "Loop through JSON Data Using jQuery", + "difficulty": 0.089, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + }, + + { + "_id": "bad87fee1348bd9ae8c08826", + "name": "Setup Click Events Using jQuery", + "difficulty": 0.089, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] + } + ] +} diff --git a/seed_data/challenges/prepwork.json b/seed_data/challenges/prepwork.json deleted file mode 100644 index 3049d6c31a..0000000000 --- a/seed_data/challenges/prepwork.json +++ /dev/null @@ -1,55 +0,0 @@ -[ - { - "_id": "bd7124d8c441eddfaeb5bdef", - "name": "Learn how Free Code Camp Works", - "difficulty": 0.01, - "challengeSeed": "125407438", - "description": [ - "Watch this 1-minute video, or simply read this summary:", - "Welcome to Free Code Camp. We're a community of busy people learning to code by building projects for nonprofits.", - "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And to stay motivated, you just need to:
          1. make friends with people who code
          2. code a little every day
            1. ", - "All our challenges are
              1. free
              2. self-paced
              3. browser-based
              ", - "We'll spend
              1. 200 hours learning tools like HTML, CSS, JavaScript, Node.js and databases
              2. 600 hours building practice projects
              3. 800 hours building full stack solutions for nonprofits
              ", - "By the end, we'll
              1. be good at coding
              2. have the portfolio of apps with happy users to prove it
              ", - "Once you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", - "Now it's time to join our chat room. Click the \"I've completed this challenge\" button to move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bd0f", - "name": "Join Our Chat Room", - "difficulty": 0.02, - "challengeSeed": "124555254", - "description": [ - "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", - "Make sure your Free Code Camp account includes your email address. You can do this here: http://freecodecamp.com/account.", - "Click this link, which will email you an invite to Free Code Camp's Slack chat room: http://freecodecamp.com/api/slack.", - "Now check your email and click the link in the email from Slack", - "Complete the sign up process, then update your biographical information and upload an image. A picture of your face works best. This is how people will see you in the chat room, so put your best foot forward.", - "Now enter the general chat room and introduce yourself to our chat room by typing: \"hello world!\".", - "Note that you're expected to follow our Code of Conduct: http://freecodecamp.com/field-guide/what-is-the-free-code-camp-code-of-conduct?", - "Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", - "Keep the chat room open while you work through the other challenges. That way you ask for help if you get stuck on a challenge. You can also socialize when you feel like taking a break.", - "You can also access this chat room by clicking the \"Chat\" button in the upper right hand corner." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bdff", - "name": "Preview our Challenge Map", - "difficulty": 0.03, - "challengeSeed": "125407437", - "description": [ - "Before you start learning how to code, we'd like to introduce you to a few things.", - "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", - "You should complete all these challenges in order.", - "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", - "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." - ], - "challengeType": 2, - "tests": [] - } -] \ No newline at end of file diff --git a/seed_data/challenges/ziplines.json b/seed_data/challenges/ziplines.json new file mode 100644 index 0000000000..ef23b63bea --- /dev/null +++ b/seed_data/challenges/ziplines.json @@ -0,0 +1,197 @@ +{ + "name": "Ziplines", + "order" : 0.009, + "challenges": [ + { + "_id": "bd7158d8c442eddfbeb5bd1f", + "name": "Get Set for Ziplines", + "difficulty": 1.00, + "challengeSeed": "125658022", + "description": [ + "Now you're ready to start our Zipline challenges. These front-end development challenges will give you many opportunities to apply the HTML, CSS, jQuery and JavaScript you've learned to build static (database-less) applications.", + "For many of these challenges, you will be using JSON data from external API endpoints, such as Twitch.tv and Twitter. Note that you don't need to have a database to use these data.", + "The easiest way to manipulate these data is with jQuery $.getJSON().", + "Whatever you do, don't get discouraged! Remember to use RSAP if you get stuck.", + "We'll build these challenges using CodePen, a popular tool for creating, sharing, and discovering static web applications.", + "Go to http://codepen.io and create an account.", + "Click your user image in the top right corner, then click the \"New pen\" button that drops down.", + "Drag the windows around and press the buttons in the lower-right hand corner to change the orientation to suit your preference.", + "Click the gear next to CSS. Then in the \"External CSS File or Another Pen\" text field, type \"bootstrap\" and scroll down until you see the latest version of Bootstrap. Click it.", + "Verify that bootstrap is active by adding the following code to your HTML: <h1 class='text-primary'>Hello CodePen!</h1>. The text's color should be Bootstrap blue.", + "Click the gear next the JavaScript. Click the \"Latest version of...\" select box and choose jQuery.", + "Now add the following code to your JavaScript: $(document).ready(function() { $('.text-primary').text('Hi CodePen!') });. Click the \"Save\" button at the top. Your \"Hello CodePen!\" should change to \"Hi CodePen!\". This means that jQuery is working.", + "Now you're ready for your first Zipline. 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." + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd1f", + "name": "Zipline: Use the Twitch.tv JSON API", + "difficulty": 1.01, + "challengeSeed": "126411564", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can see whether Free Code Camp is currently streaming on Twitch.tv.", + "User Story: As a user, I can click the status output and be sent directly to the Free Code Camp's Twitch.tv channel.", + "User Story: As a user, if Free Code Camp is streaming, I can see additional details about what they are streaming.", + "Bonus User Story: As a user, I can search through the streams listed.", + "Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", + "Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", + "Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd13", + "name": "Zipline: Build a Random Quote Machine", + "difficulty": 1.02, + "challengeSeed": "126415122", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/vEoVMw.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can click a button to show me a new random quote.", + "Bonus User Story: As a user, I can press a button to tweet out a quote.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd10", + "name": "Zipline: Show the Local Weather", + "difficulty": 1.03, + "challengeSeed": "126415127", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can see the weather in my current location.", + "Bonus User Story: As a user, I can see an icon depending on the temperature..", + "Bonus User Story: As a user, I see a different background image depending on the temperature (e.g. snowy mountain, hot desert).", + "Bonus User Story: As a user, I can push a button to toggle between Fahrenheit and Celsius.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd18", + "name": "Zipline: Stylize Stories on Camper News", + "difficulty": 1.04, + "challengeSeed": "126415129", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/Wveezv.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can browse recent posts from Camper News.", + "User Story: As a user, I can click on a post to be taken to the story's original URL.", + "User Story: As a user, I can click a link to go directly to the post's discussion page.", + "Bonus User Story: As a user, I can see how many upvotes each story has.", + "Hint: Here's the Camper News Hot Stories API endpoint: http://www.freecodecamp.com/stories/hotStories.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd19", + "name": "Zipline: Wikipedia Viewer", + "difficulty": 1.05, + "challengeSeed": "126415131", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/MwgQea.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can search Wikipedia entries in a search box and see the resulting Wikipedia entries.", + "Bonus User Story:As a user, I can click a button to see a random Wikipedia entry.", + "Bonus User Story:As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.", + "Hint: Here's an entry on using Wikipedia's API: http://www.mediawiki.org/wiki/API:Main_page.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd0f", + "name": "Zipline: Build a Pomodoro Clock", + "difficulty": 1.06, + "challengeSeed": "126411567", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/RPbGxZ/.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can start a 25 minute pomodoro, and the timer will go off once 25 minutes has elapsed.", + "Bonus User Story: As a user, I can reset the clock for my next pomodoro.", + "Bonus User Story: As a user, I can customize the length of each pomodoro.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd17", + "name": "Zipline: Build a JavaScript Calculator", + "difficulty": 1.07, + "challengeSeed": "126411565", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/zxgaqw.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can add, subtract, multiply and divide two numbers.", + "Bonus User Story: I can clear the input field with a clear button.", + "Bonus User Story: I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", + "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" + ], + "challengeType": 3, + "tests": [] + }, + { + "_id": "bd7158d8c442eddfaeb5bd1c", + "name": "Zipline: Build a Tic Tac Toe Game", + "difficulty": 1.08, + "challengeSeed": "126415123", + "description": [ + "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/alex-dixon/full/JogOpQ/.", + "Rule #1: Don't look at the example project's code. 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.", + "Here are the user stories you must enable, and optional bonus user stories:", + "User Story: As a user, I can play a game of Tic Tac Toe with the computer.", + "Bonus User Story: As a user, I can never actually win against the computer - at best I can tie.", + "Bonus User Story: As a user, my game will reset as soon as it's over so I can play again.", + "Bonus User Story: As a user, I can choose whether I want to play as X or O.", + "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" + ], + "challengeType": 3, + "tests": [] + } + ] +} diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index c8a6bb102a..17f28bfac1 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -157,8 +157,7 @@ ], "challengeSeed": [ "

              Hello

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf0887a", @@ -176,8 +175,7 @@ ], "challengeSeed": [ "

              Hello World

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08801", @@ -194,8 +192,7 @@ "challengeSeed": [ "

              Hello World

              ", "

              CatPhotoApp

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aeaf08801", @@ -214,8 +211,7 @@ "

              Hello World

              ", "

              CatPhotoApp

              ", "

              Hello Paragraph

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08802", @@ -242,8 +238,7 @@ "", "

              Hello Paragraph

              ", "-->" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08804", @@ -269,8 +264,7 @@ "", "

              Hello Paragraph

              ", "-->" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08833", @@ -294,8 +288,7 @@ "
              ", "", "

              Hello Paragraph

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fed1348bd9aedf08833", @@ -320,8 +313,7 @@ "
              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08803", @@ -340,8 +332,7 @@ "

              CatPhotoApp

              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08805", @@ -364,8 +355,7 @@ "

              CatPhotoApp

              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aecf08806", @@ -395,8 +385,7 @@ "

              CatPhotoApp

              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aefe08806", @@ -422,8 +411,7 @@ "

              CatPhotoApp

              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08806", @@ -449,8 +437,7 @@ "

              CatPhotoApp

              ", "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aede08807", @@ -479,8 +466,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08807", @@ -512,8 +498,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08808", @@ -551,8 +536,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08809", @@ -593,8 +577,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { @@ -632,8 +615,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9acdf08812", @@ -671,8 +653,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9bedf08813", @@ -715,8 +696,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08814", @@ -764,8 +744,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08815", @@ -812,8 +791,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08816", @@ -863,8 +841,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aede08817", @@ -917,8 +894,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { @@ -970,8 +946,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08820", @@ -1023,8 +998,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08818", @@ -1076,8 +1050,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0 + ] }, { @@ -1130,9 +1103,7 @@ "", "

              Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

              ", "

              Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

              " - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1191,9 +1162,7 @@ "
            2. laser pointers
            3. ", "
            4. lasagna
            5. ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1254,9 +1223,7 @@ "
            6. thunder
            7. ", "
            8. other cats
            9. ", "
            " - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1318,9 +1285,7 @@ "
          3. other cats
          4. ", "
          ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1383,9 +1348,7 @@ "
        2. other cats
        3. ", "
        ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1449,9 +1412,7 @@ "
        ", " ", "
        " - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1517,9 +1478,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1589,9 +1548,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1659,9 +1616,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1730,9 +1685,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1804,9 +1757,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -1881,8 +1832,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd8acde08812", @@ -1954,8 +1904,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { @@ -2027,8 +1976,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348cd8acef08812", @@ -2101,8 +2049,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348cd8acef08811", @@ -2175,8 +2122,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348cd8acef08813", @@ -2250,8 +2196,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348ce8acef08814", @@ -2326,8 +2271,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad88fee1348ce8acef08815", @@ -2403,8 +2347,7 @@ " ", " ", "" - ], - "challengeType": 0 + ] }, { @@ -2490,9 +2433,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2563,9 +2504,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2639,9 +2578,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2716,9 +2653,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2792,9 +2727,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2875,9 +2808,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -2968,9 +2899,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -3061,9 +2990,7 @@ " ", " ", "" - ], - "challengeType": 0, - "completionMessage": "" + ] }, { @@ -3114,8 +3041,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08822", @@ -3167,8 +3093,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08823", @@ -3219,8 +3144,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08824", @@ -3272,8 +3196,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1248bd9aedf08824", @@ -3325,8 +3248,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { "_id": "bad87fee1348bd9aedf08826", @@ -3375,8 +3297,7 @@ "
        padding
        ", "
        padding
        ", "" - ], - "challengeType": 0 + ] }, { @@ -3391,8 +3312,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3407,8 +3327,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3430,8 +3349,7 @@ " });", "fcces", "" - ], - "challengeType": 0 + ] }, { @@ -3446,8 +3364,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3462,8 +3379,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3478,8 +3394,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3494,8 +3409,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3510,8 +3424,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3526,8 +3439,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3542,8 +3454,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3558,8 +3469,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3574,8 +3484,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3590,8 +3499,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3606,8 +3514,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, @@ -3623,8 +3530,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3639,8 +3545,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3655,8 +3560,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3671,8 +3575,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3687,8 +3590,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { @@ -3703,8 +3605,7 @@ ], "challengeSeed": [ - ], - "challengeType": 0 + ] }, { From 804866013f211442d0f47fb44b90f90518ab1254 Mon Sep 17 00:00:00 2001 From: phoenixstormcrow Date: Tue, 19 May 2015 18:00:25 -0700 Subject: [PATCH 24/81] removed "white-space: pre-line" rule from pre.wrappable elements to prettify bonfire solution formatting. --- public/css/main.less | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/public/css/main.less b/public/css/main.less index 8d8986d47f..e28fb60f66 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -20,6 +20,16 @@ li, .wrappable { word-wrap: break-word; /* IE 5+ */ } +pre.wrappable { + white-space: pre; /* CSS 2.0 */ + white-space: pre-wrap; /* CSS 2.1 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: -moz-pre-wrap; /* Mozilla */ + white-space: -hp-pre-wrap; /* HP Printers */ + word-wrap: break-word; /* IE 5+ */ +} + html { position: relative; min-height: 100%; From a174a1c6305a220fd810430806e890b18063998e Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Tue, 19 May 2015 22:31:01 -0400 Subject: [PATCH 25/81] Work on challenge flow from block to block, start refactoring the name courseware to challenges in main.js --- app.js | 46 +-- controllers/challenge.js | 223 +++++++++++- controllers/resources.js | 93 ++++-- models/User.js | 14 +- .../coursewaresJSFramework_0.0.1.js | 316 +++++++++--------- public/js/main.js | 26 +- seed_data/challenges/basic-html5-and-css.json | 111 ++++-- seed_data/seed.js | 3 +- views/coursewares/showVideo.jade | 3 +- views/partials/navbar.jade | 2 +- 10 files changed, 561 insertions(+), 276 deletions(-) diff --git a/app.js b/app.js index 165061db3d..b1f65d4e37 100755 --- a/app.js +++ b/app.js @@ -36,25 +36,26 @@ var express = require('express'), /** * Controllers (route handlers). */ - homeController = require('./controllers/home'), - resourcesController = require('./controllers/resources'), - userController = require('./controllers/user'), - nonprofitController = require('./controllers/nonprofits'), - bonfireController = require('./controllers/bonfire'), - coursewareController = require('./controllers/courseware'), - fieldGuideController = require('./controllers/fieldGuide'), - challengeMapController = require('./controllers/challengeMap'), + homeController = require('./controllers/home'), + resourcesController = require('./controllers/resources'), + userController = require('./controllers/user'), + nonprofitController = require('./controllers/nonprofits'), + bonfireController = require('./controllers/bonfire'), + coursewareController = require('./controllers/courseware'), + fieldGuideController = require('./controllers/fieldGuide'), + challengeMapController = require('./controllers/challengeMap'), + challengeController = require('./controllers/challenge'), /** * Stories */ - storyController = require('./controllers/story'), + storyController = require('./controllers/story'), - /** - * API keys and Passport configuration. - */ - secrets = require('./config/secrets'), - passportConf = require('./config/passport'); + /** + * API keys and Passport configuration. + */ + secrets = require('./config/secrets'), + passportConf = require('./config/passport'); /** * Create Express server. @@ -537,17 +538,24 @@ app.post('/completed-field-guide/', fieldGuideController.completedFieldGuide); * Courseware related routes */ -app.get('/challenges/', coursewareController.returnNextCourseware); +app.get('/getstuff', challengeController.getStuff); + + +app.get('/challenges/next-challenge', challengeController.returnNextChallenge); app.get( - '/challenges/:coursewareName', - coursewareController.returnIndividualCourseware + '/challenges/:challengeName', + challengeController.returnIndividualChallenge ); -app.post('/completed-courseware/', coursewareController.completedCourseware); +app.get('/challenges/', challengeController.returnCurrentChallenge); +// todo refactor these routes +app.post('/completed-challenge/', challengeController.completedChallenge); app.post('/completed-zipline-or-basejump', - coursewareController.completedZiplineOrBasejump); + challengeController.completedZiplineOrBasejump); + +app.post('/completed-bonfire', challengeController.completedBonfire); // Unique Check API route app.get('/api/checkUniqueUsername/:username', diff --git a/controllers/challenge.js b/controllers/challenge.js index 9062945916..3894006e96 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -40,42 +40,107 @@ exports.showAllChallenges = function(req, res) { res.send(data); }; +exports.getStuff = function(req, res, next) { + res.send({withNames: challengeMapWithNames, withIds: challengeMapWithIds}); +}; + exports.returnNextChallenge = function(req, res, next) { if (!req.user) { return res.redirect('../challenges/learn-how-free-code-camp-works'); } + var completed = req.user.completedChallenges.map(function (elem) { + return elem._id; + }); + + req.user.uncompletedChallenges = resources.allChallengeIds() + .filter(function (elem) { + if (completed.indexOf(elem) === -1) { + return elem; + } + }); + req.user.save(); // find the user's current challenge and block // look in that block and find the index of their current challenge // if index + 1 <= block.challenges.length - 1 // serve index + 1 challenge // otherwise increment block key and serve the first challenge in that block var nextChallengeName; + var nextChallengeId; + var nextChallengeBlock; + var challengeId = req.user.currentChallenge.challengeId; var challengeBlock = req.user.currentChallenge.challengeBlock; + debug('this is the user challenge block', challengeBlock); var indexOfChallenge = challengeMapWithIds[challengeBlock] .indexOf(challengeId); - if (indexOfChallenge - <= challengeMapWithIds[challengeBlock].length - 1) { + debug('Logging first two challenge blocks for sanity', challengeMapWithIds[0], challengeMapWithIds[1]); + + + debug('these are the damn keys on challengeMapWithIds...', Object.keys(challengeMapWithIds)); + if (indexOfChallenge + 1 + < challengeMapWithIds[challengeBlock].length) { + debug('advancing to next challange in current block'); nextChallengeName = challengeMapWithNames[challengeBlock][indexOfChallenge + 1]; - } else if (typeof challengeMapWithIds[challengeBlock + 1] !== 'undefined') { - nextChallengeName = R.head(challengeMapWithNames[challengeBlock + 1]); + nextChallengeId = challengeMapWithIds[challengeBlock][indexOfChallenge + 1]; + nextChallengeBlock = challengeBlock; + } else if (typeof challengeMapWithIds[++challengeBlock] !== 'undefined') { + debug('Advancing to next block'); + nextChallengeName = R.head(challengeMapWithNames[challengeBlock]); + nextChallengeId = R.head(challengeMapWithNames[challengeBlock]); + nextChallengeBlock = challengeBlock; } else { + debug('completed all challenges'); req.flash('errors', { msg: 'It looks like you have finished all of our challenges.' + ' Great job! Now on to helping nonprofits!' }); - nextChallengeName = R.head(challengeMapWithNames['0'].challenges); + nextChallengeName = R.head(challengeMapWithNames[0].challenges); + nextChallengeId = R.head(challengeMapWithNames[0].challenges); + nextChallengeBlock = 0; } - var nameString = nextChallengeName.toLowerCase().replace(/\s/g, '-'); - return res.redirect('../challenges' + nameString); + req.user.currentChallenge = { + challengeId: nextChallengeId, + challengeName: nextChallengeName, + challengeBlock: nextChallengeBlock + }; + req.user.save(); + var nameString = nextChallengeName.trim() + .toLowerCase() + .replace(/[^\w\s]/g, '') + .replace(/\s/g, '-') + debug('this is the namestring we\'re going to look up', nameString); + return res.redirect('../challenges/' + nameString); +}; + +exports.returnCurrentChallenge = function(req, res, next) { + debug('these are the damn keys on challengeMapWithIds...', Object.keys(challengeMapWithIds)); + debug('sanity check', challengeMapWithIds[0], challengeMapWithIds[1]); + if (!req.user) { + return res.redirect('../challenges/learn-how-free-code-camp-works'); + } + if (!req.user.currentChallenge) { + req.user.currentChallenge = {}; + req.user.currentChallenge.challengeId = challengeMapWithIds['0'][0]; + req.user.currentChallenge.challengeName = challengeMapWithNames['0'][0]; + req.user.currentChallenge.challengeBlock = '0'; + req.user.save(); + return res.redirect('../challenges/learn-how-free-code-camp-works'); + } + var nameString = req.user.currentChallenge.challengeName.trim() + .toLowerCase() + .replace(/[^\w\s]/g, '') + .replace(/\s/g, '-'); + debug('this is the namestring we\'re going to look up', nameString); + return res.redirect('../challenges/' + nameString); }; exports.returnIndividualChallenge = function(req, res, next) { var dashedName = req.params.challengeName; var challengeName = dashedName.replace(/\-/g, ' '); + debug('looking for %s', challengeName); Challenge.find({'name': new RegExp(challengeName, 'i')}, function(err, challengeFromMongo) { @@ -84,6 +149,7 @@ exports.returnIndividualChallenge = function(req, res, next) { } // Handle not found if (challengeFromMongo.length < 1) { + debug(challengeFromMongo); req.flash('errors', { msg: '404: We couldn\'t find a challenge with that name. ' + 'Please double check the name.' @@ -91,6 +157,7 @@ exports.returnIndividualChallenge = function(req, res, next) { return res.redirect('/challenges'); } var challenge = challengeFromMongo.pop(); + debug(challenge); // Redirect to full name if the user only entered a partial var dashedNameFull = challenge.name.toLowerCase().replace(/\s/g, '-'); @@ -186,6 +253,148 @@ exports.returnIndividualChallenge = function(req, res, next) { }); }; +exports.completedBonfire = function(req, res, next) { + +}; + +exports.completedChallenge = function (req, res, next) { + + var isCompletedDate = Math.round(+new Date()); + var challengeId = req.body.challengeInfo.challengeId; + + + req.user.completedChallenges.push({ + _id: challengeId, + completedDate: isCompletedDate, + name: req.body.challengeInfo.challengeName, + solution: null, + githubLink: null, + verified: true + }); + var index = req.user.uncompletedChallenges.indexOf(challengeId); + + if (index > -1) { + req.user.progressTimestamps.push(Date.now() || 0); + req.user.uncompletedChallenges.splice(index, 1); + } + + req.user.save(function (err, user) { + if (err) { + return next(err); + } + if (user) { + res.sendStatus(200); + } + }); +}; + +exports.completedZiplineOrBasejump = function (req, res, next) { + debug('Inside controller for completed zipline or basejump with data %s', + req.body.coursewareInfo); + var isCompletedWith = req.body.coursewareInfo.completedWith || false; + var isCompletedDate = Math.round(+new Date()); + var coursewareHash = req.body.coursewareInfo.coursewareHash; + var solutionLink = req.body.coursewareInfo.publicURL; + var githubLink = req.body.coursewareInfo.challengeType === '4' + ? req.body.coursewareInfo.githubURL : true; + if (!solutionLink || !githubLink) { + req.flash('errors', { + msg: 'You haven\'t supplied the necessary URLs for us to inspect ' + + 'your work.' + }); + return res.sendStatus(403); + } + + if (isCompletedWith) { + var paired = User.find({'profile.username': isCompletedWith.toLowerCase()}).limit(1); + paired.exec(function (err, pairedWithFromMongo) { + if (err) { + return next(err); + } else { + var index = req.user.uncompletedCoursewares.indexOf(coursewareHash); + if (index > -1) { + req.user.progressTimestamps.push(Date.now() || 0); + req.user.uncompletedCoursewares.splice(index, 1); + } + var pairedWith = pairedWithFromMongo.pop(); + + req.user.completedCoursewares.push({ + _id: coursewareHash, + name: req.body.coursewareInfo.coursewareName, + completedWith: pairedWith._id, + completedDate: isCompletedDate, + solution: solutionLink, + githubLink: githubLink, + verified: false + }); + + req.user.save(function (err, user) { + if (err) { + return next(err); + } + debug('this is the user object returned %s,' + + ' this is the req.user._id %s, ' + + 'this is the pairedWith._id %s', user, req.user._id, pairedWith._id); + debug(req.user._id.toString() === pairedWith._id.toString()); + if (req.user._id.toString() === pairedWith._id.toString()) { + return res.sendStatus(200); + } + index = pairedWith.uncompletedCoursewares.indexOf(coursewareHash); + if (index > -1) { + pairedWith.progressTimestamps.push(Date.now() || 0); + pairedWith.uncompletedCoursewares.splice(index, 1); + + } + + pairedWith.completedCoursewares.push({ + _id: coursewareHash, + name: req.body.coursewareInfo.coursewareName, + completedWith: req.user._id, + completedDate: isCompletedDate, + solution: solutionLink, + githubLink: githubLink, + verified: false + }); + pairedWith.save(function (err, paired) { + if (err) { + return next(err); + } + if (user && paired) { + return res.sendStatus(200); + } + }); + }); + } + }); + } else { + + req.user.completedCoursewares.push({ + _id: coursewareHash, + name: req.body.coursewareInfo.coursewareName, + completedWith: null, + completedDate: isCompletedDate, + solution: solutionLink, + githubLink: githubLink, + verified: false + }); + + var index = req.user.uncompletedCoursewares.indexOf(coursewareHash); + if (index > -1) { + req.user.progressTimestamps.push(Date.now() || 0); + req.user.uncompletedCoursewares.splice(index, 1); + } + + req.user.save(function (err, user) { + if (err) { + return next(err); + } + if (user) { + return res.sendStatus(200); + } + }); + } +}; + /* challengeBlock { 0: { diff --git a/controllers/resources.js b/controllers/resources.js index b286a394ec..21a6d20f16 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -28,7 +28,8 @@ var async = require('async'), */ var allBonfireIds, allBonfireNames, allCoursewareIds, allCoursewareNames, allFieldGuideIds, allFieldGuideNames, allNonprofitNames, - allBonfireIndexesAndNames, challengeMap; + allBonfireIndexesAndNames, challengeMap, challengeMapWithIds, + challengeMapWithNames, allChallengeIds; /** * GET / @@ -46,55 +47,73 @@ Array.zip = function(left, right, combinerFunction) { return results; }; -buildChallengeMap = function() { - challengeMap = {}; - fs.readdir(__dirname + '../seed_data/challenges', function(err, files) { - if (err) { - debug(err); - } else { - var keyCounter = 0; - files = files.sort(function(a, b) { - return a.order < b.order ? a : b; - }); - files.forEach(function(file) { - challengeMap[keyCounter++] = file; - }); - } - }); -}; +(function() { + if (!challengeMap) { + var localChallengeMap = {}; + var files = fs.readdirSync(__dirname + '/../seed_data/challenges'); + var keyCounter = 0; + files = files.map(function (file) { + return require(__dirname + + '/../seed_data/challenges/' + file); + }); + files = files.sort(function (a, b) { + return a.order - b.order; + }); + files.forEach(function (file) { + localChallengeMap[keyCounter++] = file; + }); + challengeMap = _.cloneDeep(localChallengeMap); + } +})(); + module.exports = { getChallengeMapWithIds: function() { - // TODO finish this - if (challengeMap === null) { - buildChallengeMap(); - } - var challengeMapWithIds = {}; - Object.keys(challengeMap). - forEach(function(key) { - var onlyIds = challengeMap[key].challenges.map(function(elem) { - return elem.challengeId; + if (challengeMapWithIds) { + return challengeMapWithIds; + } else { + challengeMapWithIds = {}; + Object.keys(challengeMap).forEach(function (key) { + var onlyIds = challengeMap[key].challenges.map(function (elem) { + return elem._id; }); challengeMapWithIds[key] = onlyIds; }); - return challengeMapWithIds; + return challengeMapWithIds; + } + }, + + allChallengeIds: function() { + + if (allChallengeIds) { + return allChallengeIds; + } else { + allChallengeIds = []; + Object.keys(challengeMapWithIds).forEach(function(key) { + allChallengeIds.push(challengeMapWithIds[key].challenges); + }); + allChallengeIds = R.flatten(allChallengeIds); + } + return allChallengeIds; }, getChallengeMapWithNames: function() { - var challengeMapWithNames = {}; - Object.keys(challengeMap). - forEach(function(key) { - var onlyNames = challengeMap[key].challenges.map(function(elem) { - return elem.challengeName; + if (challengeMapWithNames) { + return challengeMapWithNames; + } else { + challengeMapWithNames = {}; + Object.keys(challengeMap). + forEach(function (key) { + var onlyNames = challengeMap[key].challenges.map(function (elem) { + return elem.name; + }); + challengeMapWithNames[key] = onlyNames; }); - challengeMapWithNames[key] = onlyNames; - }); - return challengeMapWithNames; + return challengeMapWithNames; + } }, - - sitemap: function sitemap(req, res, next) { var appUrl = 'http://www.freecodecamp.com'; var now = moment(new Date()).format('YYYY-MM-DD'); diff --git a/models/User.js b/models/User.js index 686468c8d7..6ddc3f7112 100644 --- a/models/User.js +++ b/models/User.js @@ -150,7 +150,19 @@ var userSchema = new mongoose.Schema({ finishedWaypoints: { type: Boolean, default: false }, sendMonthlyEmail: { type: Boolean, default: true }, challengesHash: {}, - currentChallenge: {} + currentChallenge: {}, + completedChallenges: [ + { + completedDate: Long, + _id: String, + name: String, + completedWith: String, + solution: String, + githubLink: String, + verified: Boolean + } + ], + uncompletedChallenges: Array }); /** diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js index d32e54428e..2534a2456a 100644 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js +++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js @@ -1,69 +1,69 @@ var widgets = []; var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { - lineNumbers: true, - mode: "javascript", - theme: 'monokai', - runnable: true, - lint: true, - matchBrackets: true, - autoCloseBrackets: true, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ["CodeMirror-lint-markers"], - onKeyEvent: doLinting + lineNumbers: true, + mode: "javascript", + theme: 'monokai', + runnable: true, + lint: true, + matchBrackets: true, + autoCloseBrackets: true, + scrollbarStyle: 'null', + lineWrapping: true, + gutters: ["CodeMirror-lint-markers"], + onKeyEvent: doLinting }); var editor = myCodeMirror; editor.setSize("100%", "auto"); // Hijack tab key to enter two spaces intead editor.setOption("extraKeys", { - Tab: function(cm) { - if (cm.somethingSelected()){ - cm.indentSelection("add"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Shift-Tab": function(cm) { - if (cm.somethingSelected()){ - cm.indentSelection("subtract"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Ctrl-Enter": function() { - bonfireExecute(); - return false; + Tab: function(cm) { + if (cm.somethingSelected()){ + cm.indentSelection("add"); + } else { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); } + }, + "Shift-Tab": function(cm) { + if (cm.somethingSelected()){ + cm.indentSelection("subtract"); + } else { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); + } + }, + "Ctrl-Enter": function() { + bonfireExecute(); + return false; + } }); var attempts = 0; if (attempts) { - attempts = 0; + attempts = 0; } var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), { - lineNumbers: false, - mode: "text", - theme: 'monokai', - readOnly: 'nocursor', - lineWrapping: true + lineNumbers: false, + mode: "text", + theme: 'monokai', + readOnly: 'nocursor', + lineWrapping: true }); codeOutput.setValue('/**\n' + -' * Your output will go here.\n' + ' * Console.log() -type statements\n' + -' * will appear in your browser\'s\n' + ' * DevTools JavaScript console.\n' + -' */'); + ' * Your output will go here.\n' + ' * Console.log() -type statements\n' + + ' * will appear in your browser\'s\n' + ' * DevTools JavaScript console.\n' + + ' */'); codeOutput.setSize("100%", "100%"); var info = editor.getScrollInfo(); var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top; if (info.top + info.clientHeight < after) - editor.scrollTo(null, after - info.clientHeight + 3); + editor.scrollTo(null, after - info.clientHeight + 3); var editorValue; @@ -73,9 +73,9 @@ var tests = tests || []; var allSeeds = ''; (function() { - challengeSeed.forEach(function(elem) { - allSeeds += elem + '\n'; - }); + challengeSeed.forEach(function(elem) { + allSeeds += elem + '\n'; + }); })(); editorValue = allSeeds; @@ -84,52 +84,52 @@ editorValue = allSeeds; myCodeMirror.setValue(editorValue); function doLinting () { - editor.operation(function () { - for (var i = 0; i < widgets.length; ++i) - editor.removeLineWidget(widgets[i]); - widgets.length = 0; - JSHINT(editor.getValue()); - for (var i = 0; i < JSHINT.errors.length; ++i) { - var err = JSHINT.errors[i]; - if (!err) continue; - var msg = document.createElement("div"); - var icon = msg.appendChild(document.createElement("span")); - icon.innerHTML = "!!"; - icon.className = "lint-error-icon"; - msg.appendChild(document.createTextNode(err.reason)); - msg.className = "lint-error"; - widgets.push(editor.addLineWidget(err.line - 1, msg, { - coverGutter: false, - noHScroll: true - })); - } - }); + editor.operation(function () { + for (var i = 0; i < widgets.length; ++i) + editor.removeLineWidget(widgets[i]); + widgets.length = 0; + JSHINT(editor.getValue()); + for (var i = 0; i < JSHINT.errors.length; ++i) { + var err = JSHINT.errors[i]; + if (!err) continue; + var msg = document.createElement("div"); + var icon = msg.appendChild(document.createElement("span")); + icon.innerHTML = "!!"; + icon.className = "lint-error-icon"; + msg.appendChild(document.createTextNode(err.reason)); + msg.className = "lint-error"; + widgets.push(editor.addLineWidget(err.line - 1, msg, { + coverGutter: false, + noHScroll: true + })); + } + }); }; $('#submitButton').on('click', function () { - bonfireExecute(); + bonfireExecute(); }); function bonfireExecute() { - attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challengeName); - userTests= null; - $('#codeOutput').empty(); - var userJavaScript = myCodeMirror.getValue(); - userJavaScript = removeComments(userJavaScript); - userJavaScript = scrapeTests(userJavaScript); - // simple fix in case the user forgets to invoke their function + attempts++; + ga('send', 'event', 'Challenge', 'ran-code', challengeName); + userTests= null; + $('#codeOutput').empty(); + var userJavaScript = myCodeMirror.getValue(); + userJavaScript = removeComments(userJavaScript); + userJavaScript = scrapeTests(userJavaScript); + // simple fix in case the user forgets to invoke their function - submit(userJavaScript, function(cls, message) { - if (cls) { - codeOutput.setValue(message.error); - runTests('Error', null); - } else { - codeOutput.setValue(message.output); - message.input = removeLogs(message.input); - runTests(null, message); - } - }); + submit(userJavaScript, function(cls, message) { + if (cls) { + codeOutput.setValue(message.error); + runTests('Error', null); + } else { + codeOutput.setValue(message.output); + message.input = removeLogs(message.input); + runTests(null, message); + } + }); } @@ -139,108 +139,108 @@ var testSalt = Math.random(); var scrapeTests = function(userJavaScript) { - // insert tests from mongo - for (var i = 0; i < tests.length; i++) { - userJavaScript += '\n' + tests[i]; + // insert tests from mongo + for (var i = 0; i < tests.length; i++) { + userJavaScript += '\n' + tests[i]; + } + + var counter = 0; + var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/); + var match = regex.exec(userJavaScript); + while (match != null) { + var replacement = '//' + counter + testSalt; + userJavaScript = userJavaScript.substring(0, match.index) + replacement + userJavaScript.substring(match.index + match[0].length); + + if (!userTests) { + userTests= []; } + userTests.push({"text": match[0], "line": counter, "err": null}); + counter++; + match = regex.exec(userJavaScript); + } - var counter = 0; - var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/); - var match = regex.exec(userJavaScript); - while (match != null) { - var replacement = '//' + counter + testSalt; - userJavaScript = userJavaScript.substring(0, match.index) + replacement + userJavaScript.substring(match.index + match[0].length); - - if (!userTests) { - userTests= []; - } - userTests.push({"text": match[0], "line": counter, "err": null}); - counter++; - match = regex.exec(userJavaScript); - } - - return userJavaScript; + return userJavaScript; }; function removeComments(userJavaScript) { - var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g); - return userJavaScript.replace(regex, ''); + var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g); + return userJavaScript.replace(regex, ''); } function removeLogs(userJavaScript) { - return userJavaScript.replace(/(console\.[\w]+\s*\(.*\;)/g, ''); + return userJavaScript.replace(/(console\.[\w]+\s*\(.*\;)/g, ''); } var pushed = false; var createTestDisplay = function() { - if (pushed) { - userTests.pop(); + if (pushed) { + userTests.pop(); + } + for (var i = 0; i < userTests.length;i++) { + var test = userTests[i]; + var testDoc = document.createElement("div"); + if (test.err != null) { + console.log('Should be displaying bad tests'); + $(testDoc) + .html("
        " + test.text + "
        " + test.err + "
        ") + .prependTo($('#testSuite')) + } else { + $(testDoc) + .html("
        " + test.text + "
        ") + .appendTo($('#testSuite')); } - for (var i = 0; i < userTests.length;i++) { - var test = userTests[i]; - var testDoc = document.createElement("div"); - if (test.err != null) { - console.log('Should be displaying bad tests'); - $(testDoc) - .html("
        " + test.text + "
        " + test.err + "
        ") - .prependTo($('#testSuite')) - } else { - $(testDoc) - .html("
        " + test.text + "
        ") - .appendTo($('#testSuite')); - } - }; + }; }; var expect = chai.expect; var reassembleTest = function(test, data) { - var lineNum = test.line; - var regexp = new RegExp("\/\/" + lineNum + testSalt); - return data.input.replace(regexp, test.text); + var lineNum = test.line; + var regexp = new RegExp("\/\/" + lineNum + testSalt); + return data.input.replace(regexp, test.text); }; var runTests = function(err, data) { - var allTestsPassed = true; - pushed = false; - $('#testSuite').children().remove(); - if (err && userTests.length > 0) { - userTests= [{text:"Program Execution Failure", err: "No user tests were run."}]; - createTestDisplay(); - } else if (userTests) { - userTests.push(false); - pushed = true; - userTests.forEach(function(test, ix, arr){ - try { - if (test) { - var output = eval(reassembleTest(test, data)); - } - } catch(error) { - allTestsPassed = false; - arr[ix].err = error.message; - } finally { - if (!test) { - createTestDisplay(); - } - } - }); - - if (allTestsPassed) { - allTestsPassed = false; - showCompletion(); + var allTestsPassed = true; + pushed = false; + $('#testSuite').children().remove(); + if (err && userTests.length > 0) { + userTests= [{text:"Program Execution Failure", err: "No user tests were run."}]; + createTestDisplay(); + } else if (userTests) { + userTests.push(false); + pushed = true; + userTests.forEach(function(test, ix, arr){ + try { + if (test) { + var output = eval(reassembleTest(test, data)); } + } catch(error) { + allTestsPassed = false; + arr[ix].err = error.message; + } finally { + if (!test) { + createTestDisplay(); + } + } + }); + if (allTestsPassed) { + allTestsPassed = false; + showCompletion(); } + + } }; function showCompletion() { - var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challengeName + ', Time: ' + time +', Attempts: ' + attempts); - $('#complete-courseware-dialog').modal('show'); - $('#complete-courseware-dialog').keydown(function(e) { - if (e.ctrlKey && e.keyCode == 13) { - $('#next-courseware-button').click(); - } - }); + var time = Math.floor(Date.now()) - started; + ga('send', 'event', 'Challenge', 'solved', challengeName + ', Time: ' + time +', Attempts: ' + attempts); + $('#complete-courseware-dialog').modal('show'); + $('#complete-courseware-dialog').keydown(function(e) { + if (e.ctrlKey && e.keyCode == 13) { + $('#next-courseware-button').click(); + } + }); } diff --git a/public/js/main.js b/public/js/main.js index d763e733a2..05136f74ca 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -127,16 +127,16 @@ $(document).ready(function() { case 1: case 2: $.post( - '/completed-courseware/', + '/completed-challenge/', { - coursewareInfo: { - coursewareHash: passedCoursewareHash, - coursewareName: passedCoursewareName + challengeInfo: { + challengeId: challengeId, + challengeName: challengeName } }).success( function(res) { if (res) { - window.location.href = '/challenges'; + window.location.href = '/challenges/next-challenge'; } } ); @@ -147,16 +147,16 @@ $(document).ready(function() { $.post( '/completed-zipline-or-basejump/', { - coursewareInfo: { - coursewareHash: passedCoursewareHash, - coursewareName: passedCoursewareName, + challengeInfo: { + challengeId: challengeId, + challengeName: challengeName, completedWith: didCompleteWith, publicURL: publicURL, challengeType: challengeType } }).success( function() { - window.location.href = '/challenges'; + window.location.href = '/challenges/next-challenge'; }).fail( function() { window.location.href = '/challenges'; @@ -169,9 +169,9 @@ $(document).ready(function() { $.post( '/completed-zipline-or-basejump/', { - coursewareInfo: { - coursewareHash: passedCoursewareHash, - coursewareName: passedCoursewareName, + challengeInfo: { + challengeId: challengeId, + challengeName: challengeName, completedWith: didCompleteWith, publicURL: publicURL, githubURL: githubURL, @@ -179,7 +179,7 @@ $(document).ready(function() { verified: false } }).success(function() { - window.location.href = '/challenges'; + window.location.href = '/challenges/next-challenge'; }).fail(function() { window.location.replace(window.location.href); }); diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json index 274d64485b..0e30ebd275 100644 --- a/seed_data/challenges/basic-html5-and-css.json +++ b/seed_data/challenges/basic-html5-and-css.json @@ -20,7 +20,8 @@ ], "challengeSeed": [ "

        Hello

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf0887a", @@ -38,7 +39,8 @@ ], "challengeSeed": [ "

        Hello World

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08801", @@ -55,7 +57,8 @@ "challengeSeed": [ "

        Hello World

        ", "

        CatPhotoApp

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aeaf08801", @@ -74,7 +77,8 @@ "

        Hello World

        ", "

        CatPhotoApp

        ", "

        Hello Paragraph

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08802", @@ -101,7 +105,8 @@ "", "

        Hello Paragraph

        ", "-->" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08804", @@ -127,7 +132,8 @@ "", "

        Hello Paragraph

        ", "-->" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08833", @@ -151,7 +157,8 @@ "
        ", "", "

        Hello Paragraph

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fed1348bd9aedf08833", @@ -176,7 +183,8 @@ "
        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08803", @@ -195,7 +203,8 @@ "

        CatPhotoApp

        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08805", @@ -218,7 +227,8 @@ "

        CatPhotoApp

        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aecf08806", @@ -248,7 +258,8 @@ "

        CatPhotoApp

        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aefe08806", @@ -274,7 +285,8 @@ "

        CatPhotoApp

        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08806", @@ -300,7 +312,8 @@ "

        CatPhotoApp

        ", "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aede08807", @@ -329,7 +342,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08807", @@ -361,7 +375,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08808", @@ -399,7 +414,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08809", @@ -440,7 +456,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { @@ -478,7 +495,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9acdf08812", @@ -516,7 +534,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9bedf08813", @@ -559,7 +578,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08814", @@ -607,7 +627,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08815", @@ -654,7 +675,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08816", @@ -704,7 +726,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aede08817", @@ -757,7 +780,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { @@ -809,7 +833,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08820", @@ -861,7 +886,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08818", @@ -913,7 +939,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { @@ -966,7 +993,8 @@ "", "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] + ], + "challengeType": 0 }, { @@ -1025,7 +1053,8 @@ "
      3. laser pointers
      4. ", "
      5. lasagna
      6. ", "" - ] + ], + "challengeType": 0 }, { @@ -1086,7 +1115,8 @@ "
      7. thunder
      8. ", "
      9. other cats
      10. ", "
      " - ] + ], + "challengeType": 0 }, { @@ -1148,7 +1178,8 @@ "
    2. other cats
    3. ", "
    ", "" - ] + ], + "challengeType": 0 }, { @@ -1211,7 +1242,8 @@ "
  3. other cats
  4. ", "
", "" - ] + ], + "challengeType": 0 }, { @@ -1275,7 +1307,8 @@ "
", " ", "
" - ] + ], + "challengeType": 0 }, { @@ -1411,7 +1444,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -1479,7 +1513,8 @@ " ", " ", "" - ] + ], + "challengeType" : 0 }, { @@ -1548,7 +1583,8 @@ " ", " ", "" - ] + ], + "challengeType" : 0 }, { @@ -1620,7 +1656,8 @@ " ", " ", "" - ] + ], + "challengeType" : 0 } ] } diff --git a/seed_data/seed.js b/seed_data/seed.js index fc87f56d02..600ea5e77a 100644 --- a/seed_data/seed.js +++ b/seed_data/seed.js @@ -32,11 +32,12 @@ Challenge.remove({}, function(err, data) { console.log('Deleted ', data); } challenges.forEach(function (file) { - Challenge.create(require('./challenges/' + file), function (err, data) { + Challenge.create(require('./challenges/' + file).challenges, function (err, data) { if (err) { console.log(err); } else { console.log('Successfully parsed %s', file); + console.log(data); } }); }); diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 053d22e12e..73ece748e7 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -29,9 +29,8 @@ block content .button-spacer script(type="text/javascript"). var tests = !{JSON.stringify(tests)}; - var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; + var challengeId = !{JSON.stringify(coursewareHash)}; var challengeName = !{JSON.stringify(name)}; - var passedCoursewareName = challengeName; var started = Math.floor(Date.now()); var challengeType = !{JSON.stringify(challengeType)}; var controlEnterHandler = function(e) { diff --git a/views/partials/navbar.jade b/views/partials/navbar.jade index 7f09909b4b..957ef9f666 100644 --- a/views/partials/navbar.jade +++ b/views/partials/navbar.jade @@ -15,7 +15,7 @@ nav.navbar.navbar-default.navbar-fixed-top.nav-height if user li - a(href='/challenges') Next Challenge + a(href='/challenges') Current Challenge li a(href='/map') Map if (user && user.sentSlackInvite) From 56bae0ca98a84d2575a369773dc6a18adb62bf3f Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 00:38:25 -0400 Subject: [PATCH 26/81] Users can now jump around and continue a linear progression through challenges. Added getstuff for easy debugging --- controllers/challenge.js | 81 +++++++++++++++++---------------- controllers/resources.js | 2 +- views/coursewares/getstuff.jade | 9 ++++ views/coursewares/showHTML.jade | 3 +- 4 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 views/coursewares/getstuff.jade diff --git a/controllers/challenge.js b/controllers/challenge.js index 3894006e96..989d7d7970 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -41,7 +41,10 @@ exports.showAllChallenges = function(req, res) { }; exports.getStuff = function(req, res, next) { - res.send({withNames: challengeMapWithNames, withIds: challengeMapWithIds}); + res.render('coursewares/getstuff', { + stuff: resources.allChallengeIds(), + stuffWithIds: challengeMapWithIds + }); }; exports.returnNextChallenge = function(req, res, next) { @@ -68,58 +71,52 @@ exports.returnNextChallenge = function(req, res, next) { var nextChallengeId; var nextChallengeBlock; - var challengeId = req.user.currentChallenge.challengeId; + var challengeId = String(req.user.currentChallenge.challengeId); var challengeBlock = req.user.currentChallenge.challengeBlock; - debug('this is the user challenge block', challengeBlock); var indexOfChallenge = challengeMapWithIds[challengeBlock] .indexOf(challengeId); - debug('Logging first two challenge blocks for sanity', challengeMapWithIds[0], challengeMapWithIds[1]); - - - debug('these are the damn keys on challengeMapWithIds...', Object.keys(challengeMapWithIds)); if (indexOfChallenge + 1 < challengeMapWithIds[challengeBlock].length) { - debug('advancing to next challange in current block'); + debug('this is index', indexOfChallenge); + debug('current block advance'); + debug(challengeMapWithNames[challengeBlock][+indexOfChallenge + 1]) nextChallengeName = - challengeMapWithNames[challengeBlock][indexOfChallenge + 1]; - nextChallengeId = challengeMapWithIds[challengeBlock][indexOfChallenge + 1]; - nextChallengeBlock = challengeBlock; + challengeMapWithNames[challengeBlock][++indexOfChallenge]; } else if (typeof challengeMapWithIds[++challengeBlock] !== 'undefined') { - debug('Advancing to next block'); + debug('next block advance'); nextChallengeName = R.head(challengeMapWithNames[challengeBlock]); - nextChallengeId = R.head(challengeMapWithNames[challengeBlock]); - nextChallengeBlock = challengeBlock; } else { - debug('completed all challenges'); + debug('finished, no advance'); req.flash('errors', { msg: 'It looks like you have finished all of our challenges.' + ' Great job! Now on to helping nonprofits!' }); nextChallengeName = R.head(challengeMapWithNames[0].challenges); - nextChallengeId = R.head(challengeMapWithNames[0].challenges); - nextChallengeBlock = 0; } - req.user.currentChallenge = { - challengeId: nextChallengeId, - challengeName: nextChallengeName, - challengeBlock: nextChallengeBlock - }; - req.user.save(); + + debug('Should be sending user to challenge %s', nextChallengeName); var nameString = nextChallengeName.trim() .toLowerCase() - .replace(/[^\w\s]/g, '') .replace(/\s/g, '-') - debug('this is the namestring we\'re going to look up', nameString); return res.redirect('../challenges/' + nameString); }; exports.returnCurrentChallenge = function(req, res, next) { - debug('these are the damn keys on challengeMapWithIds...', Object.keys(challengeMapWithIds)); - debug('sanity check', challengeMapWithIds[0], challengeMapWithIds[1]); if (!req.user) { return res.redirect('../challenges/learn-how-free-code-camp-works'); } + var completed = req.user.completedChallenges.map(function (elem) { + return elem._id; + }); + + req.user.uncompletedChallenges = resources.allChallengeIds() + .filter(function (elem) { + if (completed.indexOf(elem) === -1) { + return elem; + } + }); + req.user.save(); if (!req.user.currentChallenge) { req.user.currentChallenge = {}; req.user.currentChallenge.challengeId = challengeMapWithIds['0'][0]; @@ -130,17 +127,15 @@ exports.returnCurrentChallenge = function(req, res, next) { } var nameString = req.user.currentChallenge.challengeName.trim() .toLowerCase() - .replace(/[^\w\s]/g, '') .replace(/\s/g, '-'); - debug('this is the namestring we\'re going to look up', nameString); return res.redirect('../challenges/' + nameString); }; exports.returnIndividualChallenge = function(req, res, next) { + debug('this is the user\'s current challenge info', req.user.currentChallenge); var dashedName = req.params.challengeName; var challengeName = dashedName.replace(/\-/g, ' '); - debug('looking for %s', challengeName); Challenge.find({'name': new RegExp(challengeName, 'i')}, function(err, challengeFromMongo) { @@ -149,7 +144,6 @@ exports.returnIndividualChallenge = function(req, res, next) { } // Handle not found if (challengeFromMongo.length < 1) { - debug(challengeFromMongo); req.flash('errors', { msg: '404: We couldn\'t find a challenge with that name. ' + 'Please double check the name.' @@ -157,13 +151,28 @@ exports.returnIndividualChallenge = function(req, res, next) { return res.redirect('/challenges'); } var challenge = challengeFromMongo.pop(); - debug(challenge); // Redirect to full name if the user only entered a partial var dashedNameFull = challenge.name.toLowerCase().replace(/\s/g, '-'); if (dashedNameFull !== dashedName) { return res.redirect('../challenges/' + dashedNameFull); + } else { + req.user.currentChallenge = { + challengeId: challenge._id, + challengeName: challenge.name, + challengeBlock: R.head(R.flatten(Object.keys(challengeMapWithIds). + map(function(key) { + return challengeMapWithIds[key] + .filter(function(elem) { + return String(elem) === String(challenge._id); + }).map(function() { + return key; + }); + }) + )) + }; } + req.user.save(); var challengeType = { 0: function() { @@ -289,8 +298,7 @@ exports.completedChallenge = function (req, res, next) { }; exports.completedZiplineOrBasejump = function (req, res, next) { - debug('Inside controller for completed zipline or basejump with data %s', - req.body.coursewareInfo); + var isCompletedWith = req.body.coursewareInfo.completedWith || false; var isCompletedDate = Math.round(+new Date()); var coursewareHash = req.body.coursewareInfo.coursewareHash; @@ -332,10 +340,7 @@ exports.completedZiplineOrBasejump = function (req, res, next) { if (err) { return next(err); } - debug('this is the user object returned %s,' + - ' this is the req.user._id %s, ' + - 'this is the pairedWith._id %s', user, req.user._id, pairedWith._id); - debug(req.user._id.toString() === pairedWith._id.toString()); + if (req.user._id.toString() === pairedWith._id.toString()) { return res.sendStatus(200); } diff --git a/controllers/resources.js b/controllers/resources.js index 21a6d20f16..c8f62c679e 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -91,7 +91,7 @@ module.exports = { } else { allChallengeIds = []; Object.keys(challengeMapWithIds).forEach(function(key) { - allChallengeIds.push(challengeMapWithIds[key].challenges); + allChallengeIds.push(challengeMapWithIds[key]); }); allChallengeIds = R.flatten(allChallengeIds); } diff --git a/views/coursewares/getstuff.jade b/views/coursewares/getstuff.jade new file mode 100644 index 0000000000..6645059ee2 --- /dev/null +++ b/views/coursewares/getstuff.jade @@ -0,0 +1,9 @@ +// + Created by nathanleniz on 5/19/15. + +extends ../layout-wide +block content + script. + var stuff = !{JSON.stringify(stuff)}; + var challengeMapWithIds = !{JSON.stringify(stuffWithIds)}; + diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 2ca19662a0..79de8bf60c 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -56,9 +56,8 @@ block content $('#next-courseware-button').attr('disabled', 'disabled'); var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; + var challengeId = !{JSON.stringify(coursewareHash)}; var challengeName = !{JSON.stringify(name)}; - var passedCoursewareName = challengeName; var prodOrDev = !{JSON.stringify(environment)}; var challengeType = !{JSON.stringify(challengeType)}; var started = Math.floor(Date.now()); From 7b9faabd325d82c20ce90060d69622d085e98bd6 Mon Sep 17 00:00:00 2001 From: LumenTeun Date: Wed, 20 May 2015 16:29:05 +0200 Subject: [PATCH 27/81] Github => GitHub --- public/js/lib/codemirror/doc/releases.html | 2 +- seed_data/coursewares.json | 32 +++++++++++----------- views/account/account.jade | 2 +- views/partials/footer.jade | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/public/js/lib/codemirror/doc/releases.html b/public/js/lib/codemirror/doc/releases.html index bf26f00b92..2edd4885ac 100644 --- a/public/js/lib/codemirror/doc/releases.html +++ b/public/js/lib/codemirror/doc/releases.html @@ -723,7 +723,7 @@
  • Add support for line wrapping and code folding.
  • -
  • Add Github-style Markdown mode.
  • +
  • Add GitHub-style Markdown mode.
  • Add Monokai and Rubyblue themes.
  • Add setBookmark method.
  • diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index fffdab5fbb..e36b3476da 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -77,7 +77,7 @@ "To see your portfolio page, click your picture in the upper right hand corner.", "Your portfolio page will automatically show off your progress through Free Code Camp.", "Click the \"Update my portfolio page or manage my account\" button", - "You can link to your Github, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", + "You can link to your GitHub, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", "Be sure to click the \"Update my Bio\" or \"Update my Social Links\" button to save this new information to your portfolio page.", "Once you're happy with your portfolio page, you can move on to your next challenge." ], @@ -893,19 +893,19 @@ "Start the application by running the following command in your new terminal window: grunt serve", "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", - "Create a new Github repository by signing in to http://github.com and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", + "Create a new GitHub repository by signing in to http://github.com and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", "Enter a project name, then click the \"Create Repository\" button.", "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", - "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to Github.", - "Check back on your Github profile to verify the changes were successfully pushed up to Github.", + "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to GitHub.", + "Check back on your GitHub profile to verify the changes were successfully pushed up to GitHub.", "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.", "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c hotkey to shut down these processes.", "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login. At this point, the terminal will prompt you to log in to Heroku from the command line.", "Now run yo angular-fullstack:heroku. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab.", "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace directory by running cd ~/workspace. Then you can this code to stage the changes to your changes and commit them: git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." ], "challengeType": 4, "tests": [] @@ -919,7 +919,7 @@ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://voteplex.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an authenticated user, I can keep my polls and come back later to access them.", "User Story: As an authenticated user, I can share my polls with my friends.", @@ -929,7 +929,7 @@ "Bonus User Story: As an unauthenticated user, I can see everyone's polls, but I can't vote on anything.", "Bonus User Story: As an unauthenticated or authenticated user, I can see the results of polls in chart form. (This could be implemented using Chart.js or Google Charts.)", "Bonus User Story: As an authenticated user, if I don't like the options on a poll, I can create a new option.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -944,13 +944,13 @@ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://sociallife.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an unauthenticated user, I can view all bars in my area.", "User Story: As an authenticated user, I can add myself to a bar to indicate I am going there tonight.", "User Story: As an authenticated user, I can remove myself from a bar if I no longer want to go there.", "Bonus User Story: As an unauthenticated user, when I login I should not have to search again.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -965,13 +965,13 @@ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockjump.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As a user, I can view a graph displaying the recent trend lines for each added stock.", "User Story: As a user, I can add new stocks by their symbol name.", "User Story: As a user, I can remove stocks.", "Bonus User Story: As a user, I can see changes in real-time when any other user adds or removes a stock.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -986,13 +986,13 @@ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookoutpost.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an authenticated user, I can view all books posted by every user.", "User Story: As an authenticated user, I can add a new book.", "User Story: As an authenticated user, I can update my settings to store my full name, city, and state.", "Bonus User Story: As an authenticated user, I can propose a trade and wait for the other user to accept the trade.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -1007,7 +1007,7 @@ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://linkterest.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an unauthenticated user, I can login with Twitter.", "User Story: As an authenticated user, I can link to images.", @@ -1017,7 +1017,7 @@ "User Story: As an unauthenticated user, I can see everyone's polls, but not be able to vote.", "Bonus User Story: As an authenticated user, if I upload an image that is broken, it will be replaced by a placeholder image. (can use jQuery broken image detection)", "Hint: Masonry.js is a library that allows for Pinterest-style image grids.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, diff --git a/views/account/account.jade b/views/account/account.jade index 918531960a..3ad7a8d442 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -117,7 +117,7 @@ block content span.ion-close-circled | Your name must be fewer than 15 characters. .form-group - label.col-sm-3.col-sm-offset-2.control-label(for='email') Github + label.col-sm-3.col-sm-offset-2.control-label(for='email') GitHub .col-sm-4 input.form-control(type='url', name='githubProfile', id='githubProfile', autocomplete="off", ng-model='user.profile.githubProfile', placeholder='http://') .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.githubProfile.$error.url && !profileForm.githubProfile.$pristine") diff --git a/views/partials/footer.jade b/views/partials/footer.jade index 8fdd3f26c3..6230b178ad 100644 --- a/views/partials/footer.jade +++ b/views/partials/footer.jade @@ -1,7 +1,7 @@ .fcc-footer .col-xs-12.hidden-xs.hidden-sm a.ion-speakerphone(href='http://blog.freecodecamp.com', target='_blank')  Blog   - a.ion-social-github(href="http://github.com/freecodecamp", target='_blank')  Github   + a.ion-social-github(href="http://github.com/freecodecamp", target='_blank')  GitHub   a.ion-social-twitch-outline(href="/twitch")  Twitch  a.ion-social-facebook(href="/field-guide/how-can-i-find-other-free-code-camp-campers-in-my-city")  Facebook   a.ion-social-twitter(href="http://twitter.com/freecodecamp", target='_blank')  Twitter   From 6ba2a7ee9b5fbba549547eca420291d0b0aa0cd7 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 10:35:09 -0400 Subject: [PATCH 28/81] Rename passed variable coursewareHash to challengeId. --- controllers/challenge.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 989d7d7970..e28ca5b034 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -61,15 +61,21 @@ exports.returnNextChallenge = function(req, res, next) { return elem; } }); - req.user.save(); + // It's not important to wait for the save to finish as the updated user + // object is already in memory! We'll just check to see if there was an + // error saving and log it out to investigate in our logs. + req.user.save(function(err, data) { + if (err) { + debug('%s saving user!', err); + } + }); // find the user's current challenge and block // look in that block and find the index of their current challenge - // if index + 1 <= block.challenges.length - 1 + // if index + 1 < block.challenges.length // serve index + 1 challenge // otherwise increment block key and serve the first challenge in that block + // unless the next block is undefined, which means no next block var nextChallengeName; - var nextChallengeId; - var nextChallengeBlock; var challengeId = String(req.user.currentChallenge.challengeId); var challengeBlock = req.user.currentChallenge.challengeBlock; @@ -78,16 +84,11 @@ exports.returnNextChallenge = function(req, res, next) { if (indexOfChallenge + 1 < challengeMapWithIds[challengeBlock].length) { - debug('this is index', indexOfChallenge); - debug('current block advance'); - debug(challengeMapWithNames[challengeBlock][+indexOfChallenge + 1]) nextChallengeName = challengeMapWithNames[challengeBlock][++indexOfChallenge]; } else if (typeof challengeMapWithIds[++challengeBlock] !== 'undefined') { - debug('next block advance'); nextChallengeName = R.head(challengeMapWithNames[challengeBlock]); } else { - debug('finished, no advance'); req.flash('errors', { msg: 'It looks like you have finished all of our challenges.' + ' Great job! Now on to helping nonprofits!' @@ -95,7 +96,6 @@ exports.returnNextChallenge = function(req, res, next) { nextChallengeName = R.head(challengeMapWithNames[0].challenges); } - debug('Should be sending user to challenge %s', nextChallengeName); var nameString = nextChallengeName.trim() .toLowerCase() .replace(/\s/g, '-') @@ -132,7 +132,6 @@ exports.returnCurrentChallenge = function(req, res, next) { }; exports.returnIndividualChallenge = function(req, res, next) { - debug('this is the user\'s current challenge info', req.user.currentChallenge); var dashedName = req.params.challengeName; var challengeName = dashedName.replace(/\-/g, ' '); @@ -187,7 +186,7 @@ exports.returnIndividualChallenge = function(req, res, next) { verb: resources.randomVerb(), phrase: resources.randomPhrase(), compliment: resources.randomCompliment(), - coursewareHash: challenge._id, + challengeId: challenge._id, environment: resources.whichEnvironment(), challengeType: challenge.challengeType }); @@ -205,7 +204,7 @@ exports.returnIndividualChallenge = function(req, res, next) { verb: resources.randomVerb(), phrase: resources.randomPhrase(), compliment: resources.randomCompliment(), - coursewareHash: challenge._id, + challengeId: challenge._id, challengeType: challenge.challengeType }); }, @@ -221,7 +220,7 @@ exports.returnIndividualChallenge = function(req, res, next) { verb: resources.randomVerb(), phrase: resources.randomPhrase(), compliment: resources.randomCompliment(), - coursewareHash: challenge._id, + challengeId: challenge._id, challengeType: challenge.challengeType }); }, @@ -236,7 +235,7 @@ exports.returnIndividualChallenge = function(req, res, next) { verb: resources.randomVerb(), phrase: resources.randomPhrase(), compliment: resources.randomCompliment(), - coursewareHash: challenge._id, + challengeId: challenge._id, challengeType: challenge.challengeType }); }, @@ -251,7 +250,7 @@ exports.returnIndividualChallenge = function(req, res, next) { verb: resources.randomVerb(), phrase: resources.randomPhrase(), compliment: resources.randomCompliment(), - coursewareHash: challenge._id, + challengeId: challenge._id, challengeType: challenge.challengeType }); } From 81b2661e0ecb972d59c7eddde4f1d3eb7fdbd677 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 10:38:31 -0400 Subject: [PATCH 29/81] Rename all passedCoursewareHash variables to challengeName in relevant views. --- controllers/challenge.js | 2 +- views/coursewares/showHTML.jade | 2 +- views/coursewares/showJS.jade | 3 +-- views/coursewares/showVideo.jade | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index e28ca5b034..37618f7898 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -98,7 +98,7 @@ exports.returnNextChallenge = function(req, res, next) { var nameString = nextChallengeName.trim() .toLowerCase() - .replace(/\s/g, '-') + .replace(/\s/g, '-'); return res.redirect('../challenges/' + nameString); }; diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 79de8bf60c..c3fa9f886c 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -56,7 +56,7 @@ block content $('#next-courseware-button').attr('disabled', 'disabled'); var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var challengeId = !{JSON.stringify(coursewareHash)}; + var challengeId = !{JSON.stringify(challengeId)}; var challengeName = !{JSON.stringify(name)}; var prodOrDev = !{JSON.stringify(environment)}; var challengeType = !{JSON.stringify(challengeType)}; diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index 7e87587f93..6d5d4b65f9 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -45,10 +45,9 @@ block content script(type="text/javascript"). var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; + var challengeId = !{JSON.stringify(challengeId)}; var challengeName = !{JSON.stringify(name)}; var challengeType = !{JSON.stringify(challengeType)}; - var passedCoursewareName = challengeName; var started = Math.floor(Date.now()); .col-xs-12.col-sm-12.col-md-8 diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 73ece748e7..b0a675fc3c 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -29,7 +29,7 @@ block content .button-spacer script(type="text/javascript"). var tests = !{JSON.stringify(tests)}; - var challengeId = !{JSON.stringify(coursewareHash)}; + var challengeId = !{JSON.stringify(challengeId)}; var challengeName = !{JSON.stringify(name)}; var started = Math.floor(Date.now()); var challengeType = !{JSON.stringify(challengeType)}; From 77ddaa5b3a7d5d414579143bbb951e7b255a9d25 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 11:13:55 -0400 Subject: [PATCH 30/81] Add challenge type 5 to all bonfires --- seed_data/challenges/bonfires.json | 126 +++++++++++++++++++---------- 1 file changed, 84 insertions(+), 42 deletions(-) diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json index ad9d6c4b4e..1f26e6c533 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/bonfires.json @@ -28,7 +28,8 @@ "", "", "meetBonfire(\"You can do this!\");" - ] + ], + "challengeType": 5 }, { "_id": "a202eed8fc186c8434cb6d61", @@ -52,7 +53,8 @@ "", "reverseString('hello');" ], - "MDNlinks": ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] + "MDNlinks": ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"], + "challengeType": 5 }, { "_id": "a302f7aae1aa3152a5b413bc", @@ -77,7 +79,8 @@ "", "factorialize(5);" ], - "MDNlinks": ["Arithmetic Operators"] + "MDNlinks": ["Arithmetic Operators"], + "challengeType": 5 }, { "_id": "aaa48de84e1ecc7c742e1124", @@ -108,7 +111,8 @@ "", "palindrome(\"eye\");" ], - "MDNlinks": ["String.replace()", "String.toLowerCase()"] + "MDNlinks": ["String.replace()", "String.toLowerCase()"], + "challengeType": 5 }, { "_id": "a26cbbe9ad8655a977e1ceb5", @@ -132,7 +136,8 @@ "expect(findLongestWord('Google do a barrel roll')).to.equal(6);", "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);" ], - "MDNlinks": ["String.split()", "String.length"] + "MDNlinks": ["String.split()", "String.length"], + "challengeType": 5 }, { "_id": "ab6137d4e35944e21037b769", @@ -155,7 +160,8 @@ "expect(titleCase(\"sHoRt AnD sToUt\")).to.equal(\"Short And Stout\");", "expect(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")).to.equal(\"Here Is My Handle Here Is My Spout\");" ], - "MDNlinks": ["String.charAt()"] + "MDNlinks": ["String.charAt()"], + "challengeType": 5 }, { "_id": "a789b3483989747d63b0e427", @@ -179,7 +185,8 @@ "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", "assert(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]).should.eql([9,35,97,1000000]));" ], - "MDNlinks": ["Comparison Operators"] + "MDNlinks": ["Comparison Operators"], + "challengeType": 5 }, { "_id": "acda2fb1324d9b0fa741e6b5", @@ -203,7 +210,8 @@ "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", "assert.strictEqual(end('If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing', 'mountain'), false, 'should equal false if target does not equal end of string');" ], - "MDNlinks": ["String.substr()"] + "MDNlinks": ["String.substr()"], + "challengeType": 5 }, { "_id": "afcc8d540bea9ea2669306b6", @@ -225,7 +233,8 @@ "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", "assert.strictEqual(repeat('abc', -2), '', 'should return an empty string for negative numbers');" ], - "MDNlinks": ["Global String Object"] + "MDNlinks": ["Global String Object"], + "challengeType": 5 }, { "_id": "ac6993d51946422351508a41", @@ -248,7 +257,8 @@ "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" ], - "MDNlinks": ["String.slice()"] + "MDNlinks": ["String.slice()"], + "challengeType": 5 }, { "_id": "a9bd25c716030ec90084d8a1", @@ -270,7 +280,8 @@ "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" ], - "MDNlinks": ["Array.push()"] + "MDNlinks": ["Array.push()"], + "challengeType": 5 }, { "_id": "ab31c21b530c0dafa9e241ee", @@ -292,7 +303,8 @@ "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');" ], - "MDNlinks": ["Array.slice()", "Array.splice()"] + "MDNlinks": ["Array.slice()", "Array.splice()"], + "challengeType": 5 }, { "_id": "af2170cad53daa0770fabdea", @@ -318,7 +330,8 @@ "expect(mutation(['Mary', 'Army'])).to.be.true;", "expect(mutation(['Alien', 'line'])).to.be.true;" ], - "MDNlinks": ["Array.sort()"] + "MDNlinks": ["Array.sort()"], + "challengeType": 5 }, { "_id": "adf08ec01beb4f99fc7a68f2", @@ -341,7 +354,8 @@ "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", "assert.deepEqual(bouncer([false, null, 0]), [], 'should return empty array if all elements are falsey');" ], - "MDNlinks": ["Boolean Objects", "Array.filter()"] + "MDNlinks": ["Boolean Objects", "Array.filter()"], + "challengeType": 5 }, { "_id":"a8e512fbe388ac2f9198f0fa", @@ -363,7 +377,8 @@ "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" ], - "MDNlinks": ["Global Object", "Object.hasOwnProperty()", "Object.keys()"] + "MDNlinks": ["Global Object", "Object.hasOwnProperty()", "Object.keys()"], + "challengeType": 5 }, { "_id":"a39963a4c10bc8b4d4f06d7e", @@ -384,7 +399,8 @@ "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" ], - "MDNlinks": ["Arguments object","Array.filter()"] + "MDNlinks": ["Arguments object","Array.filter()"], + "challengeType": 5 }, { "_id": "a24c1a4622e3c05097f71d67", @@ -429,7 +445,8 @@ "expect(sumAll([5, 10])).to.equal(45);", "expect(sumAll([10, 5])).to.equal(45);" ], - "MDNlinks": ["Math.max()", "Math.min()", "Array.reduce()"] + "MDNlinks": ["Math.max()", "Math.min()", "Array.reduce()"], + "challengeType": 5 }, { "_id": "a5de63ebea8dbee56860f4f2", @@ -479,7 +496,8 @@ "", "convert(36);" ], - "MDNlinks": ["Array.splice()", "Array.indexOf()", "Array.join()"] + "MDNlinks": ["Array.splice()", "Array.indexOf()", "Array.join()"], + "challengeType": 5 }, { "_id": "a0b5010f579e69b815e7c5d6", @@ -506,7 +524,8 @@ "", "replace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" ], - "MDNlinks": ["Array.splice()", "String.replace()", "Array.join()"] + "MDNlinks": ["Array.splice()", "String.replace()", "Array.join()"], + "challengeType": 5 }, { "_id": "aa7697ea2477d1316795783b", @@ -531,7 +550,8 @@ "", "translate(\"consonant\");" ], - "MDNlinks": ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] + "MDNlinks": ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"], + "challengeType": 5 }, { "_id": "afd15382cdfb22c9efe8b7de", @@ -554,7 +574,8 @@ "", "pair(\"GCG\");" ], - "MDNlinks": ["Array.push()", "String.split()"] + "MDNlinks": ["Array.push()", "String.split()"], + "challengeType": 5 }, { "_id": "af7588ade1100bde429baf20", @@ -577,7 +598,8 @@ "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", "expect(fearNotLetter('yz')).to.be.undefined;" ], - "MDNlinks": ["String.charCodeAt()"] + "MDNlinks": ["String.charCodeAt()"], + "challengeType": 5 }, { "_id": "a77dbc43c33f39daa4429b4f", @@ -605,7 +627,8 @@ "assert.strictEqual(boo(NaN), false);", "assert.strictEqual(boo('a'), false);" ], - "MDNlinks": ["Boolean Objects"] + "MDNlinks": ["Boolean Objects"], + "challengeType": 5 }, { "_id": "a105e963526e7de52b219be9", @@ -627,7 +650,8 @@ "tests": [ "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" - ] + ], + "challengeType": 5 }, { "_id": "a6b0bb188d873cb2c8729495", @@ -648,7 +672,8 @@ "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" ], - "MDNlinks": ["RegExp"] + "MDNlinks": ["RegExp"], + "challengeType": 5 }, { "_id": "a103376db3ba46b2d50db289", @@ -672,7 +697,8 @@ "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" ], - "MDNlinks": ["RegExp", "String.replace()"] + "MDNlinks": ["RegExp", "String.replace()"], + "challengeType": 5 }, { "_id": "a5229172f011153519423690", @@ -698,7 +724,8 @@ "expect(sumFibs(75024)).to.equal(60696);", "expect(sumFibs(75025)).to.equal(135721);" ], - "MDNlinks": ["Remainder"] + "MDNlinks": ["Remainder"], + "challengeType": 5 }, { "_id": "a3bfc1673c0526e06d3ac698", @@ -720,7 +747,8 @@ "expect(sumPrimes(10)).to.be.a('number');", "expect(sumPrimes(10)).to.equal(17);", "expect(sumPrimes(977)).to.equal(73156);" - ] + ], + "challengeType": 5 }, { "_id": "ae9defd7acaf69703ab432ea", @@ -743,7 +771,8 @@ "expect(smallestCommons([1,5])).to.equal(60);", "expect(smallestCommons([5,1])).to.equal(60);", "(smallestCommons([1,13])).should.equal(360360);" - ] + ], + "challengeType": 5 }, { "_id": "a6e40f1041b06c996f7b2406", @@ -786,7 +815,8 @@ "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);" ], - "MDNlinks": ["Arguments object", "Array.shift()"] + "MDNlinks": ["Arguments object", "Array.shift()"], + "challengeType": 5 }, { "_id": "ab306dbdcc907c7ddfc30830", @@ -808,7 +838,8 @@ "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');" ], - "MDNlinks": ["Array.isArray()"] + "MDNlinks": ["Array.isArray()"], + "challengeType": 5 }, { "_id": "a8d97bd4c764e91f9d2bda01", @@ -830,7 +861,8 @@ "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" ], "MDNlinks": ["String.charCodeAt()", "String.fromCharCode()" - ] + ], + "challengeType": 5 }, { "_id" : "a3f503de51cfab748ff001aa", @@ -854,7 +886,8 @@ "expect(pairwise([1,1,1], 2)).to.equal(1);", "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", "expect(pairwise([], 100)).to.equal(0);" - ] + ], + "challengeType": 5 }, { "_id": "a10d2431ad0c6a099a4b8b52", @@ -877,7 +910,8 @@ "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" ], - "MDNlinks": ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"] + "MDNlinks": ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"], + "challengeType": 5 }, { "_id": "a97fd23d9b809dac9921074f", @@ -902,7 +936,8 @@ "expect(add(2, '3')).to.be.undefined;", "expect(add(2)([3])).to.be.undefined;" ], - "MDNlinks": ["Global Function Object", "Arguments object"] + "MDNlinks": ["Global Function Object", "Arguments object"], + "challengeType": 5 }, { "_id": "a2f1d72d9b908d0bd72bb9f6", @@ -938,7 +973,8 @@ "expect(bob.getFullName()).to.eql('George Carlin');", "bob.setFullName('Bob Ross');" ], - "MDNlinks": ["Closures", "Details of the Object Model"] + "MDNlinks": ["Closures", "Details of the Object Model"], + "challengeType": 5 }, { "_id": "af4afb223120f7348cdfc9fd", @@ -964,7 +1000,8 @@ "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" ], - "MDNlinks": ["Math.pow()"] + "MDNlinks": ["Math.pow()"], + "challengeType": 5 }, { "_id": "aff0395860f5d3034dc0bfc9", @@ -1009,7 +1046,8 @@ "", "", "telephoneCheck(\"555-555-5555\");" - ] + ], + "challengeType": 5 }, { "_id": "a3f503de51cf954ede28891d", @@ -1068,7 +1106,8 @@ "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" - ] + ], + "challengeType": 5 }, { "_id": "a56138aff60341a09ed6c480", @@ -1107,7 +1146,8 @@ "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" - ] + ], + "challengeType": 5 }, { "_id": "a7bf700cd123b9a54eef01d5", @@ -1132,7 +1172,8 @@ "expect(permAlone('abcdefa')).to.equal(3600);", "expect(permAlone('abfdefa')).to.equal(2640);", "expect(permAlone('zzzzzzzz')).to.equal(0);" - ] + ], + "challengeType": 5 }, { "_id": "a19f0fbe1872186acd434d5a", @@ -1160,7 +1201,8 @@ "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" ], - "MDNlinks": ["String.split()", "String.substr()", "parseInt()"] + "MDNlinks": ["String.split()", "String.substr()", "parseInt()"], + "challengeType": 5 } ] } From 27a14dbf0f77a4db9cc902d8e6c09d0a44a0a774 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 13:07:41 -0400 Subject: [PATCH 31/81] Create helper methods in resources. Get map view working. --- controllers/challenge.js | 4 ++ controllers/challengeMap.js | 97 ++++++++++++++++++++++++++++-------- controllers/resources.js | 31 +++++++----- views/challengeMap/show.jade | 13 +++-- 4 files changed, 108 insertions(+), 37 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 37618f7898..d6bbb42c1b 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -253,6 +253,10 @@ exports.returnIndividualChallenge = function(req, res, next) { challengeId: challenge._id, challengeType: challenge.challengeType }); + }, + + 5: function() { + // bonfire } }; diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index be7cc20eb9..7ffa2943dc 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -4,13 +4,11 @@ var async = require('async'), Story = require('./../models/Story'), Nonprofit = require('./../models/Nonprofit'), Comment = require('./../models/Comment'), - Courseware = require('./../models/Courseware'), + Challenge = require('./../models/Challenge'), resources = require('./resources'), steps = resources.steps, secrets = require('./../config/secrets'), - bonfires = require('../seed_data/bonfires.json'), nonprofits = require('../seed_data/nonprofits.json'), - coursewares = require('../seed_data/coursewares.json'), moment = require('moment'), https = require('https'), debug = require('debug')('freecc:cntr:resources'), @@ -18,38 +16,94 @@ var async = require('async'), request = require('request'), R = require('ramda'); +var challengeTypes = { + 'HTML_CSS_JQ': 0, + 'JAVASCRIPT': 1, + 'VIDEO': 2, + 'ZIPLINE': 3, + 'BASEJUMP': 4, + 'BONFIRE': 5 +}; + module.exports = { challengeMap: function challengeMap(req, res) { var completedBonfires = []; var completedList = []; if (req.user) { - completedBonfires = req.user.completedBonfires.map(function (elem) { - return elem._id; - }); + completedBonfires = req.user.completedChallenges + .filter(function (elem) { + return elem.challengeType === challengeTypes.BONFIRE; + }) + .map(function(elem) { + return elem._id; + }); } if (req.user) { - completedList = req.user.completedCoursewares.map(function (elem) { - return elem._id; - }); + completedList = req.user.completedChallenges + .filter(function (elem) { + return elem.challengeType !== challengeTypes.BONFIRE; + }); } var noDuplicateBonfires = R.uniq(completedBonfires); - var noDuplicatedCoursewares = R.uniq(completedList); + var noDuplicatedChallenges = R.uniq(completedList); - bonfireList = resources.allBonfireNames(); - completedBonfireList = noDuplicateBonfires; - coursewareList = resources.allCoursewareNames(); - completedCoursewareList = noDuplicatedCoursewares; - waypoints = coursewareList.filter(function(challenge) { - if (challenge.challengeType === 2 || challenge.challengeType === 0) { return challenge } + var completedBonfireList = noDuplicateBonfires + .map(function(bonfire) { + return bonfire._id; + }); + var challengeList = resources.allChallenges(); + var completedChallengeList = noDuplicatedChallenges + .map(function(challenge) { + return challenge._id; + }); + + var bonfireList = challengeList + .filter(function(challenge) { + return challenge.challengeType === challengeTypes.BONFIRE; + }) + .map(function(bonfire) { + return ({ + '_id': bonfire._id, + 'name': bonfire.name + }); + }); + + var waypoints = challengeList.filter(function(challenge) { + if (challenge.challengeType === challengeTypes.VIDEO + || challenge.challengeType === challengeTypes.HTML_CSS_JQ + || challenge.challengeType === challengeTypes.JAVASCRIPT) { + return challenge; + } + }).map(function(waypoint) { + return ({ + '_id': waypoint._id, + 'name': waypoint.name + }); }); - ziplines = coursewareList.filter(function(challenge) { - if (challenge.challengeType === 3) { return challenge } + + var ziplines = challengeList.filter(function(challenge) { + if (challenge.challengeType === challengeTypes.ZIPLINE) { + return challenge; + } + }).map(function(zipline) { + return ({ + '_id': zipline._id, + 'name': zipline.name + }); }); - basejumps = coursewareList.filter(function(challenge) { - if (challenge.challengeType === 4) { return challenge } + + var basejumps = challengeList.filter(function(challenge) { + if (challenge.challengeType === challengeTypes.BASEJUMP) { + return challenge; + } + }).map(function(basejump) { + return ({ + '_id': basejump._id, + 'name': basejump.name + }); }); function numberWithCommas(x) { @@ -66,6 +120,7 @@ module.exports = { debug('User err: ', err); return next(err); } + debug('Data for render is: ', completedBonfireList, completedChallengeList); res.render('challengeMap/show', { daysRunning: daysRunning, camperCount: numberWithCommas(camperCount), @@ -75,7 +130,7 @@ module.exports = { ziplines: ziplines, basejumps: basejumps, completedBonfireList: completedBonfireList, - completedCoursewareList: completedCoursewareList + completedChallengeList: completedChallengeList }); }); } diff --git a/controllers/resources.js b/controllers/resources.js index c8f62c679e..dc171d8520 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -29,7 +29,7 @@ var async = require('async'), var allBonfireIds, allBonfireNames, allCoursewareIds, allCoursewareNames, allFieldGuideIds, allFieldGuideNames, allNonprofitNames, allBonfireIndexesAndNames, challengeMap, challengeMapWithIds, - challengeMapWithNames, allChallengeIds; + challengeMapWithNames, allChallengeIds, allChallenges; /** * GET / @@ -70,9 +70,7 @@ Array.zip = function(left, right, combinerFunction) { module.exports = { getChallengeMapWithIds: function() { - if (challengeMapWithIds) { - return challengeMapWithIds; - } else { + if (!challengeMapWithIds) { challengeMapWithIds = {}; Object.keys(challengeMap).forEach(function (key) { var onlyIds = challengeMap[key].challenges.map(function (elem) { @@ -80,17 +78,15 @@ module.exports = { }); challengeMapWithIds[key] = onlyIds; }); - return challengeMapWithIds; } + return challengeMapWithIds; }, allChallengeIds: function() { - if (allChallengeIds) { - return allChallengeIds; - } else { + if (!allChallengeIds) { allChallengeIds = []; - Object.keys(challengeMapWithIds).forEach(function(key) { + Object.keys(this.getChallengeMapWithIds()).forEach(function(key) { allChallengeIds.push(challengeMapWithIds[key]); }); allChallengeIds = R.flatten(allChallengeIds); @@ -98,10 +94,19 @@ module.exports = { return allChallengeIds; }, + allChallenges: function() { + if (!allChallenges) { + allChallenges = []; + Object.keys(this.getChallengeMapWithNames()).forEach(function(key) { + allChallenges.push(challengeMap[key].challenges); + }); + allChallenges = R.flatten(allChallenges); + } + return allChallenges; + }, + getChallengeMapWithNames: function() { - if (challengeMapWithNames) { - return challengeMapWithNames; - } else { + if (!challengeMapWithNames) { challengeMapWithNames = {}; Object.keys(challengeMap). forEach(function (key) { @@ -110,8 +115,8 @@ module.exports = { }); challengeMapWithNames[key] = onlyNames; }); - return challengeMapWithNames; } + return challengeMapWithNames; }, sitemap: function sitemap(req, res, next) { diff --git a/views/challengeMap/show.jade b/views/challengeMap/show.jade index 3332d85e9c..74e3d659d8 100644 --- a/views/challengeMap/show.jade +++ b/views/challengeMap/show.jade @@ -1,5 +1,12 @@ extends ../layout block content + script. + var bonfireList = !{JSON.stringify(bonfires)}; + var waypointList = !{JSON.stringify(waypoints)}; + var ziplineList = !{JSON.stringify(ziplines)}; + var basejumpList = !{JSON.stringify(basejumps)}; + var completedBonfires = !{JSON.stringify(completedBonfireList)}; + var completedChallenges = !{JSON.stringify(completedChallengeList)}; .panel.panel-info .panel-heading.text-center h1 Challenge Map @@ -24,7 +31,7 @@ block content h3.negative-15 ol for waypoint in waypoints - if completedCoursewareList.indexOf(waypoint._id) > -1 + if completedChallengeList.indexOf(waypoint._id) > -1 .row .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center .col-xs-12.col-sm-9.col-md-10 @@ -65,7 +72,7 @@ block content h3.negative-15 ol for zipline in ziplines - if completedCoursewareList.indexOf(zipline._id) > -1 + if completedChallengeList.indexOf(zipline._id) > -1 .row .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center .col-xs-12.col-sm-9.col-md-10 @@ -85,7 +92,7 @@ block content h3.negative-15 ol for basejump in basejumps - if completedCoursewareList.indexOf(basejump._id) > -1 + if completedChallengeList.indexOf(basejump._id) > -1 .row .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center .col-xs-12.col-sm-9.col-md-10 From 16ca72f71690fe67ce7044c6bd184a3b5f9f2dcd Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Wed, 20 May 2015 21:50:31 -0400 Subject: [PATCH 32/81] Update views for new variable names. Get profile view working. Update challenge map. --- app.js | 27 +-- controllers/challenge.js | 188 +++++++++++++----- controllers/challengeMap.js | 24 +-- controllers/user.js | 4 +- models/User.js | 11 +- .../js/lib/bonfire/bonfireFramework_v0.1.3.js | 13 +- .../coursewaresHCJQFramework_0.1.1.js | 2 +- ...0.1.js => coursewaresJSFramework_0.0.2.js} | 6 +- public/js/main.js | 87 ++++---- views/account/show.jade | 2 +- views/bonfire/show.jade | 13 +- views/challengeMap/show.jade | 7 +- views/coursewares/showHTML.jade | 4 +- views/coursewares/showJS.jade | 6 +- views/coursewares/showVideo.jade | 10 +- views/coursewares/showZiplineOrBasejump.jade | 5 +- views/partials/universal-head.jade | 3 +- 17 files changed, 236 insertions(+), 176 deletions(-) rename public/js/lib/coursewares/{coursewaresJSFramework_0.0.1.js => coursewaresJSFramework_0.0.2.js} (96%) diff --git a/app.js b/app.js index b1f65d4e37..9850b756f6 100755 --- a/app.js +++ b/app.js @@ -494,35 +494,12 @@ app.get('/api/codepen/twitter/:screenName', resourcesController.codepenResources /** * Bonfire related routes */ - -app.get('/field-guide/getFieldGuideList', fieldGuideController.showAllFieldGuides); - -app.get('/playground', bonfireController.index); - -app.get('/bonfires', bonfireController.returnNextBonfire); - -app.get('/bonfire-json-generator', bonfireController.returnGenerator); - -app.post('/bonfire-json-generator', bonfireController.generateChallenge); - -app.get('/bonfire-challenge-generator', bonfireController.publicGenerator); - -app.post('/bonfire-challenge-generator', bonfireController.testBonfire); - -app.get( - '/bonfires/:bonfireName', - bonfireController.returnIndividualBonfire -); - -app.get('/bonfire', function(req, res) { - res.redirect(301, '/playground'); -}); - -app.post('/completed-bonfire/', bonfireController.completedBonfire); +app.post('/completed-bonfire/', challengeController.completedBonfire); /** * Field Guide related routes */ +app.get('/field-guide/getFieldGuideList', fieldGuideController.showAllFieldGuides); app.get('/field-guide/:fieldGuideName', diff --git a/controllers/challenge.js b/controllers/challenge.js index d6bbb42c1b..f9ca3a7ecb 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -26,10 +26,23 @@ var debug = require('debug')('freecc:cntr:courseware'), var challengeMapWithNames = resources.getChallengeMapWithNames(); var challengeMapWithIds = resources.getChallengeMapWithIds(); +function getMDNlinks(links) { + // takes in an array of links, which are strings + var populatedLinks = []; + + // for each key value, push the corresponding link from the MDNlinks object into a new array + if (links) { + links.forEach(function (value, index) { + populatedLinks.push(MDNlinks[value]); + }); + } + return populatedLinks; +} + exports.showAllChallenges = function(req, res) { var completedList = []; if (req.user) { - completedList = req.user.completedCoursewares.map(function (elem) { + completedList = req.user.completedChallenges.map(function (elem) { return elem._id; }); } @@ -150,7 +163,6 @@ exports.returnIndividualChallenge = function(req, res, next) { return res.redirect('/challenges'); } var challenge = challengeFromMongo.pop(); - // Redirect to full name if the user only entered a partial var dashedNameFull = challenge.name.toLowerCase().replace(/\s/g, '-'); if (dashedNameFull !== dashedName) { @@ -256,7 +268,25 @@ exports.returnIndividualChallenge = function(req, res, next) { }, 5: function() { - // bonfire + res.render('bonfire/show', { + completedWith: null, + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + difficulty: Math.floor(+challenge.difficulty), + brief: challenge.description.shift(), + details: challenge.description, + tests: challenge.tests, + challengeSeed: challenge.challengeSeed, + verb: resources.randomVerb(), + phrase: resources.randomPhrase(), + compliment: resources.randomCompliment(), + bonfires: challenge, + challengeId: challenge._id, + MDNkeys: challenge.MDNlinks, + MDNlinks: getMDNlinks(challenge.MDNlinks), + challengeType: challenge.challengeType + }); } }; @@ -265,8 +295,97 @@ exports.returnIndividualChallenge = function(req, res, next) { }); }; -exports.completedBonfire = function(req, res, next) { +exports.completedBonfire = function (req, res, next) { + var isCompletedWith = req.body.challengeInfo.completedWith || ''; + var isCompletedDate = Math.round(+new Date()); + var challengeId = req.body.challengeInfo.challengeId; + var isSolution = req.body.challengeInfo.solution; + var challengeName = req.body.challengeInfo.challengeName; + if (isCompletedWith) { + var paired = User.find({'profile.username': isCompletedWith + .toLowerCase()}).limit(1); + paired.exec(function (err, pairedWith) { + if (err) { + return next(err); + } else { + var index = req.user.uncompletedChallenges.indexOf(challengeId); + debug('This is the index', index); + if (index > -1) { + req.user.progressTimestamps.push(Date.now() || 0); + req.user.uncompletedChallenges.splice(index, 1); + } + pairedWith = pairedWith.pop(); + + index = pairedWith.uncompletedChallenges.indexOf(challengeId); + debug('This is the index of the search for bonfire', index); + if (index > -1) { + pairedWith.progressTimestamps.push(Date.now() || 0); + pairedWith.uncompletedChallenges.splice(index, 1); + + } + + pairedWith.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: req.user._id, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); + + req.user.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: pairedWith._id, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); + + req.user.save(function (err, user) { + if (err) { + return next(err); + } + pairedWith.save(function (err, paired) { + if (err) { + return next(err); + } + if (user && paired) { + res.send(true); + } + }); + }); + } + }); + } else { + req.user.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: null, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); + + var index = req.user.uncompletedChallenges.indexOf(challengeId); + debug('this is the challengeId we got', challengeId); + debug('This is the index of the search for bonfire', index); + if (index > -1) { + + req.user.progressTimestamps.push(Date.now() || 0); + req.user.uncompletedChallenges.splice(index, 1); + } + + req.user.save(function (err, user) { + if (err) { + return next(err); + } + if (user) { + res.send(true); + } + }); + } }; exports.completedChallenge = function (req, res, next) { @@ -274,7 +393,6 @@ exports.completedChallenge = function (req, res, next) { var isCompletedDate = Math.round(+new Date()); var challengeId = req.body.challengeInfo.challengeId; - req.user.completedChallenges.push({ _id: challengeId, completedDate: isCompletedDate, @@ -302,12 +420,12 @@ exports.completedChallenge = function (req, res, next) { exports.completedZiplineOrBasejump = function (req, res, next) { - var isCompletedWith = req.body.coursewareInfo.completedWith || false; + var isCompletedWith = req.body.challengeInfo.completedWith || false; var isCompletedDate = Math.round(+new Date()); - var coursewareHash = req.body.coursewareInfo.coursewareHash; - var solutionLink = req.body.coursewareInfo.publicURL; - var githubLink = req.body.coursewareInfo.challengeType === '4' - ? req.body.coursewareInfo.githubURL : true; + var challengeId = req.body.challengeInfo.challengeId; + var solutionLink = req.body.challengeInfo.publicURL; + var githubLink = req.body.challengeInfo.challengeType === '4' + ? req.body.challengeInfo.githubURL : true; if (!solutionLink || !githubLink) { req.flash('errors', { msg: 'You haven\'t supplied the necessary URLs for us to inspect ' + @@ -322,16 +440,16 @@ exports.completedZiplineOrBasejump = function (req, res, next) { if (err) { return next(err); } else { - var index = req.user.uncompletedCoursewares.indexOf(coursewareHash); + var index = req.user.uncompletedChallenges.indexOf(challengeId); if (index > -1) { req.user.progressTimestamps.push(Date.now() || 0); - req.user.uncompletedCoursewares.splice(index, 1); + req.user.uncompletedChallenges.splice(index, 1); } var pairedWith = pairedWithFromMongo.pop(); - req.user.completedCoursewares.push({ - _id: coursewareHash, - name: req.body.coursewareInfo.coursewareName, + req.user.completedChallenges.push({ + _id: challengeId, + name: req.body.challengeInfo.coursewareName, completedWith: pairedWith._id, completedDate: isCompletedDate, solution: solutionLink, @@ -347,16 +465,16 @@ exports.completedZiplineOrBasejump = function (req, res, next) { if (req.user._id.toString() === pairedWith._id.toString()) { return res.sendStatus(200); } - index = pairedWith.uncompletedCoursewares.indexOf(coursewareHash); + index = pairedWith.uncompletedChallenges.indexOf(challengeId); if (index > -1) { pairedWith.progressTimestamps.push(Date.now() || 0); - pairedWith.uncompletedCoursewares.splice(index, 1); + pairedWith.uncompletedChallenges.splice(index, 1); } - pairedWith.completedCoursewares.push({ - _id: coursewareHash, - name: req.body.coursewareInfo.coursewareName, + pairedWith.completedChallenges.push({ + _id: challengeId, + name: req.body.challengeInfo.coursewareName, completedWith: req.user._id, completedDate: isCompletedDate, solution: solutionLink, @@ -376,9 +494,9 @@ exports.completedZiplineOrBasejump = function (req, res, next) { }); } else { - req.user.completedCoursewares.push({ - _id: coursewareHash, - name: req.body.coursewareInfo.coursewareName, + req.user.completedChallenges.push({ + _id: challengeId, + name: req.body.challengeInfo.challengeName, completedWith: null, completedDate: isCompletedDate, solution: solutionLink, @@ -386,10 +504,10 @@ exports.completedZiplineOrBasejump = function (req, res, next) { verified: false }); - var index = req.user.uncompletedCoursewares.indexOf(coursewareHash); + var index = req.user.uncompletedChallenges.indexOf(challengeId); if (index > -1) { req.user.progressTimestamps.push(Date.now() || 0); - req.user.uncompletedCoursewares.splice(index, 1); + req.user.uncompletedChallenges.splice(index, 1); } req.user.save(function (err, user) { @@ -402,23 +520,3 @@ exports.completedZiplineOrBasejump = function (req, res, next) { }); } }; - -/* -challengeBlock { - 0: { - "name": "basic_html", - "challenges: [] - }, - 1: { - "name": "basic_css", - "challenges": [], - } -} - -currentChallenge{ - "challengeBlock": number, - "challengeId": _id, - "challengeName": string -} - */ - diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index 7ffa2943dc..9ffcdbfbc1 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -27,33 +27,15 @@ var challengeTypes = { module.exports = { challengeMap: function challengeMap(req, res) { - var completedBonfires = []; var completedList = []; if (req.user) { - completedBonfires = req.user.completedChallenges - .filter(function (elem) { - return elem.challengeType === challengeTypes.BONFIRE; - }) - .map(function(elem) { - return elem._id; - }); + completedList = req.user.completedChallenges; } - if (req.user) { - completedList = req.user.completedChallenges - .filter(function (elem) { - return elem.challengeType !== challengeTypes.BONFIRE; - }); - } - - var noDuplicateBonfires = R.uniq(completedBonfires); var noDuplicatedChallenges = R.uniq(completedList); - var completedBonfireList = noDuplicateBonfires - .map(function(bonfire) { - return bonfire._id; - }); + var challengeList = resources.allChallenges(); var completedChallengeList = noDuplicatedChallenges .map(function(challenge) { @@ -120,7 +102,6 @@ module.exports = { debug('User err: ', err); return next(err); } - debug('Data for render is: ', completedBonfireList, completedChallengeList); res.render('challengeMap/show', { daysRunning: daysRunning, camperCount: numberWithCommas(camperCount), @@ -129,7 +110,6 @@ module.exports = { waypoints: waypoints, ziplines: ziplines, basejumps: basejumps, - completedBonfireList: completedBonfireList, completedChallengeList: completedChallengeList }); }); diff --git a/controllers/user.js b/controllers/user.js index 3b8fdb3cbd..996d7b83c5 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -373,7 +373,9 @@ exports.returnUser = function(req, res, next) { website3Title: user.portfolio.website3Title, website3Image: user.portfolio.website3Image, challenges: challenges, - bonfires: user.completedBonfires, + bonfires: user.completedChallenges.filter(function(challenge) { + return challenge.challengeType === 5; + }), calender: data, moment: moment, longestStreak: user.longestStreak + (user.longestStreak === 1 ? " day" : " days"), diff --git a/models/User.js b/models/User.js index 6ddc3f7112..718a965c61 100644 --- a/models/User.js +++ b/models/User.js @@ -124,7 +124,10 @@ var userSchema = new mongoose.Schema({ uncompletedCoursewares: Array, completedCoursewares: [ { - completedDate: Long, + completedDate: { + type: Long, + default: Date.now() + }, _id: String, name: String, completedWith: String, @@ -159,7 +162,11 @@ var userSchema = new mongoose.Schema({ completedWith: String, solution: String, githubLink: String, - verified: Boolean + verified: Boolean, + challengeType: { + type: Number, + default: 0 + } } ], uncompletedChallenges: Array diff --git a/public/js/lib/bonfire/bonfireFramework_v0.1.3.js b/public/js/lib/bonfire/bonfireFramework_v0.1.3.js index 31fb730808..1a75971798 100644 --- a/public/js/lib/bonfire/bonfireFramework_v0.1.3.js +++ b/public/js/lib/bonfire/bonfireFramework_v0.1.3.js @@ -64,18 +64,19 @@ var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local if (info.top + info.clientHeight < after) editor.scrollTo(null, after - info.clientHeight + 3); + var editorValue; var challengeSeed = challengeSeed || null; var tests = tests || []; - -if (challengeSeed !== null) { - editorValue = challengeSeed; -} else { - editorValue = nonChallengeValue; -} +var allSeeds = ''; +(function() { + challengeSeed.forEach(function(elem) { + allSeeds += elem + '\n'; + }); +})(); myCodeMirror.setValue(editorValue); diff --git a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js index 192083f0a2..d3443ac6be 100644 --- a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js +++ b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.1.js @@ -139,7 +139,7 @@ function doLinting () { //$('#testSuite').empty(); function showCompletion() { var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challengeName + ', Time: ' + time); + ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time); $('#next-courseware-button').removeAttr('disabled'); $('#next-courseware-button').addClass('animated tada'); if (!userLoggedIn) { diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js similarity index 96% rename from public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js rename to public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js index 2534a2456a..01f09d8f19 100644 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.1.js +++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js @@ -112,7 +112,7 @@ $('#submitButton').on('click', function () { function bonfireExecute() { attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challengeName); + ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); userTests= null; $('#codeOutput').empty(); var userJavaScript = myCodeMirror.getValue(); @@ -193,6 +193,8 @@ var createTestDisplay = function() { }; var expect = chai.expect; +var assert = chai.assert; +var should = chai.should; var reassembleTest = function(test, data) { @@ -236,7 +238,7 @@ var runTests = function(err, data) { function showCompletion() { var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challengeName + ', Time: ' + time +', Attempts: ' + attempts); + ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time +', Attempts: ' + attempts); $('#complete-courseware-dialog').modal('show'); $('#complete-courseware-dialog').keydown(function(e) { if (e.ctrlKey && e.keyCode == 13) { diff --git a/public/js/main.js b/public/js/main.js index 05136f74ca..3b4e543bfe 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -47,28 +47,6 @@ $(document).ready(function() { } }); - function completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash, bonfireName) { - $('#complete-bonfire-dialog').modal('show'); - // Only post to server if there is an authenticated user - if ($('.signup-btn-nav').length < 1) { - $.post( - '/completed-bonfire', - { - bonfireInfo: { - completedWith: didCompleteWith, - solution: bonfireSolution, - bonfireHash: thisBonfireHash, - bonfireName: bonfireName - } - }, - function(res) { - if (res) { - window.location.href = '/bonfires' - } - }); - } - } - function completedFieldGuide(fieldGuideId) { if ($('.signup-btn-nav').length < 1) { $.post( @@ -86,15 +64,6 @@ $(document).ready(function() { } } - $('.next-bonfire-button').on('click', function() { - var bonfireSolution = myCodeMirror.getValue(); - var thisBonfireHash = passedBonfireHash || null; - var bonfireName = $('#bonfire-name').text(); - var didCompleteWith = $('#completed-with').val() || null; - completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash, bonfireName); - - }); - $('.next-field-guide-button').on('click', function() { var fieldGuideId = $('#fieldGuideId').text(); completedFieldGuide(fieldGuideId); @@ -112,26 +81,30 @@ $(document).ready(function() { $('#complete-zipline-or-basejump-dialog').modal('show'); }); - $('#complete-bonfire-dialog').on('hidden.bs.modal', function() { - editor.focus(); - }); - $('#complete-courseware-dialog').on('hidden.bs.modal', function() { editor.focus(); }); - + var challengeTypes = { + 'HTML_CSS_JQ': 0, + 'JAVASCRIPT': 1, + 'VIDEO': 2, + 'ZIPLINE': 3, + 'BASEJUMP': 4, + 'BONFIRE': 5 + }; $('#next-courseware-button').on('click', function() { if ($('.signup-btn-nav').length < 1) { switch (challengeType) { - case 0: - case 1: - case 2: + case challengeTypes.HTML_CSS_JQ: + case challengeTypes.JAVASCRIPT: + case challengeTypes.VIDEO: + console.log(challenge_Id); $.post( '/completed-challenge/', { challengeInfo: { - challengeId: challengeId, - challengeName: challengeName + challengeId: challenge_Id, + challengeName: challenge_Name } }).success( function(res) { @@ -141,15 +114,15 @@ $(document).ready(function() { } ); break; - case 3: + case challengeTypes.ZIPLINE: var didCompleteWith = $('#completed-with').val() || null; var publicURL = $('#public-url').val() || null; $.post( '/completed-zipline-or-basejump/', { challengeInfo: { - challengeId: challengeId, - challengeName: challengeName, + challengeId: challenge_Id, + challengeName: challenge_Name, completedWith: didCompleteWith, publicURL: publicURL, challengeType: challengeType @@ -162,7 +135,7 @@ $(document).ready(function() { window.location.href = '/challenges'; }); break; - case 4: + case challengeTypes.BASEJUMP: var didCompleteWith = $('#completed-with').val() || null; var publicURL = $('#public-url').val() || null; var githubURL = $('#github-url').val() || null; @@ -170,8 +143,8 @@ $(document).ready(function() { '/completed-zipline-or-basejump/', { challengeInfo: { - challengeId: challengeId, - challengeName: challengeName, + challengeId: challenge_Id, + challengeName: challenge_Name, completedWith: didCompleteWith, publicURL: publicURL, githubURL: githubURL, @@ -184,6 +157,26 @@ $(document).ready(function() { window.location.replace(window.location.href); }); break; + case challengeTypes.BONFIRE: + var bonfireSolution = myCodeMirror.getValue(); + var didCompleteWith = $('#completed-with').val() || null; + $.post( + '/completed-bonfire/', + { + challengeInfo: { + challengeId: challenge_Id, + challengeName: challenge_Name, + completedWith: didCompleteWith, + challengeType: challengeType, + solution: bonfireSolution + } + }, + function(res) { + if (res) { + window.location.href = '/challenges/next-challenge'; + } + } + ); default: break; } diff --git a/views/account/show.jade b/views/account/show.jade index f202664703..f6ab37ce92 100644 --- a/views/account/show.jade +++ b/views/account/show.jade @@ -164,7 +164,7 @@ block content for bonfire in bonfires tr td.col-xs-4 - a(href='/bonfires/' + bonfire.name)= bonfire.name + a(href='/challenges/' + bonfire.name)= bonfire.name td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-6 pre.wrappable= bonfire.solution diff --git a/views/bonfire/show.jade b/views/bonfire/show.jade index 1383241a9d..087dea3568 100644 --- a/views/bonfire/show.jade +++ b/views/bonfire/show.jade @@ -93,9 +93,10 @@ block content script(type="text/javascript"). var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var passedBonfireHash = !{JSON.stringify(bonfireHash)}; - var challengeName = !{JSON.stringify(name)}; + var challenge_Id = !{JSON.stringify(challengeId)}; + var challenge_Name = !{JSON.stringify(name)}; var started = Math.floor(Date.now()); + var challengeType = !{JSON.stringify(challengeType)}; var _ = R; var dashed = !{JSON.stringify(dashedName)}; @@ -104,11 +105,11 @@ block content form.code .form-group.codeMirrorView textarea#codeEditor(autofocus=true, style='display: none;') - script(src='/js/lib/bonfire/bonfireFramework_v0.1.3.js') + script(src='/js/lib/coursewares/coursewaresJSFramework_0.0.2.js') - #complete-bonfire-dialog.modal(tabindex='-1') + #complete-courseware-dialog.modal(tabindex='-1') .modal-dialog.animated.zoomIn.fast-animation .modal-content .modal-header.challenge-list-header= compliment @@ -129,11 +130,11 @@ block content span.ion-close-circled | Username not found - a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-bonfire-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next bonfire (ctrl + enter) + a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next bonfire (ctrl + enter) - if (user.progressTimestamps.length > 2) - a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{dashedName}&hashtags=LearnToCode, JavaScript") + a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript") i.fa.fa-twitter   = phrase - else diff --git a/views/challengeMap/show.jade b/views/challengeMap/show.jade index 74e3d659d8..ef925ecfe7 100644 --- a/views/challengeMap/show.jade +++ b/views/challengeMap/show.jade @@ -5,7 +5,6 @@ block content var waypointList = !{JSON.stringify(waypoints)}; var ziplineList = !{JSON.stringify(ziplines)}; var basejumpList = !{JSON.stringify(basejumps)}; - var completedBonfires = !{JSON.stringify(completedBonfireList)}; var completedChallenges = !{JSON.stringify(completedChallengeList)}; .panel.panel-info .panel-heading.text-center @@ -52,19 +51,19 @@ block content h3.negative-15 ol for bonfire in bonfires - if completedBonfireList.indexOf(bonfire._id) > -1 + if completedChallengeList.indexOf(bonfire._id) > -1 .row .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center .col-xs-12.col-sm-9.col-md-10 li.faded - a(href="/bonfires/#{bonfire.name}")= bonfire.name + a(href="/challenges/#{bonfire.name}")= bonfire.name else .row .hidden-xs.col-sm-3.col-md-2 span .col-xs-12.col-sm-9.col-md-10 li - a(href="/bonfires/#{bonfire.name}")= bonfire.name + a(href="/challenges/#{bonfire.name}")= bonfire.name h2 span.fa.fa-angle-double-right |   Ziplines (200 hours of front end development) diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index c3fa9f886c..c613866594 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -56,8 +56,8 @@ block content $('#next-courseware-button').attr('disabled', 'disabled'); var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var challengeId = !{JSON.stringify(challengeId)}; - var challengeName = !{JSON.stringify(name)}; + var challenge_Id = !{JSON.stringify(challengeId)}; + var challenge_Name = !{JSON.stringify(name)}; var prodOrDev = !{JSON.stringify(environment)}; var challengeType = !{JSON.stringify(challengeType)}; var started = Math.floor(Date.now()); diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index 6d5d4b65f9..8fe21bb4f1 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -45,8 +45,8 @@ block content script(type="text/javascript"). var tests = !{JSON.stringify(tests)}; var challengeSeed = !{JSON.stringify(challengeSeed)}; - var challengeId = !{JSON.stringify(challengeId)}; - var challengeName = !{JSON.stringify(name)}; + var challenge_Id = !{JSON.stringify(challengeId)}; + var challenge_Name = !{JSON.stringify(name)}; var challengeType = !{JSON.stringify(challengeType)}; var started = Math.floor(Date.now()); @@ -55,7 +55,7 @@ block content form.code .form-group.codeMirrorView textarea#codeEditor(autofocus=true, style='display: none;') - script(src='/js/lib/coursewares/coursewaresJSFramework_0.0.1.js') + script(src='/js/lib/coursewares/coursewaresJSFramework_0.0.2.js') #complete-courseware-dialog.modal(tabindex='-1') .modal-dialog.animated.zoomIn.fast-animation .modal-content diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index b0a675fc3c..f61701be28 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -28,11 +28,7 @@ block content br .button-spacer script(type="text/javascript"). - var tests = !{JSON.stringify(tests)}; - var challengeId = !{JSON.stringify(challengeId)}; - var challengeName = !{JSON.stringify(name)}; - var started = Math.floor(Date.now()); - var challengeType = !{JSON.stringify(challengeType)}; + var controlEnterHandler = function(e) { $('body').unbind('keypress'); if (e.ctrlKey && e.keyCode == 13) { @@ -75,3 +71,7 @@ block content h1 #{name} script. $('body').bind('keypress', controlEnterHandler); + script. + var challenge_Id = !{JSON.stringify(challengeId)}; + var challenge_Name = !{JSON.stringify(name)}; + var challengeType = !{JSON.stringify(challengeType)}; \ No newline at end of file diff --git a/views/coursewares/showZiplineOrBasejump.jade b/views/coursewares/showZiplineOrBasejump.jade index e9db5c16d0..e9dda03e15 100644 --- a/views/coursewares/showZiplineOrBasejump.jade +++ b/views/coursewares/showZiplineOrBasejump.jade @@ -32,9 +32,8 @@ block content var userLoggedIn = false; br script(type="text/javascript"). - var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; - var challengeName = !{JSON.stringify(name)}; - var passedCoursewareName = challengeName; + var challenge_Id = !{JSON.stringify(challengeId)}; + var challenge_Name = !{JSON.stringify(name)}; var started = Math.floor(Date.now()); var challengeType = !{JSON.stringify(challengeType)}; var controlEnterHandler = function (e) { diff --git a/views/partials/universal-head.jade b/views/partials/universal-head.jade index cfc3fc7b81..81b2895666 100644 --- a/views/partials/universal-head.jade +++ b/views/partials/universal-head.jade @@ -31,7 +31,7 @@ script(src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.2/moment.min.js") script. window.moment || document.write(' + + diff --git a/views/resources/jobs.jade b/views/resources/jobs.jade new file mode 100644 index 0000000000..4ed9f43423 --- /dev/null +++ b/views/resources/jobs.jade @@ -0,0 +1,16 @@ +extends ../layout-wide +block content + .row + .col-xs-12.col-sm-8.col-sm-offset-2.text-center + h2 We want all our campers to get awesome software engineer jobs ( + a(href='https://www.linkedin.com/groups?viewMembers=&gid=6966827&sik=1432338555021' target='_blank') and many already have + | ). + h3.hidden-xs.hidden-sm This is a small sampling of the 1,000s of junior software engineer jobs. Learn about the   + a(href='http://blog.freecodecamp.com/2014/10/the-real-reason-to-learn-mean-stack.html') the job market in aggregate + | . + .spacer + a.btn.btn-primary.btn-big(href='/jobs-form') My organization is hiring software engineers + .spacer + .embed-responsive.embed-responsive-4by3.hidden-xs.hidden-sm + iframe.embed-responsive-item(src="http://freecodecamp.simply-partner.com" scrolling="no") + .spacer diff --git a/views/resources/test.css b/views/resources/test.css new file mode 100644 index 0000000000..b9b0d329f4 --- /dev/null +++ b/views/resources/test.css @@ -0,0 +1,61 @@ +.themeCustom a.link:link, .themeCustom a.link:visited, .themeCustom a:link, .themeCustom a:visited { + color: #0066cc; +} + +.themeCustom .sh_header_search .well { + background: #dedede; +} + +.themeCustom .sh_header_search .header_wrapper { + border-bottom-color: #cccccc; +} + +.themeCustom .column-left { + background-color: #dedede; +} + +.themeCustom .column-left .filters .handle { + background-color: #dedede; +} + +.themeCustom .column-left .filters .handle:hover { + background-color: #cccccc; +} + +.themeCustom .column-left .recent_searches, .themeCustom .column-left .search_tools, .themeCustom .column-left .search_links, .themeCustom .column-left .sort_jobs { + border-top-color: #dedede; +} + +.themeCustom #search_title .text-highlight { + color: #444444; +} + +.themeCustom .inline-filters { + background: #dedede; +} + +.themeCustom input[type=radio]:checked + label > span, .themeCustom .sort_jobs input[type=radio]:checked + label > span, .themeCustom .social-network-logins input[type=radio]:checked + label > span { + background-color: #444444; + border-color: #444444; +} + +.themeCustom .filters .filter ul li a, .themeCustom #c_expired a, .themeCustom .result a, .themeCustom .expand_search a, .themeCustom .simplyhired-intl a, .themeCustom .filters .filter ul li a:visited, .themeCustom #c_expired a:visited, .themeCustom .result a:visited, .themeCustom .expand_search a:visited, .themeCustom .simplyhired-intl a:visited, .themeCustom .job h2 { + color: #0066cc;} + +.sh.theme-base .btn-sh2 { + background-color: #999999; +} + +.sh.theme-base .sh_header_search .skin-search-promo .btn-large{ + background-color: #999999; + background-image: none; +} + +.sh .job .new { + background-color: #999999; + background-image: none; +} + +.sh .job .partner-exclusive { + background-color: #F15A22; +} From b626c811d0ff5a9efa26ca019fe9255b4dfa702b Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Sat, 23 May 2015 02:26:29 -0400 Subject: [PATCH 47/81] Add initial I need help button and slack webhook integration --- app.js | 3 + config/secrets.js | 3 +- controllers/resources.js | 20 +++++- controllers/user.js | 3 +- public/css/main.css | 11 ---- public/js/main.js | 66 ++++++++++++------- .../challenges/jquery-ajax-and-json.json | 51 +++++++++----- views/coursewares/showHTML.jade | 1 + 8 files changed, 104 insertions(+), 54 deletions(-) delete mode 100644 public/css/main.css diff --git a/app.js b/app.js index 95a6c49bd3..e84b796a26 100755 --- a/app.js +++ b/app.js @@ -226,6 +226,9 @@ app.get('/nonprofit-project-instructions', function(req, res) { res.redirect(301, '/field-guide/how-do-free-code-camp\'s-nonprofit-projects-work'); }); +app.post('/get-help', resourcesController.getHelp); + + app.get('/chat', resourcesController.chat); app.get('/twitch', resourcesController.twitch); diff --git a/config/secrets.js b/config/secrets.js index 10cca4c96a..a3bd62dc81 100644 --- a/config/secrets.js +++ b/config/secrets.js @@ -58,5 +58,6 @@ module.exports = { callbackURL: '/auth/linkedin/callback', scope: ['r_basicprofile', 'r_emailaddress'], passReqToCallback: true - } + }, + slackHook: process.env.SLACK_WEBHOOK, }; diff --git a/controllers/resources.js b/controllers/resources.js index eae5a4c6bb..20a99a2080 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -9,6 +9,7 @@ var async = require('async'), _ = require('lodash'), fs = require('fs'), + constantStrings = require('./constantStrings.json'), User = require('../models/User'), Challenge = require('./../models/Challenge'), @@ -19,7 +20,9 @@ var async = require('async'), resources = require('./resources.json'), secrets = require('./../config/secrets'), nonprofits = require('../seed_data/nonprofits.json'), - fieldGuides = require('../seed_data/field-guides.json'); + fieldGuides = require('../seed_data/field-guides.json'), + Slack = require('node-slack'), + slack = new Slack(secrets.slackHook); /** * Cached values @@ -581,5 +584,20 @@ module.exports = { slack: function() { } + }, + + getHelp: function(req, res, next) { + var userName = req.user.profile.username; + var code = req.body.payload.code; + var challenge = req.body.payload.challenge; + + slack.send({ + text: "User " + userName + " needs help with challenge " + + "" + challenge + "!\n```\n" + code + "\n```", + channel: '#help', + username: userName + }); + return res.sendStatus(200); + } }; diff --git a/controllers/user.js b/controllers/user.js index 60ea801679..20e69b1825 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -79,7 +79,8 @@ exports.signout = function(req, res) { * Signup page. */ -exports.getEmailSignin = function(req, res) { +exports.getEmailSignin = function(req, res) //noinspection Eslint +{ if (req.user) { return res.redirect('/'); } diff --git a/public/css/main.css b/public/css/main.css deleted file mode 100644 index 20ea61c1ec..0000000000 --- a/public/css/main.css +++ /dev/null @@ -1,11 +0,0 @@ -@charset "UTF-8";/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#457e86}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#215f1e;text-decoration:none}a:hover,a:focus{color:#0d250c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#457e86;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#215f1e}a.text-primary:hover{color:#143812}.text-success{color:#215f1e}a.text-success:hover{color:#143812}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#215f1e}a.bg-primary:hover{background-color:#143812}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#eee;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#457e86}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#eee;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{line-height:34px;line-height:1.42857143 \0}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm{line-height:30px;line-height:1.5 \0}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg{line-height:46px;line-height:1.33 \0}_:-ms-fullscreen,:root input[type="date"],_:-ms-fullscreen,:root input[type="time"],_:-ms-fullscreen,:root input[type="datetime-local"],_:-ms-fullscreen,:root input[type="month"]{line-height:1.42857143}_:-ms-fullscreen.input-sm,:root input[type="date"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="time"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="datetime-local"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="month"].input-sm{line-height:1.5}_:-ms-fullscreen.input-lg,:root input[type="date"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="time"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="datetime-local"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="month"].input-lg{line-height:1.33}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm,.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm,select.form-group-sm .form-control{height:30px;line-height:30px}textarea.input-sm,textarea.form-group-sm .form-control,select[multiple].input-sm,select[multiple].form-group-sm .form-control{height:auto}.input-lg,.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg,select.form-group-lg .form-control{height:46px;line-height:46px}textarea.input-lg,textarea.form-group-lg .form-control,select[multiple].input-lg,select[multiple].form-group-lg .form-control{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#215f1e}.has-success .form-control{border-color:#215f1e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#143812;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #3cad36;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #3cad36}.has-success .input-group-addon{color:#215f1e;border-color:#215f1e;background-color:#dff0d8}.has-success .form-control-feedback{color:#215f1e}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#eee;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default.focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#d5d5d5;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#eee;border-color:#ccc}.btn-default .badge{color:#eee;background-color:#333}.btn-primary{color:#eee;background-color:#215f1e;border-color:#1a4c18}.btn-primary:hover,.btn-primary:focus,.btn-primary.focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#eee;background-color:#143812;border-color:#0a1d09}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#215f1e;border-color:#1a4c18}.btn-primary .badge{color:#215f1e;background-color:#eee}.btn-success{color:#eee;background-color:#457e86;border-color:#3c6e75}.btn-success:hover,.btn-success:focus,.btn-success.focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#eee;background-color:#345e64;border-color:#28484d}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#457e86;border-color:#3c6e75}.btn-success .badge{color:#457e86;background-color:#eee}.btn-info{color:#eee;background-color:#4a2b0f;border-color:#351f0b}.btn-info:hover,.btn-info:focus,.btn-info.focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#eee;background-color:#201206;border-color:#020100}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#4a2b0f;border-color:#351f0b}.btn-info .badge{color:#4a2b0f;background-color:#eee}.btn-warning{color:#eee;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning.focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#eee;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#eee}.btn-danger{color:#eee;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger.focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#eee;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#eee}.btn-link{color:#215f1e;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#0d250c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#eee;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#eee;text-decoration:none;outline:0;background-color:#215f1e}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#215f1e}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#457e86;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#457e86}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#eee;background-color:#215f1e}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#457e86}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;visibility:visible !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px;background-color:#eee !important}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#eee}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#d5d5d5;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#eee}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#4a2b0f;background-color:#eee}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#eee;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#eee}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#eee}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#4a2b0f;background-color:#eee}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#eee;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#eee}.navbar-default .navbar-link:hover{color:#4a2b0f}.navbar-default .btn-link{color:#eee}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#4a2b0f}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#777}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#eee;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#777}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#eee;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#eee;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#eee}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#eee}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#eee;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#eee;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#777}.navbar-inverse .navbar-link:hover{color:#eee}.navbar-inverse .btn-link{color:#777}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#eee}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#215f1e;background-color:#eee;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#0d250c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#eee;background-color:#215f1e;border-color:#215f1e;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#eee;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#eee;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#eee;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#eee;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#eee;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#215f1e}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#143812}.label-success{background-color:#457e86}.label-success[href]:hover,.label-success[href]:focus{background-color:#345e64}.label-info{background-color:#4a2b0f}.label-info[href]:hover,.label-info[href]:focus{background-color:#201206}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#eee;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#eee;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#215f1e;background-color:#eee}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#457e86;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#215f1e}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#215f1e}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#143812}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#eee;text-align:center;background-color:#215f1e;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#457e86}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#4a2b0f}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#eee;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#eee;background-color:#215f1e;border-color:#215f1e}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#7ad475}.list-group-item-success{color:#215f1e;background-color:#dff0d8}a.list-group-item-success{color:#215f1e}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#215f1e;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#215f1e;border-color:#215f1e}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#eee;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#dedede;border-top:1px solid #ccc;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ccc}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ccc}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#215f1e}.panel-primary>.panel-heading{color:#eee;background-color:#215f1e;border-color:#215f1e}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#215f1e}.panel-primary>.panel-heading .badge{color:#215f1e;background-color:#eee}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#215f1e}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#215f1e;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#215f1e}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#351f0b}.panel-info>.panel-heading{color:#eee;background-color:#4a2b0f;border-color:#351f0b}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#351f0b}.panel-info>.panel-heading .badge{color:#4a2b0f;background-color:#eee}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#351f0b}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #eee;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#eee;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#eee;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:left;background-color:#eee;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#e6e6e6;border-bottom:1px solid #dadada;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#eee}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#eee}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#eee}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#eee;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{transition:transform .6s ease-in-out;backface-visibility:hidden;perspective:1000}.carousel-inner>.item.next,.carousel-inner>.item.active.right{transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#eee;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#eee;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #eee;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#eee}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#eee;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)}.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em}.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em}.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em}.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:250px;margin:auto;height:34px;width:34px;padding:0}.btn-social-icon>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)}.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em}.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em}.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em}.btn-social-icon :first-child{border:none;text-align:center;width:100% !important}.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0}.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0}.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0}.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:hover,.btn-adn:focus,.btn-adn.focus,.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)}.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{background-image:none}.btn-adn.disabled,.btn-adn[disabled],fieldset[disabled] .btn-adn,.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled.focus,.btn-adn[disabled].focus,fieldset[disabled] .btn-adn.focus,.btn-adn.disabled:active,.btn-adn[disabled]:active,fieldset[disabled] .btn-adn:active,.btn-adn.disabled.active,.btn-adn[disabled].active,fieldset[disabled] .btn-adn.active{background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn .badge{color:#d87a68;background-color:#fff}.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:hover,.btn-bitbucket:focus,.btn-bitbucket.focus,.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{background-image:none}.btn-bitbucket.disabled,.btn-bitbucket[disabled],fieldset[disabled] .btn-bitbucket,.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled.focus,.btn-bitbucket[disabled].focus,fieldset[disabled] .btn-bitbucket.focus,.btn-bitbucket.disabled:active,.btn-bitbucket[disabled]:active,fieldset[disabled] .btn-bitbucket:active,.btn-bitbucket.disabled.active,.btn-bitbucket[disabled].active,fieldset[disabled] .btn-bitbucket.active{background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket .badge{color:#205081;background-color:#fff}.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:hover,.btn-dropbox:focus,.btn-dropbox.focus,.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)}.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{background-image:none}.btn-dropbox.disabled,.btn-dropbox[disabled],fieldset[disabled] .btn-dropbox,.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled.focus,.btn-dropbox[disabled].focus,fieldset[disabled] .btn-dropbox.focus,.btn-dropbox.disabled:active,.btn-dropbox[disabled]:active,fieldset[disabled] .btn-dropbox:active,.btn-dropbox.disabled.active,.btn-dropbox[disabled].active,fieldset[disabled] .btn-dropbox.active{background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox .badge{color:#1087dd;background-color:#fff}.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook.focus,.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)}.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{background-image:none}.btn-facebook.disabled,.btn-facebook[disabled],fieldset[disabled] .btn-facebook,.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled.focus,.btn-facebook[disabled].focus,fieldset[disabled] .btn-facebook.focus,.btn-facebook.disabled:active,.btn-facebook[disabled]:active,fieldset[disabled] .btn-facebook:active,.btn-facebook.disabled.active,.btn-facebook[disabled].active,fieldset[disabled] .btn-facebook.active{background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook .badge{color:#3b5998;background-color:#fff}.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr.focus,.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)}.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{background-image:none}.btn-flickr.disabled,.btn-flickr[disabled],fieldset[disabled] .btn-flickr,.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled.focus,.btn-flickr[disabled].focus,fieldset[disabled] .btn-flickr.focus,.btn-flickr.disabled:active,.btn-flickr[disabled]:active,fieldset[disabled] .btn-flickr:active,.btn-flickr.disabled.active,.btn-flickr[disabled].active,fieldset[disabled] .btn-flickr.active{background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr .badge{color:#ff0084;background-color:#fff}.btn-foursquare{color:#fff;background-color:#f94877;border-color:rgba(0,0,0,0.2)}.btn-foursquare:hover,.btn-foursquare:focus,.btn-foursquare.focus,.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)}.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{background-image:none}.btn-foursquare.disabled,.btn-foursquare[disabled],fieldset[disabled] .btn-foursquare,.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled.focus,.btn-foursquare[disabled].focus,fieldset[disabled] .btn-foursquare.focus,.btn-foursquare.disabled:active,.btn-foursquare[disabled]:active,fieldset[disabled] .btn-foursquare:active,.btn-foursquare.disabled.active,.btn-foursquare[disabled].active,fieldset[disabled] .btn-foursquare.active{background-color:#f94877;border-color:rgba(0,0,0,0.2)}.btn-foursquare .badge{color:#f94877;background-color:#fff}.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:hover,.btn-github:focus,.btn-github.focus,.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)}.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{background-image:none}.btn-github.disabled,.btn-github[disabled],fieldset[disabled] .btn-github,.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled.focus,.btn-github[disabled].focus,fieldset[disabled] .btn-github.focus,.btn-github.disabled:active,.btn-github[disabled]:active,fieldset[disabled] .btn-github:active,.btn-github.disabled.active,.btn-github[disabled].active,fieldset[disabled] .btn-github.active{background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github .badge{color:#444;background-color:#fff}.btn-google-plus{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google-plus:hover,.btn-google-plus:focus,.btn-google-plus.focus,.btn-google-plus:active,.btn-google-plus.active,.open>.dropdown-toggle.btn-google-plus{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)}.btn-google-plus:active,.btn-google-plus.active,.open>.dropdown-toggle.btn-google-plus{background-image:none}.btn-google-plus.disabled,.btn-google-plus[disabled],fieldset[disabled] .btn-google-plus,.btn-google-plus.disabled:hover,.btn-google-plus[disabled]:hover,fieldset[disabled] .btn-google-plus:hover,.btn-google-plus.disabled:focus,.btn-google-plus[disabled]:focus,fieldset[disabled] .btn-google-plus:focus,.btn-google-plus.disabled.focus,.btn-google-plus[disabled].focus,fieldset[disabled] .btn-google-plus.focus,.btn-google-plus.disabled:active,.btn-google-plus[disabled]:active,fieldset[disabled] .btn-google-plus:active,.btn-google-plus.disabled.active,.btn-google-plus[disabled].active,fieldset[disabled] .btn-google-plus.active{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google-plus .badge{color:#dd4b39;background-color:#fff}.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram.focus,.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)}.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{background-image:none}.btn-instagram.disabled,.btn-instagram[disabled],fieldset[disabled] .btn-instagram,.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled.focus,.btn-instagram[disabled].focus,fieldset[disabled] .btn-instagram.focus,.btn-instagram.disabled:active,.btn-instagram[disabled]:active,fieldset[disabled] .btn-instagram:active,.btn-instagram.disabled.active,.btn-instagram[disabled].active,fieldset[disabled] .btn-instagram.active{background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram .badge{color:#3f729b;background-color:#fff}.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:hover,.btn-linkedin:focus,.btn-linkedin.focus,.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)}.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{background-image:none}.btn-linkedin.disabled,.btn-linkedin[disabled],fieldset[disabled] .btn-linkedin,.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled.focus,.btn-linkedin[disabled].focus,fieldset[disabled] .btn-linkedin.focus,.btn-linkedin.disabled:active,.btn-linkedin[disabled]:active,fieldset[disabled] .btn-linkedin:active,.btn-linkedin.disabled.active,.btn-linkedin[disabled].active,fieldset[disabled] .btn-linkedin.active{background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin .badge{color:#007bb6;background-color:#fff}.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:hover,.btn-microsoft:focus,.btn-microsoft.focus,.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)}.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{background-image:none}.btn-microsoft.disabled,.btn-microsoft[disabled],fieldset[disabled] .btn-microsoft,.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled.focus,.btn-microsoft[disabled].focus,fieldset[disabled] .btn-microsoft.focus,.btn-microsoft.disabled:active,.btn-microsoft[disabled]:active,fieldset[disabled] .btn-microsoft:active,.btn-microsoft.disabled.active,.btn-microsoft[disabled].active,fieldset[disabled] .btn-microsoft.active{background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft .badge{color:#2672ec;background-color:#fff}.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:hover,.btn-openid:focus,.btn-openid.focus,.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)}.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{background-image:none}.btn-openid.disabled,.btn-openid[disabled],fieldset[disabled] .btn-openid,.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled.focus,.btn-openid[disabled].focus,fieldset[disabled] .btn-openid.focus,.btn-openid.disabled:active,.btn-openid[disabled]:active,fieldset[disabled] .btn-openid:active,.btn-openid.disabled.active,.btn-openid[disabled].active,fieldset[disabled] .btn-openid.active{background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid .badge{color:#f7931e;background-color:#fff}.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest.focus,.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)}.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{background-image:none}.btn-pinterest.disabled,.btn-pinterest[disabled],fieldset[disabled] .btn-pinterest,.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled.focus,.btn-pinterest[disabled].focus,fieldset[disabled] .btn-pinterest.focus,.btn-pinterest.disabled:active,.btn-pinterest[disabled]:active,fieldset[disabled] .btn-pinterest:active,.btn-pinterest.disabled.active,.btn-pinterest[disabled].active,fieldset[disabled] .btn-pinterest.active{background-color:#cb2027;border-color:rgba(0,0,0,0.2)}.btn-pinterest .badge{color:#cb2027;background-color:#fff}.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:hover,.btn-reddit:focus,.btn-reddit.focus,.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)}.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{background-image:none}.btn-reddit.disabled,.btn-reddit[disabled],fieldset[disabled] .btn-reddit,.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled.focus,.btn-reddit[disabled].focus,fieldset[disabled] .btn-reddit.focus,.btn-reddit.disabled:active,.btn-reddit[disabled]:active,fieldset[disabled] .btn-reddit:active,.btn-reddit.disabled.active,.btn-reddit[disabled].active,fieldset[disabled] .btn-reddit.active{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit .badge{color:#eff7ff;background-color:#000}.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:hover,.btn-soundcloud:focus,.btn-soundcloud.focus,.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{background-image:none}.btn-soundcloud.disabled,.btn-soundcloud[disabled],fieldset[disabled] .btn-soundcloud,.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled.focus,.btn-soundcloud[disabled].focus,fieldset[disabled] .btn-soundcloud.focus,.btn-soundcloud.disabled:active,.btn-soundcloud[disabled]:active,fieldset[disabled] .btn-soundcloud:active,.btn-soundcloud.disabled.active,.btn-soundcloud[disabled].active,fieldset[disabled] .btn-soundcloud.active{background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud .badge{color:#f50;background-color:#fff}.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:hover,.btn-tumblr:focus,.btn-tumblr.focus,.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)}.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{background-image:none}.btn-tumblr.disabled,.btn-tumblr[disabled],fieldset[disabled] .btn-tumblr,.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled.focus,.btn-tumblr[disabled].focus,fieldset[disabled] .btn-tumblr.focus,.btn-tumblr.disabled:active,.btn-tumblr[disabled]:active,fieldset[disabled] .btn-tumblr:active,.btn-tumblr.disabled.active,.btn-tumblr[disabled].active,fieldset[disabled] .btn-tumblr.active{background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr .badge{color:#2c4762;background-color:#fff}.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter.focus,.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)}.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{background-image:none}.btn-twitter.disabled,.btn-twitter[disabled],fieldset[disabled] .btn-twitter,.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled.focus,.btn-twitter[disabled].focus,fieldset[disabled] .btn-twitter.focus,.btn-twitter.disabled:active,.btn-twitter[disabled]:active,fieldset[disabled] .btn-twitter:active,.btn-twitter.disabled.active,.btn-twitter[disabled].active,fieldset[disabled] .btn-twitter.active{background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter .badge{color:#55acee;background-color:#fff}.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo.focus,.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)}.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{background-image:none}.btn-vimeo.disabled,.btn-vimeo[disabled],fieldset[disabled] .btn-vimeo,.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled.focus,.btn-vimeo[disabled].focus,fieldset[disabled] .btn-vimeo.focus,.btn-vimeo.disabled:active,.btn-vimeo[disabled]:active,fieldset[disabled] .btn-vimeo:active,.btn-vimeo.disabled.active,.btn-vimeo[disabled].active,fieldset[disabled] .btn-vimeo.active{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo .badge{color:#1ab7ea;background-color:#fff}.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:hover,.btn-vk:focus,.btn-vk.focus,.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)}.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{background-image:none}.btn-vk.disabled,.btn-vk[disabled],fieldset[disabled] .btn-vk,.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled.focus,.btn-vk[disabled].focus,fieldset[disabled] .btn-vk.focus,.btn-vk.disabled:active,.btn-vk[disabled]:active,fieldset[disabled] .btn-vk:active,.btn-vk.disabled.active,.btn-vk[disabled].active,fieldset[disabled] .btn-vk.active{background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk .badge{color:#587ea3;background-color:#fff}.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:hover,.btn-yahoo:focus,.btn-yahoo.focus,.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)}.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{background-image:none}.btn-yahoo.disabled,.btn-yahoo[disabled],fieldset[disabled] .btn-yahoo,.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled.focus,.btn-yahoo[disabled].focus,fieldset[disabled] .btn-yahoo.focus,.btn-yahoo.disabled:active,.btn-yahoo[disabled]:active,fieldset[disabled] .btn-yahoo:active,.btn-yahoo.disabled.active,.btn-yahoo[disabled].active,fieldset[disabled] .btn-yahoo.active{background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo .badge{color:#720e9e;background-color:#fff}/*! -Ionicons, v2.0.0 -Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ -https://twitter.com/benjsperry https://twitter.com/ionicframework -MIT License: https://github.com/driftyco/ionicons -*/@font-face{font-family:"Ionicons";src:url("../fonts/ionicons.eot?v=2.0.0");src:url("../fonts/ionicons.eot?v=2.0.0#iefix") format("embedded-opentype"),url("../fonts/ionicons.ttf?v=2.0.0") format("truetype"),url("../fonts/ionicons.woff?v=2.0.0") format("woff"),url("../fonts/ionicons.svg?v=2.0.0#Ionicons") format("svg");font-weight:normal;font-style:normal}.ion,.ion-loading-a,.ion-loading-b,.ion-loading-c,.ion-loading-d,.ion-looping,.ion-refreshing,.ion-ios7-reloading,.ionicons,.ion-alert:before,.ion-alert-circled:before,.ion-android-add:before,.ion-android-add-circle:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done:before,.ion-android-done-all:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite:before,.ion-android-favorite-outline:before,.ion-android-film:before,.ion-android-folder:before,.ion-android-folder-open:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone:before,.ion-android-microphone-off:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person:before,.ion-android-person-add:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove:before,.ion-android-remove-circle:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share:before,.ion-android-share-alt:before,.ion-android-star:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace:before,.ion-backspace-outline:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox:before,.ion-chatbox-working:before,.ion-chatboxes:before,.ion-chatbubble:before,.ion-chatbubble-working:before,.ion-chatbubbles:before,.ion-checkmark:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close:before,.ion-close-circled:before,.ion-close-round:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code:before,.ion-code-download:before,.ion-code-working:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document:before,.ion-document-text:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email:before,.ion-email-unread:before,.ion-erlenmeyer-flask:before,.ion-erlenmeyer-flask-bubbles:before,.ion-eye:before,.ion-eye-disabled:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash:before,.ion-flash-off:before,.ion-folder:before,.ion-fork:before,.ion-fork-repo:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy:before,.ion-happy-outline:before,.ion-headphone:before,.ion-heart:before,.ion-heart-broken:before,.ion-help:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information:before,.ion-information-circled:before,.ion-ionic:before,.ion-ios-alarm:before,.ion-ios-alarm-outline:before,.ion-ios-albums:before,.ion-ios-albums-outline:before,.ion-ios-americanfootball:before,.ion-ios-americanfootball-outline:before,.ion-ios-analytics:before,.ion-ios-analytics-outline:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at:before,.ion-ios-at-outline:before,.ion-ios-barcode:before,.ion-ios-barcode-outline:before,.ion-ios-baseball:before,.ion-ios-baseball-outline:before,.ion-ios-basketball:before,.ion-ios-basketball-outline:before,.ion-ios-bell:before,.ion-ios-bell-outline:before,.ion-ios-body:before,.ion-ios-body-outline:before,.ion-ios-bolt:before,.ion-ios-bolt-outline:before,.ion-ios-book:before,.ion-ios-book-outline:before,.ion-ios-bookmarks:before,.ion-ios-bookmarks-outline:before,.ion-ios-box:before,.ion-ios-box-outline:before,.ion-ios-briefcase:before,.ion-ios-briefcase-outline:before,.ion-ios-browsers:before,.ion-ios-browsers-outline:before,.ion-ios-calculator:before,.ion-ios-calculator-outline:before,.ion-ios-calendar:before,.ion-ios-calendar-outline:before,.ion-ios-camera:before,.ion-ios-camera-outline:before,.ion-ios-cart:before,.ion-ios-cart-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatbubble:before,.ion-ios-chatbubble-outline:before,.ion-ios-checkmark:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock:before,.ion-ios-clock-outline:before,.ion-ios-close:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-cloud:before,.ion-ios-cloud-download:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloudy:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-outline:before,.ion-ios-cog:before,.ion-ios-cog-outline:before,.ion-ios-color-filter:before,.ion-ios-color-filter-outline:before,.ion-ios-color-wand:before,.ion-ios-color-wand-outline:before,.ion-ios-compose:before,.ion-ios-compose-outline:before,.ion-ios-contact:before,.ion-ios-contact-outline:before,.ion-ios-copy:before,.ion-ios-copy-outline:before,.ion-ios-crop:before,.ion-ios-crop-strong:before,.ion-ios-download:before,.ion-ios-download-outline:before,.ion-ios-drag:before,.ion-ios-email:before,.ion-ios-email-outline:before,.ion-ios-eye:before,.ion-ios-eye-outline:before,.ion-ios-fastforward:before,.ion-ios-fastforward-outline:before,.ion-ios-filing:before,.ion-ios-filing-outline:before,.ion-ios-film:before,.ion-ios-film-outline:before,.ion-ios-flag:before,.ion-ios-flag-outline:before,.ion-ios-flame:before,.ion-ios-flame-outline:before,.ion-ios-flask:before,.ion-ios-flask-outline:before,.ion-ios-flower:before,.ion-ios-flower-outline:before,.ion-ios-folder:before,.ion-ios-folder-outline:before,.ion-ios-football:before,.ion-ios-football-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-b:before,.ion-ios-game-controller-b-outline:before,.ion-ios-gear:before,.ion-ios-gear-outline:before,.ion-ios-glasses:before,.ion-ios-glasses-outline:before,.ion-ios-grid-view:before,.ion-ios-grid-view-outline:before,.ion-ios-heart:before,.ion-ios-heart-outline:before,.ion-ios-help:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-home:before,.ion-ios-home-outline:before,.ion-ios-infinite:before,.ion-ios-infinite-outline:before,.ion-ios-information:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-ionic-outline:before,.ion-ios-keypad:before,.ion-ios-keypad-outline:before,.ion-ios-lightbulb:before,.ion-ios-lightbulb-outline:before,.ion-ios-list:before,.ion-ios-list-outline:before,.ion-ios-location:before,.ion-ios-location-outline:before,.ion-ios-locked:before,.ion-ios-locked-outline:before,.ion-ios-loop:before,.ion-ios-loop-strong:before,.ion-ios-medical:before,.ion-ios-medical-outline:before,.ion-ios-medkit:before,.ion-ios-medkit-outline:before,.ion-ios-mic:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-minus:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-monitor:before,.ion-ios-monitor-outline:before,.ion-ios-moon:before,.ion-ios-moon-outline:before,.ion-ios-more:before,.ion-ios-more-outline:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate:before,.ion-ios-navigate-outline:before,.ion-ios-nutrition:before,.ion-ios-nutrition-outline:before,.ion-ios-paper:before,.ion-ios-paper-outline:before,.ion-ios-paperplane:before,.ion-ios-paperplane-outline:before,.ion-ios-partlysunny:before,.ion-ios-partlysunny-outline:before,.ion-ios-pause:before,.ion-ios-pause-outline:before,.ion-ios-paw:before,.ion-ios-paw-outline:before,.ion-ios-people:before,.ion-ios-people-outline:before,.ion-ios-person:before,.ion-ios-person-outline:before,.ion-ios-personadd:before,.ion-ios-personadd-outline:before,.ion-ios-photos:before,.ion-ios-photos-outline:before,.ion-ios-pie:before,.ion-ios-pie-outline:before,.ion-ios-pint:before,.ion-ios-pint-outline:before,.ion-ios-play:before,.ion-ios-play-outline:before,.ion-ios-plus:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetags:before,.ion-ios-pricetags-outline:before,.ion-ios-printer:before,.ion-ios-printer-outline:before,.ion-ios-pulse:before,.ion-ios-pulse-strong:before,.ion-ios-rainy:before,.ion-ios-rainy-outline:before,.ion-ios-recording:before,.ion-ios-recording-outline:before,.ion-ios-redo:before,.ion-ios-redo-outline:before,.ion-ios-refresh:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-reload:before,.ion-ios-reverse-camera:before,.ion-ios-reverse-camera-outline:before,.ion-ios-rewind:before,.ion-ios-rewind-outline:before,.ion-ios-rose:before,.ion-ios-rose-outline:before,.ion-ios-search:before,.ion-ios-search-strong:before,.ion-ios-settings:before,.ion-ios-settings-strong:before,.ion-ios-shuffle:before,.ion-ios-shuffle-strong:before,.ion-ios-skipbackward:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipforward:before,.ion-ios-skipforward-outline:before,.ion-ios-snowy:before,.ion-ios-speedometer:before,.ion-ios-speedometer-outline:before,.ion-ios-star:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-stopwatch:before,.ion-ios-stopwatch-outline:before,.ion-ios-sunny:before,.ion-ios-sunny-outline:before,.ion-ios-telephone:before,.ion-ios-telephone-outline:before,.ion-ios-tennisball:before,.ion-ios-tennisball-outline:before,.ion-ios-thunderstorm:before,.ion-ios-thunderstorm-outline:before,.ion-ios-time:before,.ion-ios-time-outline:before,.ion-ios-timer:before,.ion-ios-timer-outline:before,.ion-ios-toggle:before,.ion-ios-toggle-outline:before,.ion-ios-trash:before,.ion-ios-trash-outline:before,.ion-ios-undo:before,.ion-ios-undo-outline:before,.ion-ios-unlocked:before,.ion-ios-unlocked-outline:before,.ion-ios-upload:before,.ion-ios-upload-outline:before,.ion-ios-videocam:before,.ion-ios-videocam-outline:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass:before,.ion-ios-wineglass-outline:before,.ion-ios-world:before,.ion-ios-world-outline:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon:before,.ion-navicon-round:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person:before,.ion-person-add:before,.ion-person-stalker:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply:before,.ion-reply-all:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad:before,.ion-sad-outline:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android:before,.ion-social-android-outline:before,.ion-social-angular:before,.ion-social-angular-outline:before,.ion-social-apple:before,.ion-social-apple-outline:before,.ion-social-bitcoin:before,.ion-social-bitcoin-outline:before,.ion-social-buffer:before,.ion-social-buffer-outline:before,.ion-social-chrome:before,.ion-social-chrome-outline:before,.ion-social-codepen:before,.ion-social-codepen-outline:before,.ion-social-css3:before,.ion-social-css3-outline:before,.ion-social-designernews:before,.ion-social-designernews-outline:before,.ion-social-dribbble:before,.ion-social-dribbble-outline:before,.ion-social-dropbox:before,.ion-social-dropbox-outline:before,.ion-social-euro:before,.ion-social-euro-outline:before,.ion-social-facebook:before,.ion-social-facebook-outline:before,.ion-social-foursquare:before,.ion-social-foursquare-outline:before,.ion-social-freebsd-devil:before,.ion-social-github:before,.ion-social-github-outline:before,.ion-social-google:before,.ion-social-google-outline:before,.ion-social-googleplus:before,.ion-social-googleplus-outline:before,.ion-social-hackernews:before,.ion-social-hackernews-outline:before,.ion-social-html5:before,.ion-social-html5-outline:before,.ion-social-instagram:before,.ion-social-instagram-outline:before,.ion-social-javascript:before,.ion-social-javascript-outline:before,.ion-social-linkedin:before,.ion-social-linkedin-outline:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest:before,.ion-social-pinterest-outline:before,.ion-social-python:before,.ion-social-reddit:before,.ion-social-reddit-outline:before,.ion-social-rss:before,.ion-social-rss-outline:before,.ion-social-sass:before,.ion-social-skype:before,.ion-social-skype-outline:before,.ion-social-snapchat:before,.ion-social-snapchat-outline:before,.ion-social-tumblr:before,.ion-social-tumblr-outline:before,.ion-social-tux:before,.ion-social-twitch:before,.ion-social-twitch-outline:before,.ion-social-twitter:before,.ion-social-twitter-outline:before,.ion-social-usd:before,.ion-social-usd-outline:before,.ion-social-vimeo:before,.ion-social-vimeo-outline:before,.ion-social-whatsapp:before,.ion-social-whatsapp-outline:before,.ion-social-windows:before,.ion-social-windows-outline:before,.ion-social-wordpress:before,.ion-social-wordpress-outline:before,.ion-social-yahoo:before,.ion-social-yahoo-outline:before,.ion-social-yen:before,.ion-social-yen-outline:before,.ion-social-youtube:before,.ion-social-youtube-outline:before,.ion-soup-can:before,.ion-soup-can-outline:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle:before,.ion-toggle-filled:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt:before,.ion-tshirt-outline:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before{display:inline-block;font-family:"Ionicons";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-spin,.ion-loading-a,.ion-loading-b,.ion-loading-c,.ion-loading-d,.ion-looping,.ion-refreshing,.ion-ios7-reloading{-webkit-animation:spin 1s infinite linear;-moz-animation:spin 1s infinite linear;-o-animation:spin 1s infinite linear;animation:spin 1s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.ion-loading-a{-webkit-animation-timing-function:steps(8, start);-moz-animation-timing-function:steps(8, start);animation-timing-function:steps(8, start)}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}/*! -Animate.css - http://daneden.me/animate -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2014 Daniel Eden -*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}@-webkit-keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(.755, .05, .855, .06);transition-timing-function:cubic-bezier(.755, .05, .855, .06);-webkit-transform:translate3d(0, -30px, 0);transform:translate3d(0, -30px, 0)}70%{-webkit-transition-timing-function:cubic-bezier(.755, .05, .855, .06);transition-timing-function:cubic-bezier(.755, .05, .855, .06);-webkit-transform:translate3d(0, -15px, 0);transform:translate3d(0, -15px, 0)}90%{-webkit-transform:translate3d(0, -4px, 0);transform:translate3d(0, -4px, 0)}}@keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1);-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(.755, .05, .855, .06);transition-timing-function:cubic-bezier(.755, .05, .855, .06);-webkit-transform:translate3d(0, -30px, 0);transform:translate3d(0, -30px, 0)}70%{-webkit-transition-timing-function:cubic-bezier(.755, .05, .855, .06);transition-timing-function:cubic-bezier(.755, .05, .855, .06);-webkit-transform:translate3d(0, -15px, 0);transform:translate3d(0, -15px, 0)}90%{-webkit-transform:translate3d(0, -4px, 0);transform:translate3d(0, -4px, 0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;-ms-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}50%{-webkit-transform:scale3d(1.05, 1.05, 1.05);transform:scale3d(1.05, 1.05, 1.05)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}50%{-webkit-transform:scale3d(1.05, 1.05, 1.05);transform:scale3d(1.05, 1.05, 1.05)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}30%{-webkit-transform:scale3d(1.25, .75, 1);transform:scale3d(1.25, .75, 1)}40%{-webkit-transform:scale3d(.75, 1.25, 1);transform:scale3d(.75, 1.25, 1)}50%{-webkit-transform:scale3d(1.15, .85, 1);transform:scale3d(1.15, .85, 1)}65%{-webkit-transform:scale3d(.95, 1.05, 1);transform:scale3d(.95, 1.05, 1)}75%{-webkit-transform:scale3d(1.05, .95, 1);transform:scale3d(1.05, .95, 1)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}30%{-webkit-transform:scale3d(1.25, .75, 1);transform:scale3d(1.25, .75, 1)}40%{-webkit-transform:scale3d(.75, 1.25, 1);transform:scale3d(.75, 1.25, 1)}50%{-webkit-transform:scale3d(1.15, .85, 1);transform:scale3d(1.15, .85, 1)}65%{-webkit-transform:scale3d(.95, 1.05, 1);transform:scale3d(.95, 1.05, 1)}75%{-webkit-transform:scale3d(1.05, .95, 1);transform:scale3d(1.05, .95, 1)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px, 0, 0);transform:translate3d(-10px, 0, 0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px, 0, 0);transform:translate3d(10px, 0, 0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px, 0, 0);transform:translate3d(-10px, 0, 0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px, 0, 0);transform:translate3d(10px, 0, 0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0, 0, 1, 15deg);transform:rotate3d(0, 0, 1, 15deg)}40%{-webkit-transform:rotate3d(0, 0, 1, -10deg);transform:rotate3d(0, 0, 1, -10deg)}60%{-webkit-transform:rotate3d(0, 0, 1, 5deg);transform:rotate3d(0, 0, 1, 5deg)}80%{-webkit-transform:rotate3d(0, 0, 1, -5deg);transform:rotate3d(0, 0, 1, -5deg)}100%{-webkit-transform:rotate3d(0, 0, 1, 0deg);transform:rotate3d(0, 0, 1, 0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0, 0, 1, 15deg);transform:rotate3d(0, 0, 1, 15deg)}40%{-webkit-transform:rotate3d(0, 0, 1, -10deg);transform:rotate3d(0, 0, 1, -10deg)}60%{-webkit-transform:rotate3d(0, 0, 1, 5deg);transform:rotate3d(0, 0, 1, 5deg)}80%{-webkit-transform:rotate3d(0, 0, 1, -5deg);transform:rotate3d(0, 0, 1, -5deg)}100%{-webkit-transform:rotate3d(0, 0, 1, 0deg);transform:rotate3d(0, 0, 1, 0deg)}}.swing{-webkit-transform-origin:top center;-ms-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}10%,20%{-webkit-transform:scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);transform:scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes tada{0%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}10%,20%{-webkit-transform:scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);transform:scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);transform:scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)}100%{-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);transform:translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)}30%{-webkit-transform:translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);transform:translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)}45%{-webkit-transform:translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);transform:translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)}60%{-webkit-transform:translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);transform:translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)}75%{-webkit-transform:translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);transform:translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);transform:translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg)}30%{-webkit-transform:translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);transform:translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg)}45%{-webkit-transform:translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);transform:translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg)}60%{-webkit-transform:translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);transform:translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg)}75%{-webkit-transform:translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);transform:translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg)}100%{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(.9, .9, .9);transform:scale3d(.9, .9, .9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(.97, .97, .97);transform:scale3d(.97, .97, .97)}100%{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(.9, .9, .9);transform:scale3d(.9, .9, .9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(.97, .97, .97);transform:scale3d(.97, .97, .97)}100%{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(0, -3000px, 0);transform:translate3d(0, -3000px, 0)}60%{opacity:1;-webkit-transform:translate3d(0, 25px, 0);transform:translate3d(0, 25px, 0)}75%{-webkit-transform:translate3d(0, -10px, 0);transform:translate3d(0, -10px, 0)}90%{-webkit-transform:translate3d(0, 5px, 0);transform:translate3d(0, 5px, 0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(0, -3000px, 0);transform:translate3d(0, -3000px, 0)}60%{opacity:1;-webkit-transform:translate3d(0, 25px, 0);transform:translate3d(0, 25px, 0)}75%{-webkit-transform:translate3d(0, -10px, 0);transform:translate3d(0, -10px, 0)}90%{-webkit-transform:translate3d(0, 5px, 0);transform:translate3d(0, 5px, 0)}100%{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(-3000px, 0, 0);transform:translate3d(-3000px, 0, 0)}60%{opacity:1;-webkit-transform:translate3d(25px, 0, 0);transform:translate3d(25px, 0, 0)}75%{-webkit-transform:translate3d(-10px, 0, 0);transform:translate3d(-10px, 0, 0)}90%{-webkit-transform:translate3d(5px, 0, 0);transform:translate3d(5px, 0, 0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(-3000px, 0, 0);transform:translate3d(-3000px, 0, 0)}60%{opacity:1;-webkit-transform:translate3d(25px, 0, 0);transform:translate3d(25px, 0, 0)}75%{-webkit-transform:translate3d(-10px, 0, 0);transform:translate3d(-10px, 0, 0)}90%{-webkit-transform:translate3d(5px, 0, 0);transform:translate3d(5px, 0, 0)}100%{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(3000px, 0, 0);transform:translate3d(3000px, 0, 0)}60%{opacity:1;-webkit-transform:translate3d(-25px, 0, 0);transform:translate3d(-25px, 0, 0)}75%{-webkit-transform:translate3d(10px, 0, 0);transform:translate3d(10px, 0, 0)}90%{-webkit-transform:translate3d(-5px, 0, 0);transform:translate3d(-5px, 0, 0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(3000px, 0, 0);transform:translate3d(3000px, 0, 0)}60%{opacity:1;-webkit-transform:translate3d(-25px, 0, 0);transform:translate3d(-25px, 0, 0)}75%{-webkit-transform:translate3d(10px, 0, 0);transform:translate3d(10px, 0, 0)}90%{-webkit-transform:translate3d(-5px, 0, 0);transform:translate3d(-5px, 0, 0)}100%{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(0, 3000px, 0);transform:translate3d(0, 3000px, 0)}60%{opacity:1;-webkit-transform:translate3d(0, -20px, 0);transform:translate3d(0, -20px, 0)}75%{-webkit-transform:translate3d(0, 10px, 0);transform:translate3d(0, 10px, 0)}90%{-webkit-transform:translate3d(0, -5px, 0);transform:translate3d(0, -5px, 0)}100%{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}}@keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215, .61, .355, 1);transition-timing-function:cubic-bezier(.215, .61, .355, 1)}0%{opacity:0;-webkit-transform:translate3d(0, 3000px, 0);transform:translate3d(0, 3000px, 0)}60%{opacity:1;-webkit-transform:translate3d(0, -20px, 0);transform:translate3d(0, -20px, 0)}75%{-webkit-transform:translate3d(0, 10px, 0);transform:translate3d(0, 10px, 0)}90%{-webkit-transform:translate3d(0, -5px, 0);transform:translate3d(0, -5px, 0)}100%{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9, .9, .9);transform:scale3d(.9, .9, .9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}100%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9, .9, .9);transform:scale3d(.9, .9, .9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}100%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0, 10px, 0);transform:translate3d(0, 10px, 0)}40%,45%{opacity:1;-webkit-transform:translate3d(0, -20px, 0);transform:translate3d(0, -20px, 0)}100%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0, 10px, 0);transform:translate3d(0, 10px, 0)}40%,45%{opacity:1;-webkit-transform:translate3d(0, -20px, 0);transform:translate3d(0, -20px, 0)}100%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px, 0, 0);transform:translate3d(20px, 0, 0)}100%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px, 0, 0);transform:translate3d(20px, 0, 0)}100%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px, 0, 0);transform:translate3d(-20px, 0, 0)}100%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px, 0, 0);transform:translate3d(-20px, 0, 0)}100%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0, -10px, 0);transform:translate3d(0, -10px, 0)}40%,45%{opacity:1;-webkit-transform:translate3d(0, 20px, 0);transform:translate3d(0, 20px, 0)}100%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0, -10px, 0);transform:translate3d(0, -10px, 0)}40%,45%{opacity:1;-webkit-transform:translate3d(0, 20px, 0);transform:translate3d(0, 20px, 0)}100%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0, -100%, 0);transform:translate3d(0, -100%, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0, -100%, 0);transform:translate3d(0, -100%, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, 100%, 0);transform:translate3d(0, 100%, 0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, 2000px, 0);transform:translate3d(0, 2000px, 0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px, 0, 0);transform:translate3d(-2000px, 0, 0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px, 0, 0);transform:translate3d(2000px, 0, 0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, -100%, 0);transform:translate3d(0, -100%, 0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, -100%, 0);transform:translate3d(0, -100%, 0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0, -2000px, 0);transform:translate3d(0, -2000px, 0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -360deg);transform:perspective(400px) rotate3d(0, 1, 0, -360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95, .95, .95);transform:perspective(400px) scale3d(.95, .95, .95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -360deg);transform:perspective(400px) rotate3d(0, 1, 0, -360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);transform:perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95, .95, .95);transform:perspective(400px) scale3d(.95, .95, .95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 90deg);transform:perspective(400px) rotate3d(1, 0, 0, 90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -20deg);transform:perspective(400px) rotate3d(1, 0, 0, -20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 10deg);transform:perspective(400px) rotate3d(1, 0, 0, 10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -5deg);transform:perspective(400px) rotate3d(1, 0, 0, -5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 90deg);transform:perspective(400px) rotate3d(1, 0, 0, 90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -20deg);transform:perspective(400px) rotate3d(1, 0, 0, -20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 10deg);transform:perspective(400px) rotate3d(1, 0, 0, 10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -5deg);transform:perspective(400px) rotate3d(1, 0, 0, -5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible !important;backface-visibility:visible !important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 90deg);transform:perspective(400px) rotate3d(0, 1, 0, 90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -20deg);transform:perspective(400px) rotate3d(0, 1, 0, -20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 10deg);transform:perspective(400px) rotate3d(0, 1, 0, 10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -5deg);transform:perspective(400px) rotate3d(0, 1, 0, -5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 90deg);transform:perspective(400px) rotate3d(0, 1, 0, 90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -20deg);transform:perspective(400px) rotate3d(0, 1, 0, -20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 10deg);transform:perspective(400px) rotate3d(0, 1, 0, 10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -5deg);transform:perspective(400px) rotate3d(0, 1, 0, -5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible !important;backface-visibility:visible !important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -20deg);transform:perspective(400px) rotate3d(1, 0, 0, -20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 90deg);transform:perspective(400px) rotate3d(1, 0, 0, 90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, -20deg);transform:perspective(400px) rotate3d(1, 0, 0, -20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1, 0, 0, 90deg);transform:perspective(400px) rotate3d(1, 0, 0, 90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-backface-visibility:visible !important;backface-visibility:visible !important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -15deg);transform:perspective(400px) rotate3d(0, 1, 0, -15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 90deg);transform:perspective(400px) rotate3d(0, 1, 0, 90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, -15deg);transform:perspective(400px) rotate3d(0, 1, 0, -15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0, 1, 0, 90deg);transform:perspective(400px) rotate3d(0, 1, 0, 90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible !important;backface-visibility:visible !important;-webkit-animation-name:flipOutY;animation-name:flipOutY;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%, 0, 0) skewX(-30deg);transform:translate3d(100%, 0, 0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%, 0, 0) skewX(-30deg);transform:translate3d(100%, 0, 0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%, 0, 0) skewX(30deg);transform:translate3d(100%, 0, 0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%, 0, 0) skewX(30deg);transform:translate3d(100%, 0, 0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0, 0, 1, -200deg);transform:rotate3d(0, 0, 1, -200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0, 0, 1, -200deg);transform:rotate3d(0, 0, 1, -200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, -90deg);transform:rotate3d(0, 0, 1, -90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, -90deg);transform:rotate3d(0, 0, 1, -90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0, 0, 1, 200deg);transform:rotate3d(0, 0, 1, 200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0, 0, 1, 200deg);transform:rotate3d(0, 0, 1, 200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, 45deg);transform:rotate3d(0, 0, 1, 45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0, 0, 1, -45deg);transform:rotate3d(0, 0, 1, -45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, 90deg);transform:rotate3d(0, 0, 1, 90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0, 0, 1, 90deg);transform:rotate3d(0, 0, 1, 90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0, 0, 1, 80deg);transform:rotate3d(0, 0, 1, 80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0, 0, 1, 60deg);transform:rotate3d(0, 0, 1, 60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0, 700px, 0);transform:translate3d(0, 700px, 0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0, 0, 1, 80deg);transform:rotate3d(0, 0, 1, 80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0, 0, 1, 60deg);transform:rotate3d(0, 0, 1, 60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0, 700px, 0);transform:translate3d(0, 700px, 0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);transform:translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);transform:translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);transform:translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);transform:translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, -1000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, -1000px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, -1000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, -1000px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);transform:scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(10px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(10px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);transform:scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(10px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(10px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(1000px, 0, 0);transform:scale3d(.1, .1, .1) translate3d(1000px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(-10px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(-10px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(1000px, 0, 0);transform:scale3d(.1, .1, .1) translate3d(1000px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(-10px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(-10px, 0, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, 1000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, 1000px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, 1000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, 1000px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}60%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3, .3, .3);transform:scale3d(.3, .3, .3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}100%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, 2000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, 2000px, 0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, -60px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}100%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, 2000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, 2000px, 0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(42px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(42px, 0, 0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px, 0, 0);transform:scale(.1) translate3d(-2000px, 0, 0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(42px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(42px, 0, 0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px, 0, 0);transform:scale(.1) translate3d(-2000px, 0, 0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(-42px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(-42px, 0, 0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px, 0, 0);transform:scale(.1) translate3d(2000px, 0, 0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(-42px, 0, 0);transform:scale3d(.475, .475, .475) translate3d(-42px, 0, 0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px, 0, 0);transform:scale(.1) translate3d(2000px, 0, 0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}100%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, -2000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, -2000px, 0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);transform:scale3d(.475, .475, .475) translate3d(0, 60px, 0);-webkit-animation-timing-function:cubic-bezier(.55, .055, .675, .19);animation-timing-function:cubic-bezier(.55, .055, .675, .19)}100%{opacity:0;-webkit-transform:scale3d(.1, .1, .1) translate3d(0, -2000px, 0);transform:scale3d(.1, .1, .1) translate3d(0, -2000px, 0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175, .885, .32, 1);animation-timing-function:cubic-bezier(.175, .885, .32, 1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);visibility:visible}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes slideInDown{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);visibility:visible}100%{-webkit-transform:translateY(0);transform:translateY(0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);visibility:visible}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInLeft{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);visibility:visible}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translateX(100%);transform:translateX(100%);visibility:visible}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInRight{0%{-webkit-transform:translateX(100%);transform:translateX(100%);visibility:visible}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translateY(100%);transform:translateY(100%);visibility:visible}100%{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes slideInUp{0%{-webkit-transform:translateY(100%);transform:translateY(100%);visibility:visible}100%{-webkit-transform:translateY(0);transform:translateY(0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%)}}@keyframes slideOutDown{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{visibility:hidden;-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes slideOutLeft{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{visibility:hidden;-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{visibility:hidden;-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes slideOutRight{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{visibility:hidden;-webkit-transform:translateX(100%);transform:translateX(100%)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{visibility:hidden;-webkit-transform:translateY(-100%);transform:translateY(-100%)}}@keyframes slideOutUp{0%{-webkit-transform:translateY(0);transform:translateY(0)}100%{visibility:hidden;-webkit-transform:translateY(-100%);transform:translateY(-100%)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}html,body,div,span,a,li,td,th{font-family:'Lato',sans-serif;font-weight:300}li,.wrappable{white-space:pre;white-space:pre-wrap;white-space:pre-line;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:-moz-pre-wrap;white-space:-hp-pre-wrap;word-wrap:break-word}html{position:relative;min-height:100%;overflow-x:hidden}input[type=checkbox]{-ms-transform:scale(2);-moz-transform:scale(2);-webkit-transform:scale(2);-o-transform:scale(2);padding:10px}body.full-screen-body-background{background-color:#eee}body.top-and-bottom-margins{padding-top:80px;margin-bottom:60px}body.no-top-and-bottom-margins{margin:70px 20px 50px 20px}h1,h2{font-weight:400}.btn{font-weight:400}h1,h2,h3,h4,h5,h6,p,li{padding-top:5px;padding-bottom:5px}.alert{margin-top:20px}.thumbnail{padding:0;border-radius:0;box-shadow:0 0 5px #ccc,inset 0 0 0 #000}.fa,[class^='ion-']{margin-right:5px}.img-center{margin:0 auto}.three-by-three{height:100px}.darker-background{background-color:#dedede}.btn-cta{font-size:40px}.nonprofit-cta{font-size:28px}.btn,.shadow{white-space:normal;-webkit-box-shadow:2px 4px 1px rgba(0,0,0,0.3);-moz-box-shadow:2px 4px 1px rgba(0,0,0,0.3);box-shadow:2px 4px 1px rgba(0,0,0,0.3)}.btn,.shadow{white-space:normal;-webkit-box-shadow:2px 4px 1px rgba(0,0,0,0.3);-moz-box-shadow:2px 4px 1px rgba(0,0,0,0.3);box-shadow:2px 4px 1px rgba(0,0,0,0.3)}.btn-nav{margin-top:10px}ul{list-style:none;word-wrap:break-word}.img-center{margin:0 auto}.centered-iframe{display:block}@media (min-width:767px){.landing-panel-body{padding-left:40px;padding-right:40px}}.landing-panel-heading{font-size:40px}.panel-heading{font-size:25px}.panel-heading>h1{font-size:25px;padding:2px;margin:2px}.navbar-brand{font-size:26px}.ten-pixel-break{height:10px}.fifteen-pixel-break{height:15px}.nav-height{height:50px;border:none}.landing-icon{height:200px;width:200px}.completion-icon{font-size:150px}.responsive-container{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}.responsive-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.positive-5{margin-top:5px}.positive-10{padding-top:10px}.positive-15{margin-top:15px}.negative-45{margin-top:-45px;margin-bottom:-45px}.negative-10{margin-top:-10px}.negative-28{margin-top:-28px}.negative-35{margin-top:-35px}.negative-30{margin-top:-30px}.negative-5{margin-top:-5px}.negative-15{margin-top:-15px}.negative-20{margin-top:-20px}.landing-p{font-size:18px !important}.text-success{color:#457e86}.delay-1{-webkit-animation-delay:1s;animation-delay:1s}.delay-2{-webkit-animation-delay:2s;animation-delay:2s}.delay-4{-webkit-animation-delay:4s;animation-delay:4s}.delay-10{-webkit-animation-delay:10s;animation-delay:10s}.fast-animation{-webkit-animation-duration:.5s;animation-duration:.5s}.slow-animation{-webkit-animation-duration:1.5s;animation-duration:1.5s}.disabled{pointer-events:none;cursor:default;color:graytext !important}.hidden-element{display:none}.button-container{height:120px}.nav-logo{height:40px;margin-top:-10px}@media (max-width:381px){.nav-logo{height:30px;margin-top:-5px}}@media (min-width:767px){.navbar-right{padding-right:50px}}@media (max-width:991px) and (min-width:768px){.navbar-right{position:absolute;right:0;margin-right:10px;white-space:nowrap}}.navbar{white-space:nowrap;border:none}@media (min-width:767px){.navbar{padding-left:30px;padding-right:30px}}.panel-body{margin-bottom:-6px}.strikethrough{text-decoration:line-through}.btn-social{width:250px;margin:auto}.btn-link-social{max-width:400px;margin:auto;margin-bottom:10px}.navbar{background-color:#4a2b0f}.navbar-nav>li>a{color:#eee}.navbar-nav>li>a:hover{color:#4a2b0f}.hug-top{margin-top:-35px;margin-bottom:-10px}.nonprofit-landing{font-size:50px}.big-text{font-size:63px}.scroll-lock{overflow:hidden;height:100%}.signup-btn.btn{background-color:#ffac33;background-image:linear-gradient(#ffcc4d, #ffac33);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffcc4d, endColorstr=#ffac33, GradientType=0)";border-color:#f1a02a;color:#292f33 !important;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.signup-btn:hover,.signup-btn:focus{background-color:#e99110;background-image:linear-gradient(#ffcc4d, #e99110);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffcc4d, endColorstr=#e99110, GradientType=0)";border-color:#ec8b11;color:#292f33 !important}.signup-btn:active{background-color:#f2a330;background-image:none;box-shadow:inset 0 1px 4px rgba(0,0,0,0.3)}.profile-image{border-radius:5px;width:200px;height:200px;padding-left:5px;padding-right:5px}.team-member{height:420px}*,*:before,*:after{box-sizing:border-box !important}.masonry-row{-moz-column-width:18em;-webkit-column-width:18em;-moz-column-gap:1em;-webkit-column-gap:1em}.masonry-block{display:inline-block;padding:.25rem;width:100%}.masonry-relative{position:relative;display:block}.next-challenge-button{max-width:1500px;margin:0 auto}.btn-big{font-size:30px}.big-text-field{font-size:30px;height:57px}@media (max-width:768px){.btn-responsive{font-size:15px;height:26.5px;padding-top:1px}}@media (max-width:768px){.field-responsive{font-size:15px;height:26.5px}}.table{margin-left:-16px}thead{font-size:150%}.nowrap{white-space:nowrap}.big-break{margin-top:50px;margin-bottom:50px}.profile-picture{height:50px;width:50px}.navbar-nav a{color:#eee;font-size:20px;margin-top:-5px;margin-bottom:-5px}.navbar-toggle{color:#eee}.navbar-right{background-color:#4a2b0f;text-align:center}.signup-btn-nav{margin-top:-2px !important;padding-top:10px !important;padding-bottom:10px !important}.nameline{margin-top:-5px;font-size:40px}.public-profile-img{height:200px;width:200px;border-radius:5px}.ng-invalid.ng-dirty{border-color:#fa787e}.ng-valid.ng-dirty{border-color:#78fa89}@media (min-width:767px){.desktop-narrow{marign:0 auto;width:80%}}.min650{min-height:630px}.portfolio-image{height:225px;width:300px;border-radius:5px}.flat-top{margin-top:-5px}.negative-bottom{margin-bottom:-20px}.min-height-1000{min-height:1000px}.points-on-top{color:#eee;font-size:35px;z-index:2;width:60%;margin:0 auto;position:relative;top:50%;transform:translateY(-50%)}.landing-skill-icon{color:#215f1e;font-size:150px}.black-text{color:#333;font-weight:400;font-size:40px}.font-awesome-padding{margin-top:45px;margin-bottom:20px}.background-svg{width:220px;height:220px;background-image:url("https://s3.amazonaws.com/freecodecamp/certificate-icon.svg");background-size:120%;background-repeat:no-repeat;background-position:center}.testimonial-image{border-radius:5px;height:200px;width:200px;color:#090}.testimonial-copy{font-size:20px;text-align:center}@media (min-width:991px) and (max-width:1199px){.testimonial-copy{height:120px}}@media (min-width:1200px){.testimonial-copy{height:90px}}@media (max-width:768px){.hamburger-dropdown{margin-top:-5px}}.challenge-list-header{background-color:#215f1e;color:#eee;font-size:36px;text-align:center;margin-bottom:-30px;border-radius:5px 5px 0 0;padding-left:50px}.all-list-header{background-color:#4a2b0f;color:#eee;font-size:36px;text-align:center;margin-bottom:-30px;border-radius:5px 5px 0 0;padding-left:50px}.closing-x{color:#eee;font-size:50px;text-align:right}.fcc-footer{width:100%;height:50px;text-align:center;background-color:#4a2b0f;padding:12px;bottom:0;left:0;position:absolute}.fcc-footer a{font-size:20px;color:#eee;margin-left:0;margin-right:0;padding-left:10px;padding-right:10px}.fcc-footer a:hover{padding-top:14px;padding-bottom:14px;color:#4a2b0f;background-color:#eee;text-decoration:none}.embed-responsive-twitch-chat{padding-bottom:117%}#directions{text-align:left;font-size:15px}.jquery-exercises-well{text-align:left;height:200px}#exercise-directory{font-size:20px}#current-exercise{text-size:250px}.bonfire-instructions{margin-bottom:5px}.graph-rect{fill:#ddd !important}form.code span{font-size:18px;font-family:"Ubuntu Mono";padding-bottom:0;margin-bottom:0;height:100%}.CodeMirror-linenumber{font-size:18px;font-family:"Ubuntu Mono"}#mainEditorPanel{height:100%}.big-error-icon{font-size:40px;color:#d9534f}.big-success-icon{font-size:40px;color:#215f1e}.test-output{font-size:15px;font-family:"Ubuntu Mono"}#mainEditorPanel .panel-body{padding-bottom:0}.panel-bonfire{height:100%}div.CodeMirror-scroll{padding-bottom:30px}.test-vertical-center{margin-top:8px}.cm-s-monokai.CodeMirror{border-radius:5px}.bonfire-flames{margin-top:-20px;margin-bottom:-2px}.bonfire-top{margin-top:-30px}iframe.iphone{border:none}@media (min-width:992px){iframe.iphone{width:280px;height:500px;position:absolute;top:70px;right:25px;overflow-y:scroll}}@media (max-width:991px){iframe.iphone{width:100%;border-radius:5px;overflow-y:visible}}.nonprofit-help-select-text-height{font-size:40px;padding-top:20px}.iphone-position{position:absolute;top:-50px;right:-205px;z-index:-1}.courseware-height{min-height:650px}.icon-lock{font-size:0}.stats-text{font-size:26px;line-height:150%}.github-and-twitter-button-text{padding-top:10px}.gitter-imbed{height:100%;margin-bottom:50px}.btn-primary-ghost{background:transparent;color:#215f1e;-webkit-transition:background .2s ease-in-out,border .2s ease-in-out;-moz-transition:background .2s ease-in-out,border .2s ease-in-out;-ms-transition:background .2s ease-in-out,border .2s ease-in-out;-o-transition:background .2s ease-in-out,border .2s ease-in-out;transition:background .2s ease-in-out,border .2s ease-in-out}@media (max-width:991px){.navbar-header{float:none}.navbar-toggle{display:block}.navbar-collapse.collapse{display:none !important}.navbar-nav{float:none !important;margin:7.5px -15px}.navbar-nav>li{float:none}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.navbar-text{float:none;margin:15px 0}.navbar-collapse.collapse.in{display:block !important}.collapsing{overflow:hidden !important}}.hamburger{width:80px;padding-left:0;padding-right:8px;margin-left:0;margin-right:2px;text-align:left;font-size:10px}.hamburger-text{line-height:.75em;margin-top:10px;font-size:16px;margin-left:-8px}.tight-h3{margin-top:-4px;margin-bottom:-4px}.story-list{padding-bottom:30px;margin-bottom:30px}.big-ion-up-arrow{font-size:45px;margin-top:-10px;margin-bottom:-15px;text-align:center}.big-ion-up-arrow #upvote,#reply-to-main-post{cursor:pointer}.story-up-votes{padding-top:0;margin-left:-5px;text-align:center}.control-label .control-label-story-submission{telt-align:left}.img-story-post{max-width:110px;max-height:110px}.button-spacer{padding:3px 0 2px 0}.spacer{padding:15px 0 15px 0}.img-news{width:50px;height:50px}.url-preview{max-width:250px;max-height:250px}@media (min-width:768px){.news-box{margin-top:-40px}}@media (max-width:767px){.news-box{padding:5px;border-color:#4a2b0f;border-width:1px;border-style:solid;border-radius:5px;width:100%;float:left}}@media (min-width:768px){.news-box-search{margin-top:-50px}}@media (max-width:767px){.news-box-search{padding:5px;border-color:#4a2b0f;border-width:1px;border-style:solid;border-radius:5px;width:100%;float:left}}.story-headline{font-size:20px;margin-left:14px;margin-top:-5px}.mobile-story-headline{font-size:20px}.story-byline{margin-top:5px;font-size:14px}.media-stories{margin-left:20px}hr{-moz-border-bottom-colors:none;-moz-border-image:none;-moz-border-left-colors:none;-moz-border-right-colors:none;-moz-border-top-colors:none;border-color:#555;border-style:solid none;border-width:1px 0;margin:18px 0}#reply-to-main-post,#upvote{cursor:pointer}.btn-no-shadow{-webkit-box-shadow:0 0 0 rgba(0,0,0,0);-moz-box-shadow:0 0 0 rgba(0,0,0,0);box-shadow:0 0 0 rgba(0,0,0,0)}.dotted-underline{border-bottom:dashed 1px #457e86}.d3-centered{width:771px;margin:0 auto}.cal-heatmap-container{background-color:#eee}.checkbox-table label{margin-left:10px}.interested-camper-image{height:50px;width:50px;padding:5px}.svg-challenge-map{fill:#333;height:40px}.news-number{font-size:30px;text-align:center}.mobile-story-image{border-radius:5px;width:100%}@media (max-width:768px){.mobile-story-image{margin-right:5px}}.alert a{text-decoration:underline}.step-text{line-height:120%;padding-bottom:10px}.faded{opacity:.5}.same-line{display:inline-block}.padded-ionic-icon{padding-top:5px}.checklist-element{margin-left:-60px;margin-right:-20px}.profile-social-icons{margin-left:8px}.border-radius-5{border-radius:5px}.grayed-out-test-output{color:#777} \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index 3b4e543bfe..901182006a 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -16,6 +16,28 @@ $(document).ready(function() { setCSRFToken($('meta[name="csrf-token"]').attr('content')); + $('#i-need-help').on('click', function() { + var editorValue = editor.getValue(); + var currentLocation = window.location.href + console.log('clicked!'); + $.post( + '/get-help', + { + payload: { + code: editorValue, + challenge: currentLocation + } + }, + function(res) { + console.log(res); + if (res) { + window.location.href = 'https://freecode.slack.com/messages/help/' + } + } + ); + + }); + $('.checklist-element').each(function() { var checklistElementId = $(this).attr('id'); if(!!localStorage[checklistElementId]) { @@ -372,28 +394,28 @@ profileValidation.directive('uniqueUsername', ['$http', function($http) { profileValidation.directive('existingUsername', ['$http', function($http) { - return { - restrict: 'A', - require: 'ngModel', - link: function (scope, element, attrs, ngModel) { - element.bind('keyup', function (event) { - if (element.val().length > 0) { - ngModel.$setValidity('exists', false); - } else { - element.removeClass('ng-dirty'); - ngModel.$setPristine(); - } - if (element.val()) { - $http - .get('/api/checkExistingUsername/' + element.val()) - .success(function (data) { - ngModel.$setValidity('exists', data); - }); - } - }); - } - }; -}]); + return { + restrict: 'A', + require: 'ngModel', + link: function (scope, element, attrs, ngModel) { + element.bind('keyup', function (event) { + if (element.val().length > 0) { + ngModel.$setValidity('exists', false); + } else { + element.removeClass('ng-dirty'); + ngModel.$setPristine(); + } + if (element.val()) { + $http + .get('/api/checkExistingUsername/' + element.val()) + .success(function (data) { + ngModel.$setValidity('exists', data); + }); + } + }); + } + }; + }]); profileValidation.directive('uniqueEmail', ['$http', function($http) { return { diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json index 8a51f9ddbb..e5893a4a5e 100644 --- a/seed_data/challenges/jquery-ajax-and-json.json +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -10,8 +10,7 @@ "Test" ], "tests": [ - "assert($('#target').hasClass('disabled'), 'The button with the ID of \"target\" should continue to have the \"disabled\" class.')", - "assert(!!$('#target[disabled]'), 'Enable the button with the ID of \"target\" by using jQuery.')", + "assert(typeof $('#target').attr('disabled') === 'undefined', 'Change the disabled attribute of the \"target\" button to false');", "expect($('#target')).to.exist()" ], "challengeSeed": [ @@ -21,7 +20,8 @@ " });", "fcces", "" - ] + ], + "challengeType": 0 }, { @@ -51,7 +51,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -66,7 +67,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -81,7 +83,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -96,7 +99,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -126,7 +130,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -141,7 +146,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -156,7 +162,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -171,7 +178,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -186,7 +194,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, @@ -202,7 +211,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -217,7 +227,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -232,7 +243,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -247,7 +259,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -262,7 +275,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -277,7 +291,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 } ] } diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 50f20eb569..6f1d23338b 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -19,6 +19,7 @@ block content script(src='/js/lib/codemirror/mode/css/css.js') script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') .row.courseware-height + .btn.btn-warning#i-need-help I need help! .col-xs-12.col-sm-12.col-md-3.col-lg-3 .well .row From 9da9b016077518afcd87652b119d0d9e028ce2e7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Fri, 22 May 2015 23:36:42 -0700 Subject: [PATCH 48/81] update challenge map challenge --- seed_data/challenges/getting-set-for-free-code-camp.json | 3 ++- seed_data/coursewares.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/seed_data/challenges/getting-set-for-free-code-camp.json b/seed_data/challenges/getting-set-for-free-code-camp.json index 92c5cc6f8b..8f6a23b779 100644 --- a/seed_data/challenges/getting-set-for-free-code-camp.json +++ b/seed_data/challenges/getting-set-for-free-code-camp.json @@ -50,7 +50,8 @@ "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", "You should complete all these challenges in order.", "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", - "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." + "This challenge map is just for your reference. You can always just press the \"Learn\" button, and it will take you to your next challenge.", + "Finally, please note that our open-source curriculum is a work in progress. Our volunteer community is constantly improving it. If you think you've encountered a bug, typo, or something that seems confusing, please open a GitHub issue: https://github.com/FreeCodeCamp/freecodecamp/issues." ], "challengeType": 2, "tests": [] diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 1e35a0175d..348e3fb76a 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -47,7 +47,8 @@ "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", "You should complete all these challenges in order.", "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", - "This challenge map is just for your reference. When you return to FreeCodeCamp.com, we'll automatically redirect you to the next challenge that you should be doing." + "This challenge map is just for your reference. You can always just press the \"Learn\" button, and it will take you to your next challenge.", + "Finally, please note that our open-source curriculum is a work in progress. Our volunteer community is constantly improving it. If you encounter a bug or something you think is unnecessarily hard, let us know: https://github.com/FreeCodeCamp/freecodecamp/issues." ], "challengeType": 2, "tests": [] From a3ab32f339614cae5b9e020e3dff216ff546215a Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 23 May 2015 00:53:41 -0700 Subject: [PATCH 49/81] improve get help and add find a pair --- app.js | 1 + controllers/resources.js | 24 +++++++++++++++++++++--- package.json | 1 + public/js/main.js | 26 ++++++++++++++++++++------ views/coursewares/showHTML.jade | 5 ++++- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/app.js b/app.js index e84b796a26..843aaa367f 100755 --- a/app.js +++ b/app.js @@ -228,6 +228,7 @@ app.get('/nonprofit-project-instructions', function(req, res) { app.post('/get-help', resourcesController.getHelp); +app.post('/get-pair', resourcesController.getPair); app.get('/chat', resourcesController.chat); diff --git a/controllers/resources.js b/controllers/resources.js index 20a99a2080..c3d71ac6bd 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -592,10 +592,28 @@ module.exports = { var challenge = req.body.payload.challenge; slack.send({ - text: "User " + userName + " needs help with challenge " + - "" + challenge + "!\n```\n" + code + "\n```", + text: "*" + userName + "* wants help with " + challenge + "\n```\n" + + code + "\n```\n Hey, *" + userName + "*, if no one helps you right " + + "away, try typing out your problem in detail to me. Like this: " + + "http://en.wikipedia.org/wiki/Rubber_duck_debugging", channel: '#help', - username: userName + username: "Debuggy the Rubber Duck", + icon_emoji: ":hatched_chick:" + }); + return res.sendStatus(200); + + }, + + getPair: function(req, res, next) { + var userName = req.user.profile.username; + var challenge = req.body.payload.challenge; + console.log('test'); + + slack.send({ + text: "Anyone want to pair with *" + userName + "* on " + challenge + "? (In the meantime, keep coding, *" + userName + "*)", + channel: '#letspair', + username: "Perry the Matchmaker", + icon_emoji: ":dancers:" }); return res.sendStatus(200); diff --git a/package.json b/package.json index 72dae9262c..1b5f3b319c 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "mongoose": "~4.0.1", "mongoose-long": "0.0.2", "morgan": "~1.5.0", + "node-slack": "0.0.7", "nodemailer": "~1.3.0", "passport": "~0.2.1", "passport-facebook": "~1.0.3", diff --git a/public/js/main.js b/public/js/main.js index 901182006a..9f2392fc00 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -16,26 +16,40 @@ $(document).ready(function() { setCSRFToken($('meta[name="csrf-token"]').attr('content')); - $('#i-need-help').on('click', function() { + $('#i-want-help').on('click', function() { var editorValue = editor.getValue(); - var currentLocation = window.location.href - console.log('clicked!'); + var currentLocation = window.location.href; $.post( '/get-help', { payload: { code: editorValue, + challenge: currentLocation, + } + }, + function(res) { + if (res) { + window.open('https://freecode.slack.com/messages/help/', '_blank') + } + } + ); + }); + + $('#i-want-to-pair').on('click', function() { + var currentLocation = window.location.href; + $.post( + '/get-pair', + { + payload: { challenge: currentLocation } }, function(res) { - console.log(res); if (res) { - window.location.href = 'https://freecode.slack.com/messages/help/' + window.open('https://freecode.slack.com/messages/letspair/', '_blank') } } ); - }); $('.checklist-element').each(function() { diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 6f1d23338b..05dd0cbaa9 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -19,7 +19,6 @@ block content script(src='/js/lib/codemirror/mode/css/css.js') script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') .row.courseware-height - .btn.btn-warning#i-need-help I need help! .col-xs-12.col-sm-12.col-md-3.col-lg-3 .well .row @@ -44,6 +43,10 @@ block content | Go to my next challenge br | (ctrl + enter) + .button-spacer + a.btn.btn-warning.btn-big.btn-block#i-want-help Get help + .button-spacer + a.btn.btn-success.btn-big.btn-block#i-want-to-pair Find a Pair script. var userLoggedIn = true; - else From 27a35e65a73380627fb663652f0b1e27c04cb6e2 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 23 May 2015 16:48:55 -0700 Subject: [PATCH 50/81] make a ton of small improvements related to github issues --- controllers/resources.js | 9 +- controllers/story.js | 6 +- models/User.js | 1 - seed_data/challenges.json | 1 - seed_data/challenges/basejumps.json | 6 +- seed_data/field-guides.json | 405 ++++++++++++++-------------- views/account/show.jade | 4 +- views/coursewares/showBonfire.jade | 6 + views/field-guide/show.jade | 4 +- views/stories/news-nav.jade | 15 +- 10 files changed, 233 insertions(+), 224 deletions(-) delete mode 100644 seed_data/challenges.json diff --git a/controllers/resources.js b/controllers/resources.js index c3d71ac6bd..e9fb94849d 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -588,12 +588,14 @@ module.exports = { getHelp: function(req, res, next) { var userName = req.user.profile.username; - var code = req.body.payload.code; + var code = req.body.payload.code ? '\n```\n' + + req.body.payload.code + '\n```\n' + : ''; var challenge = req.body.payload.challenge; slack.send({ - text: "*" + userName + "* wants help with " + challenge + "\n```\n" - + code + "\n```\n Hey, *" + userName + "*, if no one helps you right " + + text: "*" + userName + "* wants help with " + challenge + " " + + code + "Hey, *" + userName + "*, if no one helps you right " + "away, try typing out your problem in detail to me. Like this: " + "http://en.wikipedia.org/wiki/Rubber_duck_debugging", channel: '#help', @@ -601,7 +603,6 @@ module.exports = { icon_emoji: ":hatched_chick:" }); return res.sendStatus(200); - }, getPair: function(req, res, next) { diff --git a/controllers/story.js b/controllers/story.js index 4f3321f669..233f929b69 100755 --- a/controllers/story.js +++ b/controllers/story.js @@ -558,12 +558,10 @@ exports.storySubmission = function(req, res, next) { ' replied to your post on Camper News', text: [ 'Just a quick heads-up: ', - data.author.username, - ' replied to you on Camper News.', + data.author.username + ' replied to you on Camper News.', 'You can keep this conversation going.', 'Just head back to the discussion here: ', - 'http://freecodecamp.com/news/', - data.originalStoryLink, + 'http://freecodecamp.com/news/' + data.originalStoryLink, '- the Free Code Camp Volunteer Team' ].join('\n') }; diff --git a/models/User.js b/models/User.js index 718a965c61..e47d75326f 100644 --- a/models/User.js +++ b/models/User.js @@ -150,7 +150,6 @@ var userSchema = new mongoose.Schema({ // needsMigration has been deprecated, use needsSomeDataModeled needsMigration: { type: Boolean, default: true }, - finishedWaypoints: { type: Boolean, default: false }, sendMonthlyEmail: { type: Boolean, default: true }, challengesHash: {}, currentChallenge: {}, diff --git a/seed_data/challenges.json b/seed_data/challenges.json deleted file mode 100644 index c1212e28a1..0000000000 --- a/seed_data/challenges.json +++ /dev/null @@ -1 +0,0 @@ -["./challenges/prepwork.json", "./challenges/basics.json"] \ No newline at end of file diff --git a/seed_data/challenges/basejumps.json b/seed_data/challenges/basejumps.json index 95ec8505f8..3681225266 100644 --- a/seed_data/challenges/basejumps.json +++ b/seed_data/challenges/basejumps.json @@ -42,7 +42,11 @@ "Start the application by running the following command in your new terminal window: grunt serve", "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", - "Create a new Github repository by signing in to http://github.com and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", + "Now we need to add your github SSH key to c9.io. Click the \"Add-on Services\" button in the lower left of your C9 dashboard. Click \"activate\" next to the GitHub icon.", + "A pop up will appear. Allow access to your account.", + "While still on the dashboard, under “Account Settings”, click the link for \"Show your SSH key\". Copy the key to you clipboard.", + "Sign in to http://github.com and navigate to the GitHub SSH settings page. Click the \"Add SSH Key\". Give your key the title \"cloud 9\". Paste your SSH Key into the \"Key\" box, then click \"Add Key\".", + "Create a new Github repository by and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", "Enter a project name, then click the \"Create Repository\" button.", "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to Github.", diff --git a/seed_data/field-guides.json b/seed_data/field-guides.json index a9a0166545..d8a3147aee 100644 --- a/seed_data/field-guides.json +++ b/seed_data/field-guides.json @@ -4,9 +4,9 @@ "name": "How do I use this guide?", "description": [ "
    ", - "

    This guide strives to provide clear answers to common questions about Free Code Camp, learning to code, and getting a coding job.

    ", - "

    If you're logged in, you can click the \"Next article\" button to go to your next article.

    ", - "

    You can also click the \"Show me all articles\" button to browse all the questions we answer.

    ", + "

    This guide strives to provide clear answers to common questions about Free Code Camp, learning to code, and getting a coding job.

    ", + "

    If you're logged in, you can click the \"Next article\" button to go to your next article.

    ", + "

    You can also click the \"Show me all articles\" button to browse all the questions we answer.

    ", "
    " ] }, @@ -15,15 +15,15 @@ "name": "What exactly is Free Code Camp?", "description": [ "
    ", - "

    We're a community of busy people who learn to code by building projects for nonprofits.

    ", - "

    We help our campers (students):

    ", - "

    ", + "

    We're a community of busy people who learn to code by building projects for nonprofits.

    ", + "

    We help our campers (students):

    ", + "

    ", "

      ", "
    1. Learn full stack JavaScript
    2. ", "
    3. Build a portfolio of real apps that real people are using
    4. ", "
    5. Get a coding job
    6. ", "
    ", - " ", + "

    ", "
    " ] }, @@ -32,15 +32,15 @@ "name": "Why do I need Free Code Camp?", "description": [ "
    ", - "

    Learning to code is hard.

    ", - "

    Most people who successfully learn to code:

    ", - "

    ", + "

    Learning to code is hard.

    ", + "

    Most people who successfully learn to code:

    ", + "

    ", "

      ", "
    1. Make friends with people who code
    2. ", "
    3. Code a little every day
    4. ", "
    ", - " ", - "

    We give you the structure and the community you need so you can successfully learn to code.

    ", + "

    ", + "

    We give you the structure and the community you need so you can successfully learn to code.

    ", "
    " ] }, @@ -49,14 +49,14 @@ "name": "What are the main advantages of Free Code Camp?", "description": [ "
    ", - "

    Our main advantage is that we're accessible to busy adults who want to change careers. Specifically, we're:

    ", - "

    ", + "

    Our main advantage is that we're accessible to busy adults who want to change careers. Specifically, we're:

    ", + "

    ", "

      ", "
    • • Free
    • ", "
    • • Self-paced
    • ", "
    • • Browser-based
    • ", "
    ", - " ", + "

    ", "
    " ] }, @@ -65,7 +65,7 @@ "name": "How does Free Code Camp work?", "description": [ "
    ", - "

    Our free, self-paced, browser-based program takes about 1,600 hours to complete.", + "

    Our free, self-paced, browser-based program takes about 1,600 hours to complete.", "
    ", " An image of a table showing the different segments of Free Code Camp", "
    ", @@ -86,17 +86,17 @@ "name": "Will I really be able to get a job after Free Code Camp?", "description": [ "
    ", - "

    If you complete this program, you will be able to get a coding job. Many of our campers have already gotten coding jobs.

    ", + "

    If you complete this program, you will be able to get a coding job. Many of our campers have already gotten coding jobs.

    ", " ", - "

    Here are the facts:

    ", - "

    ", + "

    Here are the facts:

    ", + "

    ", "

      ", "
    • • There are hundreds of thousands of unfilled coding jobs.
    • ", "
    • • Employers and the US government have joined together to promote nontraditional coding programs like Free Code Camp.
    • ", "
    • • Full stack JavaScript is one of best paying skill sets, and has a ton of job openings.
    • ", "
    • • The best proof that you're an employable developer is a portfolio filled with real apps that real people are using.
    • ", "
    ", - "

    ", + "

    ", "
    " ] }, @@ -105,8 +105,8 @@ "name": "What will I learn, and in what sequence?", "description": [ "
    ", - "

    First, you'll learn basic web design tools like:", - "

    ", + "

    First, you'll learn basic web design tools like:

    ", + "

    ", "

      ", "
    • • HTML - the structure of web pages
    • ", "
    • • CSS - the visual style of web pages
    • ", @@ -114,16 +114,16 @@ "
    • • jQuery - an easy tool for controlling content in the browser
    • ", "
    • • Chrome DevTools - a tool for understanding and debugging websites, right in your browser
    • ", "
    ", - " ", - "

    Then you'll learn computer science and the art of programming:

    ", - "

    ", + "

    ", + "

    Then you'll learn computer science and the art of programming:

    ", + "

    ", "

      ", "
    • • JavaScript - the one programming language that all web browsers use
    • ", "
    • • Algorithms - step-by-step recipes for getting things done
    • ", "
    ", - " ", - "

    Finally you'll learn Agile Methodologies and Full Stack JavaScript to build projects for nonprofits:

    ", - "

    ", + "

    ", + "

    Finally you'll learn Agile Methodologies and Full Stack JavaScript to build projects for nonprofits:

    ", + "

    ", "

      ", "
    • • Agile - a set of software development principles that focus the design and production of a project on the needs of its users
    • ", "
    • • Git - a version control system for saving and sharing your projects
    • ", @@ -132,7 +132,7 @@ "
    • • Express.js - a powerful web development framework
    • ", "
    • • Node.js - a platform for creating scalable network applications.
    • ", "
    ", - " ", + "

    ", "
    " ] }, @@ -141,8 +141,8 @@ "name": "How long does Free Code Camp take?", "description": [ "
    ", - "

    It takes about 1,600 hours of coding to develop the skills you'll need to get an entry level software engineering job.

    ", - "

    Most coding bootcamps try to jam all this into 3 or 4 months of intensive study. Free Code Camp is fully online, and there will always be other people at your skill level that you can pair program with, so you can learn at your own pace. Here are some example coding schedules:

    ", + "

    It takes about 1,600 hours of coding to develop the skills you'll need to get an entry level software engineering job.

    ", + "

    Most coding bootcamps try to jam all this into 3 or 4 months of intensive study. Free Code Camp is fully online, and there will always be other people at your skill level that you can pair program with, so you can learn at your own pace. Here are some example coding schedules:

    ", " ", " ", " ", @@ -178,9 +178,9 @@ "name": "Why does Free Code Camp use JavaScript instead of Ruby or Python?", "description": [ "
    ", - "

    Like JavaScript, Ruby and Python are high-level scripting languages that can be used for full stack web development.

    ", - "

    But even if you learned these languages, you'd still need to learn JavaScript. That's because JavaScript is the only language that runs in web browsers. JavaScript has been around for 20 years, and it is still growing in popularity.

    ", - "

    Because of this, JavaScript has more tools and online learning resources than any other language.

    ", + "

    Like JavaScript, Ruby and Python are high-level scripting languages that can be used for full stack web development.

    ", + "

    But even if you learned these languages, you'd still need to learn JavaScript. That's because JavaScript is the only language that runs in web browsers. JavaScript has been around for 20 years, and it is still growing in popularity.

    ", + "

    Because of this, JavaScript has more tools and online learning resources than any other language.

    ", " \"A", "
    ", "
    " @@ -191,10 +191,10 @@ "name": "What is pair programming, and why is it special?", "description": [ "
    ", - "

    Pair programming is where two people code together on one computer.

    ", + "

    Pair programming is where two people code together on one computer.

    ", " ", - "

    You discuss different approaches to solving problems, and keep each other motivated. The result is better code than either of you could have written by yourselves. Because of its benefits, many engineers pair program full time. And it's the best way to learn coding. Thanks to tools that allow two people to share mouse and keyboard inputs, you can pair program with a friend without needing to be in the same room.

    ", - "

    By pair programming with other Free Code Camp students on our coding challenges. Eventually, you'll work with people at nonprofits to build real-life software solutions.

    ", + "

    You discuss different approaches to solving problems, and keep each other motivated. The result is better code than either of you could have written by yourselves. Because of its benefits, many engineers pair program full time. And it's the best way to learn coding. Thanks to tools that allow two people to share mouse and keyboard inputs, you can pair program with a friend without needing to be in the same room.

    ", + "

    By pair programming with other Free Code Camp students on our coding challenges. Eventually, you'll work with people at nonprofits to build real-life software solutions.

    ", "
    " ] }, @@ -203,20 +203,20 @@ "name": "How do I get help when I get stuck?", "description": [ "
    ", - "

    When you get stuck, remember: RSAP.

    ", - "

    ", + "

    When you get stuck, remember: RSAP.

    ", + "

    ", "

      ", "
    1. Read the documentation or error
    2. ", "
    3. Search Google
    4. ", "
    5. Ask your friends for help
    6. ", "
    7. Post on Stack Overflow
    8. ", "
    ", - " ", - "

    This is the most time-efficient way to handle being stuck, and it's the most respectful of other people's time, too.

    ", - "

    Most of the time, you'll solve your problem after just one or two steps of this algorithm.

    ", - "

    We have a special chat room just for getting help: https://freecode.slack.com/messages/help/

    ", - "

    Also, if you need to post on Stack Overflow, be sure to read their guide to asking good questions: http://stackoverflow.com/help/how-to-ask.

    ", - "

    Learning to code is hard. But it's a lot easier if you ask for help when you need it!

    ", + "

    ", + "

    This is the most time-efficient way to handle being stuck, and it's the most respectful of other people's time, too.

    ", + "

    Most of the time, you'll solve your problem after just one or two steps of this algorithm.

    ", + "

    We have a special chat room just for getting help: https://freecode.slack.com/messages/help/

    ", + "

    Also, if you need to post on Stack Overflow, be sure to read their guide to asking good questions: http://stackoverflow.com/help/how-to-ask.

    ", + "

    Learning to code is hard. But it's a lot easier if you ask for help when you need it!

    ", "
    " ] }, @@ -225,9 +225,9 @@ "name": "Can I jump around in this guide?", "description": [ "
    ", - "

    This guide was designed as a reference for you. You shouldn't try to read it all today.

    ", - "

    Feel free to come back any time and jump around, reading any articles that seem interesting to you at the time.

    ", - "

    If you're currently doing our \"Browse our Field Guide\" Waypoint, go ahead and mark that challenge complete and move on to your next Waypoint.

    ", + "

    This guide was designed as a reference for you. You shouldn't try to read it all today.

    ", + "

    Feel free to come back any time and jump around, reading any articles that seem interesting to you at the time.

    ", + "

    If you're currently doing our \"Browse our Field Guide\" Waypoint, go ahead and mark that challenge complete and move on to your next Waypoint.

    ", "
    " ] }, @@ -236,10 +236,10 @@ "name": "If Free Code Camp is free, how does it make money?", "description": [ "
    ", - "

    We are completely free for both students and for nonprofits.

    ", - "

    Our name is Free Code Camp. We are a free code camp. If you had to pay us (or sign over future earnings), we'd have to change our name. And we are not going to do that.

    ", - "

    We don't make any money at all. Everyone working on our community and our open source projects is a volunteer.

    ", - "

    We plan to eventually cover our operational costs by earning job placement bonuses from companies who hire our graduates. Note that we will not actually garnish any wages from our graduates - employers are already paying recruiters thousands of dollars to find successful candidates. Employers will simply pay the recruitment bonus to Free Code Camp instead of paying a recruiter.

    ", + "

    We are completely free for both students and for nonprofits.

    ", + "

    Our name is Free Code Camp. We are a free code camp. If you had to pay us (or sign over future earnings), we'd have to change our name. And we are not going to do that.

    ", + "

    Everyone working on our community and our open source projects is a volunteer.

    ", + "

    We plan to eventually cover our operational costs by earning job placement bonuses from companies who hire our graduates. Note that we will not actually garnish any wages from our graduates - employers are already paying recruiters thousands of dollars to find successful candidates. Employers will simply pay the recruitment bonus to Free Code Camp instead of paying a recruiter.

    ", "
    " ] }, @@ -248,9 +248,9 @@ "name": "Does Free Code Camp have an application process?", "description": [ "
    ", - "

    Unlike coding bootcamps, anyone can study at Free Code Camp.

    ", - "

    We're not going to tell you that you can't become a software engineer. We believe the only person who should be able to tell you that is you.

    ", - "

    If you persevere, and keep working through our challenges and nonprofit projects, you will become an employable software engineer.

    ", + "

    Unlike coding bootcamps, anyone can study at Free Code Camp.

    ", + "

    We're not going to tell you that you can't become a software engineer. We believe the only person who should be able to tell you that is you.

    ", + "

    If you persevere, and keep working through our challenges and nonprofit projects, you will become an employable software engineer.

    ", "
    " ] }, @@ -259,18 +259,18 @@ "name": "How can I stream my live coding sessions on Free Code Camp's Twitch.tv channel?", "description": [ "
    ", - "

    If you're interested in coding JavaScript live in front of dozens of people on our popular twitch.tv channel, we'd love to have you.

    ", - "

    Please follow these steps to get started:

    ", - "

    ", + "

    If you're interested in coding JavaScript live in front of dozens of people on our popular twitch.tv channel, we'd love to have you.

    ", + "

    Please follow these steps to get started:

    ", + "

    ", "

      ", "
    1. Follow this tutorial to set up your computer for streaming.
    2. ", "
    3. Contact Jason Ruekert - he's @jsonify in Slack. He's in charge of our Twitch.tv channel. Tell him what you'd like to stream, and when you're available to stream.
    4. ", "
    5. Jason will pair with you using Screen Hero to verify your computer is configured properly to stream.
    6. ", "
    ", - " ", - "

    Be respectful of your audience. Everything you stream should be related to coding JavaScript, and should be acceptable for children. (Yes, children do sometimes watch our Twitch stream to learn to code).

    ", - "

    While you're streaming, keep the chat room open so you can respond to questions from your viewers. If someone follows Free Code Camp on Twitch, try to thank them.

    ", - "

    If you do a good job, we'll invite you back to stream some more. Who knows, you might become one of our regular streamers!

    ", + "

    ", + "

    Be respectful of your audience. Everything you stream should be related to coding JavaScript, and should be acceptable for children. (Yes, children do sometimes watch our Twitch stream to learn to code).

    ", + "

    While you're streaming, keep the chat room open so you can respond to questions from your viewers. If someone follows Free Code Camp on Twitch, try to thank them.

    ", + "

    If you do a good job, we'll invite you back to stream some more. Who knows, you might become one of our regular streamers!

    ", "
    " ] }, @@ -279,8 +279,8 @@ "name": "How can I find other Free Code Camp campers in my city?", "description": [ "
    ", - "

    Find your city below and join their group. This is a great way to hang out with other coders, share insights, and pair program.

    ", - "

    ", + "

    Find your city below and join their group. This is a great way to hang out with other coders, share insights, and pair program.

    ", + "

    ", "
      ", "
    1. Atlanta
    2. ", "
    3. Austin
    4. ", @@ -372,9 +372,9 @@ "
    5. Verde Valley
    6. ", "
    7. Washington, DC
    8. ", "
    ", - "

    ", - "

    If you didn't see your city on this list, you should create your own Facebook group for your city. Please follow these steps:

    ", - "

    ", + "

    ", + "

    If you didn't see your city on this list, you should create your own Facebook group for your city. Please follow these steps:

    ", + "

    ", "

      ", "
    1. Sign in to Facebook.
    2. ", "
    3. Click the down arrow in the upper right corner of the screen, then choose \"Create Group\" from the options.", @@ -387,7 +387,10 @@ " a screenshot telling you to choose the graduation icon, which is on the forth row of icons, seven icons from the left.", "
    4. Click the \"...\" menu, then click \"Edit group settings\" in the dropdown menu.
    5. ", " a screenshot telling you to click the \"...\" button then choose the \"Edit group settings\" option", - "
    6. Click the \"Customize Address\" button.", + "
    7. Set the group's privacy setting to public.
    8. ", + "
    9. Set your group's membership approval to where any member can add or approve members
    10. ", + " a screenshot showing the Facebook settings panel and where you can click to set the group to public and allow all members to be able to add or approve members>",
+      "      <li>Click the \"Customize Address\" button.</li>",
       "      <img class=", "
    11. Enter \"free.code.camp.your.city.name\" with each word separated by periods.", " a screenshot telling you to enter free.code.camp.your.city.name with each word seperated by periods.", @@ -398,9 +401,9 @@ "
    12. Message @quincylarson in Slack with a link to your city's group page and he'll include it here.
    13. ", "
    14. Join our #local-group-leaders channel on Slack, where we share ideas about involving campers in your city.
    15. ", "
    ", - " ", - "

    If you don't have a Facebook page, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.

    ", - "

    If Facebook is blocked in your country, feel free to use social network with a similar group functionality that's popular in your region.

    ", + "

    ", + "

    If you don't have a Facebook page, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.

    ", + "

    If Facebook is blocked in your country, feel free to use social network with a similar group functionality that's popular in your region.

    ", "
    " ] }, @@ -418,10 +421,10 @@ "name": "How do I best use the Global Control Shortcuts for Mac?", "description": [ "
    ", - "

    These Global Control Shortcuts for Mac will save you hours by speeding up your typing.


    ", + "

    These Global Control Shortcuts for Mac will save you hours by speeding up your typing.


    ", "
    ", - "

    These global shortcuts work everywhere on a Mac:

    ", - "

    ", + "

    These global shortcuts work everywhere on a Mac:

    ", + "

    ", "

      ", "
    • Control + F = Forward
    • ", "
    • Control + B = Backward
    • ", @@ -433,7 +436,7 @@ "
    • Control + E = End of Line
    • ", "
    • Control + K = Kill line
    • ", "
    ", - "

    ", + "

    ", "
    " ] }, @@ -442,12 +445,12 @@ "name": "How can I get to Inbox Zero with Gmail shortcuts?", "description": [ "
    ", - "

    These Gmail Shortcuts will save you hours and help you get to Inbox Zero.


    ", + "

    These Gmail Shortcuts will save you hours and help you get to Inbox Zero.


    ", "
    ", " ", "
    ", - "

    The shortcuts:

    ", - "

    ", + "

    The shortcuts:

    ", + "

    ", "

      ", "
    • j - move down
    • ", "
    • k - move up
    • ", @@ -461,7 +464,7 @@ "
    • ! - mark spam
    • ", "
    • z - undo
    • ", "
    ", - "

    ", + "

    ", "
    " ] }, @@ -470,20 +473,20 @@ "name": "How can I deploy a website without writing any code at all?", "description": [ "
    ", - "

    It's possible to build dynamic, mobile-responsive websites without writing any code at all, in just a few minutes.


    ", + "

    It's possible to build dynamic, mobile-responsive websites without writing any code at all, in just a few minutes.


    ", "
    ", " ", "
    ", - "

    Here are the technologies we used here:

    ", - "

    ", + "

    Here are the technologies we used here:

    ", + "

    ", "

      ", "
    • atom.io - a free code editor
    • ", "
    • startbootstrap.com - a collection of free responsive (Bootstrap) templates
    • ", "
    • powr.io - a collection of free JavaScript plugins
    • ", "
    • bitballoon.com - a tool for drag and drop website deployment
    • ", "
    ", - "

    ", - "

    You will quickly reach the limits of what you can do without actually coding, but it's nice to be able to rapidly build working prototype websites like this.

    ", + "

    ", + "

    You will quickly reach the limits of what you can do without actually coding, but it's nice to be able to rapidly build working prototype websites like this.

    ", "
    " ] }, @@ -492,72 +495,72 @@ "name": "How do Free Code Camp's Nonprofit Projects work?", "description": [ "
    ", - "

    Building nonprofit projects is the main way that our campers learn full stack JavaScript and agile software development. Once you complete the Free Code Camp Waypoints, Bonfires, Ziplines and Basejumps, you'll begin this process.

    ", - "

    Starting with the end in mind

    ", - "

    Our goal at Free Code Camp is to help you land a job as a junior software developer (or, if you prefer, a 'pivot job' that leads your current career in a more technical direction).

    ", - "

    You'll continue to work on nonprofit projects until you've built a sufficiently impressive portfolio and references to start your job search. Your portfolio will ultimately have three to five nonprofit projects. We estimate that the 900 hours of nonprofit projects you're going to complete, in addition to the 100 hours of challenges you've already completed, will be enough to qualify you for your first coding job. This will produce a much broader portfolio than a traditional coding bootcamp, which generally only has one or two capstone projects.

    ", - "

    Choosing your first Nonprofit Project

    ", - "

    We've categorized all the nonprofit projects by estimated time investment per camper: 100 hours, 200 hours, and 300 hours. These are only rough estimates.

    ", - "

    Example: if you and the camper you're paired up with (your pair) each stated you could work 20 hours per week. If the project is a 100 hour per camper project, you should be able to complete it in about 5 weeks.

    ", - "

    Our team of nonprofit project camp counselors will match you and your pair based on:

    ", - "

    ", + "

    Building nonprofit projects is the main way that our campers learn full stack JavaScript and agile software development. Once you complete the Free Code Camp Waypoints, Bonfires, Ziplines and Basejumps, you'll begin this process.

    ", + "

    Starting with the end in mind

    ", + "

    Our goal at Free Code Camp is to help you land a job as a junior software developer (or, if you prefer, a 'pivot job' that leads your current career in a more technical direction).

    ", + "

    You'll continue to work on nonprofit projects until you've built a sufficiently impressive portfolio and references to start your job search. Your portfolio will ultimately have three to five nonprofit projects. We estimate that the 900 hours of nonprofit projects you're going to complete, in addition to the 100 hours of challenges you've already completed, will be enough to qualify you for your first coding job. This will produce a much broader portfolio than a traditional coding bootcamp, which generally only has one or two capstone projects.

    ", + "

    Choosing your first Nonprofit Project

    ", + "

    We've categorized all the nonprofit projects by estimated time investment per camper: 100 hours, 200 hours, and 300 hours. These are only rough estimates.

    ", + "

    Example: if you and the camper you're paired up with (your pair) each stated you could work 20 hours per week. If the project is a 100 hour per camper project, you should be able to complete it in about 5 weeks.

    ", + "

    Our team of nonprofit project camp counselors will match you and your pair based on:

    ", + "

    ", "

      ", "
    1. Your estimated time commitment (10, 20 or 40 hours per week)
    2. ", "
    3. Your time zone
    4. ", "
    5. The nonprofit projects you've chosen
    6. ", "
    7. Prior coding experience (we'd like both campers to be able to contribute equally)
    8. ", "
    ", - " ", - "

    We won't take age or gender into account. This will provide you with valuable experience in meshing with diverse teams, which is a reality of the contemporary workplace.

    ", - "

    You'll only work on one project at a time. Once you start a nonprofit project, we'll remove you from all other nonprofit project you've expressed interest in. There's a good chance those projects will no longer be available when you finish your current project, anyway. Don't worry, though - we get new nonprofit project requests every day, so there will be plenty more projects for you to consider after you finish your current one.

    ", - "

    Finalizing the Project

    ", - "

    Before you can start working on the project, our team of Nonprofit Project Coordinators will go through the following process:

    ", - "

    ", + "

    ", + "

    We won't take age or gender into account. This will provide you with valuable experience in meshing with diverse teams, which is a reality of the contemporary workplace.

    ", + "

    You'll only work on one project at a time. Once you start a nonprofit project, we'll remove you from all other nonprofit project you've expressed interest in. There's a good chance those projects will no longer be available when you finish your current project, anyway. Don't worry, though - we get new nonprofit project requests every day, so there will be plenty more projects for you to consider after you finish your current one.

    ", + "

    Finalizing the Project

    ", + "

    Before you can start working on the project, our team of Nonprofit Project Coordinators will go through the following process:

    ", + "

    ", "

      ", "
    1. We'll wait until there are two campers who have chosen the same project and look like they're a good match for one another based on the factors mentioned above.
    2. ", "
    3. We'll call the stakeholder to confirm once again that he or she agrees with our  terms  and has signed our  Nonprofit Project Stakeholder Pledge.
    4. ", "
    5. We'll set an initial meeting with representatives from Free Code Camp, the two campers, and the stakeholder.
    6. ", "
    7. If the stakeholder and both campers shows up promptly, and seem enthusiastic and professional, we'll start the project.
    8. ", "
    ", - " ", - "

    This lengthy process serves an important purpose: it reduces the likelihood that any of our campers or stakeholders will waste their precious time.

    ", - "

    Nonprofit Stakeholders

    ", - "

    Each nonprofit project was submitted by a nonprofit. A representative from this nonprofit has agreed to serve as a \"stakeholder\" - an authorative person who understands the organization and its needs for this particular project.

    ", - "

    Stakeholders have a deep understanding of their organizations' needs. Campers will work with them to figure out the best solutions to these needs.

    ", - "

    When you and your pair first speak with your nonprofit stakeholder, you'll:

    ", - "

    ", + "

    ", + "

    This lengthy process serves an important purpose: it reduces the likelihood that any of our campers or stakeholders will waste their precious time.

    ", + "

    Nonprofit Stakeholders

    ", + "

    Each nonprofit project was submitted by a nonprofit. A representative from this nonprofit has agreed to serve as a \"stakeholder\" - an authorative person who understands the organization and its needs for this particular project.

    ", + "

    Stakeholders have a deep understanding of their organizations' needs. Campers will work with them to figure out the best solutions to these needs.

    ", + "

    When you and your pair first speak with your nonprofit stakeholder, you'll:

    ", + "

    ", "

      ", "
    • talk at length to better understand their needs.
    • ", "
    • create a new Trello board and use it to prioritize what needs to be built.
    • ", "
    • and establish deadlines based on your weekly time commitment, and how long you think each task will take.
    • ", "
    ", - " ", - "

    It's notoriously difficult to estimate how long building software projects will take, so feel free to ask camp counselors for help.

    ", - "

    You'll continue to meet with your stakeholder at least twice a month in your project's Slack channel.

    ", - "

    You should also ask questions in your project's Slack channel as they come up throughout the week, and your stakeholder can answer them asynchronously.

    ", - "

    Getting \"blocked\" on a task can take away your sense of forward momentum, so be sure to proactively seek answers to any ambiguities you encounter.

    ", - "

    Ultimately, the project will be considered complete once both the stakeholder's needs have been met, and you and your pair are happy with the project. Then you can add it to your portfolio!

    ", - "

    Working with your Pair

    ", - "

    You and your pair will pair program (code together on the same computer virtually) about half of the time, and work independently the other half of the time.

    ", - "

    Here are our recommended ways of collaborating:

    ", - "

    ", + "

    ", + "

    It's notoriously difficult to estimate how long building software projects will take, so feel free to ask camp counselors for help.

    ", + "

    You'll continue to meet with your stakeholder at least twice a month in your project's Slack channel.

    ", + "

    You should also ask questions in your project's Slack channel as they come up throughout the week, and your stakeholder can answer them asynchronously.

    ", + "

    Getting \"blocked\" on a task can take away your sense of forward momentum, so be sure to proactively seek answers to any ambiguities you encounter.

    ", + "

    Ultimately, the project will be considered complete once both the stakeholder's needs have been met, and you and your pair are happy with the project. Then you can add it to your portfolio!

    ", + "

    Working with your Pair

    ", + "

    You and your pair will pair program (code together on the same computer virtually) about half of the time, and work independently the other half of the time.

    ", + "

    Here are our recommended ways of collaborating:

    ", + "

    ", "

      ", "
    • • Slack has robust private messaging functionality. It's the main way our team communicates, and we recommend it over email.
    • ", "
    • • Trello is great for managing projects. Work with your stakeholder to create Trello cards, and update these cards regularly as you make progress on them.
    • ", "
    • • Screen Hero or Team Viewer - These are the ideal way to pair program. Tools like TMUX are good, but difficult to use. We discourage you from using screen sharing tools where only one person has control of the keyboard and mouse - that isn't real pair programming.
    • ", "
    • • Write clear and readable code, commit messages, branch names, and pull request messages.
    • ", "
    ", - " ", - "

    Hosting Apps

    ", - "

    Unless your stakeholder has an existing modern host (AWS, Digital Ocean), you'll need to transition them over to a new platform. We believe Heroku is the best choice for a vast majority of web projects. It's free, easy to use, and has both browser and command line interfaces. It's owned by Salesforce and used by a ton of companies, so it's accountable and unlikely to go away.

    ", - "

    If you need help convincing your stakeholder that Heroku is the ideal platform, we'll be happy to talk with them.

    ", - "

    Maintaining Apps

    ", - "

    Once you complete a nonprofit project, your obligation to its stakeholder is finished. You goal is to leave behind a well documented solution that can be easily maintained by a contract JavaScript developer (or even a less-technical \"super user\").

    ", - "

    While you will no longer need to help with feature development, we encourage you to consider helping your stakeholder with occasional patches down the road. After all, this project will be an important piece of your portfolio, and you'll want it to remain in good shape for curious future employers.

    ", - "

    Pledging to finish the project

    ", - "

    Your nonprofit stakeholder, your pair, and the volunteer camp counselor team are all counting on you to finish your nonprofit project. If you walk away from an unfinished nonprofit project, you'll become ineligible to ever be assigned another one.

    ", - "

    To confirm that you understand the seriousness of this commitment, we require that all campers  sign this pledge  before starting on their nonprofit projects.

    ", - "

    There will likely be times of confusion or frustration. This is normal in software development. The most important thing is that you do not give up and instead persevere through these setbacks. As Steve Jobs famously said, \"Real artists ship.\" And you are going to ship one successful nonprofit project after another until you feel ready to take the next step in your promising career.

    ", + "

    ", + "

    Hosting Apps

    ", + "

    Unless your stakeholder has an existing modern host (AWS, Digital Ocean), you'll need to transition them over to a new platform. We believe Heroku is the best choice for a vast majority of web projects. It's free, easy to use, and has both browser and command line interfaces. It's owned by Salesforce and used by a ton of companies, so it's accountable and unlikely to go away.

    ", + "

    If you need help convincing your stakeholder that Heroku is the ideal platform, we'll be happy to talk with them.

    ", + "

    Maintaining Apps

    ", + "

    Once you complete a nonprofit project, your obligation to its stakeholder is finished. You goal is to leave behind a well documented solution that can be easily maintained by a contract JavaScript developer (or even a less-technical \"super user\").

    ", + "

    While you will no longer need to help with feature development, we encourage you to consider helping your stakeholder with occasional patches down the road. After all, this project will be an important piece of your portfolio, and you'll want it to remain in good shape for curious future employers.

    ", + "

    Pledging to finish the project

    ", + "

    Your nonprofit stakeholder, your pair, and the volunteer camp counselor team are all counting on you to finish your nonprofit project. If you walk away from an unfinished nonprofit project, you'll become ineligible to ever be assigned another one.

    ", + "

    To confirm that you understand the seriousness of this commitment, we require that all campers  sign this pledge  before starting on their nonprofit projects.

    ", + "

    There will likely be times of confusion or frustration. This is normal in software development. The most important thing is that you do not give up and instead persevere through these setbacks. As Steve Jobs famously said, \"Real artists ship.\" And you are going to ship one successful nonprofit project after another until you feel ready to take the next step in your promising career.

    ", "
    " ] }, @@ -566,9 +569,9 @@ "name": "How do I install Screenhero?", "description": [ "
    ", - "

    Download for Mac

    ", - "

    Download for Windows

    ", - "

    You'll use Screen Hero to pair program starting with http://freecodecamp.com/challenges/pair-program-on-bonfires

    ", + "

    Download for Mac

    ", + "

    Download for Windows

    ", + "

    You'll use Screen Hero to pair program starting with http://freecodecamp.com/challenges/pair-program-on-bonfires

    ", "
    " ] }, @@ -577,8 +580,8 @@ "name": "What is the style guide for Bonfires?", "description": [ "
    ", - "

    Writing Bonfire challenges is a great way to exercise your own problem solving and testing abilities. Follow this process closely to maximize the chances of us accepting your bonfire.

    ", - "

    ", + "

    Writing Bonfire challenges is a great way to exercise your own problem solving and testing abilities. Follow this process closely to maximize the chances of us accepting your bonfire.

    ", + "

    ", "

      ", "
    1. Fork the Free Code Camp repository and open seed_data/bonfires.json to become familiar with the format of our bonfires.
    2. ", "
    3. Regardless of your bonfire's difficulty, put it as the last bonfire in the JSON file. Change one of the numbers in the ID to ensure that your bonfire has a unique ID.
    4. ", @@ -586,24 +589,24 @@ "
    5. Solved your own Bonfire. Confirmed that your tests work as expected and that your instructions are sufficiently clear.
    6. ", "
    7. Submit a pull request to Free Code Camp's Staging branch and in the pull request body, link to a gist that has your algorithmic solution.
    8. ", "
    ", - " ", - "

    Here is a description of each of the Bonfires' fields.

    ", - "

    Name

    ", - "

    The name of your challenge. It's OK for this to be humorous but it must be brief and relevant to the task.

    ", - "

    Difficulty

    ", - "

    Attempt to rate difficulty compared against existing bonfire challenges. A good proxy for the difficulty of a bonfire is how long it takes you to solve it. For every 15 minutes it takes, increase the difficulty. For example, a one-hour bonfire should probably be a 4.

    ", - "

    Description

    ", - "

    Separate paragraphs with a line break. Only the first paragraph is visible prior to a user before they click the the 'More information' button.

    ", - "

    All necessary information must be included in the first paragraph. Write this first paragraph as succinctly as possible. Subsequent paragraphs should offer hints or details if needed.

    ", - "

    If your subject matter warrants deeper understanding, you may link to Wikipedia.

    ", - "

    Challenge Seed

    ", - "

    This is where you set up what will be in the editor when the camper starts the bonfire.

    ", - "

    Tests

    ", - "

    These tests are what bring your challenge to life. Without them, we cannot confirm the accuracy of a user's submitted answer. Choose your tests wisely.

    ", - "

    Bonfire tests are written using the Chai.js assertion library. Please use the should and expect syntax for end user readability. As an example of what not do to, many of the original Bonfire challenges are written with assert syntax and many of the test cases are difficult to read.

    ", - "

    If your bonfire question has a lot of edge cases, you will need to write many tests for full coverage. If you find yourself writing more tests than you desire, you may consider simplifying the requirements of your bonfire challenge. For difficulty level 1 through 3, you will generally only need 2 to 4 tests.

    ", - "

    MDNlinks

    ", - "

    Take a look at seed_data/bonfireMDNlinks.js. If any of these concepts are relevant to your bonfire, be sure to include them. If you know of an MDN article that isn't linked here, you can add it to the bonfireMDNlinks.js file before adding it to your bonfire.

    ", + "

    ", + "

    Here is a description of each of the Bonfires' fields.

    ", + "

    Name

    ", + "

    The name of your challenge. It's OK for this to be humorous but it must be brief and relevant to the task.

    ", + "

    Difficulty

    ", + "

    Attempt to rate difficulty compared against existing bonfire challenges. A good proxy for the difficulty of a bonfire is how long it takes you to solve it. For every 15 minutes it takes, increase the difficulty. For example, a one-hour bonfire should probably be a 4.

    ", + "

    Description

    ", + "

    Separate paragraphs with a line break. Only the first paragraph is visible prior to a user before they click the the 'More information' button.

    ", + "

    All necessary information must be included in the first paragraph. Write this first paragraph as succinctly as possible. Subsequent paragraphs should offer hints or details if needed.

    ", + "

    If your subject matter warrants deeper understanding, you may link to Wikipedia.

    ", + "

    Challenge Seed

    ", + "

    This is where you set up what will be in the editor when the camper starts the bonfire.

    ", + "

    Tests

    ", + "

    These tests are what bring your challenge to life. Without them, we cannot confirm the accuracy of a user's submitted answer. Choose your tests wisely.

    ", + "

    Bonfire tests are written using the Chai.js assertion library. Please use the should and expect syntax for end user readability. As an example of what not do to, many of the original Bonfire challenges are written with assert syntax and many of the test cases are difficult to read.

    ", + "

    If your bonfire question has a lot of edge cases, you will need to write many tests for full coverage. If you find yourself writing more tests than you desire, you may consider simplifying the requirements of your bonfire challenge. For difficulty level 1 through 3, you will generally only need 2 to 4 tests.

    ", + "

    MDNlinks

    ", + "

    Take a look at seed_data/bonfireMDNlinks.js. If any of these concepts are relevant to your bonfire, be sure to include them. If you know of an MDN article that isn't linked here, you can add it to the bonfireMDNlinks.js file before adding it to your bonfire.

    ", "
    " ] }, @@ -612,22 +615,22 @@ "name": "What is the Free Code Camp Code of Conduct?", "description": [ "
    ", - "

    Free Code Camp is friendly place to learn to code. We're committed to keeping it that way.

    ", - "

    All campers are required to agree with the following code of conduct. We'll enforce this code. We're expecting cooperation from all campers in ensuring a friendly environment for everybody.

    ", - "

    In short: be nice to your fellow campers.

    ", - "

    Remember these 3 things and your fellow campers will like you:

    ", - "

    ", + "

    Free Code Camp is friendly place to learn to code. We're committed to keeping it that way.

    ", + "

    All campers are required to agree with the following code of conduct. We'll enforce this code. We're expecting cooperation from all campers in ensuring a friendly environment for everybody.

    ", + "

    In short: be nice to your fellow campers.

    ", + "

    Remember these 3 things and your fellow campers will like you:

    ", + "

    ", "

      ", "
    1. Compliment your fellow campers when they do good work. Congratulate them when they accomplish something (like finishing a nonprofit project or getting a job).
    2. ", "
    3. Critique the work, not the camper doing it.
    4. ", "
    5. Only argue about something if it's important to the greater discussion.
    6. ", "
    ", - " ", - "

    Free Code Camp should be a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, national origin, or religion (or lack thereof).

    ", - "

    We do not tolerate harassment of campers in any form, anywhere on Free Code Camp's online media (Slack, Twitch, etc.) or during pair programming. Harassment includes sexual language and imagery, deliberate intimidation, stalking, unwelcome sexual attention, libel, and any malicious hacking or social engineering.

    ", - "

    If a camper engages in harassing behavior, our team will take any action we deem appropriate, up to and including banning them from Free Code Camp.

    ", - "

    We want everyone to feel safe and respected. If you are being harassed or notice that someone else is being harassed, say something! Message @quincylarson, @terakilobyte and @codenonprofit in Slack (preferably with a screen shot of the offending language) so we can take fast action.

    ", - "

    If you have questions about this code of conduct, email us at team@freecodecamp.com.

    ", + "

    ", + "

    Free Code Camp should be a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, national origin, or religion (or lack thereof).

    ", + "

    We do not tolerate harassment of campers in any form, anywhere on Free Code Camp's online media (Slack, Twitch, etc.) or during pair programming. Harassment includes sexual language and imagery, deliberate intimidation, stalking, unwelcome sexual attention, libel, and any malicious hacking or social engineering.

    ", + "

    If a camper engages in harassing behavior, our team will take any action we deem appropriate, up to and including banning them from Free Code Camp.

    ", + "

    We want everyone to feel safe and respected. If you are being harassed or notice that someone else is being harassed, say something! Message @quincylarson, @terakilobyte and @codenonprofit in Slack (preferably with a screen shot of the offending language) so we can take fast action.

    ", + "

    If you have questions about this code of conduct, email us at team@freecodecamp.com.

    ", "
    " ] }, @@ -636,39 +639,39 @@ "name": "What is the Free Code Camp Privacy Policy?", "description": [ "
    ", - "

    Free Code Camp is committed to respecting the privacy of visitors to our web sites and web applications. The guidelines below explain how we protect the privacy of visitors to FreeCodeCamp.com and its features.

    ", - "

    Personally Identifiable Information

    ", - "

    Free Code Camp protects the identity of visitors to FreeCodeCamp.com by limiting the collection of personally identifiable information.

    ", - "

    Free Code Camp does not knowingly collect or solicit personally identifiable information from or about children under 13, except as permitted by law. If we discover we have received any information from a child under 13 in violation of this policy, we will delete that information immediately. If you believe Free Code Camp has any information from or about anyone under 13, please email us at team@freecodecamp.com.

    ", - "

    All personally identifiable information you provide to us is used by Free Code Camp and its team to process and manage your account, analyze the demographic of our users, or to deliver services through the site.

    ", - "

    If you choose to provide personally identifiable information to us, you may receive occasional emails from us that are relevant to Free Code Camp, getting a job, or learning to code in general.

    ", - "

    Free Code Camp may also use other third-party providers to facilitate the delivery of the services described above, and these third-party providers may be supplied with or have access to personally identifiable information for the sole purpose of providing these services, to you on behalf of Free Code Camp.

    ", - "

    Free Code Camp may also disclose personally identifiable information in special legal circumstances. For instance, such information may be used where it is necessary to protect our copyright or intellectual property rights, or if the law requires us to do so.

    ", - "

    Anonymous Information

    ", - "

    Anonymous aggregated data may be provided to other organizations we associate with for statistical purposes. For example, we may report to an organization that a certain percentage of our site's visitors are adults between the ages of 25 and 35.

    ", - "

    Cookies and Beacons—Use by Free Code Camp; Opting Out

    ", - "

    We use cookies and software logs to monitor the use of FreeCodeCamp.com and to gather non-personal information about visitors to the site. Cookies are small files that Free Code Camp transfers to the hard drives of visitors for record-keeping purposes. These monitoring systems allow us to track general information about our visitors, such as the type of browsers (for example, Firefox or Internet Explorer), the operating systems (for instance, Windows or Macintosh), or the Internet providers (for instance, Comcast) they use. This information is used for statistical and market research purposes to tailor content to usage patterns and to provide services requested by our customers. To delete these cookies, please see your browser's privacy settings.

    ", - "

    A beacon is an electronic file object (typically a transparent image) placed in the code of a Web page. We use third party beacons to monitor the traffic patterns of visitors from one Free Code Camp.com page to another and to improve site performance.

    ", - "

    None of the information we gather in this way can be used to identify any individual who visits our site.

    ", - "

    Security

    ", - "

    Any personally identifiable information collected through this site is stored on limited-access servers. We will maintain safeguards to protect these servers and the information they store.

    ", - "

    Surveys

    ", - "

    We may occasionally conduct on-line surveys. All surveys are voluntary and you may decline to participate.

    ", - "

    Copyright

    ", - "

    All of the content on FreeCodeCamp.com is copyrighted by Free Code Camp. If you'd like to redistribute it beyond simply sharing it through social media, please contact us at team@freecodecamp.com.

    ", - "

    Contacting Us

    ", - "

    If you have questions about Free Code Camp, or to correct, update, or remove personally identifiable information, please email us at team@freecodecamp.com.

    ", - "

    Links to Other Web sites

    ", - "

    Free Code Camp's sites each contain links to other Web sites. Free Code Camp is not responsible for the privacy practices or content of these third-party Web sites. We urge all FreeCodeCamp.com visitors to follow safe Internet practices: Do not supply Personally Identifiable Information to these Web sites unless you have verified their security and privacy policies.

    ", - "

    Data Retention

    ", - "

    We retain your information for as long as necessary to permit us to use it for the purposes that we have communicated to you and comply with applicable law or regulations.

    ", - "

    Business Transfers

    ", - "

    As we continue to develop our business, we might sell or buy subsidiaries, or business units. In such transactions, customer information generally is one of the transferred business assets but remains subject to the promises made in any pre-existing Privacy Policy (unless, of course, the customer consents otherwise). Also, in the unlikely event that Free Code Camp, or substantially all of its assets are acquired, customer information will be one of the transferred assets, and will remain subject to our Privacy Policy.

    ", - "

    Your California Privacy Rights

    ", - "

    If you are a California resident, you are entitled to prevent sharing of your personal information with third parties for their own marketing purposes through a cost-free means. If you send a request to the address above, Free Code Camp will provide you with a California Customer Choice Notice that you may use to opt-out of such information sharing. To receive this notice, submit a written request to team@freecodecamp.com, specifying that you seek your "California Customer Choice Notice." Please allow at least thirty (30) days for a response.

    ", - "

    Acceptance of Privacy Policy Terms and Conditions

    ", - "

    By using this site, you signify your agreement to the terms and conditions of this FreeCodeCamp.com Privacy Policy. If you do not agree to these terms, please do not use this site. We reserve the right, at our sole discretion, to change, modify, add, or remove portions of this policy at any time. All amended terms automatically take effect 30 days after they are initially posted on the site. Please check this page periodically for any modifications. Your continued use of FreeCodeCamp.com following the posting of any changes to these terms shall mean that you have accepted those changes.

    ", - "

    If you have any questions or concerns, please send an email to team@freecodecamp.com.

    ", + "

    Free Code Camp is committed to respecting the privacy of visitors to our web sites and web applications. The guidelines below explain how we protect the privacy of visitors to FreeCodeCamp.com and its features.

    ", + "

    Personally Identifiable Information

    ", + "

    Free Code Camp protects the identity of visitors to FreeCodeCamp.com by limiting the collection of personally identifiable information.

    ", + "

    Free Code Camp does not knowingly collect or solicit personally identifiable information from or about children under 13, except as permitted by law. If we discover we have received any information from a child under 13 in violation of this policy, we will delete that information immediately. If you believe Free Code Camp has any information from or about anyone under 13, please email us at team@freecodecamp.com.

    ", + "

    All personally identifiable information you provide to us is used by Free Code Camp and its team to process and manage your account, analyze the demographic of our users, or to deliver services through the site.

    ", + "

    If you choose to provide personally identifiable information to us, you may receive occasional emails from us that are relevant to Free Code Camp, getting a job, or learning to code in general.

    ", + "

    Free Code Camp may also use other third-party providers to facilitate the delivery of the services described above, and these third-party providers may be supplied with or have access to personally identifiable information for the sole purpose of providing these services, to you on behalf of Free Code Camp.

    ", + "

    Free Code Camp may also disclose personally identifiable information in special legal circumstances. For instance, such information may be used where it is necessary to protect our copyright or intellectual property rights, or if the law requires us to do so.

    ", + "

    Anonymous Information

    ", + "

    Anonymous aggregated data may be provided to other organizations we associate with for statistical purposes. For example, we may report to an organization that a certain percentage of our site's visitors are adults between the ages of 25 and 35.

    ", + "

    Cookies and Beacons—Use by Free Code Camp; Opting Out

    ", + "

    We use cookies and software logs to monitor the use of FreeCodeCamp.com and to gather non-personal information about visitors to the site. Cookies are small files that Free Code Camp transfers to the hard drives of visitors for record-keeping purposes. These monitoring systems allow us to track general information about our visitors, such as the type of browsers (for example, Firefox or Internet Explorer), the operating systems (for instance, Windows or Macintosh), or the Internet providers (for instance, Comcast) they use. This information is used for statistical and market research purposes to tailor content to usage patterns and to provide services requested by our customers. To delete these cookies, please see your browser's privacy settings.

    ", + "

    A beacon is an electronic file object (typically a transparent image) placed in the code of a Web page. We use third party beacons to monitor the traffic patterns of visitors from one Free Code Camp.com page to another and to improve site performance.

    ", + "

    None of the information we gather in this way can be used to identify any individual who visits our site.

    ", + "

    Security

    ", + "

    Any personally identifiable information collected through this site is stored on limited-access servers. We will maintain safeguards to protect these servers and the information they store.

    ", + "

    Surveys

    ", + "

    We may occasionally conduct on-line surveys. All surveys are voluntary and you may decline to participate.

    ", + "

    Copyright

    ", + "

    All of the content on FreeCodeCamp.com is copyrighted by Free Code Camp. If you'd like to redistribute it beyond simply sharing it through social media, please contact us at team@freecodecamp.com.

    ", + "

    Contacting Us

    ", + "

    If you have questions about Free Code Camp, or to correct, update, or remove personally identifiable information, please email us at team@freecodecamp.com.

    ", + "

    Links to Other Web sites

    ", + "

    Free Code Camp's sites each contain links to other Web sites. Free Code Camp is not responsible for the privacy practices or content of these third-party Web sites. We urge all FreeCodeCamp.com visitors to follow safe Internet practices: Do not supply Personally Identifiable Information to these Web sites unless you have verified their security and privacy policies.

    ", + "

    Data Retention

    ", + "

    We retain your information for as long as necessary to permit us to use it for the purposes that we have communicated to you and comply with applicable law or regulations.

    ", + "

    Business Transfers

    ", + "

    As we continue to develop our business, we might sell or buy subsidiaries, or business units. In such transactions, customer information generally is one of the transferred business assets but remains subject to the promises made in any pre-existing Privacy Policy (unless, of course, the customer consents otherwise). Also, in the unlikely event that Free Code Camp, or substantially all of its assets are acquired, customer information will be one of the transferred assets, and will remain subject to our Privacy Policy.

    ", + "

    Your California Privacy Rights

    ", + "

    If you are a California resident, you are entitled to prevent sharing of your personal information with third parties for their own marketing purposes through a cost-free means. If you send a request to the address above, Free Code Camp will provide you with a California Customer Choice Notice that you may use to opt-out of such information sharing. To receive this notice, submit a written request to team@freecodecamp.com, specifying that you seek your "California Customer Choice Notice." Please allow at least thirty (30) days for a response.

    ", + "

    Acceptance of Privacy Policy Terms and Conditions

    ", + "

    By using this site, you signify your agreement to the terms and conditions of this FreeCodeCamp.com Privacy Policy. If you do not agree to these terms, please do not use this site. We reserve the right, at our sole discretion, to change, modify, add, or remove portions of this policy at any time. All amended terms automatically take effect 30 days after they are initially posted on the site. Please check this page periodically for any modifications. Your continued use of FreeCodeCamp.com following the posting of any changes to these terms shall mean that you have accepted those changes.

    ", + "

    If you have any questions or concerns, please send an email to team@freecodecamp.com.

    ", "
    " ] }, @@ -677,16 +680,16 @@ "name": "How can I reach the Free Code Camp team to interview them for my publication?", "description": [ "
    ", - "

    We're happy to do a quick interview for your publication or show. Here's whom you should contact about what, and how to best reach them:

    ", - "

    ", + "

    We're happy to do a quick interview for your publication or show. Here's whom you should contact about what, and how to best reach them:

    ", + "

    ", "

      ", "
    1. Want to talk to about Free Code Camp's curriculum or long-term vision? Reach out to Quincy Larson. He's @ossia on Twitter and @quincylarson on Slack.
    2. ", "
    3. Want to talk about Free Code Camp's open source codebase, infrastructure, or JavaScript in general? Talk to Nathan Leniz. He's @terakilobyte on Twitter and @terakilobyte on Slack.
    4. ", "
    5. Want to explore our efforts to empower nonprofits with code? Michael D. Johnson eats, sleeps and breathes that. He's @figitalboy on Twitter and @codenonprofit on Slack.
    6. ", "
    7. Want to get a camper's perspective on our community? Talk with Bianca Mihai (@biancamihai on Slack and @bubuslubu on Twitter) or Suzanne Atkinson (@adventurebear on Slack and @steelcitycoach on Twitter).", "
    ", - " ", - "

    We strive to be helpful and transparent in everything we do. We'll do what we can to help you share our community with your audience.

    ", + "

    ", + "

    We strive to be helpful and transparent in everything we do. We'll do what we can to help you share our community with your audience.

    ", "
    " ] }, @@ -695,13 +698,13 @@ "name": "How can I contribute to this guide?", "description": [ "
    ", - "

    Contributing to our field guide is a great way to establish your history on GitHub, add to your portfolio, and help other campers. If you have a question about JavaScript or programming in general that you'd like us to add to the field guide, here are two ways to get it into the guide:

    ", - "

    ", + "

    Contributing to our field guide is a great way to establish your history on GitHub, add to your portfolio, and help other campers. If you have a question about JavaScript or programming in general that you'd like us to add to the field guide, here are two ways to get it into the guide:

    ", + "

    ", "

      ", "
    1. You can message @alex-dixon in Slack with your question.
    2. ", "
    3. You can also contribute to this field guide directly via GitHub pull request, by cloning Free Code Camp's main repository and modifying field-guides.json.
    4. ", "
    ", - "

    ", + "

    ", "
    " ] } diff --git a/views/account/show.jade b/views/account/show.jade index f6ab37ce92..c3255edd26 100644 --- a/views/account/show.jade +++ b/views/account/show.jade @@ -150,7 +150,7 @@ block content td.col-xs-4= challenge.name td.col-xs-2= moment(challenge.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-6 - a(href=challenge.solution) View my solution + a(href=challenge.solution, target='_blank') View my solution br - if (bonfires.length > 0) @@ -164,7 +164,7 @@ block content for bonfire in bonfires tr td.col-xs-4 - a(href='/challenges/' + bonfire.name)= bonfire.name + a(href='/challenges/' + bonfire.name, target='_blank')= bonfire.name td.col-xs-2= moment(bonfire.completedDate, 'x').format("MMM DD, YYYY") td.col-xs-6 pre.wrappable= bonfire.solution diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index bd5e999af8..a47ba56402 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -83,6 +83,12 @@ block content | Less information #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) + .button-spacer + a.btn.btn-warning.btn-big.btn-block#i-want-help Help + .button-spacer + a.btn.btn-success.btn-big.btn-block#i-want-to-pair Pair + .button-spacer + a.btn.btn-success.btn-big.btn-block#i-found-a-bug Report Bug br form.code .form-group.codeMirrorView diff --git a/views/field-guide/show.jade b/views/field-guide/show.jade index dc159ef470..7fe274edcd 100644 --- a/views/field-guide/show.jade +++ b/views/field-guide/show.jade @@ -7,10 +7,8 @@ block content h1= title .panel-body div!= description - .spacer - .spacer - .spacer .col-xs-12.col-sm-6.col-sm-offset-3 + .spacer .text-center if user && user.uncompletedFieldGuides.length > 0 .next-field-guide-button.btn.btn-primary.btn-big.btn-block Next article (ctrl + enter) diff --git a/views/stories/news-nav.jade b/views/stories/news-nav.jade index 22d9ffceab..3f0f3fa320 100644 --- a/views/stories/news-nav.jade +++ b/views/stories/news-nav.jade @@ -1,16 +1,17 @@ .row - .col-xs-12.col-sm-9 - .input-group - input#searchArea.big-text-field.field-responsive.form-control(type='text', placeholder='Search our links') - span.input-group-btn - button#searchbutton.btn.btn-big.btn-primary.btn-responsive(type='button') Search - .visible-xs - .button-spacer .col-xs-12.col-sm-3 span a.btn.btn-primary.btn-big.btn-block.btn-responsive(href='/stories/submit' class="#{ page === 'hot' ? '' : 'hidden' }") Submit span a.btn.btn-success.btn-big.btn-block.btn-responsive(href='/news/' class="#{ (page !== 'hot') ? '' : 'hidden' }") All + .visible-xs + .button-spacer + .col-xs-12.col-sm-9 + .input-group + input#searchArea.big-text-field.field-responsive.form-control(type='text', placeholder='Search our links') + span.input-group-btn + button#searchbutton.btn.btn-big.btn-primary.btn-responsive(type='button') Search + .spacer .row .col-xs-12.col-sm-8.col-sm-offset-2.well From 19490056322cc0abe1dc512610de8e8f7a92e0a4 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sat, 23 May 2015 18:39:30 -0700 Subject: [PATCH 51/81] remove modal from field guide and create index view --- app.js | 3 +-- controllers/fieldGuide.js | 14 +++++++------- controllers/resources.js | 4 ++-- public/js/main.js | 4 ---- views/field-guide/all-articles.jade | 24 ++++++++++++++++++++++++ views/field-guide/show.jade | 11 ++--------- views/nonprofits/directory.jade | 2 ++ 7 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 views/field-guide/all-articles.jade diff --git a/app.js b/app.js index 843aaa367f..db9a2ec031 100755 --- a/app.js +++ b/app.js @@ -502,8 +502,7 @@ app.get('/api/codepen/twitter/:screenName', resourcesController.codepenResources /** * Field Guide related routes */ -app.get('/field-guide/getFieldGuideList', fieldGuideController.showAllFieldGuides); - +app.get('/field-guide/all-articles', fieldGuideController.showAllFieldGuides); app.get('/field-guide/:fieldGuideName', fieldGuideController.returnIndividualFieldGuide diff --git a/controllers/fieldGuide.js b/controllers/fieldGuide.js index c498368f92..2d0809b6a3 100644 --- a/controllers/fieldGuide.js +++ b/controllers/fieldGuide.js @@ -54,16 +54,16 @@ exports.returnIndividualFieldGuide = function(req, res, next) { }; exports.showAllFieldGuides = function(req, res) { - var data = {}; - data.fieldGuideList = resources.allFieldGuideNames(); - data.fieldGuideIds = resources.allFieldGuideIds(); + var allFieldGuideNamesAndIds = resources.allFieldGuideNamesAndIds(); + var completedFieldGuides = []; if (req.user && req.user.completedFieldGuides) { - data.completedFieldGuides = req.user.completedFieldGuides; - } else { - data.completedFieldGuides = []; + completedFieldGuides = req.user.completedFieldGuides; } - res.send(data); + res.render('field-guide/all-articles', { + allFieldGuideNamesAndIds: allFieldGuideNamesAndIds, + completedFieldGuides: completedFieldGuides + }); }; exports.returnNextFieldGuide = function(req, res, next) { diff --git a/controllers/resources.js b/controllers/resources.js index e9fb94849d..ff1205aa94 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -436,12 +436,12 @@ module.exports = { } }, - allFieldGuideNames: function() { + allFieldGuideNamesAndIds: function() { if (allFieldGuideNames) { return allFieldGuideNames; } else { allFieldGuideNames = fieldGuides.map(function (elem) { - return { name: elem.name }; + return { name: elem.name, id: elem._id }; }); return allFieldGuideNames; } diff --git a/public/js/main.js b/public/js/main.js index 9f2392fc00..3a3e6e4359 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -220,10 +220,6 @@ $(document).ready(function() { } }); - $('#showAllButton').on('click', function() { - $('#show-all-dialog').modal('show'); - }); - $('.next-challenge-button').on('click', function() { l = location.pathname.split('/'); window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1); diff --git a/views/field-guide/all-articles.jade b/views/field-guide/all-articles.jade new file mode 100644 index 0000000000..32dc9d600b --- /dev/null +++ b/views/field-guide/all-articles.jade @@ -0,0 +1,24 @@ +extends ../layout +block content + .col-xs-12.col-sm-12.col-md-12 + .panel.panel-info + .panel-heading.text-center Read our Field Guide in any order + .panel-body + .col-xs-12.col-md-8.col-md-offset-2 + .col-xs-12.no-right-padding + h3 + ol + each fieldGuide in allFieldGuideNamesAndIds + if completedFieldGuides.indexOf(fieldGuide.id) > -1 + .row + .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center + .col-xs-12.col-sm-9.col-md-10 + li.faded + a(href="/field-guide/#{fieldGuide.name}")= fieldGuide.name + else + .row + .hidden-xs.col-sm-3.col-md-2 + span + .col-xs-12.col-sm-9.col-md-10 + li + a(href="/field-guide/#{fieldGuide.name}")= fieldGuide.name diff --git a/views/field-guide/show.jade b/views/field-guide/show.jade index 7fe274edcd..a81eb6682f 100644 --- a/views/field-guide/show.jade +++ b/views/field-guide/show.jade @@ -13,18 +13,11 @@ block content if user && user.uncompletedFieldGuides.length > 0 .next-field-guide-button.btn.btn-primary.btn-big.btn-block Next article (ctrl + enter) .ten-pixel-break - #showAllButton.btn.btn-info.btn-big.btn-block Show me all articles + a.btn.btn-info.btn-big.btn-block(href='/field-guide/all-articles') Show me all articles if !user .ten-pixel-break - a.btn.btn-big.signup-btn.btn-block(href="/login") Start learning to code (it's free) + a.btn.btn-big.signup-btn.btn-block(href='/login') Start learning to code (it's free) .spacer - #show-all-dialog.modal(tabindex='-1') - .modal-dialog.animated.fadeInUp.fast-animation - .modal-content - .modal-header.all-list-header Field Guide Articles - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body - include ../partials/field-guide #fieldGuideId.hidden= fieldGuideId script. $(document).ready(function() { diff --git a/views/nonprofits/directory.jade b/views/nonprofits/directory.jade index b39ce839fa..8fb6d2c14b 100644 --- a/views/nonprofits/directory.jade +++ b/views/nonprofits/directory.jade @@ -6,6 +6,8 @@ block content .panel.panel-info .panel-heading.text-center Nonprofits We Help .panel-body + .col-xs-12.col-md-8.col-md-offset-2 + .no-right-padding for nonprofit in nonprofits .spacer .row From bf0cf4cc7d4bd4cd64110facccde3a01d5e866ed Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 00:53:01 -0700 Subject: [PATCH 52/81] add the bug, pair and help buttons to challenge views --- controllers/resources.js | 19 +++++++++------- public/js/main.js | 23 +++++++++++++++++++- views/coursewares/showBonfire.jade | 14 ++++++++---- views/coursewares/showHTML.jade | 9 ++++++-- views/coursewares/showJS.jade | 11 ++++++++++ views/coursewares/showVideo.jade | 10 ++++++++- views/coursewares/showZiplineOrBasejump.jade | 12 ++++++++++ 7 files changed, 82 insertions(+), 16 deletions(-) diff --git a/controllers/resources.js b/controllers/resources.js index ff1205aa94..8a9fa041c1 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -594,13 +594,13 @@ module.exports = { var challenge = req.body.payload.challenge; slack.send({ - text: "*" + userName + "* wants help with " + challenge + " " + + text: "*" + userName + "* wants help with " + challenge + ". " + code + "Hey, *" + userName + "*, if no one helps you right " + "away, try typing out your problem in detail to me. Like this: " + "http://en.wikipedia.org/wiki/Rubber_duck_debugging", channel: '#help', username: "Debuggy the Rubber Duck", - icon_emoji: ":hatched_chick:" + icon_url: "https://pbs.twimg.com/profile_images/3609875545/569237541c920fa78d78902069615caf.jpeg" }); return res.sendStatus(200); }, @@ -608,15 +608,18 @@ module.exports = { getPair: function(req, res, next) { var userName = req.user.profile.username; var challenge = req.body.payload.challenge; - console.log('test'); - slack.send({ - text: "Anyone want to pair with *" + userName + "* on " + challenge + "? (In the meantime, keep coding, *" + userName + "*)", + text: "Anyone want to pair with *" + userName + "* on " + challenge + + "?\nMake sure you install Screen Hero here:" + + "http://freecodecamp.com/field-guide/how-do-i-install-screenhero\n" + + "Then start your pair program session with *" + userName + + "* by typing \"/hero @" + userName + "\" into Slack.\n* And"+ userName + + "*, be sure to launch Screen Hero, then keep coding." + + "Another camper may pair with you soon.", channel: '#letspair', - username: "Perry the Matchmaker", - icon_emoji: ":dancers:" + username: "Companion Cube", + icon_url: "https://lh3.googleusercontent.com/-f6xDPDV2rPE/AAAAAAAAAAI/AAAAAAAAAAA/mdlESXQu11Q/photo.jpg" }); return res.sendStatus(200); - } }; diff --git a/public/js/main.js b/public/js/main.js index 3a3e6e4359..ef692b4d42 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -24,7 +24,7 @@ $(document).ready(function() { { payload: { code: editorValue, - challenge: currentLocation, + challenge: currentLocation } }, function(res) { @@ -35,6 +35,27 @@ $(document).ready(function() { ); }); + $('#i-want-help-editorless').on('click', function() { + var currentLocation = window.location.href; + $.post( + '/get-help', + { + payload: { + challenge: currentLocation + } + }, + function(res) { + if (res) { + window.open('https://freecode.slack.com/messages/help/', '_blank') + } + } + ); + }); + + $('#report-issue').on('click', function() { + window.open('https://github.com/freecodecamp/freecodecamp/issues/new?title=Challenge '+ window.location.href +' has an issue &body=Please%20tell%20us%20in%20detail%20here%20how%20we%20can%20make%20this%20challenge%20better.', '_blank') + }); + $('#i-want-to-pair').on('click', function() { var currentLocation = window.location.href; $.post( diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index a47ba56402..6fc6e0ed2b 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -84,11 +84,17 @@ block content #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) .button-spacer - a.btn.btn-warning.btn-big.btn-block#i-want-help Help + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help + i.fa.fa-medkit + |   Help + label.btn.btn-success#i-want-to-pair + i.fa.fa-user-plus + |   Pair + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug .button-spacer - a.btn.btn-success.btn-big.btn-block#i-want-to-pair Pair - .button-spacer - a.btn.btn-success.btn-big.btn-block#i-found-a-bug Report Bug br form.code .form-group.codeMirrorView diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 05dd0cbaa9..ad9481e868 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -44,9 +44,14 @@ block content br | (ctrl + enter) .button-spacer - a.btn.btn-warning.btn-big.btn-block#i-want-help Get help + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help + i.fa.fa-medkit + |   Help + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug .button-spacer - a.btn.btn-success.btn-big.btn-block#i-want-to-pair Find a Pair script. var userLoggedIn = true; - else diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index f881f8f9cf..d7b914005e 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -35,6 +35,17 @@ block content span.ion-arrow-up-b | Less information #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) + .button-spacer + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help + i.fa.fa-medkit + |   Help + label.btn.btn-success#i-want-to-pair + i.fa.fa-user-plus + |   Pair + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug br form.code .form-group.codeMirrorView diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index f61701be28..0bbb9ee6be 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -27,6 +27,14 @@ block content var userLoggedIn = false; br .button-spacer + .btn-group.input-group.btn-group-justified + .btn.btn-success#i-want-help-editorless + i.fa.fa-medkit + |   Get help from our community + .btn.btn-success#report-issue + i.fa.fa-bug + |   Report a bug or typo in this challenge + .button-spacer script(type="text/javascript"). var controlEnterHandler = function(e) { @@ -74,4 +82,4 @@ block content script. var challenge_Id = !{JSON.stringify(challengeId)}; var challenge_Name = !{JSON.stringify(name)}; - var challengeType = !{JSON.stringify(challengeType)}; \ No newline at end of file + var challengeType = !{JSON.stringify(challengeType)}; diff --git a/views/coursewares/showZiplineOrBasejump.jade b/views/coursewares/showZiplineOrBasejump.jade index e9dda03e15..f18409c78d 100644 --- a/views/coursewares/showZiplineOrBasejump.jade +++ b/views/coursewares/showZiplineOrBasejump.jade @@ -24,6 +24,18 @@ block content br - if (user) a.btn.btn-primary.btn-lg.btn-block#completed-zipline-or-basejump I've completed this challenge (ctrl + enter) + .button-spacer + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help-editorless + i.fa.fa-medkit + |   Help + label.btn.btn-success#i-want-to-pair + i.fa.fa-user-plus + |   Pair + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug + .button-spacer script. var userLoggedIn = true; - else From 7d1c47b39954162199494d97f11714c14b4d1db6 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 01:38:39 -0700 Subject: [PATCH 53/81] remove the tip copy and move it into each bonfire, zipline and basejump --- seed_data/challenges/bonfires.json | 135 ++++++++++++------ .../challenges/full-stack-javascript.json | 50 +++++-- seed_data/challenges/ziplines.json | 8 ++ views/coursewares/showBonfire.jade | 3 - views/coursewares/showVideo.jade | 8 +- views/coursewares/showZiplineOrBasejump.jade | 13 +- 6 files changed, 144 insertions(+), 73 deletions(-) diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json index 1f26e6c533..73a9827702 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/bonfires.json @@ -44,7 +44,8 @@ "description": [ "Reverse the provided string.", "You may need to turn the string into an array before you can reverse it.", - "Your result must be a string." + "Your result must be a string.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function reverseString(str) {", @@ -70,7 +71,8 @@ "Return the factorial of the provided integer.", "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.", "Factorials are often represented with the shorthand notation n!", - "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f" + "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function factorialize(num) {", @@ -90,7 +92,8 @@ "Return true if the given string is a palindrome. Otherwise, return false.", "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.", "You'll need to remove punctuation and turn everything lower case in order to check for palindromes.", - "We'll pass strings with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others." + "We'll pass strings with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "tests": [ "expect(palindrome(\"eye\")).to.be.a(\"boolean\");", @@ -120,7 +123,8 @@ "difficulty": "1.04", "description": [ "Return the length of the longest word in the provided sentence.", - "Your response should be a number." + "Your response should be a number.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function findLongestWord(str) {", @@ -145,7 +149,8 @@ "difficulty": "1.05", "description": [ "Return the provided string with the first letter of each word capitalized.", - "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'." + "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function titleCase(str) {", @@ -170,7 +175,8 @@ "description": [ "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", - "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays." + "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function largestOfFour(arr) {", @@ -193,7 +199,8 @@ "name": "Confirm the Ending", "difficulty": "1.07", "description": [ - "Check if a string (first argument) ends with the given target string (second argument)." + "Check if a string (first argument) ends with the given target string (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ @@ -218,7 +225,8 @@ "name": "Repeat a string repeat a string", "difficulty": "1.08", "description": [ - "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number." + "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function repeat(str, num) {", @@ -242,7 +250,8 @@ "difficulty": "1.09", "description": [ "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", - "Note that the three dots at the end add to the string length." + "Note that the three dots at the end add to the string length.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function truncate(str, num) {", @@ -265,7 +274,8 @@ "name": "Chunky Monkey", "difficulty": "1.10", "description": [ - "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array." + "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function chunk(arr, size) {", @@ -288,7 +298,8 @@ "name": "Slasher Flick", "difficulty": "1.11", "description": [ - "Return the remaining elements of an array after chopping off n elements from the head." + "Return the remaining elements of an array after chopping off n elements from the head.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function slasher(arr, howMany) {", @@ -314,7 +325,8 @@ "Return true if the string in the first element of the array contains the letters of the string in the second element of the array.", "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", - "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'." + "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function mutation(arr) {", @@ -339,7 +351,8 @@ "difficulty": "1.50", "description": [ "Remove all falsey values from an array.", - "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN." + "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function bouncer(arr) {", @@ -362,7 +375,8 @@ "name":"Where art thou", "difficulty":"1.55", "description":[ - "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument)." + "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function where(collection, source) {", @@ -385,7 +399,8 @@ "name":"Seek and Destroy", "difficulty":"1.60", "description":[ - "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments." + "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function destroyer(arr) {", @@ -408,7 +423,8 @@ "difficulty": "1.61", "description": [ "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", - "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 (0th index), but less than 2 (1st index).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function where(arr, num) {", @@ -429,7 +445,8 @@ "difficulty": "2.00", "description": [ "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", - "The lowest number will not always come first." + "The lowest number will not always come first.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function sumAll(arr) {", @@ -453,7 +470,8 @@ "name": "Diff Two Arrays", "difficulty": "2.01", "description": [ - "Compare two arrays and return a new array with any items not found in both of the original arrays." + "Compare two arrays and return a new array with any items not found in both of the original arrays.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function diff(arr1, arr2) {", @@ -487,7 +505,8 @@ "difficulty": "2.02", "description": [ "Convert the number be a roman numeral.", - "All roman numerals answers should be provided in upper-case." + "All roman numerals answers should be provided in upper-case.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function convert(num) {", @@ -515,7 +534,8 @@ "First argument is the sentence the perform the search and replace on.", "Second argument is the word that you will be replacing (before).", "Third argument is what you will be replacing the second argument with (after).", - "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'" + "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function replace(str, before, after) {", @@ -541,7 +561,8 @@ "description": [ "Translate the provided string to pig latin.", "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", - "If a word begins with a vowel you just add \"way\" to the end." + "If a word begins with a vowel you just add \"way\" to the end.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function translate(str) {", @@ -565,7 +586,8 @@ "description": [ "The DNA strand is missing the pairing element. Match each character with the missing element and return the results as a 2d array.", "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", - "Return the provided character as the first element in each array." + "Return the provided character as the first element in each array.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function pair(str) {", @@ -583,7 +605,8 @@ "difficulty": "2.05", "description" : [ "Find the missing letter in the passed letter range and return it.", - "If all letters are present in the range, return undefined." + "If all letters are present in the range, return undefined.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function fearNotLetter(str) {", @@ -607,7 +630,8 @@ "difficulty": "2.06", "description": [ "Check if a value is classified as a boolean primitive. Return true or false.", - "Boolean primitives are true and false." + "Boolean primitives are true and false.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function boo(bool) {", @@ -638,7 +662,8 @@ "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.", "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", - "Check the assertion tests for examples." + "Check the assertion tests for examples.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function unite(arr1, arr2, arr3) {", @@ -658,7 +683,8 @@ "name": "Convert HTML Entities", "difficulty": "2.07", "description": [ - "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities." + "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function convert(str) {", @@ -680,7 +706,8 @@ "name": "Spinal Tap Case", "difficulty": "2.08", "description": [ - "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes." + "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function spinalCase(str) {", @@ -707,7 +734,8 @@ "description": [ "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", - "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3." + "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function sumFibs(num) {", @@ -734,7 +762,8 @@ "description": [ "Sum all the prime numbers up to and including the provided number.", "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", - "The provided number may not be a prime." + "The provided number may not be a prime.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function sumPrimes(num) {", @@ -756,7 +785,8 @@ "difficulty": "2.11", "description": [ "Find the smallest number that is evenly divisible by all numbers in the provided range.", - "The range will be an array of two numbers that will not necessarily be in numerical order." + "The range will be an array of two numbers that will not necessarily be in numerical order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function smallestCommons(arr) {", @@ -779,7 +809,8 @@ "name": "Finders Keepers", "difficulty": "2.12", "description": [ - "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument)." + "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument).", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function find(arr, func) {", @@ -800,7 +831,8 @@ "name": "Drop it like it's hot", "difficulty": "2.13", "description": [ - "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true." + "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function drop(arr, func) {", @@ -823,7 +855,8 @@ "name": "Steamroller", "difficulty": "2.14", "description": [ - "Flatten a nested array. You must account for varying levels of nesting." + "Flatten a nested array. You must account for varying levels of nesting.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function steamroller(arr) {", @@ -847,7 +880,8 @@ "difficulty": "2.15", "description": [ "Return an English translated sentence of the passed binary string.", - "The binary string will be space separated." + "The binary string will be space separated.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function binaryAgent(str) {", @@ -871,7 +905,8 @@ "description": [ "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", - "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!" + "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function pairwise(arr, arg) {", @@ -896,7 +931,8 @@ "description": [ "Check if the predicate (second argument) returns truthy (defined) for 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 RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function every(collection, pre) {", @@ -920,7 +956,8 @@ "description": [ "Create a function that sums two arguments together. If only one argument is provided, return a function that expects one additional argument and will return the sum.", "For example, add(2, 3) should return 5, and add(2) should return a function that is waiting for an argument so that var sum2And = add(2); return sum2And(3); // 5", - "If either argument isn't a valid number, return undefined." + "If either argument isn't a valid number, return undefined.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function add() {", @@ -947,7 +984,8 @@ "Fill in the object constructor with the methods specified in the tests.", "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", "All functions that take an argument have an arity of 1, and the argument will be a string.", - "These methods must be the only available means for interacting with the object." + "These methods must be the only available means for interacting with the object.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "var Person = function(firstAndLast) {", @@ -985,7 +1023,8 @@ "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", "You can read about orbital periods on wikipedia.", "The values should be rounded to the nearest whole number. The body being orbited is Earth.", - "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418" + "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function orbitalPeriod(arr) {", @@ -1011,7 +1050,8 @@ "Return true if the passed string is a valid US phone number", "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", - "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false." + "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "tests": [ "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", @@ -1055,7 +1095,8 @@ "difficulty": "4.02", "description": [ "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", - "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both." + "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function sym(args) {", @@ -1076,7 +1117,8 @@ "name": "Cash Register", "difficulty": "4.03", "description": [ - "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order." + "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function drawer(price, cash, cid) {", @@ -1114,7 +1156,8 @@ "name": "Inventory Update", "difficulty": "4.04", "description": [ - "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order." + "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function inventory(arr1, arr2) {", @@ -1155,7 +1198,8 @@ "difficulty": "4.05", "description": [ "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", - "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating." + "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function permAlone(str) {", @@ -1184,7 +1228,8 @@ "It must not show any redundant information in the date range.", "For example, if the year and month are the same then only the day range should be displayed.", "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", - "Input date is formatted as YYYY-MM-DD" + "Input date is formatted as YYYY-MM-DD", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ "function friendly(str) {", diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index c1491ce793..74e63fa473 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -77,9 +77,9 @@ "Open up http://c9.io and sign in to your account.", "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Choose Node.js in the selection area below the name field.", + "Click the Create button.", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", "Click the \"Start Editing\" button.", "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", "Run this command: sudo npm install how-to-npm -g", @@ -96,19 +96,45 @@ "difficulty": 0.40, "challengeSeed": "126411561", "description": [ - "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", + "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud. We'll do the first 7 steps of Node School's LearnYouNode challenges.", "If you don't already have Cloud 9 account, create one now at http://c9.io.", "Open up http://c9.io and sign in to your account.", "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Choose Node.js in the selection area below the name field.", + "Click the Create button.", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", "Click the \"Start Editing\" button.", "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", "Run this command: sudo npm install learnyounode -g", "Now start this tutorial by running learnyounode", "Note that you can resize the c9.io's windows by dragging their borders.", + "Follow the directions and work through the tutorial's steps 1 through 7 before moving on." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7153d8c441eddfaeb5bdfe", + "name": "Continue working with Node.js Servers", + "difficulty": 0.41, + "challengeSeed": "126411561", + "description": [ + "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 8 through 10.", + "Return to the c9.io workspace you created Now start this tutorial by running learnyounode", + "Follow the directions and work through all of the the tutorial's steps before moving on." + ], + "challengeType": 2, + "tests": [] + }, + { + "_id": "bd7153d8c441eddfaeb5bdfd", + "name": "Finish working with Node.js Servers", + "difficulty": 0.42, + "challengeSeed": "126411561", + "description": [ + "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 11 through 13.", + "Return to the c9.io workspace you created for the previous LearnYouNode challenges and start the tutorial by running learnyounode", "Follow the directions and work through all of the the tutorial's steps before moving on." ], "challengeType": 2, @@ -117,7 +143,7 @@ { "_id": "bd7153d8c441eddfaeb5bd1f", "name": "Build Web Apps with Express.js", - "difficulty": 0.41, + "difficulty": 0.43, "challengeSeed": "126411559", "description": [ "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", @@ -125,9 +151,9 @@ "Open up http://c9.io and sign in to your account.", "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", + "Choose Node.js in the selection area below the name field.", + "Click the Create button.", + "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", "Click the \"Start Editing\" button.", "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", "Run this command: git clone http://github.com/reddock/fcc_express && chmod 744 fcc_express/setup.sh && fcc_express/setup.sh && source ~/.profile", @@ -141,7 +167,7 @@ { "_id": "bd7140d8c441eddfaeb5bdef", "name": "Manage Source Code with Git", - "difficulty": 0.43, + "difficulty": 0.44, "challengeSeed": "114635309", "description": [ "Version Control Systems like Git ensure that, no matter how you experiment with your code, you can always roll back your app to a stable previous state.", diff --git a/seed_data/challenges/ziplines.json b/seed_data/challenges/ziplines.json index ef23b63bea..2cbf2eff80 100644 --- a/seed_data/challenges/ziplines.json +++ b/seed_data/challenges/ziplines.json @@ -43,6 +43,7 @@ "Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", "Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", "Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", + "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.", "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" ], @@ -62,6 +63,7 @@ "Here are the user stories you must enable, and optional bonus user stories:", "User Story: As a user, I can click a button to show me a new random quote.", "Bonus User Story: As a user, I can press a button to tweet out a quote.", + "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.", "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" ], @@ -83,6 +85,7 @@ "Bonus User Story: As a user, I can see an icon depending on the temperature..", "Bonus User Story: As a user, I see a different background image depending on the temperature (e.g. snowy mountain, hot desert).", "Bonus User Story: As a user, I can push a button to toggle between Fahrenheit and Celsius.", + "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.", "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" ], @@ -105,6 +108,7 @@ "User Story: As a user, I can click a link to go directly to the post's discussion page.", "Bonus User Story: As a user, I can see how many upvotes each story has.", "Hint: Here's the Camper News Hot Stories API endpoint: http://www.freecodecamp.com/stories/hotStories.", + "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.", "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" ], @@ -126,6 +130,7 @@ "Bonus User Story:As a user, I can click a button to see a random Wikipedia entry.", "Bonus User Story:As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.", "Hint: Here's an entry on using Wikipedia's API: http://www.mediawiki.org/wiki/API:Main_page.", + "Remember to use RSAP if you get stuck. Try using jQuery's $.getJSON() to consume APIs.", "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" ], @@ -146,6 +151,7 @@ "User Story: As a user, I can start a 25 minute pomodoro, and the timer will go off once 25 minutes has elapsed.", "Bonus User Story: As a user, I can reset the clock for my next pomodoro.", "Bonus User Story: As a user, I can customize the length of each pomodoro.", + "Remember to use RSAP 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" ], @@ -166,6 +172,7 @@ "User Story: As a user, I can add, subtract, multiply and divide two numbers.", "Bonus User Story: I can clear the input field with a clear button.", "Bonus User Story: I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", + "Remember to use RSAP 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" ], @@ -187,6 +194,7 @@ "Bonus User Story: As a user, I can never actually win against the computer - at best I can tie.", "Bonus User Story: As a user, my game will reset as soon as it's over so I can play again.", "Bonus User Story: As a user, I can choose whether I want to play as X or O.", + "Remember to use RSAP 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/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index 6fc6e0ed2b..e0e2f89502 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -58,9 +58,6 @@ block content i.ion-ios-flame i.ion-ios-flame i.ion-ios-flame - p.text-center Tips: Use  - a(href='/field-guide/how-do-i-get-help-when-I-get-stuck') RSAP - | . Try to pair program. Write your own code. .well .row .col-xs-12 diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 0bbb9ee6be..277c5e1267 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -28,12 +28,12 @@ block content br .button-spacer .btn-group.input-group.btn-group-justified - .btn.btn-success#i-want-help-editorless + .btn.btn-success.btn-big#i-want-help-editorless i.fa.fa-medkit - |   Get help from our community - .btn.btn-success#report-issue + |   Get help + .btn.btn-success.btn-big#report-issue i.fa.fa-bug - |   Report a bug or typo in this challenge + |   Report a bug .button-spacer script(type="text/javascript"). diff --git a/views/coursewares/showZiplineOrBasejump.jade b/views/coursewares/showZiplineOrBasejump.jade index f18409c78d..bc890d9afc 100644 --- a/views/coursewares/showZiplineOrBasejump.jade +++ b/views/coursewares/showZiplineOrBasejump.jade @@ -3,11 +3,6 @@ block content .row .col-xs-12.col-sm-12.col-md-4.bonfire-top h1.text-center= name - p.text-center Tips: Use  - a(href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank') RSAP - | . Try using   - a(href='http://api.jquery.com/jquery.each/' target='_blank') jQuery's $.getJSON() - |  to consume APIs. .well h4 ol @@ -23,16 +18,16 @@ block content iframe.embed-responsive-item(src='//player.vimeo.com/video/#{video}') br - if (user) - a.btn.btn-primary.btn-lg.btn-block#completed-zipline-or-basejump I've completed this challenge (ctrl + enter) + a.btn.btn-primary.btn-big.btn-block#completed-zipline-or-basejump I've completed this challenge (ctrl + enter) .button-spacer .btn-group.input-group.btn-group-justified - label.btn.btn-success#i-want-help-editorless + .btn.btn-success.btn-big#i-want-help-editorless i.fa.fa-medkit |   Help - label.btn.btn-success#i-want-to-pair + .btn.btn-success.btn-big#i-want-to-pair i.fa.fa-user-plus |   Pair - label.btn.btn-success#report-issue + .btn.btn-success.btn-big#report-issue i.fa.fa-bug |   Bug .button-spacer From a6cd73d2f131ab0cbee120f1444f36a2c3b3f02f Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 15:43:16 -0700 Subject: [PATCH 54/81] manually merge improvements to bonfires to challenges/bonfires.json --- seed_data/challenges/bonfires.json | 78 ++++++++++++++++++------------ views/coursewares/showBonfire.jade | 1 - 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json index 73a9827702..fcbe1ecac6 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/bonfires.json @@ -434,10 +434,12 @@ "", "where([40, 60], 50);" ], + "MDNlinks" : ["Array.sort()"], "tests": [ "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" - ] + ], + "challengeType": 5 }, { "_id": "a3566b1109230028080c9345", @@ -490,7 +492,10 @@ "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" - ] + ], + "MDNlinks" : ["Comparison Operators", "String.slice()", "Array.filter()", "Array.indexOf()", "String.concat()"], + "challengeType": 5 + }, { "_id": "a7f4d8f2483413a6ce226cac", @@ -504,7 +509,7 @@ ], "difficulty": "2.02", "description": [ - "Convert the number be a roman numeral.", + "Convert the given number into a roman numeral.", "All roman numerals answers should be provided in upper-case.", "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], @@ -676,6 +681,7 @@ "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" ], + "MDNlinks" : ["Array.reduce()"], "challengeType": 5 }, { @@ -777,6 +783,7 @@ "expect(sumPrimes(10)).to.equal(17);", "expect(sumPrimes(977)).to.equal(73156);" ], + "MDNlinks" : ["For Loops", "Array.push()"], "challengeType": 5 }, { @@ -802,6 +809,7 @@ "expect(smallestCommons([5,1])).to.equal(60);", "(smallestCommons([1,13])).should.equal(360360);" ], + "MDNlinks" : ["Smallest Common Multiple"], "challengeType": 5 }, { @@ -824,7 +832,8 @@ "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" ], - "MDNlinks": ["Array.some()"] + "MDNlinks": ["Array.some()"], + "challengeType": 5 }, { "_id": "a5deed1811a43193f9f1c841", @@ -898,32 +907,6 @@ ], "challengeType": 5 }, - { - "_id" : "a3f503de51cfab748ff001aa", - "name": "Pairwise", - "difficulty": "2.16", - "description": [ - "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", - "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", - "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function pairwise(arr, arg) {", - " return arg;", - "}", - "", - "pairwise([1,4,2,3,0,5], 7);" - ], - "tests": [ - "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", - "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", - "expect(pairwise([1,1,1], 2)).to.equal(1);", - "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", - "expect(pairwise([], 100)).to.equal(0);" - ], - "challengeType": 5 - }, { "_id": "a10d2431ad0c6a099a4b8b52", "name": "Everything Be True", @@ -1042,6 +1025,33 @@ "MDNlinks": ["Math.pow()"], "challengeType": 5 }, + { + "_id" : "a3f503de51cfab748ff001aa", + "name": "Pairwise", + "difficulty": "3.51", + "description": [ + "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", + "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", + "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function pairwise(arr, arg) {", + " return arg;", + "}", + "", + "pairwise([1,4,2,3,0,5], 7);" + ], + "tests": [ + "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", + "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", + "expect(pairwise([1,1,1], 2)).to.equal(1);", + "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", + "expect(pairwise([], 100)).to.equal(0);" + ], + "MDNlinks" : ["Array.reduce()"], + "challengeType": 5 + }, { "_id": "aff0395860f5d3034dc0bfc9", "name": "Validate US Telephone Numbers", @@ -1087,6 +1097,7 @@ "", "telephoneCheck(\"555-555-5555\");" ], + "MDNlinks" : ["RegExp"], "challengeType": 5 }, { @@ -1110,7 +1121,9 @@ "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" - ] + ], + "MDNlinks" : ["Array.reduce()"], + "challengeType": 5 }, { "_id": "aa2e6f85cab2ab736c9a9b24", @@ -1149,6 +1162,7 @@ "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" ], + "MDNlinks" : ["Global Object"], "challengeType": 5 }, { @@ -1190,6 +1204,7 @@ "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" ], + "MDNlinks" : ["Global Array Object"], "challengeType": 5 }, { @@ -1217,6 +1232,7 @@ "expect(permAlone('abfdefa')).to.equal(2640);", "expect(permAlone('zzzzzzzz')).to.equal(0);" ], + "MDNlinks" : ["Permutations", "RegExp"], "challengeType": 5 }, { diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index e0e2f89502..e68b9d4115 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -92,7 +92,6 @@ block content i.fa.fa-bug |   Bug .button-spacer - br form.code .form-group.codeMirrorView textarea#codeOutput(style='display: none;') From c02167515540e1a4adb26ead6066d42c06e2fca7 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 15:59:52 -0700 Subject: [PATCH 55/81] update the basejumps and other challenges that had changed --- seed_data/challenges/basejumps.json | 45 +++++++++---------- .../getting-set-for-free-code-camp.json | 2 +- seed_data/coursewares.json | 3 +- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/seed_data/challenges/basejumps.json b/seed_data/challenges/basejumps.json index 3681225266..5ef3deb8bc 100644 --- a/seed_data/challenges/basejumps.json +++ b/seed_data/challenges/basejumps.json @@ -6,7 +6,7 @@ "_id": "bd7158d8c443eddfaeb5bcef", "name": "Get Set for Basejumps", "difficulty": 2.00, - "challengeSeed": "126433451", + "challengeSeed": "128451852", "description": [ "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.", "We'll build our Basejumps on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", @@ -42,23 +42,23 @@ "Start the application by running the following command in your new terminal window: grunt serve", "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", - "Now we need to add your github SSH key to c9.io. Click the \"Add-on Services\" button in the lower left of your C9 dashboard. Click \"activate\" next to the GitHub icon.", + "Now we need to add your GitHub SSH key to c9.io. Click the \"Add-on Services\" button in the lower left of your C9 dashboard. Click \"activate\" next to the GitHub icon.", "A pop up will appear. Allow access to your account.", "While still on the dashboard, under “Account Settings”, click the link for \"Show your SSH key\". Copy the key to you clipboard.", "Sign in to http://github.com and navigate to the GitHub SSH settings page. Click the \"Add SSH Key\". Give your key the title \"cloud 9\". Paste your SSH Key into the \"Key\" box, then click \"Add Key\".", - "Create a new Github repository by and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", + "Create a new GitHub repository by and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", "Enter a project name, then click the \"Create Repository\" button.", "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", - "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to Github.", - "Check back on your Github profile to verify the changes were successfully pushed up to Github.", + "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to GitHub.", + "Check back on your GitHub profile to verify the changes were successfully pushed up to GitHub.", "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.", "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c hotkey to shut down these processes.", "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login. At this point, the terminal will prompt you to log in to Heroku from the command line.", "Now run yo angular-fullstack:heroku. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab.", "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace directory by running cd ~/workspace. Then you can this code to stage the changes to your changes and commit them: git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." ], "challengeType": 4, "tests": [] @@ -67,12 +67,12 @@ "_id": "bd7158d8c443eddfaeb5bdef", "name": "Basejump: Build a Voting App", "difficulty": 2.01, - "challengeSeed": "123488494", + "challengeSeed": "128451852", "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://voteplex.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an authenticated user, I can keep my polls and come back later to access them.", "User Story: As an authenticated user, I can share my polls with my friends.", @@ -82,7 +82,7 @@ "Bonus User Story: As an unauthenticated user, I can see everyone's polls, but I can't vote on anything.", "Bonus User Story: As an unauthenticated or authenticated user, I can see the results of polls in chart form. (This could be implemented using Chart.js or Google Charts.)", "Bonus User Story: As an authenticated user, if I don't like the options on a poll, I can create a new option.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -92,18 +92,18 @@ "_id": "bd7158d8c443eddfaeb5bdff", "name": "Basejump: Build a Nightlife Coordination App", "difficulty": 2.02, - "challengeSeed": "123488494", + "challengeSeed": "128451852", "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://sociallife.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an unauthenticated user, I can view all bars in my area.", "User Story: As an authenticated user, I can add myself to a bar to indicate I am going there tonight.", "User Story: As an authenticated user, I can remove myself from a bar if I no longer want to go there.", "Bonus User Story: As an unauthenticated user, when I login I should not have to search again.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -113,18 +113,18 @@ "_id": "bd7158d8c443eddfaeb5bd0e", "name": "Basejump: Chart the Stock Market", "difficulty": 2.03, - "challengeSeed": "123488494", + "challengeSeed": "128451852", "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockjump.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As a user, I can view a graph displaying the recent trend lines for each added stock.", "User Story: As a user, I can add new stocks by their symbol name.", "User Story: As a user, I can remove stocks.", "Bonus User Story: As a user, I can see changes in real-time when any other user adds or removes a stock.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -134,18 +134,18 @@ "_id": "bd7158d8c443eddfaeb5bd0f", "name": "Basejump: Manage a Book Trading Club", "difficulty": 2.04, - "challengeSeed": "123488494", + "challengeSeed": "128451852", "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookoutpost.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an authenticated user, I can view all books posted by every user.", "User Story: As an authenticated user, I can add a new book.", "User Story: As an authenticated user, I can update my settings to store my full name, city, and state.", "Bonus User Story: As an authenticated user, I can propose a trade and wait for the other user to accept the trade.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, @@ -155,22 +155,21 @@ "_id": "bd7158d8c443eddfaeb5bdee", "name": "Basejump: Build a Pinterest Clone", "difficulty": 2.05, - "challengeSeed": "123488494", + "challengeSeed": "128451852", "description": [ "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://linkterest.herokuapp.com/ and deploy it to Heroku.", "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to Github by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", + "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", "Here are the specific User Stories you should implement for this Basejump:", "User Story: As an unauthenticated user, I can login with Twitter.", "User Story: As an authenticated user, I can link to images.", "User Story: As an authenticated user, I can delete images that I've linked to.", "User Story: As an authenticated user, I can see a Pinterest-style wall of all the images I've linked to.", "User Story: As an unauthenticated user, I can browse other users' walls of images.", - "User Story: As an unauthenticated user, I can see everyone's polls, but not be able to vote.", "Bonus User Story: As an authenticated user, if I upload an image that is broken, it will be replaced by a placeholder image. (can use jQuery broken image detection)", "Hint: Masonry.js is a library that allows for Pinterest-style image grids.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your Github repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", + "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

    Click here then add your link to your tweet's text" ], "challengeType": 4, diff --git a/seed_data/challenges/getting-set-for-free-code-camp.json b/seed_data/challenges/getting-set-for-free-code-camp.json index 8f6a23b779..3ff60924b0 100644 --- a/seed_data/challenges/getting-set-for-free-code-camp.json +++ b/seed_data/challenges/getting-set-for-free-code-camp.json @@ -81,7 +81,7 @@ "To see your portfolio page, click your picture in the upper right hand corner.", "Your portfolio page will automatically show off your progress through Free Code Camp.", "Click the \"Update my portfolio page or manage my account\" button", - "You can link to your Github, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", + "You can link to your GitHub, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", "Be sure to click the \"Update my Bio\" or \"Update my Social Links\" button to save this new information to your portfolio page.", "Once you're happy with your portfolio page, you can move on to your next challenge." ], diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json index 6e61d69c23..c463b195fb 100644 --- a/seed_data/coursewares.json +++ b/seed_data/coursewares.json @@ -47,8 +47,7 @@ "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", "You should complete all these challenges in order.", "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", - "This challenge map is just for your reference. You can always just press the \"Learn\" button, and it will take you to your next challenge.", - "Finally, please note that our open-source curriculum is a work in progress. Our volunteer community is constantly improving it. If you encounter a bug or something you think is unnecessarily hard, let us know: https://github.com/FreeCodeCamp/freecodecamp/issues." + "This challenge map is just for your reference. You can always just press the \"Learn\" button, and it will take you to your next challenge." ], "challengeType": 2, "tests": [] From 48acbd2ea7ef3bd5c371ec1e53c21988fe2827d4 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 16:08:19 -0700 Subject: [PATCH 56/81] more minor QA tasks on seed files --- seed_data/challenges/basic-html5-and-css.json | 78 +++++++++---------- seed_data/challenges/basic-javascript.json | 57 ++++++++------ seed_data/challenges/bootstrap.json | 70 +++++++++++------ .../challenges/jquery-ajax-and-json.json | 6 +- 4 files changed, 123 insertions(+), 88 deletions(-) diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json index 0e30ebd275..568c54b32c 100644 --- a/seed_data/challenges/basic-html5-and-css.json +++ b/seed_data/challenges/basic-html5-and-css.json @@ -1,10 +1,10 @@ { - "name": "Basic HTML5 and CSS", + "name": "Waypoint: Basic HTML5 and CSS", "order" : 0.002, "challenges": [ { "_id": "bd7123c8c441eddfaeb5bdef", - "name": "Use HTML Elements", + "name": "Waypoint: Use HTML Elements", "difficulty": 0.0085, "description": [ "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", @@ -25,7 +25,7 @@ }, { "_id": "bad87fee1348bd9aedf0887a", - "name": "Use the h2 Element", + "name": "Waypoint: Use the h2 Element", "difficulty": 0.010, "description": [ "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", @@ -44,7 +44,7 @@ }, { "_id": "bad87fee1348bd9aedf08801", - "name": "Use the Paragraph Element", + "name": "Waypoint: Use the Paragraph Element", "difficulty": 0.011, "description": [ "Create a paragraph element below the h2 element, and give it the text \"Hello Paragraph\".", @@ -62,7 +62,7 @@ }, { "_id": "bad87fee1348bd9aeaf08801", - "name": "Add a Line Break to Visually Separate Elements", + "name": "Waypoint: Add a Line Break to Visually Separate Elements", "difficulty": 0.012, "description": [ "Add a line break between the <h2> and <p> elements.", @@ -82,7 +82,7 @@ }, { "_id": "bad87fee1348bd9aedf08802", - "name": "Uncomment HTML", + "name": "Waypoint: Uncomment HTML", "difficulty": 0.013, "description": [ "Uncomment the h1, h2 and p elements.", @@ -110,7 +110,7 @@ }, { "_id": "bad87fee1348bd9aedf08804", - "name": "Comment out HTML", + "name": "Waypoint: Comment out HTML", "difficulty": 0.014, "description": [ "Comment out the h1 element and the p element, but leave the h2 element uncommented.", @@ -137,7 +137,7 @@ }, { "_id": "bad87fee1348bd9aedf08833", - "name": "Use Lorem Ipsum Text as a Placeholder", + "name": "Waypoint: Use Lorem Ipsum Text as a Placeholder", "difficulty": 0.015, "description": [ "Change the text in the p element to use the first few words of Kitty Ipsum text.", @@ -162,7 +162,7 @@ }, { "_id": "bad87fed1348bd9aedf08833", - "name": "Delete HTML Elements", + "name": "Waypoint: Delete HTML Elements", "difficulty": 0.016, "description": [ "Delete the h1 and br elements so we can simplify our view.", @@ -188,7 +188,7 @@ }, { "_id": "bad87fee1348bd9aedf08803", - "name": "Change the Color of Text", + "name": "Waypoint: Change the Color of Text", "difficulty": 0.017, "description": [ "Change the h2 element's style so that its text color is red.", @@ -208,7 +208,7 @@ }, { "_id": "bad87fee1348bd9aedf08805", - "name": "Use CSS Selectors to Style Elements", + "name": "Waypoint: Use CSS Selectors to Style Elements", "difficulty": 0.018, "description": [ "Delete your h2 element's style tag and write the CSS to make all h2 elements blue.", @@ -232,7 +232,7 @@ }, { "_id": "bad87fee1348bd9aecf08806", - "name": "Use a CSS Class to Style an Element", + "name": "Waypoint: Use a CSS Class to Style an Element", "difficulty": 0.019, "description": [ "Create a CSS class called \"red-text\" and apply it to your h2 element.", @@ -263,7 +263,7 @@ }, { "_id": "bad87fee1348bd9aefe08806", - "name": "Use a CSS Class to Style Multiple Elements", + "name": "Waypoint: Use a CSS Class to Style Multiple Elements", "difficulty": 0.020, "description": [ "Apply the \"red-text\" class to the h2 and p elements.", @@ -290,7 +290,7 @@ }, { "_id": "bad87fee1348bd9aedf08806", - "name": "Change the Font Size of an Element", + "name": "Waypoint: Change the Font Size of an Element", "difficulty": 0.021, "description": [ "Create a second p element. Then set the font size of all p elements to 16 pixels.", @@ -317,7 +317,7 @@ }, { "_id": "bad87fee1348bd9aede08807", - "name": "Set the Font Family of an Element", + "name": "Waypoint: Set the Font Family of an Element", "difficulty": 0.022, "description": [ "Make all paragraph elements use the \"Monospace\" font.", @@ -347,7 +347,7 @@ }, { "_id": "bad87fee1348bd9aedf08807", - "name": "Import a Google Font", + "name": "Waypoint: Import a Google Font", "difficulty": 0.023, "description": [ "Apply the font-family of \"Lobster\" to your h2 element.", @@ -380,7 +380,7 @@ }, { "_id": "bad87fee1348bd9aedf08808", - "name": "Specify How Fonts Should Degrade", + "name": "Waypoint: Specify How Fonts Should Degrade", "difficulty": 0.024, "description": [ "Make all your h2 elements use \"Lobster\" as their font family, but degrade to the \"Monospace\" font when the \"Lobster\" font isn't available.", @@ -419,7 +419,7 @@ }, { "_id": "bad87fee1348bd9aedf08809", - "name": "Using Important to Override Styles", + "name": "Waypoint: Using Important to Override Styles", "difficulty": 0.025, "description": [ "Create a \"blue-text\" class that gives an element the font-color of blue. Also create a \"urgently-red\" class that give an element the font-color of red, but use !important to ensure the element is rendered as being red. Apply both classes to your h2 element.", @@ -462,7 +462,7 @@ { "_id": "bad87fee1348bd9aedf08812", - "name": "Add an Image to your Website", + "name": "Waypoint: Add an Image to your Website", "difficulty": 0.026, "description": [ "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", @@ -500,7 +500,7 @@ }, { "_id": "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size", + "name": "Waypoint: Specify an Image Size", "difficulty": 0.027, "description": [ "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", @@ -539,7 +539,7 @@ }, { "_id": "bad87fee1348bd9bedf08813", - "name": "Add a Border Around an Element", + "name": "Waypoint: Add a Border Around an Element", "difficulty": 0.028, "description": [ "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border around an HTML element, and apply it to your cat photo.", @@ -583,7 +583,7 @@ }, { "_id": "bad87fee1348bd9aedf08814", - "name": "Add Rounded Corners with a Border Radius", + "name": "Waypoint: Add Rounded Corners with a Border Radius", "difficulty": 0.029, "description": [ "Give your cat photo a border radius of 10 pixels.", @@ -632,7 +632,7 @@ }, { "_id": "bad87fee1348bd9aedf08815", - "name": "Make an Image Circular with a Border Radius", + "name": "Waypoint: Make an Image Circular with a Border Radius", "difficulty": 0.030, "description": [ "Give your cat photo a border-radius of 50%.", @@ -680,7 +680,7 @@ }, { "_id": "bad87fee1348bd9aedf08816", - "name": "Use an Anchor Tag to Link to an External Page", + "name": "Waypoint: Use an Anchor Tag to Link to an External Page", "difficulty": 0.031, "description": [ "Create an anchor element that links to http://catphotoapp.com and has \"cat photos\" as its anchor text (link text).", @@ -731,7 +731,7 @@ }, { "_id": "bad87fee1348bd9aede08817", - "name": "Wrap an Anchor Element within a Paragraph", + "name": "Waypoint: Wrap an Anchor Element within a Paragraph", "difficulty": 0.032, "description": [ "Now wrap your anchor element within a paragraph element so that the surrounding paragraph says \"click here for cat photos\", but where only \"cat photos\" is a link - the rest is plain text.", @@ -786,7 +786,7 @@ { "_id": "bad87fee1348bd9aedf08817", - "name": "Make Dead Links using the Hash Symbol", + "name": "Waypoint: Make Dead Links using the Hash Symbol", "difficulty": 0.033, "description": [ "Use the hash symbol(#) to turn your anchor element's link into a dead link.", @@ -838,7 +838,7 @@ }, { "_id": "bad87fee1348bd9aedf08820", - "name": "Turn an Image into a Link", + "name": "Waypoint: Turn an Image into a Link", "difficulty": 0.034, "description": [ "Wrap your img element inside an anchor element with a dead link.", @@ -891,7 +891,7 @@ }, { "_id": "bad87fee1348bd9aedf08818", - "name": "Add Alt Text to an image", + "name": "Waypoint: Add Alt Text to an image", "difficulty": 0.035, "description": [ "Add the alt text \"A cute orange cat lying on its back\" to our cat photo", @@ -945,7 +945,7 @@ { "_id" : "bad87fee1348bd9aedf08827", - "name": "Create a Bulleted Unordered List", + "name": "Waypoint: Create a Bulleted Unordered List", "difficulty" : 0.036, "description": [ "Replace the paragraph elements with an unordered list of three things that cats love.", @@ -999,7 +999,7 @@ { "_id" : "bad87fee1348bd9aedf08828", - "name": "Create an Ordered List", + "name": "Waypoint: Create an Ordered List", "difficulty" : 0.037, "description": [ "Create an ordered list of the the top 3 things cats hate the most.", @@ -1059,7 +1059,7 @@ { "_id" : "bad87fee1348bd9aedf08829", - "name": "Create a Text Field", + "name": "Waypoint: Create a Text Field", "difficulty" : 0.038, "description": [ "Now we'll create a web form. Create a text field under your lists.", @@ -1121,7 +1121,7 @@ { "_id" : "bad87fee1348bd9aedf08830", - "name": "Add Placeholder Text to a Text Field", + "name": "Waypoint: Add Placeholder Text to a Text Field", "difficulty" : 0.039, "description": [ "Add the placeholder text \"type a cat photo URL here\" to your text field.", @@ -1184,7 +1184,7 @@ { "_id" : "bad87fee1348bd9aede08830", - "name": "Create a basic Form Element", + "name": "Waypoint: Create a basic Form Element", "difficulty" : 0.040, "description": [ "Wrap your text field in a <form> element. Add the action=\"/submit-cat-photo\" attribute to this form element.", @@ -1248,7 +1248,7 @@ { "_id" : "bad87fee1348bd9aedd08830", - "name": "Add a Submit Button to a Form", + "name": "Waypoint: Add a Submit Button to a Form", "difficulty" : 0.041, "description": [ "Add a submit button to your form field.", @@ -1313,7 +1313,7 @@ { "_id" : "bad87fee1348bd9aedc08830", - "name": "Use HTML5 to Make a Field Required", + "name": "Waypoint: Use HTML5 to Make a Field Required", "difficulty" : 0.042, "description": [ "Make it required for your user to input text into your form before being able to submit it.", @@ -1379,7 +1379,7 @@ { "_id" : "bad87fee1348bd9aedf08834", - "name": "Create a Set of Radio Buttons", + "name": "Waypoint: Create a Set of Radio Buttons", "difficulty" : 0.043, "description": [ "Add to your form a pair of radio buttons that are wrapped in label elements and share a name attribute, with the options of \"indoor\" and \"outdoor\".", @@ -1450,7 +1450,7 @@ { "_id" : "bad87fee1348bd9aedf08835", - "name": "Create a Set of Checkboxes", + "name": "Waypoint: Create a Set of Checkboxes", "difficulty" : 0.044, "description": [ "Add to your form a set of three checkbox elements that are wrapped in label elements and share the same name attribute.", @@ -1519,7 +1519,7 @@ { "_id" : "bad87fee1348bd9aede08835", - "name": "Clean up your form using Linebreaks", + "name": "Waypoint: Clean up your form using Linebreaks", "difficulty" : 0.045, "description": [ "Clean up your form by adding linebreaks between form elements.", @@ -1589,7 +1589,7 @@ { "_id" : "bad87fee1348bd9aedd08835", - "name": "Check Radio Buttons and Checkboxes by Default", + "name": "Waypoint: Check Radio Buttons and Checkboxes by Default", "difficulty" : 0.046, "description": [ "Set one of your radio buttons and one of your checkboxes to be checked by default.", diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index 7f33bd5bbc..1f18b89bc7 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -1,10 +1,10 @@ { - "name": "Basic JavaScript", + "name": "Waypoint: Basic JavaScript", "order" : 0.006, "challenges": [ { "_id": "bd7129d8c441eddfaeb5bdef", - "name": "Build an Adventure Game", + "name": "Waypoint: Build an Adventure Game", "difficulty": 0.24, "challengeSeed": "114604814", "description": [ @@ -15,11 +15,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-x9DnD/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7130d8c441eddfaeb5bdef", - "name": "Build Rock Paper Scissors", + "name": "Waypoint: Build Rock Paper Scissors", "difficulty": 0.25, "challengeSeed": "114604815", "description": [ @@ -28,11 +29,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-Bthev-mskY8/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7131d8c441eddfaeb5bdef", - "name": "Learn JavaScript For Loops", + "name": "Waypoint: Learn JavaScript For Loops", "difficulty": 0.26, "challengeSeed": "114614220", "description": [ @@ -41,11 +43,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-XEDZA/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7132d8c441eddfaeb5bdef", - "name": "Learn JavaScript While Loops", + "name": "Waypoint: Learn JavaScript While Loops", "difficulty": 0.27, "challengeSeed": "114612889", "description": [ @@ -53,11 +56,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-mrTNH-6VIZ9/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7133d8c441eddfaeb5bdef", - "name": "Learn Control Flow", + "name": "Waypoint: Learn Control Flow", "difficulty": 0.28, "challengeSeed": "114612888", "description": [ @@ -67,11 +71,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-ZA2rb/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7134d8c441eddfaeb5bdef", - "name": "Build a Contact List", + "name": "Waypoint: Build a Contact List", "difficulty": 0.29, "challengeSeed": "114612887", "description": [ @@ -80,11 +85,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-3bmfN/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7135d8c441eddfaeb5bdef", - "name": "Build an Address Book", + "name": "Waypoint: Build an Address Book", "difficulty": 0.30, "challengeSeed": "114612885", "description": [ @@ -93,11 +99,12 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/building-an-address-book/0/1?curriculum_id=506324b3a7dffd00020bf661." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7136d8c441eddfaeb5bdef", - "name": "Build a Cash Register", + "name": "Waypoint: Build a Cash Register", "difficulty": 0.31, "challengeSeed": "114612882", "description": [ @@ -106,11 +113,12 @@ "Be sure to also complete the final section: http://www.codecademy.com/courses/close-the-super-makert/0/1." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7118d8c441eddfaeb5bdef", - "name": "Discover Chrome's DevTools", + "name": "Waypoint: Discover Chrome's DevTools", "difficulty": 0.32, "challengeSeed": "110752743", "description": [ @@ -120,11 +128,12 @@ "Go to http://discover-devtools.codeschool.com and complete this short course." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7138d8c441eddfaeb5bdef", - "name": "Learn Regular Expressions", + "name": "Waypoint: Learn Regular Expressions", "difficulty": 0.33, "challengeSeed": "112547802", "description": [ @@ -134,11 +143,12 @@ "Note that you can click \"continue\" to move on to the next step as soon as all the tasks have green check marks beside them. You can often do this just by using the wildcard \"dot\" operator, but try to use the techniques that each lesson recommends." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 }, { "_id": "bd7139d8c441eddfaeb5bdef", - "name": "Pair Program on Bonfires", + "name": "Waypoint: Pair Program on Bonfires", "difficulty": 0.44, "challengeSeed": "119657641", "description": [ @@ -161,7 +171,8 @@ "Mark this challenge as complete and move on to the Bonfires." ], "challengeType": 2, - "tests": [] + "tests": [], + "challengeType": 0 } ] } diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index 5c86dce808..0a2d1e245a 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -74,7 +74,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd8acde08812", @@ -146,9 +147,9 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, - { "_id": "bad87fee1348cd8acdf08812", "name": "Create a Bootstrap Button", @@ -218,7 +219,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08812", @@ -291,7 +293,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08811", @@ -364,7 +367,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348cd8acef08813", @@ -438,7 +442,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348ce8acef08814", @@ -513,7 +518,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad88fee1348ce8acef08815", @@ -589,7 +595,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -675,7 +682,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -746,7 +754,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -820,7 +829,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -895,7 +905,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -969,7 +980,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -1050,7 +1062,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -1141,7 +1154,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -1232,7 +1246,8 @@ " ", " ", "" - ] + ], + "challengeType": 0 }, { @@ -1283,7 +1298,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08822", @@ -1335,7 +1351,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08823", @@ -1386,7 +1403,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08824", @@ -1438,7 +1456,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1248bd9aedf08824", @@ -1490,7 +1509,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { "_id": "bad87fee1348bd9aedf08826", @@ -1539,7 +1559,8 @@ "
    padding
    ", "
    padding
    ", "" - ] + ], + "challengeType": 0 }, { @@ -1554,7 +1575,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json index e5893a4a5e..15d941d50e 100644 --- a/seed_data/challenges/jquery-ajax-and-json.json +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -36,7 +36,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { @@ -115,7 +116,8 @@ ], "challengeSeed": [ - ] + ], + "challengeType": 0 }, { From 3ee2c293247dfe2efc4e9e7d3cfc27db56325658 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Sun, 24 May 2015 23:51:56 -0700 Subject: [PATCH 57/81] more challenge-related view and copy improvements --- app.js | 19 + controllers/challengeMap.js | 51 +- models/Challenge.js | 1 - public/css/main.less | 4 +- seed_data/bonfires.json | 1167 ----- seed_data/challenges/basejumps.json | 2 +- seed_data/challenges/basic-html5-and-css.json | 33 +- seed_data/challenges/bonfires.json | 90 +- seed_data/challenges/bootstrap.json | 48 +- seed_data/challenges/computer-science.json | 12 +- .../challenges/full-stack-javascript.json | 22 +- .../getting-set-for-free-code-camp.json | 16 +- .../challenges/jquery-ajax-and-json.json | 38 +- seed_data/challenges/ziplines.json | 2 +- seed_data/coursewares.json | 4361 ----------------- seed_data/future-coursewares.json | 1 - views/challengeMap/show.jade | 99 +- 17 files changed, 172 insertions(+), 5794 deletions(-) delete mode 100644 seed_data/bonfires.json delete mode 100644 seed_data/coursewares.json delete mode 100644 seed_data/future-coursewares.json diff --git a/app.js b/app.js index db9a2ec031..55dc7bdb90 100755 --- a/app.js +++ b/app.js @@ -234,6 +234,25 @@ app.get('/chat', resourcesController.chat); app.get('/twitch', resourcesController.twitch); +app.get('/cats.json', function(req, res) { + res.send( + [ + { + "name": "cute", + "imageLink": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRaP1ecF2jerISkdhjr4R9yM9-8ClUy-TA36MnDiFBukd5IvEME0g" + }, + { + "name": "grumpy", + "imageLink": "http://cdn.grumpycats.com/wp-content/uploads/2012/09/GC-Gravatar-copy.png" + }, + { + "name": "mischievous", + "imageLink": "http://www.kittenspet.com/wp-content/uploads/2012/08/cat_with_funny_face_3-200x200.jpg" + } + ] + ) +}); + // Agile Project Manager Onboarding app.get('/pmi-acp-agile-project-managers', diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index afda188330..945c5e9aee 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -29,52 +29,6 @@ module.exports = { return challenge._id; }); - var bonfireList = challengeList - .filter(function(challenge) { - return challenge.challengeType === challengeTypes.BONFIRE; - }) - .map(function(bonfire) { - return ({ - '_id': bonfire._id, - 'name': bonfire.name - }); - }); - - var waypoints = challengeList.filter(function(challenge) { - if (challenge.challengeType === challengeTypes.VIDEO - || challenge.challengeType === challengeTypes.HTML_CSS_JQ - || challenge.challengeType === challengeTypes.JAVASCRIPT) { - return challenge; - } - }).map(function(waypoint) { - return ({ - '_id': waypoint._id, - 'name': waypoint.name - }); - }); - - var ziplines = challengeList.filter(function(challenge) { - if (challenge.challengeType === challengeTypes.ZIPLINE) { - return challenge; - } - }).map(function(zipline) { - return ({ - '_id': zipline._id, - 'name': zipline.name - }); - }); - - var basejumps = challengeList.filter(function(challenge) { - if (challenge.challengeType === challengeTypes.BASEJUMP) { - return challenge; - } - }).map(function(basejump) { - return ({ - '_id': basejump._id, - 'name': basejump.name - }); - }); - function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); } @@ -93,10 +47,7 @@ module.exports = { daysRunning: daysRunning, camperCount: numberWithCommas(camperCount), title: "A map of all Free Code Camp's Challenges", - bonfires: bonfireList, - waypoints: waypoints, - ziplines: ziplines, - basejumps: basejumps, + challengeList: challengeList, completedChallengeList: completedChallengeList }); }); diff --git a/models/Challenge.js b/models/Challenge.js index e1971943be..bb4cfcd954 100644 --- a/models/Challenge.js +++ b/models/Challenge.js @@ -15,7 +15,6 @@ var challengeSchema = new mongoose.Schema({ description: Array, tests: Array, challengeSeed: Array, - completionMessage: String, // Congratulations! You've finished our HTML and CSS track! challengeType: Number, // 0 = html, 1 = javascript only, 2 = video, 3 = zipline, 4 = basejump MDNlinks: Array }); diff --git a/public/css/main.less b/public/css/main.less index e28fb60f66..c9337072f3 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -246,8 +246,8 @@ ul { margin-top: -20px; } -.landing-p { - font-size: 18px !important; +.large-p { + font-size: 24px; } .text-success { diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json deleted file mode 100644 index 9bf3f9fd41..0000000000 --- a/seed_data/bonfires.json +++ /dev/null @@ -1,1167 +0,0 @@ -[ - { - "_id": "ad7123c8c441eddfaeb5bdef", - "name": "Meet Bonfire", - "difficulty": "0", - "description": [ - "Click the button below for further instructions.", - "Your goal is to fix the failing test.", - "First, run all the tests by clicking \"Run code\" or by pressing Control + Enter", - "The failing test is in red. Fix the code so that all tests pass. Then you can move on to the next Bonfire.", - "Make this function return true no matter what." - ], - "tests": [ - "expect(meetBonfire()).to.be.a(\"boolean\");", - "expect(meetBonfire()).to.be.true;" - ], - "challengeSeed": [ - "function meetBonfire(argument) {", - " // Good luck!", - " console.log(\"you can read this function's argument in the developer tools\", argument);", - "", - " return false;", - "}", - "", - "", - "", - "meetBonfire(\"You can do this!\");" - ] - }, - { - "_id": "a202eed8fc186c8434cb6d61", - "name": "Reverse a String", - "difficulty": "1.01", - "tests": [ - "expect(reverseString('hello')).to.be.a('String');", - "expect(reverseString('hello')).to.equal('olleh');", - "expect(reverseString('Howdy')).to.equal('ydwoH');", - "expect(reverseString('Greetings from Earth')).to.equal('htraE morf sgniteerG');" - ], - "description": [ - "Reverse the provided string.", - "You may need to turn the string into an array before you can reverse it.", - "Your result must be a string." - ], - "challengeSeed": [ - "function reverseString(str) {", - " return str;", - "}", - "", - "reverseString('hello');" - ], - "MDNlinks": ["Global String Object", "String.split()", "Array.reverse()", "Array.join()"] - }, - { - "_id": "a302f7aae1aa3152a5b413bc", - "name": "Factorialize a Number", - "tests": [ - "expect(factorialize(5)).to.be.a(\"Number\");", - "expect(factorialize(5)).to.equal(120);", - "expect(factorialize(10)).to.equal(3628800);", - "expect(factorialize(20)).to.equal(2432902008176640000);" - ], - "difficulty": "1.02", - "description": [ - "Return the factorial of the provided integer.", - "If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.", - "Factorials are often represented with the shorthand notation n!", - "For example: 5! = 1 * 2 * 3 * 4 * 5 = 120f" - ], - "challengeSeed": [ - "function factorialize(num) {", - " return num;", - "}", - "", - "factorialize(5);" - ], - "MDNlinks": ["Arithmetic Operators"] - }, - { - "_id": "aaa48de84e1ecc7c742e1124", - "name": "Check for Palindromes", - "difficulty": "1.03", - "description": [ - "Return true if the given string is a palindrome. Otherwise, return false.", - "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.", - "You'll need to remove punctuation and turn everything lower case in order to check for palindromes.", - "We'll pass strings with varying formats, such as \"racecar\", \"RaceCar\", and \"race CAR\" among others." - ], - "tests": [ - "expect(palindrome(\"eye\")).to.be.a(\"boolean\");", - "assert.deepEqual(palindrome(\"eye\"), true);", - "assert.deepEqual(palindrome(\"race car\"), true);", - "assert.deepEqual(palindrome(\"not a palindrome\"), false);", - "assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);", - "assert.deepEqual(palindrome(\"never odd or even\"), true);", - "assert.deepEqual(palindrome(\"nope\"), false);" - ], - "challengeSeed": [ - "function palindrome(str) {", - " // Good luck!", - " return true;", - "}", - "", - "", - "", - "palindrome(\"eye\");" - ], - "MDNlinks": ["String.replace()", "String.toLowerCase()"] - }, - { - "_id": "a26cbbe9ad8655a977e1ceb5", - "name": "Find the Longest Word in a String", - "difficulty": "1.04", - "description": [ - "Return the length of the longest word in the provided sentence.", - "Your response should be a number." - ], - "challengeSeed": [ - "function findLongestWord(str) {", - " return str.length;", - "}", - "", - "findLongestWord('The quick brown fox jumped over the lazy dog');" - ], - "tests": [ - "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.be.a('Number');", - "expect(findLongestWord('The quick brown fox jumped over the lazy dog')).to.equal(6);", - "expect(findLongestWord('May the force be with you')).to.equal(5);", - "expect(findLongestWord('Google do a barrel roll')).to.equal(6);", - "expect(findLongestWord('What is the average airspeed velocity of an unladen swallow')).to.equal(8);" - ], - "MDNlinks": ["String.split()", "String.length"] - }, - { - "_id": "ab6137d4e35944e21037b769", - "name": "Title Case a Sentence", - "difficulty": "1.05", - "description": [ - "Return the provided string with the first letter of each word capitalized.", - "For the purpose of this exercise, you should also capitalize connecting words like 'the' and 'of'." - ], - "challengeSeed": [ - "function titleCase(str) {", - " return str;", - "}", - "", - "titleCase(\"I'm a little tea pot\");" - ], - "tests": [ - "expect(titleCase(\"I'm a little tea pot\")).to.be.a('String');", - "expect(titleCase(\"I'm a little tea pot\")).to.equal(\"I'm A Little Tea Pot\");", - "expect(titleCase(\"sHoRt AnD sToUt\")).to.equal(\"Short And Stout\");", - "expect(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\")).to.equal(\"Here Is My Handle Here Is My Spout\");" - ], - "MDNlinks": ["String.charAt()"] - }, - { - "_id": "a789b3483989747d63b0e427", - "name": "Return Largest Numbers in Arrays", - "difficulty": "1.06", - "description": [ - "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", - "Remember, you can iterate through an array with a simple for loop, and access each member with array syntax arr[i] .", - "If you are writing your own Chai.js tests, be sure to use a deep equal statement instead of an equal statement when comparing arrays." - ], - "challengeSeed": [ - "function largestOfFour(arr) {", - " // You can do this!", - " return arr;", - "}", - "", - "largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);" - ], - "tests": [ - "expect(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).to.be.a('array');", - "(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]])).should.eql([5,27,39,1001]);", - "assert(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]).should.eql([9,35,97,1000000]));" - ], - "MDNlinks": ["Comparison Operators"] - }, - { - "_id": "acda2fb1324d9b0fa741e6b5", - "name": "Confirm the Ending", - "difficulty": "1.07", - "description": [ - "Check if a string (first argument) ends with the given target string (second argument)." - ], - - "challengeSeed": [ - "function end(str, target) {", - " // \"Never give up and good luck will find you.\"", - " // -- Falcor", - " return str;", - "}", - "", - "end('Bastian', 'n');" - ], - "tests": [ - "assert.strictEqual(end('Bastian', 'n'), true, 'should equal true if target equals end of string');", - "assert.strictEqual(end('He has to give me a new name', 'name'), true, 'should equal true if target equals end of string');", - "assert.strictEqual(end('If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing', 'mountain'), false, 'should equal false if target does not equal end of string');" - ], - "MDNlinks": ["String.substr()"] - }, - { - "_id": "afcc8d540bea9ea2669306b6", - "name": "Repeat a string repeat a string", - "difficulty": "1.08", - "description": [ - "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number." - ], - "challengeSeed": [ - "function repeat(str, num) {", - " // repeat after me", - " return str;", - "}", - "", - "repeat('abc', 3);" - ], - "tests": [ - "assert.strictEqual(repeat('*', 3), '***', 'should repeat a string n times');", - "assert.strictEqual(repeat('abc', 3), 'abcabcabc', 'should repeat a string n times');", - "assert.strictEqual(repeat('abc', -2), '', 'should return an empty string for negative numbers');" - ], - "MDNlinks": ["Global String Object"] - }, - { - "_id": "ac6993d51946422351508a41", - "name": "Truncate a string", - "difficulty": "1.09", - "description": [ - "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", - "Note that the three dots at the end add to the string length." - ], - "challengeSeed": [ - "function truncate(str, num) {", - " // Clear out that junk in your trunk", - " return str;", - "}", - "", - "truncate('A-tisket a-tasket A green and yellow basket', 11);" - ], - "tests": [ - "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", - "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", - "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" - ], - "MDNlinks": ["String.slice()"] - }, - { - "_id": "a9bd25c716030ec90084d8a1", - "name": "Chunky Monkey", - "difficulty": "1.10", - "description": [ - "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array." - ], - "challengeSeed": [ - "function chunk(arr, size) {", - " // Break it up.", - " return arr;", - "}", - "", - "chunk(['a', 'b', 'c', 'd'], 2);" - ], - "tests": [ - "assert.deepEqual(chunk(['a', 'b', 'c', 'd'], 2), [['a', 'b'], ['c', 'd']], 'should return chunked arrays');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'should return chunked arrays');", - "assert.deepEqual(chunk([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'should return the last chunk as remaining elements');" - ], - "MDNlinks": ["Array.push()"] - }, - { - "_id": "ab31c21b530c0dafa9e241ee", - "name": "Slasher Flick", - "difficulty": "1.11", - "description": [ - "Return the remaining elements of an array after chopping off n elements from the head." - ], - "challengeSeed": [ - "function slasher(arr, howMany) {", - " // it doesn't always pay to be first", - " return arr;", - "}", - "", - "slasher([1, 2, 3], 2);" - ], - "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');" - ], - "MDNlinks": ["Array.slice()", "Array.splice()"] - }, - { - "_id": "af2170cad53daa0770fabdea", - "name": "Mutations", - "difficulty": "1.12", - "description": [ - "Return true if the string in the first element of the array contains the letters of the string in the second element of the array.", - "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", - "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", - "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'." - ], - "challengeSeed": [ - "function mutation(arr) {", - " return arr;", - "}", - "", - "mutation(['hello', 'hey']);" - ], - "tests": [ - "expect(mutation(['hello', 'hey'])).to.be.false;", - "expect(mutation(['hello', 'Hello'])).to.be.true;", - "expect(mutation(['zyxwvutsrqponmlkjihgfedcba', 'qrstu'])).to.be.true;", - "expect(mutation(['Mary', 'Army'])).to.be.true;", - "expect(mutation(['Alien', 'line'])).to.be.true;" - ], - "MDNlinks": ["Array.sort()"] - }, - { - "_id": "adf08ec01beb4f99fc7a68f2", - "name": "Falsey Bouncer", - "difficulty": "1.50", - "description": [ - "Remove all falsey values from an array.", - "Falsey values in javascript are false, null, 0, \"\", undefined, and NaN." - ], - "challengeSeed": [ - "function bouncer(arr) {", - " // Don't show a false ID to this bouncer.", - " return arr;", - "}", - "", - "bouncer([7, 'ate', '', false, 9]);" - ], - "tests": [ - "assert.deepEqual(bouncer([7, 'ate', '', false, 9]), [7, 'ate', 9], 'should remove falsey values');", - "assert.deepEqual(bouncer(['a', 'b', 'c']), ['a', 'b', 'c'], 'should return full array if no falsey elements');", - "assert.deepEqual(bouncer([false, null, 0]), [], 'should return empty array if all elements are falsey');" - ], - "MDNlinks": ["Boolean Objects", "Array.filter()"] - }, - { - "_id":"a8e512fbe388ac2f9198f0fa", - "name":"Where art thou", - "difficulty":"1.55", - "description":[ - "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument)." - ], - "challengeSeed": [ - "function where(collection, source) {", - " var arr = [];", - " // What's in a name?", - " return arr;", - "}", - "", - "where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' });" - ], - "tests":[ - "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');", - "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');" - ], - "MDNlinks": ["Global Object", "Object.hasOwnProperty()", "Object.keys()"] - }, - { - "_id":"a39963a4c10bc8b4d4f06d7e", - "name":"Seek and Destroy", - "difficulty":"1.60", - "description":[ - "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments." - ], - "challengeSeed": [ - "function destroyer(arr) {", - " // Remove all the values", - " return arr;", - "}", - "", - "destroyer([1, 2, 3, 1, 2, 3], 2, 3);" - ], - "tests": [ - "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" - ], - "MDNlinks": ["Arguments object","Array.filter()"] - }, - { - "_id": "a24c1a4622e3c05097f71d67", - "name": "Where do I belong", - "difficulty": "1.61", - "description": [ - "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", - "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)." - ], - "challengeSeed": [ - "function where(arr, num) {", - " // Find my place in this sorted array.", - " return num;", - "}", - "", - "where([40, 60], 50);" - ], - "tests": [ - "expect(where([10, 20, 30, 40, 50], 35)).to.equal(3);", - "expect(where([10, 20, 30, 40, 50], 30)).to.equal(2);" - ], - "MDNlinks" : ["Array.sort()"] - }, - { - "_id": "a3566b1109230028080c9345", - "name": "Sum All Numbers in a Range", - "difficulty": "2.00", - "description": [ - "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", - "The lowest number will not always come first." - ], - "challengeSeed": [ - "function sumAll(arr) {", - " return(1);", - "}", - "", - "sumAll([1, 4]);" - ], - "tests": [ - "expect(sumAll([1, 4])).to.be.a('Number');", - "expect(sumAll([1, 4])).to.equal(10);", - "expect(sumAll([4, 1])).to.equal(10);", - "expect(sumAll([5, 10])).to.equal(45);", - "expect(sumAll([10, 5])).to.equal(45);" - ], - "MDNlinks": ["Math.max()", "Math.min()", "Array.reduce()"] - }, - { - "_id": "a5de63ebea8dbee56860f4f2", - "name": "Diff Two Arrays", - "difficulty": "2.01", - "description": [ - "Compare two arrays and return a new array with any items not found in both of the original arrays." - ], - "challengeSeed": [ - "function diff(arr1, arr2) {", - " var newArr = [];", - " // Same, same; but different.", - " return newArr;", - "}", - "", - "diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" - ], - "tests": [ - "expect(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])).to.be.a('array');", - "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');", - "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');", - "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');", - "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');", - "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');", - "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');" - ], - "MDNlinks" : ["Comparison Operators", "String.slice()", "Array.filter()", "Array.indexOf()", "String.concat()"] - }, - { - "_id": "a7f4d8f2483413a6ce226cac", - "name": "Roman Numeral Converter", - "tests": [ - "expect(convert(12)).to.equal(\"XII\");", - "expect(convert(5)).to.equal(\"V\");", - "expect(convert(9)).to.equal(\"IX\");", - "expect(convert(29)).to.equal(\"XXIX\");", - "expect(convert(16)).to.equal(\"XVI\");" - ], - "difficulty": "2.02", - "description": [ - "Convert the given number into a roman numeral.", - "All roman numerals answers should be provided in upper-case." - ], - "challengeSeed": [ - "function convert(num) {", - " return num;", - "}", - "", - "convert(36);" - ], - "MDNlinks": ["Array.splice()", "Array.indexOf()", "Array.join()"] - }, - { - "_id": "a0b5010f579e69b815e7c5d6", - "name": "Search and Replace", - "tests": [ - "expect(replace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", - "expect(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", - "expect(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\")).to.equal(\"This has a spelling error\");", - "expect(replace(\"His name is Tom\", \"Tom\", \"john\")).to.equal(\"His name is John\");", - "expect(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")).to.equal(\"Let us get back to more Bonfires\");" - ], - "difficulty": "2.03", - "description": [ - "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", - "First argument is the sentence the perform the search and replace on.", - "Second argument is the word that you will be replacing (before).", - "Third argument is what you will be replacing the second argument with (after).", - "NOTE: Preserve the case of the original word when you are replacing it. For example if you mean to replace the word 'Book' with the word 'dog', it should be replaced as 'Dog'" - ], - "challengeSeed": [ - "function replace(str, before, after) {", - " return str;", - "}", - "", - "replace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" - ], - "MDNlinks": ["Array.splice()", "String.replace()", "Array.join()"] - }, - { - "_id": "aa7697ea2477d1316795783b", - "name": "Pig Latin", - "tests": [ - "expect(translate(\"california\")).to.equal(\"aliforniacay\");", - "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", - "expect(translate(\"glove\")).to.equal(\"oveglay\");", - "expect(translate(\"algorithm\")).to.equal(\"algorithmway\");", - "expect(translate(\"eight\")).to.equal(\"eightway\");" - ], - "difficulty": "2.04", - "description": [ - "Translate the provided string to pig latin.", - "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".", - "If a word begins with a vowel you just add \"way\" to the end." - ], - "challengeSeed": [ - "function translate(str) {", - " return str;", - "}", - "", - "translate(\"consonant\");" - ], - "MDNlinks": ["Array.indexOf()", "Array.push()", "Array.join()", "String.substr()", "String.split()"] - }, - { - "_id": "afd15382cdfb22c9efe8b7de", - "name": "DNA Pairing", - "tests": [ - "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'should return the dna pair');", - "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'should return the dna pair');", - "assert.deepEqual(pair(\"CTCTA\"),[['C','G'],['T','A'],['C','G'],['T','A'],['A','T']], 'should return the dna pair');" - ], - "difficulty": "2.05", - "description": [ - "The DNA strand is missing the pairing element. Match each character with the missing element and return the results as a 2d array.", - "Base pairs are a pair of AT and CG. Match the missing element to the provided character.", - "Return the provided character as the first element in each array." - ], - "challengeSeed": [ - "function pair(str) {", - " return str;", - "}", - "", - "pair(\"GCG\");" - ], - "MDNlinks": ["Array.push()", "String.split()"] - }, - { - "_id": "af7588ade1100bde429baf20", - "name" : "Missing letters", - "difficulty": "2.05", - "description" : [ - "Find the missing letter in the passed letter range and return it.", - "If all letters are present in the range, return undefined." - ], - "challengeSeed": [ - "function fearNotLetter(str) {", - " return str;", - "}", - "", - "fearNotLetter('abce');" - ], - "tests": [ - "expect(fearNotLetter('abce')).to.equal('d');", - "expect(fearNotLetter('bcd')).to.be.undefined;", - "expect(fearNotLetter('abcdefghjklmno')).to.equal('i');", - "expect(fearNotLetter('yz')).to.be.undefined;" - ], - "MDNlinks": ["String.charCodeAt()"] - }, - { - "_id": "a77dbc43c33f39daa4429b4f", - "name": "Boo who", - "difficulty": "2.06", - "description": [ - "Check if a value is classified as a boolean primitive. Return true or false.", - "Boolean primitives are true and false." - ], - "challengeSeed": [ - "function boo(bool) {", - " // What is the new fad diet for ghost developers? The Boolean.", - " return bool;", - "}", - "", - "boo(null);" - ], - "tests": [ - "assert.strictEqual(boo(true), true);", - "assert.strictEqual(boo(false), true);", - "assert.strictEqual(boo([1, 2, 3]), false);", - "assert.strictEqual(boo([].slice), false);", - "assert.strictEqual(boo({ 'a': 1 }), false);", - "assert.strictEqual(boo(1), false);", - "assert.strictEqual(boo(NaN), false);", - "assert.strictEqual(boo('a'), false);" - ], - "MDNlinks": ["Boolean Objects"] - }, - { - "_id": "a105e963526e7de52b219be9", - "name": "Sorted Union", - "difficulty": "2.07", - "description": [ - "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", - "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.", - "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.", - "Check the assertion tests for examples." - ], - "challengeSeed": [ - "function unite(arr1, arr2, arr3) {", - " return arr1;", - "}", - "", - "unite([1, 2, 3], [5, 2, 1, 4], [2, 1]);" - ], - "tests": [ - "assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'should return the union of the given arrays');", - "assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'should not flatten nested arrays');" - ], - "MDNlinks" : ["Array.reduce()"] - }, - { - "_id": "a6b0bb188d873cb2c8729495", - "name": "Convert HTML Entities", - "difficulty": "2.07", - "description": [ - "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities." - ], - "challengeSeed": [ - "function convert(str) {", - " // :)", - " return str;", - "}", - "", - "convert('Dolce & Gabbana');" - ], - "tests": [ - "assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');", - "assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');" - ], - "MDNlinks": ["RegExp"] - }, - { - "_id": "a103376db3ba46b2d50db289", - "name": "Spinal Tap Case", - "difficulty": "2.08", - "description": [ - "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes." - ], - "challengeSeed": [ - "function spinalCase(str) {", - " // \"It's such a fine line between stupid, and clever.\"", - " // --David St. Hubbins", - " return str;", - "}", - "", - "spinalCase('This Is Spinal Tap');" - ], - "tests": [ - "assert.strictEqual(spinalCase('This Is Spinal Tap'), 'this-is-spinal-tap', 'should return spinal case from string with spaces');", - "assert.strictEqual(spinalCase('thisIsSpinalTap'), 'this-is-spinal-tap', 'should return spinal case from string with camel case');", - "assert.strictEqual(spinalCase('The_Andy_Griffith_Show'), 'the-andy-griffith-show', 'should return spinal case from string with snake case');", - "assert.strictEqual(spinalCase('Teletubbies say Eh-oh'), 'teletubbies-say-eh-oh', 'should return spinal case from string with spaces and hyphens');" - ], - "MDNlinks": ["RegExp", "String.replace()"] - }, - { - "_id": "a5229172f011153519423690", - "name": "Sum All Odd Fibonacci Numbers", - "difficulty": "2.09", - "description": [ - "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", - "The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8, and each subsequent number is the sum of the previous two numbers.", - "As an example, passing 4 to the function should return 5 because all the odd Fibonacci numbers under 4 are 1, 1, and 3." - ], - "challengeSeed": [ - "function sumFibs(num) {", - " return num;", - "}", - "", - "sumFibs(4);" - ], - "tests": [ - "expect(sumFibs(1)).to.be.a('number');", - "expect(sumFibs(1000)).to.equal(1785);", - "expect(sumFibs(4000000)).to.equal(4613732);", - "expect(sumFibs(4)).to.equal(5);", - "expect(sumFibs(75024)).to.equal(60696);", - "expect(sumFibs(75025)).to.equal(135721);" - ], - "MDNlinks": ["Remainder"] - }, - { - "_id": "a3bfc1673c0526e06d3ac698", - "name": "Sum All Primes", - "difficulty": "2.10", - "description": [ - "Sum all the prime numbers up to and including the provided number.", - "A prime number is defined as having only two divisors, 1 and itself. For example, 2 is a prime number because it's only divisible by 1 and 2. 1 isn't a prime number, because it's only divisible by itself.", - "The provided number may not be a prime." - ], - "challengeSeed": [ - "function sumPrimes(num) {", - " return num;", - "}", - "", - "sumPrimes(10);" - ], - "tests": [ - "expect(sumPrimes(10)).to.be.a('number');", - "expect(sumPrimes(10)).to.equal(17);", - "expect(sumPrimes(977)).to.equal(73156);" - ], - "MDNlinks" : ["For Loops", "Array.push()"] - }, - { - "_id": "ae9defd7acaf69703ab432ea", - "name": "Smallest Common Multiple", - "difficulty": "2.11", - "description": [ - "Find the smallest number that is evenly divisible by all numbers in the provided range.", - "The range will be an array of two numbers that will not necessarily be in numerical order." - ], - "challengeSeed": [ - "function smallestCommons(arr) {", - " return arr;", - "}", - "", - "", - "smallestCommons([1,5]);" - ], - "tests": [ - "expect(smallestCommons([1,5])).to.be.a('number');", - "expect(smallestCommons([1,5])).to.equal(60);", - "expect(smallestCommons([5,1])).to.equal(60);", - "(smallestCommons([1,13])).should.equal(360360);" - ], - "MDNlinks" : ["Smallest Common Multiple"] - }, - { - "_id": "a6e40f1041b06c996f7b2406", - "name": "Finders Keepers", - "difficulty": "2.12", - "description": [ - "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument)." - ], - "challengeSeed": [ - "function find(arr, func) {", - " var num = 0;", - " return num;", - "}", - "", - "find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" - ], - "tests": [ - "assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'should return first found value');", - "assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'should return undefined if not found');" - ], - "MDNlinks": ["Array.some()"] - }, - { - "_id": "a5deed1811a43193f9f1c841", - "name": "Drop it like it's hot", - "difficulty": "2.13", - "description": [ - "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true." - ], - "challengeSeed": [ - "function drop(arr, func) {", - " // Drop them elements.", - " return arr;", - "}", - "", - "drop([1, 2, 3], function(n) {return n < 3; });" - ], - "tests": [ - "expect(drop([1, 2, 3, 4], function(n) {return n >= 3; })).to.eqls([3, 4]);", - "expect(drop([1, 2, 3], function(n) {return n > 0; })).to.eqls([1, 2, 3]);", - "expect(drop([1, 2, 3, 4], function(n) {return n > 5; })).to.eqls([]);" - ], - "MDNlinks": ["Arguments object", "Array.shift()"] - }, - { - "_id": "ab306dbdcc907c7ddfc30830", - "name": "Steamroller", - "difficulty": "2.14", - "description": [ - "Flatten a nested array. You must account for varying levels of nesting." - ], - "challengeSeed": [ - "function steamroller(arr) {", - " // I'm a steamroller, baby", - " return arr;", - "}", - "", - "steamroller([1, [2], [3, [[4]]]]);" - ], - "tests": [ - "assert.deepEqual(steamroller([[['a']], [['b']]]), ['a', 'b'], 'should flatten nested arrays');", - "assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'should flatten nested arrays');", - "assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'should work with empty arrays');" - ], - "MDNlinks": ["Array.isArray()"] - }, - { - "_id": "a8d97bd4c764e91f9d2bda01", - "name": "Binary Agents", - "difficulty": "2.15", - "description": [ - "Return an English translated sentence of the passed binary string.", - "The binary string will be space separated." - ], - "challengeSeed": [ - "function binaryAgent(str) {", - " return str;", - "}", - "", - "binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111');" - ], - "tests": [ - "expect(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111')).to.equal(\"Aren't bonfires fun!?\");", - "expect(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001')).to.equal(\"I love FreeCodeCamp!\");" - ], - "MDNlinks": ["String.charCodeAt()", "String.fromCharCode()" - ] - }, - { - "_id": "a10d2431ad0c6a099a4b8b52", - "name": "Everything Be True", - "difficulty": "2.21", - "description": [ - "Check if the predicate (second argument) returns truthy (defined) for 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." - ], - "challengeSeed": [ - "function every(collection, pre) {", - " // Does everyone have one of these?", - " return pre;", - "}", - "", - "every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex');" - ], - "tests": [ - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], 'sex'), true, 'should return true if predicate returns truthy for all elements in the collection');", - "assert.strictEqual(every([{'user': 'Tinky-Winky', 'sex': 'male'}, {'user': 'Dipsy', 'sex': 'male'}, {'user': 'Laa-Laa', 'sex': 'female'}, {'user': 'Po', 'sex': 'female'}], {'sex': 'female'}), false, 'should return false if predicate returns falsey for any element in the collection');" - ], - "MDNlinks": ["Object.hasOwnProperty()", "Object.getOwnPropertyNames()"] - }, - { - "_id": "a97fd23d9b809dac9921074f", - "name": "Arguments Optional", - "difficulty": "2.22", - "description": [ - "Create a function that sums two arguments together. If only one argument is provided, return a function that expects one additional argument and will return the sum.", - "For example, add(2, 3) should return 5, and add(2) should return a function that is waiting for an argument so that var sum2And = add(2); return sum2And(3); // 5", - "If either argument isn't a valid number, return undefined." - ], - "challengeSeed": [ - "function add() {", - " return false;", - "}", - "", - "add(2,3);" - ], - "tests": [ - "expect(add(2, 3)).to.equal(5);", - "expect(add(2)(3)).to.equal(5);", - "expect(add('http://bit.ly/IqT6zt')).to.be.undefined;", - "expect(add(2, '3')).to.be.undefined;", - "expect(add(2)([3])).to.be.undefined;" - ], - "MDNlinks": ["Global Function Object", "Arguments object", "Closures", "Currying"] - }, - { - "_id": "a2f1d72d9b908d0bd72bb9f6", - "name": "Make a Person", - "difficulty": "3.12", - "description": [ - "Fill in the object constructor with the methods specified in the tests.", - "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", - "All functions that take an argument have an arity of 1, and the argument will be a string.", - "These methods must be the only available means for interacting with the object." - ], - "challengeSeed": [ - "var Person = function(firstAndLast) {", - " return firstAndLast;", - "};", - "", - "var bob = new Person('Bob Ross');", - "bob.getFullName();" - ], - "tests": [ - "expect(Object.keys(bob).length).to.eql(6);", - "expect(bob instanceof Person).to.be.true;", - "expect(bob.firstName).to.be.undefined();", - "expect(bob.lastName).to.be.undefined();", - "expect(bob.getFirstName()).to.eql('Bob');", - "expect(bob.getLastName()).to.eql('Ross');", - "expect(bob.getFullName()).to.eql('Bob Ross');", - "bob.setFirstName('Happy');", - "expect(bob.getFirstName()).to.eql('Happy');", - "bob.setLastName('Trees');", - "expect(bob.getLastName()).to.eql('Trees');", - "bob.setFullName('George Carlin');", - "expect(bob.getFullName()).to.eql('George Carlin');", - "bob.setFullName('Bob Ross');" - ], - "MDNlinks": ["Closures", "Details of the Object Model"] - }, - { - "_id": "af4afb223120f7348cdfc9fd", - "name": "Map the Debris", - "difficulty": "3.50", - "description": [ - "Return a new array that transforms the element's average altitude into their orbital periods.", - "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", - "You can read about orbital periods on wikipedia.", - "The values should be rounded to the nearest whole number. The body being orbited is Earth.", - "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418" - ], - "challengeSeed": [ - "function orbitalPeriod(arr) {", - " var GM = 398600.4418;", - " var earthRadius = 6367.4447;", - " return arr;", - "}", - "", - "orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);" - ], - "tests": [ - "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", - "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" - ], - "MDNlinks": ["Math.pow()"] - }, - { - "_id" : "a3f503de51cfab748ff001aa", - "name": "Pairwise", - "difficulty": "3.51", - "description": [ - "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", - "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", - "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!" - ], - "challengeSeed": "function pairwise(arr, arg) {\n return arg;\n}\n\npairwise([1,4,2,3,0,5], 7);", - "tests": [ - "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", - "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", - "expect(pairwise([1,1,1], 2)).to.equal(1);", - "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", - "expect(pairwise([], 100)).to.equal(0);" - ], - "MDNlinks" : ["Array.reduce()"] - }, - { - "_id": "aff0395860f5d3034dc0bfc9", - "name": "Validate US Telephone Numbers", - "difficulty": "4.01", - "description": [ - "Return true if the passed string is a valid US phone number", - "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", - "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", - "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false." - ], - "tests": [ - "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", - "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", - "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", - "assert.deepEqual(telephoneCheck(\"55555555\"), false);", - "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", - "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", - "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" - ], - "MDNlinks" : ["RegExp"], - "challengeSeed": [ - "function telephoneCheck(str) {", - " // Good luck!", - " return true;", - "}", - "", - "", - "", - "telephoneCheck(\"555-555-5555\");" - ] - }, - { - "_id": "a3f503de51cf954ede28891d", - "name": "Symmetric Difference", - "difficulty": "4.02", - "description": [ - "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", - "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both." - ], - "challengeSeed": [ - "function sym(args) {", - " return arguments;", - "}", - "", - "sym([1, 2, 3], [5, 2, 1, 4]);" - ], - "tests": [ - "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", - "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", - "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", - "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" - ], - "MDNlinks" : ["Array.reduce()"] - }, - { - "_id": "aa2e6f85cab2ab736c9a9b24", - "name": "Cash Register", - "difficulty": "4.03", - "description": [ - "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order." - ], - "challengeSeed": [ - "function drawer(price, cash, cid) {", - " var change;", - " // Here is your change, ma'am.", - " return change;", - "}", - "", - "// Example cash-in-drawer array:", - "// [['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]]", - "", - "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" - ], - "tests": [ - "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", - "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", - "expect(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", - "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" - ], - "MDNlinks" : ["Global Object"] - }, - { - "_id": "a56138aff60341a09ed6c480", - "name": "Inventory Update", - "difficulty": "4.04", - "description": [ - "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order." - ], - "challengeSeed": [ - "function inventory(arr1, arr2) {", - " // All inventory must be accounted for or you're fired!", - " return arr1;", - "}", - "", - "// Example inventory lists", - "var curInv = [", - " [21, 'Bowling Ball'],", - " [2, 'Dirty Sock'],", - " [1, 'Hair Pin'],", - " [5, 'Microphone']", - "];", - "", - "var newInv = [", - " [2, 'Hair Pin'],", - " [3, 'Half-Eaten Apple'],", - " [67, 'Bowling Ball'],", - " [7, 'Toothpaste']", - "];", - "", - "inventory(curInv, newInv);" - ], - "tests": [ - "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", - "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", - "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" - ], - "MDNlinks" : ["Global Array Object"] - }, - { - "_id": "a7bf700cd123b9a54eef01d5", - "name": "No repeats please", - "difficulty": "4.05", - "description": [ - "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", - "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating." - ], - "challengeSeed": [ - "function permAlone(str) {", - " return str;", - "}", - "", - "permAlone('aab');" - ], - "tests": [ - "expect(permAlone('aab')).to.be.a.number;", - "expect(permAlone('aab')).to.equal(2);", - "expect(permAlone('aaa')).to.equal(0);", - "expect(permAlone('aabb')).to.equal(8);", - "expect(permAlone('abcdefa')).to.equal(3600);", - "expect(permAlone('abfdefa')).to.equal(2640);", - "expect(permAlone('zzzzzzzz')).to.equal(0);" - ], - "MDNlinks" : ["Permutations", "RegExp"] - }, - { - "_id": "a19f0fbe1872186acd434d5a", - "name": "Friendly Date Ranges", - "difficulty": "4.06", - "description": [ - "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", - "It must not show any redundant information in the date range.", - "For example, if the year and month are the same then only the day range should be displayed.", - "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", - "Input date is formatted as YYYY-MM-DD" - ], - "challengeSeed": [ - "function friendly(str) {", - " return str;", - "}", - "", - "friendly(['2015-07-01', '2015-07-04']);" - ], - "tests": [ - "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", - "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", - "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", - "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th, 2016']);", - "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", - "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" - ], - "MDNlinks": ["String.split()", "String.substr()", "parseInt()"] - } -] diff --git a/seed_data/challenges/basejumps.json b/seed_data/challenges/basejumps.json index 5ef3deb8bc..d47df7972c 100644 --- a/seed_data/challenges/basejumps.json +++ b/seed_data/challenges/basejumps.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7158d8c443eddfaeb5bcef", - "name": "Get Set for Basejumps", + "name": "Waypoint: Get Set for Basejumps", "difficulty": 2.00, "challengeSeed": "128451852", "description": [ diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json index 568c54b32c..a3827c4395 100644 --- a/seed_data/challenges/basic-html5-and-css.json +++ b/seed_data/challenges/basic-html5-and-css.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7123c8c441eddfaeb5bdef", - "name": "Waypoint: Use HTML Elements", + "name": "Waypoint: Say Hello to HTML Elements", "difficulty": 0.0085, "description": [ "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", @@ -25,7 +25,7 @@ }, { "_id": "bad87fee1348bd9aedf0887a", - "name": "Waypoint: Use the h2 Element", + "name": "Waypoint: Headline with the h2 Element", "difficulty": 0.010, "description": [ "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", @@ -44,7 +44,7 @@ }, { "_id": "bad87fee1348bd9aedf08801", - "name": "Waypoint: Use the Paragraph Element", + "name": "Waypoint: Inform with the Paragraph Element", "difficulty": 0.011, "description": [ "Create a paragraph element below the h2 element, and give it the text \"Hello Paragraph\".", @@ -62,7 +62,7 @@ }, { "_id": "bad87fee1348bd9aeaf08801", - "name": "Waypoint: Add a Line Break to Visually Separate Elements", + "name": "Waypoint: Visually Separate Elements with Line Breaks", "difficulty": 0.012, "description": [ "Add a line break between the <h2> and <p> elements.", @@ -137,7 +137,7 @@ }, { "_id": "bad87fee1348bd9aedf08833", - "name": "Waypoint: Use Lorem Ipsum Text as a Placeholder", + "name": "Waypoint: Fill in the Blank with Placeholder Text", "difficulty": 0.015, "description": [ "Change the text in the p element to use the first few words of Kitty Ipsum text.", @@ -263,7 +263,7 @@ }, { "_id": "bad87fee1348bd9aefe08806", - "name": "Waypoint: Use a CSS Class to Style Multiple Elements", + "name": "Waypoint: Style Multiple Elements with a CSS Classes", "difficulty": 0.020, "description": [ "Apply the \"red-text\" class to the h2 and p elements.", @@ -419,7 +419,7 @@ }, { "_id": "bad87fee1348bd9aedf08809", - "name": "Waypoint: Using Important to Override Styles", + "name": "Waypoint: Override Styles with Important", "difficulty": 0.025, "description": [ "Create a \"blue-text\" class that gives an element the font-color of blue. Also create a \"urgently-red\" class that give an element the font-color of red, but use !important to ensure the element is rendered as being red. Apply both classes to your h2 element.", @@ -462,7 +462,7 @@ { "_id": "bad87fee1348bd9aedf08812", - "name": "Waypoint: Add an Image to your Website", + "name": "Waypoint: Add Images to your Website", "difficulty": 0.026, "description": [ "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", @@ -500,7 +500,7 @@ }, { "_id": "bad87fee1348bd9acdf08812", - "name": "Waypoint: Specify an Image Size", + "name": "Waypoint: Size your Images", "difficulty": 0.027, "description": [ "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", @@ -539,7 +539,7 @@ }, { "_id": "bad87fee1348bd9bedf08813", - "name": "Waypoint: Add a Border Around an Element", + "name": "Waypoint: Add Borders Around your Elements", "difficulty": 0.028, "description": [ "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border around an HTML element, and apply it to your cat photo.", @@ -632,7 +632,7 @@ }, { "_id": "bad87fee1348bd9aedf08815", - "name": "Waypoint: Make an Image Circular with a Border Radius", + "name": "Waypoint: Make Circular Images with a Border Radius", "difficulty": 0.030, "description": [ "Give your cat photo a border-radius of 50%.", @@ -680,7 +680,7 @@ }, { "_id": "bad87fee1348bd9aedf08816", - "name": "Waypoint: Use an Anchor Tag to Link to an External Page", + "name": "Waypoint: Link to External Pages with Anchor Elements", "difficulty": 0.031, "description": [ "Create an anchor element that links to http://catphotoapp.com and has \"cat photos\" as its anchor text (link text).", @@ -891,7 +891,7 @@ }, { "_id": "bad87fee1348bd9aedf08818", - "name": "Waypoint: Add Alt Text to an image", + "name": "Waypoint: Add Alt Text to an Image for Accessibility", "difficulty": 0.035, "description": [ "Add the alt text \"A cute orange cat lying on its back\" to our cat photo", @@ -1184,7 +1184,7 @@ { "_id" : "bad87fee1348bd9aede08830", - "name": "Waypoint: Create a basic Form Element", + "name": "Waypoint: Create a Form Element", "difficulty" : 0.040, "description": [ "Wrap your text field in a <form> element. Add the action=\"/submit-cat-photo\" attribute to this form element.", @@ -1313,7 +1313,7 @@ { "_id" : "bad87fee1348bd9aedc08830", - "name": "Waypoint: Use HTML5 to Make a Field Required", + "name": "Waypoint: Use HTML5 to Require a Field", "difficulty" : 0.042, "description": [ "Make it required for your user to input text into your form before being able to submit it.", @@ -1593,7 +1593,8 @@ "difficulty" : 0.046, "description": [ "Set one of your radio buttons and one of your checkboxes to be checked by default.", - "" + "You set a checkbox or radio button to be checked by default using the checked attribute.", + "Just add the word \"checked\" to the inside of your input element. For example, <input type='radio' name='test-name' checked>." ], "tests": [ "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')", diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json index fcbe1ecac6..9f7289e409 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/bonfires.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "ad7123c8c441eddfaeb5bdef", - "name": "Meet Bonfire", + "name": "Bonfire: Meet Bonfire", "difficulty": "0", "description": [ "Click the button below for further instructions.", @@ -33,7 +33,7 @@ }, { "_id": "a202eed8fc186c8434cb6d61", - "name": "Reverse a String", + "name": "Bonfire: Reverse a String", "difficulty": "1.01", "tests": [ "expect(reverseString('hello')).to.be.a('String');", @@ -59,7 +59,7 @@ }, { "_id": "a302f7aae1aa3152a5b413bc", - "name": "Factorialize a Number", + "name": "Bonfire: Factorialize a Number", "tests": [ "expect(factorialize(5)).to.be.a(\"Number\");", "expect(factorialize(5)).to.equal(120);", @@ -86,7 +86,7 @@ }, { "_id": "aaa48de84e1ecc7c742e1124", - "name": "Check for Palindromes", + "name": "Bonfire: Check for Palindromes", "difficulty": "1.03", "description": [ "Return true if the given string is a palindrome. Otherwise, return false.", @@ -119,7 +119,7 @@ }, { "_id": "a26cbbe9ad8655a977e1ceb5", - "name": "Find the Longest Word in a String", + "name": "Bonfire: Find the Longest Word in a String", "difficulty": "1.04", "description": [ "Return the length of the longest word in the provided sentence.", @@ -145,7 +145,7 @@ }, { "_id": "ab6137d4e35944e21037b769", - "name": "Title Case a Sentence", + "name": "Bonfire: Title Case a Sentence", "difficulty": "1.05", "description": [ "Return the provided string with the first letter of each word capitalized.", @@ -170,7 +170,7 @@ }, { "_id": "a789b3483989747d63b0e427", - "name": "Return Largest Numbers in Arrays", + "name": "Bonfire: Return Largest Numbers in Arrays", "difficulty": "1.06", "description": [ "Return an array consisting of the largest number from each provided sub-array. For simplicity, the provided array will contain exactly 4 sub-arrays.", @@ -196,7 +196,7 @@ }, { "_id": "acda2fb1324d9b0fa741e6b5", - "name": "Confirm the Ending", + "name": "Bonfire: Confirm the Ending", "difficulty": "1.07", "description": [ "Check if a string (first argument) ends with the given target string (second argument).", @@ -222,7 +222,7 @@ }, { "_id": "afcc8d540bea9ea2669306b6", - "name": "Repeat a string repeat a string", + "name": "Bonfire: Repeat a string repeat a string", "difficulty": "1.08", "description": [ "Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number.", @@ -246,7 +246,7 @@ }, { "_id": "ac6993d51946422351508a41", - "name": "Truncate a string", + "name": "Bonfire: Truncate a string", "difficulty": "1.09", "description": [ "Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a '...' ending.", @@ -271,7 +271,7 @@ }, { "_id": "a9bd25c716030ec90084d8a1", - "name": "Chunky Monkey", + "name": "Bonfire: Chunky Monkey", "difficulty": "1.10", "description": [ "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.", @@ -295,7 +295,7 @@ }, { "_id": "ab31c21b530c0dafa9e241ee", - "name": "Slasher Flick", + "name": "Bonfire: Slasher Flick", "difficulty": "1.11", "description": [ "Return the remaining elements of an array after chopping off n elements from the head.", @@ -319,7 +319,7 @@ }, { "_id": "af2170cad53daa0770fabdea", - "name": "Mutations", + "name": "Bonfire: Mutations", "difficulty": "1.12", "description": [ "Return true if the string in the first element of the array contains the letters of the string in the second element of the array.", @@ -347,7 +347,7 @@ }, { "_id": "adf08ec01beb4f99fc7a68f2", - "name": "Falsey Bouncer", + "name": "Bonfire: Falsey Bouncer", "difficulty": "1.50", "description": [ "Remove all falsey values from an array.", @@ -372,7 +372,7 @@ }, { "_id":"a8e512fbe388ac2f9198f0fa", - "name":"Where art thou", + "name": "Bonfire: Where art thou", "difficulty":"1.55", "description":[ "Make a function that looks through a list (first argument) and returns an array of all objects that have equivalent property values (second argument).", @@ -396,7 +396,7 @@ }, { "_id":"a39963a4c10bc8b4d4f06d7e", - "name":"Seek and Destroy", + "name": "Bonfire: Seek and Destroy", "difficulty":"1.60", "description":[ "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.", @@ -419,7 +419,7 @@ }, { "_id": "a24c1a4622e3c05097f71d67", - "name": "Where do I belong", + "name": "Bonfire: Where do I belong", "difficulty": "1.61", "description": [ "Return the lowest index at which a value (second argument) should be inserted into a sorted array (first argument).", @@ -443,7 +443,7 @@ }, { "_id": "a3566b1109230028080c9345", - "name": "Sum All Numbers in a Range", + "name": "Bonfire: Sum All Numbers in a Range", "difficulty": "2.00", "description": [ "We'll pass you an array of two numbers. Return the sum of those two numbers and all numbers between them.", @@ -469,7 +469,7 @@ }, { "_id": "a5de63ebea8dbee56860f4f2", - "name": "Diff Two Arrays", + "name": "Bonfire: Diff Two Arrays", "difficulty": "2.01", "description": [ "Compare two arrays and return a new array with any items not found in both of the original arrays.", @@ -499,7 +499,7 @@ }, { "_id": "a7f4d8f2483413a6ce226cac", - "name": "Roman Numeral Converter", + "name": "Bonfire: Roman Numeral Converter", "tests": [ "expect(convert(12)).to.equal(\"XII\");", "expect(convert(5)).to.equal(\"V\");", @@ -525,7 +525,7 @@ }, { "_id": "a0b5010f579e69b815e7c5d6", - "name": "Search and Replace", + "name": "Bonfire: Search and Replace", "tests": [ "expect(replace(\"Let us go to the store\", \"store\", \"mall\")).to.equal(\"Let us go to the mall\");", "expect(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")).to.equal(\"He is Sitting on the couch\");", @@ -554,7 +554,7 @@ }, { "_id": "aa7697ea2477d1316795783b", - "name": "Pig Latin", + "name": "Bonfire: Pig Latin", "tests": [ "expect(translate(\"california\")).to.equal(\"aliforniacay\");", "expect(translate(\"paragraphs\")).to.equal(\"aragraphspay\");", @@ -581,7 +581,7 @@ }, { "_id": "afd15382cdfb22c9efe8b7de", - "name": "DNA Pairing", + "name": "Bonfire: DNA Pairing", "tests": [ "assert.deepEqual(pair(\"ATCGA\"),[['A','T'],['T','A'],['C','G'],['G','C'],['A','T']], 'should return the dna pair');", "assert.deepEqual(pair(\"TTGAG\"),[['T','A'],['T','A'],['G','C'],['A','T'],['G','C']], 'should return the dna pair');", @@ -631,7 +631,7 @@ }, { "_id": "a77dbc43c33f39daa4429b4f", - "name": "Boo who", + "name": "Bonfire: Boo who", "difficulty": "2.06", "description": [ "Check if a value is classified as a boolean primitive. Return true or false.", @@ -661,7 +661,7 @@ }, { "_id": "a105e963526e7de52b219be9", - "name": "Sorted Union", + "name": "Bonfire: Sorted Union", "difficulty": "2.07", "description": [ "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.", @@ -686,7 +686,7 @@ }, { "_id": "a6b0bb188d873cb2c8729495", - "name": "Convert HTML Entities", + "name": "Bonfire: Convert HTML Entities", "difficulty": "2.07", "description": [ "Convert the characters \"&\", \"<\", \">\", '\"', and \"'\", in a string to their corresponding HTML entities.", @@ -709,7 +709,7 @@ }, { "_id": "a103376db3ba46b2d50db289", - "name": "Spinal Tap Case", + "name": "Bonfire: Spinal Tap Case", "difficulty": "2.08", "description": [ "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.", @@ -735,7 +735,7 @@ }, { "_id": "a5229172f011153519423690", - "name": "Sum All Odd Fibonacci Numbers", + "name": "Bonfire: Sum All Odd Fibonacci Numbers", "difficulty": "2.09", "description": [ "Return the sum of all odd Fibonacci numbers up to and including the passed number if it is a Fibonacci number.", @@ -763,7 +763,7 @@ }, { "_id": "a3bfc1673c0526e06d3ac698", - "name": "Sum All Primes", + "name": "Bonfire: Sum All Primes", "difficulty": "2.10", "description": [ "Sum all the prime numbers up to and including the provided number.", @@ -788,7 +788,7 @@ }, { "_id": "ae9defd7acaf69703ab432ea", - "name": "Smallest Common Multiple", + "name": "Bonfire: Smallest Common Multiple", "difficulty": "2.11", "description": [ "Find the smallest number that is evenly divisible by all numbers in the provided range.", @@ -814,7 +814,7 @@ }, { "_id": "a6e40f1041b06c996f7b2406", - "name": "Finders Keepers", + "name": "Bonfire: Finders Keepers", "difficulty": "2.12", "description": [ "Create a function that looks through an array (first argument) and returns the first element in the array that passes a truth test (second argument).", @@ -837,7 +837,7 @@ }, { "_id": "a5deed1811a43193f9f1c841", - "name": "Drop it like it's hot", + "name": "Bonfire: Drop it like it's hot", "difficulty": "2.13", "description": [ "Drop the elements of an array (first argument), starting from the front, until the predicate (second argument) returns true.", @@ -861,7 +861,7 @@ }, { "_id": "ab306dbdcc907c7ddfc30830", - "name": "Steamroller", + "name": "Bonfire: Steamroller", "difficulty": "2.14", "description": [ "Flatten a nested array. You must account for varying levels of nesting.", @@ -885,7 +885,7 @@ }, { "_id": "a8d97bd4c764e91f9d2bda01", - "name": "Binary Agents", + "name": "Bonfire: Binary Agents", "difficulty": "2.15", "description": [ "Return an English translated sentence of the passed binary string.", @@ -909,7 +909,7 @@ }, { "_id": "a10d2431ad0c6a099a4b8b52", - "name": "Everything Be True", + "name": "Bonfire: Everything Be True", "difficulty": "2.21", "description": [ "Check if the predicate (second argument) returns truthy (defined) for all elements of a collection (first argument).", @@ -934,7 +934,7 @@ }, { "_id": "a97fd23d9b809dac9921074f", - "name": "Arguments Optional", + "name": "Bonfire: Arguments Optional", "difficulty": "2.22", "description": [ "Create a function that sums two arguments together. If only one argument is provided, return a function that expects one additional argument and will return the sum.", @@ -961,7 +961,7 @@ }, { "_id": "a2f1d72d9b908d0bd72bb9f6", - "name": "Make a Person", + "name": "Bonfire: Make a Person", "difficulty": "3.12", "description": [ "Fill in the object constructor with the methods specified in the tests.", @@ -999,7 +999,7 @@ }, { "_id": "af4afb223120f7348cdfc9fd", - "name": "Map the Debris", + "name": "Bonfire: Map the Debris", "difficulty": "3.50", "description": [ "Return a new array that transforms the element's average altitude into their orbital periods.", @@ -1027,7 +1027,7 @@ }, { "_id" : "a3f503de51cfab748ff001aa", - "name": "Pairwise", + "name": "Bonfire: Pairwise", "difficulty": "3.51", "description": [ "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", @@ -1054,7 +1054,7 @@ }, { "_id": "aff0395860f5d3034dc0bfc9", - "name": "Validate US Telephone Numbers", + "name": "Bonfire: Validate US Telephone Numbers", "difficulty": "4.01", "description": [ "Return true if the passed string is a valid US phone number", @@ -1102,7 +1102,7 @@ }, { "_id": "a3f503de51cf954ede28891d", - "name": "Symmetric Difference", + "name": "Bonfire: Symmetric Difference", "difficulty": "4.02", "description": [ "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", @@ -1127,7 +1127,7 @@ }, { "_id": "aa2e6f85cab2ab736c9a9b24", - "name": "Cash Register", + "name": "Bonfire: Cash Register", "difficulty": "4.03", "description": [ "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order.", @@ -1167,7 +1167,7 @@ }, { "_id": "a56138aff60341a09ed6c480", - "name": "Inventory Update", + "name": "Bonfire: Inventory Update", "difficulty": "4.04", "description": [ "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", @@ -1209,7 +1209,7 @@ }, { "_id": "a7bf700cd123b9a54eef01d5", - "name": "No repeats please", + "name": "Bonfire: No repeats please", "difficulty": "4.05", "description": [ "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", @@ -1237,7 +1237,7 @@ }, { "_id": "a19f0fbe1872186acd434d5a", - "name": "Friendly Date Ranges", + "name": "Bonfire: Friendly Date Ranges", "difficulty": "4.06", "description": [ "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index 0a2d1e245a..cc5aba1e81 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bad87fee1348bd9acde08812", - "name": "Use Bootstrap for Responsive Images", + "name": "Waypoint: Mobile Responsive Images", "difficulty": 0.047, "description": [ "Add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to the image.", @@ -79,7 +79,7 @@ }, { "_id": "bad87fee1348bd8acde08812", - "name": "Center Text with Bootstrap", + "name": "Waypoint: Center Text with Bootstrap", "difficulty": 0.048, "description": [ "Add Bootstrap's text-center class to your h2 element.", @@ -152,7 +152,7 @@ }, { "_id": "bad87fee1348cd8acdf08812", - "name": "Create a Bootstrap Button", + "name": "Waypoint: Create a Bootstrap Button", "difficulty": 0.049, "description": [ "Create a new button below your large kitten photo with the class \"btn\" and the text of \"like this photo\".", @@ -224,7 +224,7 @@ }, { "_id": "bad87fee1348cd8acef08812", - "name": "Create a Block Element Bootstrap Button", + "name": "Waypoint: Create a Block Element Bootstrap Button", "difficulty": 0.050, "description": [ "Add Bootstrap's btn-block class to your Bootstrap button.", @@ -298,7 +298,7 @@ }, { "_id": "bad87fee1348cd8acef08811", - "name": "Color a Bootstrap Button with Button Primary", + "name": "Waypoint: Rock Bootstrap Buttons", "difficulty": 0.051, "description": [ "Add Bootstrap's btn-block class to both of your buttons.", @@ -372,7 +372,7 @@ }, { "_id": "bad87fee1348cd8acef08813", - "name": "Color a Bootstrap Button with Button Info", + "name": "Waypoint: Color a Bootstrap Button with Button Info", "difficulty": 0.052, "description": [ "Create a new block-level Bootstrap button below your \"like\" button with the text \"Info\", and add Bootstrap's btn-info class to it.", @@ -447,7 +447,7 @@ }, { "_id": "bad87fee1348ce8acef08814", - "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", + "name": "Waypoint: Warn your Users of a Dangerous Action", "difficulty": 0.053, "description": [ "Create a button with the text \"delete\" and give it the class btn-danger.", @@ -523,7 +523,7 @@ }, { "_id": "bad88fee1348ce8acef08815", - "name": "Use the Bootstrap Grid to Put Elements Side By Side", + "name": "Waypoint: Use the Bootstrap Grid to Put Elements Side By Side", "difficulty": 0.054, "description": [ "Put the \"like\", \"Info\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"col-xs-4\"> element.", @@ -601,7 +601,7 @@ { "_id" : "bad87fee1348bd9aedf08845", - "name": "Use Bootstrap Text Primary Class instead of Custom CSS", + "name": "Waypoint: Ditch Custom CSS for Bootstrap", "difficulty" : 0.055, "description": [ "Delete the following from your style tag: .red-text, p, .smaller-image. Delete the p element with the dead link. Remove your red-text class from your h2 element and instead apply the text-primary Bootstrap class. Replace the smaller-image class on your top image with the img-responsive class." @@ -688,7 +688,7 @@ { "_id" : "bad87fee1348bd9aede08845", - "name": "Create a Custom Heading", + "name": "Waypoint: Create a Custom Heading", "difficulty" : 0.056, "description": [ "Wrap your first image and your h2 element in a <div class='row'> element. Wrap your h2 text in a <div class='col-xs-8'> and your image in a <div class='col-xs-4'> so that they are on the same line." @@ -760,7 +760,7 @@ { "_id" : "bad87fee1348bd9aedd08845", - "name": "Add Font Awesome Icons to our Buttons", + "name": "Waypoint: Add Font Awesome Icons to our Buttons", "difficulty" : 0.057, "description": [ "Use Font Awesome to add a \"like\" icon to your like button.", @@ -835,7 +835,7 @@ { "_id" : "bad87fee1348bd9aedc08845", - "name": "Add Font Awesome Icons all of our Buttons", + "name": "Waypoint: Add Font Awesome Icons all of our Buttons", "difficulty" : 0.058, "description": [ "Use Font Awesome to add a \"info-circle\" icon to your info button and a \"trash\" button to your delete button.", @@ -911,7 +911,7 @@ { "_id" : "bad87fee1348bd9aedb08845", - "name": "Use Bootstrap to Responsively Style a Radio Buttons", + "name": "Waypoint: Responsively Style a Radio Buttons", "difficulty" : 0.059, "description": [ "Wrap all of your radio buttons in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-6'> element." @@ -986,7 +986,7 @@ { "_id" : "bad87fee1348bd9aeda08845", - "name": "Use Bootstrap to Responsively Style Checkboxes", + "name": "Waypoint: Responsively Style Checkboxes", "difficulty" : 0.060, "description": [ "Wrap all your checkboxes in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-4'> element." @@ -1068,7 +1068,7 @@ { "_id" : "bad87fee1348bd9aed908845", - "name": "Style a Text Input with the Bootstrap Form Control Class", + "name": "Waypoint: Style a Text Input with the Bootstrap Form Control Class", "difficulty" : 0.061, "description": [ "Give your form's text input field in a class of \"form-control\". Give your form's submit button the classes \"btn btn-primary\" and give it the Font Awesome icon of \"fa-paper-plane\"." @@ -1160,7 +1160,7 @@ { "_id" : "bad87fee1348bd9aec908845", - "name": "Line up Form Elements Responsively with Bootstrap", + "name": "Waypoint: Line up Form Elements Responsively with Bootstrap", "difficulty" : 0.062, "description": [ "Wrap both your form's text input field and submit button within a div with the class \"row\". Wrap your form's text input field within a div with the class of \"col-xs-7\". Wrap your form's submit button the in a div with the class \"col-xs-5\"." @@ -1252,7 +1252,7 @@ { "_id": "bad88fee1348bd9aedf08825", - "name": "Adjusting the Padding of an Element", + "name": "Waypoint: Adjusting the Padding of an Element", "difficulty": 0.064, "description": [ "Change the padding of the green box to match that of the red box.", @@ -1303,7 +1303,7 @@ }, { "_id": "bad87fee1348bd9aedf08822", - "name": "Adjust the Margin of an Element", + "name": "Waypoint: Adjust the Margin of an Element", "difficulty": 0.065, "description": [ "Change the margin of the green box to match that of the red box.", @@ -1356,7 +1356,7 @@ }, { "_id": "bad87fee1348bd9aedf08823", - "name": "Add a Negative Margin to an Element", + "name": "Waypoint: Add a Negative Margin to an Element", "difficulty": 0.066, "description": [ "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", @@ -1408,7 +1408,7 @@ }, { "_id": "bad87fee1348bd9aedf08824", - "name": "Add Different Padding to Each Side of an Element TEST", + "name": "Waypoint: Add Different Padding to Each Side of an Element TEST", "difficulty": 0.067, "description": [ "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", @@ -1461,7 +1461,7 @@ }, { "_id": "bad87fee1248bd9aedf08824", - "name": "Add Different a Margin to Each Side of an Element TEST", + "name": "Waypoint: Add Different a Margin to Each Side of an Element TEST", "difficulty": 0.068, "description": [ "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", @@ -1514,7 +1514,7 @@ }, { "_id": "bad87fee1348bd9aedf08826", - "name": "Use Clockwise Notation to Specify an Element's Padding", + "name": "Waypoint: Use Clockwise Notation to Specify an Element's Padding", "difficulty": 0.069, "description": [ "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", @@ -1565,7 +1565,7 @@ { "_id": "bad87fee1348bd9aede08826", - "name": "Use Hex Codes for Precise Colors", + "name": "Waypoint: Use Hex Codes for Precise Colors", "difficulty": 0.070, "description": [ @@ -1581,7 +1581,7 @@ { "_id": "bad87fee1348bd9aedd08826", - "name": "Use Shortened Hex Codes for Colors", + "name": "Waypoint: Use Shortened Hex Codes for Colors", "difficulty": 0.071, "description": [ diff --git a/seed_data/challenges/computer-science.json b/seed_data/challenges/computer-science.json index 50c0b873a5..13f3d624b4 100644 --- a/seed_data/challenges/computer-science.json +++ b/seed_data/challenges/computer-science.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7123d8c441eddfaeb5bdef", - "name": "Learn Basic Computer Science", + "name": "Waypoint: Learn Basic Computer Science", "difficulty": 0.90, "challengeSeed": "114628241", "description": [ @@ -18,7 +18,7 @@ }, { "_id": "bd8124d8c441eddfaeb5bdef", - "name": "Learn Loops", + "name": "Waypoint: Learn Loops", "difficulty": 0.19, "challengeSeed": "114597348", "description": [ @@ -31,7 +31,7 @@ }, { "_id": "bd8125d8c441eddfaeb5bdef", - "name": "Learn Computer Hardware", + "name": "Waypoint: Learn Computer Hardware", "difficulty": 0.20, "challengeSeed": "114597347", "description": [ @@ -44,7 +44,7 @@ }, { "_id": "bd8126d8c441eddfaeb5bdef", - "name": "Learn Computer Networking", + "name": "Waypoint: Learn Computer Networking", "difficulty": 0.21, "challengeSeed": "114604811", "description": [ @@ -57,7 +57,7 @@ }, { "_id": "bd8127d8c441eddfaeb5bdef", - "name": "Learn Boolean Logic", + "name": "Waypoint: Learn Boolean Logic", "difficulty": 0.22, "challengeSeed": "114604812", "description": [ @@ -70,7 +70,7 @@ }, { "_id": "bd8128d8c441eddfaeb5bdef", - "name": "Learn Computer Security", + "name": "Waypoint: Learn Computer Security", "difficulty": 0.23, "challengeSeed": "114604813", "description": [ diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index 74e63fa473..4a9b880ff9 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7154d8c441eddfaeb5bdef", - "name": "Get Started with Angular.js", + "name": "Waypoint: Get Started with Angular.js", "difficulty": 0.34, "challengeSeed": "114684726", "description": [ @@ -17,7 +17,7 @@ }, { "_id": "bd7155d8c441eddfaeb5bdef", - "name": "Apply Angular.js Directives", + "name": "Waypoint: Apply Angular.js Directives", "difficulty": 0.35, "challengeSeed": "114684727", "description": [ @@ -30,7 +30,7 @@ }, { "_id": "bd7156d8c441eddfaeb5bdef", - "name": "Power Forms with Angular.js", + "name": "Waypoint: Power Forms with Angular.js", "difficulty": 0.36, "challengeSeed": "114684729", "description": [ @@ -43,7 +43,7 @@ }, { "_id": "bd7157d8c441eddfaeb5bdef", - "name": "Customize Angular.js Directives", + "name": "Waypoint: Customize Angular.js Directives", "difficulty": 0.37, "challengeSeed": "114685062", "description": [ @@ -55,7 +55,7 @@ }, { "_id": "bd7158d8c441eddfaeb5bdef", - "name": "Create Angular.js Services", + "name": "Waypoint: Create Angular.js Services", "difficulty": 0.38, "challengeSeed": "114685060", "description": [ @@ -68,7 +68,7 @@ }, { "_id": "bd7153d8c441eddfaeb5bd0f", - "name": "Manage Packages with NPM", + "name": "Waypoint: Manage Packages with NPM", "difficulty": 0.39, "challengeSeed": "126433450", "description": [ @@ -92,7 +92,7 @@ }, { "_id": "bd7153d8c441eddfaeb5bdff", - "name": "Start a Node.js Server", + "name": "Waypoint: Start a Node.js Server", "difficulty": 0.40, "challengeSeed": "126411561", "description": [ @@ -116,7 +116,7 @@ }, { "_id": "bd7153d8c441eddfaeb5bdfe", - "name": "Continue working with Node.js Servers", + "name": "Waypoint: Continue working with Node.js Servers", "difficulty": 0.41, "challengeSeed": "126411561", "description": [ @@ -129,7 +129,7 @@ }, { "_id": "bd7153d8c441eddfaeb5bdfd", - "name": "Finish working with Node.js Servers", + "name": "Waypoint: Finish working with Node.js Servers", "difficulty": 0.42, "challengeSeed": "126411561", "description": [ @@ -142,7 +142,7 @@ }, { "_id": "bd7153d8c441eddfaeb5bd1f", - "name": "Build Web Apps with Express.js", + "name": "Waypoint: Build Web Apps with Express.js", "difficulty": 0.43, "challengeSeed": "126411559", "description": [ @@ -166,7 +166,7 @@ }, { "_id": "bd7140d8c441eddfaeb5bdef", - "name": "Manage Source Code with Git", + "name": "Waypoint: Manage Source Code with Git", "difficulty": 0.44, "challengeSeed": "114635309", "description": [ diff --git a/seed_data/challenges/getting-set-for-free-code-camp.json b/seed_data/challenges/getting-set-for-free-code-camp.json index 3ff60924b0..3af8a0b0de 100644 --- a/seed_data/challenges/getting-set-for-free-code-camp.json +++ b/seed_data/challenges/getting-set-for-free-code-camp.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7124d8c441eddfaeb5bdef", - "name": "Learn how Free Code Camp Works", + "name": "Waypoint: Learn how Free Code Camp Works", "difficulty": 0.001, "challengeSeed": "125407438", "description": [ @@ -22,7 +22,7 @@ }, { "_id": "bd7125d8c441eddfaeb5bd0f", - "name": "Join Our Chat Room", + "name": "Waypoint: Join Our Chat Room", "difficulty": 0.002, "challengeSeed": "124555254", "description": [ @@ -42,7 +42,7 @@ }, { "_id": "bd7125d8c441eddfaeb5bdff", - "name": "Preview our Challenge Map", + "name": "Waypoint: Preview our Challenge Map", "difficulty": 0.003, "challengeSeed": "125407437", "description": [ @@ -58,7 +58,7 @@ }, { "_id": "bd7125d8c441eddfaeb5bd1f", - "name": "Browse our Field Guide", + "name": "Waypoint: Browse our Field Guide", "difficulty": 0.004, "challengeSeed": "125407435", "description": [ @@ -73,7 +73,7 @@ }, { "_id": "bd7125d8c441eddfaeb5bd2f", - "name": "Customize your Portfolio Page", + "name": "Waypoint: Customize your Portfolio Page", "difficulty": 0.005, "challengeSeed": "125407433", "description": [ @@ -90,7 +90,7 @@ }, { "_id": "bd7126d8c441eddfaeb5bd3f", - "name": "Try Camper News", + "name": "Waypoint: Try Camper News", "difficulty": 0.006, "challengeSeed": "124553410", "description": [ @@ -109,7 +109,7 @@ }, { "_id": "bd7126d8c441eddfaeb5bd3e", - "name": "Meet Other Campers in your City", + "name": "Waypoint: Meet Other Campers in your City", "difficulty": 0.007, "challengeSeed": "127358841", "description": [ @@ -127,7 +127,7 @@ }, { "_id": "bd7137d8c441eddfaeb5bdef", - "name": "Get Help the Hacker Way with RSAP", + "name": "Waypoint: Get Help the Hacker Way with RSAP", "difficulty": 0.008, "challengeSeed": "125407432", "description": [ diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json index 15d941d50e..23bfa3c991 100644 --- a/seed_data/challenges/jquery-ajax-and-json.json +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -1,10 +1,10 @@ { - "name": "jQuery Ajax and JSON", + "name": "jQuery, Ajax and JSON", "order" : 0.004, "challenges": [ { "_id": "bad87fee1348bd9acdd08826", - "name": "Learn how Script Tags and Document Ready Work", + "name": "Waypoint: Learn how Script Tags and Document Ready Work", "difficulty": 0.072, "description": [ "Test" @@ -26,7 +26,7 @@ { "_id": "bad87fee1348bd9aedc08826", - "name": "Target Elements by Selectors Using jQuery", + "name": "Waypoint: Target Elements by Selectors Using jQuery", "difficulty": 0.073, "description": [ @@ -42,7 +42,7 @@ { "_id": "bad87fee1348bd9aedb08826", - "name": "Target Elements by Class Using jQuery", + "name": "Waypoint: Target Elements by Class Using jQuery", "difficulty": 0.074, "description": [ @@ -58,7 +58,7 @@ { "_id": "bad87fee1348bd9aeda08826", - "name": "Target an element by ID Using jQuery", + "name": "Waypoint: Target an element by ID Using jQuery", "difficulty": 0.075, "description": [ @@ -74,7 +74,7 @@ { "_id": "bad87fee1348bd9aed908826", - "name": "Change the CSS of an Element Using jQuery", + "name": "Waypoint: Change the CSS of an Element Using jQuery", "difficulty": 0.076, "description": [ @@ -90,7 +90,7 @@ { "_id": "bad87fee1348bd9aed808826", - "name": "Disable an Element Using jQuery", + "name": "Waypoint: Disable an Element Using jQuery", "difficulty": 0.077, "description": [ @@ -106,7 +106,7 @@ { "_id": "bad87fee1348bd9aed708826", - "name": "Remove an Element Using jQuery", + "name": "Waypoint: Remove an Element Using jQuery", "difficulty": 0.078, "description": [ @@ -122,7 +122,7 @@ { "_id": "bad87fee1348bd9aed608826", - "name": "Move an Element Using jQuery", + "name": "Waypoint: Move an Element Using jQuery", "difficulty": 0.079, "description": [ @@ -138,7 +138,7 @@ { "_id": "bad87fee1348bd9aed508826", - "name": "Clone an Element Using jQuery", + "name": "Waypoint: Clone an Element Using jQuery", "difficulty": 0.080, "description": [ @@ -154,7 +154,7 @@ { "_id": "bad87fee1348bd9aed408826", - "name": "Animate an Element Using jQuery", + "name": "Waypoint: Animate an Element Using jQuery", "difficulty": 0.081, "description": [ @@ -170,7 +170,7 @@ { "_id": "bad87fee1348bd9aed308826", - "name": "Target the Parent of an Element Using jQuery", + "name": "Waypoint: Target the Parent of an Element Using jQuery", "difficulty": 0.082, "description": [ @@ -186,7 +186,7 @@ { "_id": "bad87fee1348bd9aed208826", - "name": "Target the Children of an Element Using jQuery", + "name": "Waypoint: Target the Children of an Element Using jQuery", "difficulty": 0.083, "description": [ @@ -203,7 +203,7 @@ { "_id": "bad87fee1348bd9aed108826", - "name": "Target a Specific Child of an Element Using jQuery", + "name": "Waypoint: Target a Specific Child of an Element Using jQuery", "difficulty": 0.084, "description": [ @@ -219,7 +219,7 @@ { "_id": "bad87fee1348bd9aed008826", - "name": "Target Even Numbered Elements Using jQuery", + "name": "Waypoint: Target Even Numbered Elements Using jQuery", "difficulty": 0.085, "description": [ @@ -235,7 +235,7 @@ { "_id": "bad87fee1348bd9aecc08826", - "name": "Read Data from an Element Using jQuery", + "name": "Waypoint: Read Data from an Element Using jQuery", "difficulty": 0.086, "description": [ @@ -251,7 +251,7 @@ { "_id": "bad87fee1348bd9aebc08826", - "name": "Get Data from an URL Using jQuery", + "name": "Waypoint: Get Data from an URL Using jQuery", "difficulty": 0.087, "description": [ @@ -267,7 +267,7 @@ { "_id": "bad87fee1348bd9ae9c08826", - "name": "Loop through JSON Data Using jQuery", + "name": "Waypoint: Loop through JSON Data Using jQuery", "difficulty": 0.089, "description": [ @@ -283,7 +283,7 @@ { "_id": "bad87fee1348bd9ae8c08826", - "name": "Setup Click Events Using jQuery", + "name": "Waypoint: Setup Click Events Using jQuery", "difficulty": 0.089, "description": [ diff --git a/seed_data/challenges/ziplines.json b/seed_data/challenges/ziplines.json index 2cbf2eff80..9efe5bdd35 100644 --- a/seed_data/challenges/ziplines.json +++ b/seed_data/challenges/ziplines.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7158d8c442eddfbeb5bd1f", - "name": "Get Set for Ziplines", + "name": "Waypoint: Get Set for Ziplines", "difficulty": 1.00, "challengeSeed": "125658022", "description": [ diff --git a/seed_data/coursewares.json b/seed_data/coursewares.json deleted file mode 100644 index c463b195fb..0000000000 --- a/seed_data/coursewares.json +++ /dev/null @@ -1,4361 +0,0 @@ -[ - { - "_id": "bd7124d8c441eddfaeb5bdef", - "name": "Learn how Free Code Camp Works", - "difficulty": 0.001, - "challengeSeed": "125407438", - "description": [ - "Watch this 1-minute video, or simply read this summary:", - "Welcome to Free Code Camp. We're a community of busy people who learn to code, then practice by building projects for nonprofits.", - "We built this community because learning to code is hard. But anyone who can stay motivated can learn to code. And to stay motivated, you just need to:
    1. make friends with people who code
    2. code a little every day
      1. ", - "All our challenges are
        1. free
        2. self-paced
        3. browser-based
        ", - "We'll spend
        1. 200 hours learning tools like HTML, CSS, JavaScript, Node.js and databases
        2. 600 hours building practice projects
        3. 800 hours building full stack solutions for nonprofits
        ", - "By the end, we'll
        1. be good at coding
        2. have the portfolio of apps with happy users to prove it
        ", - "Once you make it through Free Code Camp, you will be able to get a coding job. There are far more job openings out there than there are qualified coders to fill them.", - "Now it's time to join our chat room. Click the \"I've completed this challenge\" button to move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bd0f", - "name": "Join Our Chat Room", - "difficulty": 0.002, - "challengeSeed": "124555254", - "description": [ - "Now we're going to join the Free Code Camp chat room. You can come here any time of day to hang out, ask questions, or find another camper to pair program with.", - "Make sure your Free Code Camp account includes your email address. You can do this here: http://freecodecamp.com/account. Please note that the email address you use will be invisible to the public, but Slack will make it visible to other campers in our slack chat rooms.", - "Click this link, which will email you an invite to Free Code Camp's Slack chat rooms: http://freecodecamp.com/api/slack.", - "Now check your email and click the link in the email from Slack.", - "Complete the sign up process, then update your biographical information and upload an image. A picture of your face works best. This is how people will see you in our chat rooms, so put your best foot forward.", - "Now enter the General chat room and introduce yourself to our chat room by typing: \"Hello world!\".", - "Tell your fellow campers how you found Free Code Camp. Also tell us why you want to learn to code.", - "Keep the chat room open while you work through the other challenges. That way you ask for help if you get stuck on a challenge. You can also socialize when you feel like taking a break.", - "You can also access this chat room by clicking the \"Chat\" button in the upper right hand corner.", - "In order to keep our community a friendly and positive place to learn to code, please read and follow our Code of Conduct: http://freecodecamp.com/field-guide/what-is-the-free-code-camp-code-of-conduct?" - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bdff", - "name": "Preview our Challenge Map", - "difficulty": 0.003, - "challengeSeed": "125407437", - "description": [ - "Before you start learning how to code, we'd like to introduce you to a few things.", - "Let's look at our Challenge Map. Click on the \"Map\" button in the upper right hand corner. This map shows all the challenges that will teach you how to code.", - "You should complete all these challenges in order.", - "Once you finish these Waypoint challenges, you'll move on to Bonfires (algorithm practice), then Ziplines (front end development practice) and finally Basejumps (full stack development practice). After that, you'll start building projects for nonprofits.", - "This challenge map is just for your reference. You can always just press the \"Learn\" button, and it will take you to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bd1f", - "name": "Browse our Field Guide", - "difficulty": 0.004, - "challengeSeed": "125407435", - "description": [ - "Free Code Camp has an up-to-date field guide that will answer your many questions.", - "Click the \"Field Guide\" button in the upper right hand corner.", - "You can browse the field guide at your convenience. Most of its articles take less than 1 minute to read.", - "When you click the Field Guide button, it will always take you back to whichever article you were last reading.", - "Read a few field guide articles, then move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7125d8c441eddfaeb5bd2f", - "name": "Customize your Portfolio Page", - "difficulty": 0.005, - "challengeSeed": "125407433", - "description": [ - "You and all your fellow campers have portfolio pages.", - "To see your portfolio page, click your picture in the upper right hand corner.", - "Your portfolio page will automatically show off your progress through Free Code Camp.", - "Click the \"Update my portfolio page or manage my account\" button", - "You can link to your GitHub, Twitter and LinkedIn accounts. If you've already built some websites, you can link to them here as well.", - "Be sure to click the \"Update my Bio\" or \"Update my Social Links\" button to save this new information to your portfolio page.", - "Once you're happy with your portfolio page, you can move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7126d8c441eddfaeb5bd3f", - "name": "Try Camper News", - "difficulty": 0.006, - "challengeSeed": "124553410", - "description": [ - "Camper News is the best place for our campers to share and discuss helpful links.", - "Click \"News\" in the upper right hand corner.", - "You'll see a variety of links that have been submitted. Click on the \"Discuss\" button under one of them.", - "You can upvote links. This will push the link up the rankings of hot links.", - "You can also comment on a link. If someone responds to your comment, you'll get an email notification so you can come back and respond to them.", - "You can also submit links. You can modify the link's headline and also leave an initial comment about the link.", - "You can view the portfolio pages of any camper who has posted links or comments on Camper News. Just click on their photo.", - "When you submit a link, you'll get a point. You will also get a point each time someone upvotes your link.", - "Now that you've learned how to use Camper News, let's move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7126d8c441eddfaeb5bd3e", - "name": "Meet Other Campers in your City", - "difficulty": 0.007, - "challengeSeed": "127358841", - "description": [ - "One of the best ways to stay motivated when learning to code is to hang out with other campers.", - "Slack and Camper News are great ways to communicate with other campers, but there's no substitute for meeting people in-person.", - "The easiest way to meet other campers in your city is to join your city's Facebook Group. Click here to view our growing list of local groups.", - "Click the link to your city, then, once Facebook loads, click \"Join group\".", - "Our local groups are new, so if you don't see your city on this list, you should follow the directions to create a Facebook group for your city.", - "If you don't have a Facebook account, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.", - "Our groups allow you to create events, coordinate those events, and share photos from the events afterward.", - "Whether you're hosting a study group, pair programming at your local library, or going to a weekend hackathon, your city's group will help you make it happen." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7137d8c441eddfaeb5bdef", - "name": "Get Help the Hacker Way with RSAP", - "difficulty": 0.008, - "challengeSeed": "125407432", - "description": [ - "Let's cover one last thing before you start working through our lessons: how to get help.", - "Any time you get stuck or don't know what to do next, follow this simple algorithm (procedure): RSAP (Read, Search, Ask, Post).", - "First, R - Read the documentation or error message. A key skill that good coders have is the ability to interpret and then follow instructions.", - "Next, S - Search Google. Good Google queries take a lot of practice. When you search Google, you usually want to include the language or framework you're using. You also want to limit the results to a recent period.", - "Then, if you still haven't found an answer to your question, A - Ask your friends. If you have trouble, you can ask your fellow campers. We have a special chat room specifically for getting help with tools you learn through these Free Code Camp Challenges. Go to https://freecode.slack.com/messages/help/. Keep this chat open while you work on the remaining challenges.", - "Finally, P - Post on Stack Overflow. Before you attempt to do this, read Stack Overflow's guide to asking good questions: http://stackoverflow.com/help/how-to-ask.", - "Here's our detailed field guide on getting help: http://freecodecamp.com/field-guide/how-do-i-get-help-when-i-get-stuck.", - "Now you have a clear algorithm to follow when you need help! Let's start coding! Move on to your next challenge." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7123c8c441eddfaeb5bdef", - "name": "Use HTML Elements", - "difficulty": 0.0085, - "description": [ - "Welcome to Free Code Camp's first coding challenge! Click on the button below for further instructions.", - "Awesome. Now you can read the rest of this challenge's instructions.", - "You can edit code in your text editor, which we've embedded into this web page.", - "Do you see the code in your text editor that says <h1>Hello</h1>? That's an HTML element.", - "Most HTML elements have an opening tag and a closing tag. Opening tags look like this: <h1>. Closing tags look like this: </h1>. Note that the only difference between opening and closing tags is that closing tags have a slash after their opening angle bracket.", - "Once you've completed each challenge, and all its tests are passing, the \"Go to my next challenge\" button will become enabled. Click it - or press control and enter at the same time - to advance to the next challenge.", - "To enable the \"Go to my next challenge\" button on this exercise, change your h1 tag's text to say \"Hello World\" instead of \"Hello\"." - ], - "tests": [ - "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" - ], - "challengeSeed": [ - "

        Hello

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf0887a", - "name": "Use the h2 Element", - "difficulty": 0.010, - "description": [ - "Add an h2 tag that says \"CatPhotoApp\" to create a second HTML element below your \"Hello World\" h1 element.", - "The h2 element you enter will create an h2 element on the website.", - "This element tells the browser how to render the text that it contains.", - "h2 elements are slightly smaller than h1 elements. There are also h3, h4, h5 and h6 elements." - ], - "tests": [ - "assert.isTrue((/cat(\\s)?photo(\\s)?app/gi).test($('h2').text()), 'Your h2 element should have the text \"CatPhotoApp\"')", - "assert.isTrue((/hello(\\s)+world/gi).test($('h1').text()), 'Your h1 element should have the text \"Hello World\"')" - ], - "challengeSeed": [ - "

        Hello World

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08801", - "name": "Use the Paragraph Element", - "difficulty": 0.011, - "description": [ - "Create a paragraph element below the h2 element, and give it the text \"Hello Paragraph\".", - "Paragraph elements are the preferred element for normal-sized paragraph text on websites.", - "You can create a paragraph element like so: <p>I'm a p tag!</p>" - ], - "tests": [ - "assert.isTrue((/hello(\\s)+paragraph/gi).test($('p').text()), 'Your paragraph element should have the text \"Hello Paragraph\"')" - ], - "challengeSeed": [ - "

        Hello World

        ", - "

        CatPhotoApp

        " - ] - }, - { - "_id": "bad87fee1348bd9aeaf08801", - "name": "Add a Line Break to Visually Separate Elements", - "difficulty": 0.012, - "description": [ - "Add a line break between the <h2> and <p> elements.", - "You can create an line break element with <br/>.", - "Note that <br/> has no closing tag. It is a self-closing element. See how a forward-slash precedes the closing bracket?", - "You'll encounter other self-closing element tags soon." - ], - "tests": [ - "assert(($('br').length > 0), 'You should have a br element between your h2 and paragraph elements.')" - ], - "challengeSeed": [ - "

        Hello World

        ", - "

        CatPhotoApp

        ", - "

        Hello Paragraph

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08802", - "name": "Uncomment HTML", - "difficulty": 0.013, - "description": [ - "Uncomment the h1, h2 and p elements.", - "Commenting is a way that you can leave comments within your code without affecting the code itself.", - "Commenting is also a convenient way to make code inactive without having to delete it entirely.", - "You can start a comment with <!-- and end a comment with -->." - ], - "tests": [ - "assert(($('h1').length > 0), 'The h1 element should not commented. It should be visible in the browser.')", - "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", - "assert(($('p').length > 0), 'The paragraph element should not commented. It should be visible in the browser.')" - ], - "challengeSeed": [ - "" - ] - }, - { - "_id": "bad87fee1348bd9aedf08804", - "name": "Comment out HTML", - "difficulty": 0.014, - "description": [ - "Comment out the h1 element and the p element, but leave the h2 element uncommented.", - "Remember that in order to start a comment, you need to use <!-- and to end a comment, you need to use -->.", - "Here you'll need to end the comment before the h2 element begins." - ], - "tests": [ - "assert(($('h1').length == 0), 'The h1 element should be commented. It should not be visible in the browser.')", - "assert(($('h2').length > 0), 'The h2 element should not commented. It should be visible in the browser.')", - "assert(($('p').length == 0), 'The paragraph element should be commented. It should not be visible in the browser.')" - ], - "challengeSeed": [ - "" - ] - }, - { - "_id": "bad87fee1348bd9aedf08833", - "name": "Use Lorem Ipsum Text as a Placeholder", - "difficulty": 0.015, - "description": [ - "Change the text in the p element to use the first few words of Kitty Ipsum text.", - "Web developers traditionally use Lorem Ipsum as placeholder text. It's called Lorem Ipsum text because those are the first two words of a famous passage by Cicero of Ancient Rome.", - "Lorem Ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web.", - "Well, 5 centuries is long enough. Since we're building a CatPhotoApp, let's use something called Kitty Ipsum!", - "Here are the first few words of Kitty Ipsum text, which you can copy and paste into the right position: Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff." - ], - "tests": [ - "assert.isTrue((/Kitty(\\s)+ipsum(\\s)+dolor/gi).test($('p').text()), 'Your paragraph element should contain the first few words of the famous Kitty Ipsum text.')" - ], - "challengeSeed": [ - "

        Hello World

        ", - "", - "

        CatPhotoApp

        ", - "", - "
        ", - "", - "

        Hello Paragraph

        " - ] - }, - { - "_id": "bad87fed1348bd9aedf08833", - "name": "Delete HTML Elements", - "difficulty": 0.016, - "description": [ - "Delete the h1 and br elements so we can simplify our view.", - "Our phone doesn't have much space, for HTML elements.", - "Let's remove the unnecessary elements so we can start building our CatPhotoApp." - ], - "tests": [ - "assert(($('h1').length == 0), 'Delete the h1 element.')", - "assert(($('h2').length > 0), 'Leave the h2 element on the page.')", - "assert(($('br').length == 0), 'Delete the br element.')", - "assert(($('p').length > 0), 'Leave the paragraph element on the page.')" - ], - "challengeSeed": [ - "

        Hello World

        ", - "", - "

        CatPhotoApp

        ", - "", - "
        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08803", - "name": "Change the Color of Text", - "difficulty": 0.017, - "description": [ - "Change the h2 element's style so that its text color is red.", - "We can do this by changing the style of the h2 element.", - "The style that is responsible for the color of an element's text is the \"color\" style.", - "Here's how you would set your h2 element's text color to blue: <h2 style=\"color: blue\">CatPhotoApp<h2>" - ], - "tests": [ - "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" - ], - "challengeSeed": [ - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08805", - "name": "Use CSS Selectors to Style Elements", - "difficulty": 0.018, - "description": [ - "Delete your h2 element's style tag and write the CSS to make all h2 elements blue.", - "With CSS, there are hundreds of CSS attributes that you can use to change the way an element looks on a web page.", - "When you entered <h2 style=\"color: red\">CatPhotoApp<h2>, you were giving that individual h2 element an inline style", - "That's one way to add style to an element, but a better way is by using Cascading Style Sheets (CSS).", - "At the top of your code, create a style tag like this: <style></style>", - "Inside that style element, you can create a css selector for all h2 elements. For example, if you wanted all h2 elements to be red, your style element would look like this: <style>h2 {color: red;}</style>", - "Note that it's important to have opening and closing curly braces ({ and }) around each element's style. You also need to make sure your element's style is between the opening and closing style tags. Finally, be sure to add the semicolon to the end of each of your element's styles." - ], - "tests": [ - "assert($('h2').css('color') === 'rgb(0, 0, 255)', 'Your h2 element should be blue.')", - "assert(!$('h2').attr('style'), 'You should remove the style attribute from your h2 element.')" - ], - "challengeSeed": [ - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aecf08806", - "name": "Use a CSS Class to Style an Element", - "difficulty": 0.019, - "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:", - "a diagram of how style tags are composed, which is also described in detail on the following lines.", - "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.", - "Instead of creating a new Style tag, try removing the h2 style declaration from the existing style element, and replace it with the class declaration for \".red-text\"." - ], - "tests": [ - "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", - "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')" - ], - "challengeSeed": [ - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aefe08806", - "name": "Use a CSS Class to Style Multiple Elements", - "difficulty": 0.020, - "description": [ - "Apply the \"red-text\" class to the h2 and p elements.", - "Remember that you can attach classes to HTML elements by using the class=\"class\" within the relevant element's opening tag." - ], - "tests": [ - "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')", - "assert($('h2').hasClass('red-text'), 'You h2 element should have the class \"red-text\".')", - "assert($('p').css('color') === 'rgb(255, 0, 0)', 'Your paragraph element should be red.')", - "assert($('p').hasClass('red-text'), 'You paragraph element should have the class \"red-text\".')" - ], - "challengeSeed": [ - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08806", - "name": "Change the Font Size of an Element", - "difficulty": 0.021, - "description": [ - "Create a second p element. Then set the font size of all p elements to 16 pixels.", - "Font size is controlled by the font-size CSS attribute, like this: h1 { font-size: 30px; }.", - "First, create a second paragraph element with the following Kitty Ipsum text: Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.", - "See if you can figure out how to give both of your paragraph elements the font-size of 16 pixels (16px). You can do this inside the same <style> tag that we created for your \"red-text\" class." - ], - "tests": [ - "assert($('p').length > 1, 'You need 2 paragraph elements with Kitty Ipsum text.')", - "assert($('p').css('font-size') === '16px', 'Your paragraph elements should have the font-size of 16px.')" - ], - "challengeSeed": [ - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        " - ] - }, - { - "_id": "bad87fee1348bd9aede08807", - "name": "Set the Font Family of an Element", - "difficulty": 0.022, - "description": [ - "Make all paragraph elements use the \"Monospace\" font.", - "You can set an element's font by using the font-family attribute.", - "For example, if you wanted to set your h2 element's font to \"San-serif\", you would use the following CSS: h2 { font-family: 'San-serif'; }" - ], - "tests": [ - "assert($('p').css('font-family').match(/monospace/i), 'Your paragraph elements should use the font \"Monospace\".')" - ], - "challengeSeed": [ - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08807", - "name": "Import a Google Font", - "difficulty": 0.023, - "description": [ - "Apply the font-family of \"Lobster\" to your h2 element.", - "First, you'll need to make a call to Google to grab the \"Lobster\" font and load it into your HTML.", - "Copy the following code snippet and paste it into your code editor above your style element:", - "<link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>", - "Now you can set \"Lobster\" as a font-family attribute on your h2 element." - ], - "tests": [ - "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')" - ], - "challengeSeed": [ - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08808", - "name": "Specify How Fonts Should Degrade", - "difficulty": 0.024, - "description": [ - "Make all your h2 elements use \"Lobster\" as their font family, but degrade to the \"Monospace\" font when the \"Lobster\" font isn't available.", - "You can leave \"Lobster\" your h2 element's font-family, and have it \"degrade\" to a different font when \"Lobster\" isn't available.", - "For example, if you wanted an element to use the \"Helvetica\" font, but also degrade to the \"Sans-Serif\" font when \"Helvetica\" wasn't available, you could do use this CSS style: p { font-family: \"Helvetica\", \"Sans-Serif\"; }.", - "There are several default fonts that are available in all browsers. These include \"Monospace\", \"Serif\" and \"Sans-Serif\". See if you can set your h2 elements to use \"Lobster\" and degrade to \"Monospace\".", - "Now try commenting out your call to Google Fonts, so that the \"Lobster\" font isn't available. Notice how it degrades to the \"Monospace\" font." - ], - "tests": [ - "assert($('h2').css('font-family').match(/lobster/i), 'Your h2 element should use the font \"Lobster\".')", - "assert($('h2').css('font-family').match(/monospace/i), 'Your h2 element should degrade to the font \"Monospace\" when \"Lobster\" is not available.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08809", - "name": "Using Important to Override Styles", - "difficulty": 0.025, - "description": [ - "Create a \"blue-text\" class that gives an element the font-color of blue. Also create a \"urgently-red\" class that give an element the font-color of red, but use !important to ensure the element is rendered as being red. Apply both classes to your h2 element.", - "Sometimes HTML elements will receive conflicting information from CSS classes as to how they should be styled.", - "If there's a conflict in the CSS, the browser will use whichever style declaration is closest to the bottom of the CSS document (whichever declaration comes last). Note that in-line style declarations are the final authority in how an HTML element will be rendered.", - "There's one way to ensure that an element is rendered with a certain style, regardless of where that declaration is located. That one way is to use !important.", - "In case you're curious, this is the priority hierarchy for element styles: !important > inline style > css class selector > css selector. That is, !important trumps all other styles, and inline styles trump style tag declarations.", - "Here's an example of a CSS style that uses !important: <style> .urgently-blue { color: blue !important; } </style>.", - "Now see if you can make sure the h2 element is rendered in the color red without removing the \"blue-text\" class, doing an in-line styling, or changing the sequence of CSS class declarations." - ], - "tests": [ - "assert($('h2').hasClass('blue-text'), 'Your h2 element should have the class \"blue-text\".')", - "assert($('h2').hasClass('urgently-red'), 'Your h2 element should have the class \"urgently-red\".')", - "assert($('h2').css('color') === 'rgb(255, 0, 0)', 'Your h2 element should be red.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - - { - "_id": "bad87fee1348bd9aedf08812", - "name": "Add an Image to your Website", - "difficulty": 0.026, - "description": [ - "Use an img element to add the image http://bit.ly/fcc-kittens to your website.", - "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.", - "Try it with this image: http://bit.ly/fcc-kittens." - ], - "tests": [ - "assert($('img').length > 0, 'Your webpage should have an image element.')", - "assert(!!$('img').attr('src'), 'Your image should have have a src attribute that points to the kitten image.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9acdf08812", - "name": "Specify an Image Size", - "difficulty": 0.027, - "description": [ - "Create a class called smaller-image and use it to resize the image so that it's only 100 pixels wide.", - "CSS has an attribute called width that controls an element's width. Just like with fonts, we'll use pixels(px) to specify the images width.", - "For example, if we wanted to create a CSS class called \"larger-image\" that gave HTML elements a width of 500 pixels, we'd use: <style> .larger-image { width: 500px; } </style>." - ], - "tests": [ - "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", - "assert($('img').width() === 100, 'Your image should be 100 pixels wide.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9bedf08813", - "name": "Add a Border Around an Element", - "difficulty": 0.028, - "description": [ - "Create a class called \"thick-green-border\" that puts a 10-pixel-wide green border around an HTML element, and apply it to your cat photo.", - "CSS borders have attributes like style, color and width.", - "For example, if we wanted to create a red, 5 pixel border around an HTML element, we could use this class: <style> .thin-red-border { border-color: red; border-width: 5px; border-style: solid; } </style>." - ], - "tests": [ - "assert($('img').hasClass('smaller-image'), 'Your img element should have the class \"smaller-image\".')", - "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", - "assert(parseInt($('img').css('border-left-width')) > 8, 'Your image should have a border with a width of 10 pixels.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08814", - "name": "Add Rounded Corners with a Border Radius", - "difficulty": 0.029, - "description": [ - "Give your cat photo a border radius of 10 pixels.", - "Your cat photo currently has sharp corners. We can round out those corners with a CSS attribute called border-radius.", - "You can specify a border-radius with pixels. This will affect how rounded the corners are. Add this attribute to your thick-green-border class and set it to 10 pixels." - ], - "tests": [ - "assert($('img').hasClass('thick-green-border'), 'Your image element should have the class \"thick-green-border\".')", - "assert(parseInt($('img').css('border-top-left-radius')) > 8, 'Your image should have a border radius of 10 pixels')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08815", - "name": "Make an Image Circular with a Border Radius", - "difficulty": 0.030, - "description": [ - "Give your cat photo a border-radius of 50%.", - "In addition to pixels, you can also specify a border-radius using a percentage." - ], - "tests": [ - "assert(parseInt($('img').css('border-top-left-radius')) > 48, 'Your image should have a border radius of 50 percent, making it perfectly circular.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08816", - "name": "Use an Anchor Tag to Link to an External Page", - "difficulty": 0.031, - "description": [ - "Create an anchor element that links to http://catphotoapp.com and has \"cat photos\" as its anchor text (link text).", - "Here's a diagram of an anchor tag. In this case, it's used in the middle of a paragraph element, which means your link will appear in the middle of your sentence.", - "a diagram of how anchor tags are composed with the same text as on the following line", - "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>" - ], - "tests": [ - "assert((/photo/gi).test($('a').text()), 'You need an anchor element that links to \"catphotoapp.com\".')", - "assert($('a').filter(function(index) { return /photo/gi.test($('a')[index]); }).length === 1, 'Your anchor element should have the anchor text of \"See my cat photos\"')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aede08817", - "name": "Wrap an Anchor Element within a Paragraph", - "difficulty": 0.032, - "description": [ - "Now wrap your anchor element within a paragraph element so that the surrounding paragraph says \"click here for cat photos\", but where only \"cat photos\" is a link - the rest is plain text.", - "Again, here's a diagram of an anchor tag for your reference:", - "a diagram of how anchor tags are composed with the same text as on the following line", - "Here's an example: <p>Here's a <a href='http://freecodecamp.com'> link to Free Code Camp</a> for you to follow.</p>" - ], - "tests": [ - "assert((/photo/gi).test($('a').text()), 'You need an anchor element that links to \"catphotoapp.com\".')", - "assert($('a').filter(function(index) { return /photo/gi.test($('a')[index]); }).length === 1, 'Your anchor element should have the anchor text of \"See my cat photos\"')", - "assert($('a').parent().is('p'), 'Your anchor element should be wrapped within a paragraph element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "cat photos", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - - { - "_id": "bad87fee1348bd9aedf08817", - "name": "Make Dead Links using the Hash Symbol", - "difficulty": 0.033, - "description": [ - "Use the hash symbol(#) to turn your anchor element's link into a dead link.", - "Sometimes you want to add anchor elements to your website before you know where they will link.", - "This is also handy when you're changing the behavior of a link using jQuery, which we'll learn about later.", - "Replace your anchor element's href attribute with a hash symbol to turn it into a dead link." - ], - "tests": [ - "assert($('a').attr('href') === '#', 'Your anchor element should be a dead link with a href attribute set to \"#\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08820", - "name": "Turn an Image into a Link", - "difficulty": 0.034, - "description": [ - "Wrap your img element inside an anchor element with a dead link.", - "You can make elements into links by wrapping them in an anchor tag.", - "Wrap your image in an anchor tag. Here's an example: <a href='#'><img src='http://bit.ly/fcc-kittens2'></a>", - "Remember to use the hash symbol as your anchor tag's href property in order to turn it into a dead link.", - "Once you've done this, hover over your image with your cursor. Your cursor's normal pointer should become the link clicking pointer. The photo is now a link." - ], - "tests": [ - "assert($('a').filter(function(index) { return /#/gi.test($('a')[index]); }).length > 1, 'Wrap your image element inside an anchor element that has its href attribute set to \"#\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08818", - "name": "Add Alt Text to an image", - "difficulty": 0.035, - "description": [ - "Add the alt text \"A cute orange cat lying on its back\" to our cat photo", - "alt text is what browsers will display if they fail to load the image. alt text is also important for blind or visually impaired users to understand what an image portrays. Search engines also look at alt text.", - "In short, every image should have alt text!", - "Alt text is a useful way to tell people (and web crawlers like Google) what is pictured in a photo. It's extremely important for helping blind or visually impaired people understand the content of your website.", - "You can add alt text right in the img element like this: <img src=\"www.your-image-source.com/your-image.jpg\" alt=\"your alt text\"/>." - ], - "tests": [ - "assert($('img').filter(function(){ return /cat/gi.test(this.alt) }).length > 0, 'Your image element should have an alt attribute set to \"A cute orange cat lying on its back\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08827", - "name": "Create a Bulleted Unordered List", - "difficulty" : 0.036, - "description": [ - "Replace the paragraph elements with an unordered list of three things that cats love.", - "HTML has a special element for creating unordered lists, or bullet point-style lists.", - "Unordered lists start with a <ul> element. Then they contain some number of <li> elements.", - "For example: <ul><li>milk</li><li>cheese</li><ul> would create a bulleted list of \"milk\" and \"cheese\"." - ], - "tests": [ - "assert($('ul').length > 0, 'Create a ul element.')", - "assert($('li').length > 2, 'Add three li elements to your ul element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Kitty ipsum dolor sit amet, shed everywhere shed everywhere stretching attack your ankles chase the red dot, hairball run catnip eat the grass sniff.

        ", - "

        Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.

        " - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08828", - "name": "Create an Ordered List", - "difficulty" : 0.037, - "description": [ - "Create an ordered list of the the top 3 things cats hate the most.", - "HTML has a special element for creating ordered lists, or numbered-style lists.", - "Ordered lists start with a <ol> element. Then they contain some number of <li> elements.", - "For example: <ol><li>hydrogen</li><li>helium</li><ol> would create a numbered list of \"hydrogen\" and \"helium\"." - ], - "tests": [ - "assert($('ul').length > 0, 'You should have an ul element on your webpage.')", - "assert($('ol').length > 0, 'You should have an ol element on your webpage.')", - "assert($('li').length > 5, 'You should have three li elements on within your ul element.')", - "assert($('li').length > 5, 'You should have three li elements on within your ol element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        " - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08829", - "name": "Create a Text Field", - "difficulty" : 0.038, - "description": [ - "Now we'll create a web form. Create a text field under your lists.", - "Text inputs are a convenient way to get input from your user.", - "You can create one like this: <input type='text'>" - ], - "tests": [ - "assert($('input[type=\"text\"').length > 0, 'Your webpage should have an text field input element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        " - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08830", - "name": "Add Placeholder Text to a Text Field", - "difficulty" : 0.039, - "description": [ - "Add the placeholder text \"type a cat photo URL here\" to your text field.", - "Placeholder text will appear in your text field before your user has inputed anything.", - "For example: <input type='text' placeholder='this is placeholder text'>" - ], - "tests": [ - "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"cat photo URL\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aede08830", - "name": "Create a basic Form Element", - "difficulty" : 0.040, - "description": [ - "Wrap your text field in a <form> element. Add the action=\"/submit-cat-photo\" attribute to this form element.", - "You can build web forms that actually submit data to a server using nothing more than pure HTML. You can do this by specifying an action on your form element.", - "For example: <form action=\"/url-where-you-want-to-submit-form-data\"></form>" - ], - "tests": [ - "assert($('form').length > 0, 'Wrap your text input element within a form element.')", - "assert($('form').attr('action'), 'Your form element should have an action attribute.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedd08830", - "name": "Add a Submit Button to a Form", - "difficulty" : 0.041, - "description": [ - "Add a submit button to your form field.", - "Let's add a submit button to your form. Clicking this button will send the date from your form to the URL you specified with your form's action attribute.", - "Here's an example submit button: <button type='submit'>this button submits the form</button>" - ], - "tests": [ - "assert($('button').length > 0, 'Your form should have a button inside it.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedc08830", - "name": "Use HTML5 to Make a Field Required", - "difficulty" : 0.042, - "description": [ - "Make it required for your user to input text into your form before being able to submit it.", - "You can require your user to complete specific form fields before they will be able to submit your form.", - "For example, if you wanted to make a text input field required, you can just add the word \"required\" within your input element use: <input type='text' required>" - ], - "tests": [ - "assert($('input').prop('required'), 'Your text field have the property of being required.')", - "assert($('[placeholder]').length > 0, 'Your text field should have the placeholder text of \"cat photo URL\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08834", - "name": "Create a Set of Radio Buttons", - "difficulty" : 0.043, - "description": [ - "Add to your form a pair of radio buttons that are wrapped in label elements and share a name attribute, with the options of \"indoor\" and \"outdoor\".", - "You can use radio buttons for questions where you want the user to only give you one answer.", - "Radio buttons are a type of input.", - "Radio buttons should be wrapped within label elements.", - "All related radio buttons should have the same name attribute.", - "Here's an example of a radio button: <label><input type='radio' name='indoor-outdoor'> Indoor</label>" - ], - "tests": [ - "assert($('input[type=\"radio\"').length > 1, 'Your webpage should have two radio button elements.')", - "assert($('input[type=\"radio\"').attr('name'), 'Both of your radio button should have name attributes with the same value.')", - "assert($('label').length > 1, 'Each of your two radio button elements should be wrapped in a label element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08835", - "name": "Create a Set of Checkboxes", - "difficulty" : 0.044, - "description": [ - "Add to your form a set of three checkbox elements that are wrapped in label elements and share the same name attribute.", - "Forms commonly use checkbox elements for questions that may have more than one answer.", - "For example: <label><input type='checkbox' name='personality'> Loving</label>" - ], - "tests": [ - "assert($('input[type=\"checkbox\"').length > 2, 'Your webpage should have three checkbox elements.')", - "assert($('label').length > 2, 'Each of your three checkbox elements should be wrapped in a label element.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aede08835", - "name": "Clean up your form using Linebreaks", - "difficulty" : 0.045, - "description": [ - "Clean up your form by adding linebreaks between form elements.", - "Remember that you can create a linebreak element by using the code: <br>" - ], - "tests": [ - "assert($('br').length > 1, 'Add at least 2 line breaks to visually separate your form elements.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedd08835", - "name": "Check Radio Buttons and Checkboxes by Default", - "difficulty" : 0.046, - "description": [ - "Set one of your radio buttons and one of your checkboxes to be checked by default.", - "" - ], - "tests": [ - "assert($('input[type=\"radio\"').prop('checked'), 'One of the radio buttons on your form should be checked by default.')", - "assert($('input[type=\"checkbox\"').prop('checked'), 'One of the checkboxes on your form should be checked by default.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id": "bad87fee1348bd9acde08812", - "name": "Use Bootstrap for Responsive Images", - "difficulty": 0.047, - "description": [ - "Add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to the image.", - "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", - "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", - "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", - "Now all you need to do is add the img-responsive class to your image." - ], - "tests": [ - "assert($('img').hasClass('img-responsive'), 'Your new image should have the class \"img-responsive\"')", - "assert($('img').length > 1, 'You should add an image with the src of \"http://bit.ly/fcc-kittens2\"')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad87fee1348bd8acde08812", - "name": "Center Text with Bootstrap", - "difficulty": 0.048, - "description": [ - "Add Bootstrap's text-center class to your h2 element.", - "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note 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>." - ], - "tests": [ - "assert($('h2').hasClass('text-center'), 'Your h2 element should be centered by applying the class \"text-center\"')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id": "bad87fee1348cd8acdf08812", - "name": "Create a Bootstrap Button", - "difficulty": 0.049, - "description": [ - "Create a new button below your large kitten photo with the class \"btn\" and the text of \"like this photo\".", - "Bootstrap has its own button styles, which look much better than the plain HTML ones." - ], - "tests": [ - "assert($('.btn').length > 0, 'your new button should have the class \"btn\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad87fee1348cd8acef08812", - "name": "Create a Block Element Bootstrap Button", - "difficulty": 0.050, - "description": [ - "Add Bootstrap's btn-block class to your Bootstrap button.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "assert($('.btn-block').length > 0, 'your new button should have the class \"btn-block\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad87fee1348cd8acef08811", - "name": "Color a Bootstrap Button with Button Primary", - "difficulty": 0.051, - "description": [ - "Add Bootstrap's btn-block class to both of your buttons.", - "Normally, your buttons are only as wide as the text they contain. By making them block elements, your button will stretch to fill your page's entire horizontal space.", - "Note that these buttons still need the btn class." - ], - "tests": [ - "assert($('.btn-primary').length > 0, 'your new button should have the class \"btn-primary\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad87fee1348cd8acef08813", - "name": "Color a Bootstrap Button with Button Info", - "difficulty": 0.052, - "description": [ - "Create a new block-level Bootstrap button below your \"like\" button with the text \"Info\", and add Bootstrap's btn-info class to it.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", - "Note that these buttons still need the btn and btn-block classes." - ], - "tests": [ - "assert($('.btn-info').length > 0, 'your new button should have the class \"btn-info\".')", - "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad87fee1348ce8acef08814", - "name": "Warn your Users of a Dangerous Action with the Bootstrap Button Danger Class", - "difficulty": 0.053, - "description": [ - "Create a button with the text \"delete\" and give it the class btn-danger.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", - "Note that this button still needs the btn and btn-block classes." - ], - "tests": [ - "assert($('.btn-danger').length > 0, 'Your new button should have the class \"btn-danger\".')", - "assert($('.btn-block').length > 1, 'Both of your Bootstrap buttons should have the class \"btn-block\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - { - "_id": "bad88fee1348ce8acef08815", - "name": "Use the Bootstrap Grid to Put Elements Side By Side", - "difficulty": 0.054, - "description": [ - "Put the \"like\", \"Info\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"col-xs-4\"> element.", - "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." - ], - "tests": [ - "assert($('.row').length > 0, 'Your new button should be wrapped within a div with the class \"row\".')", - "assert($('.col-xs-4').length > 2, 'Each of your bootstrap buttons should be wrapped in a div with the class \"col-xs-4\".')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "", - "", - "", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedf08845", - "name": "Use Bootstrap Text Primary Class instead of Custom CSS", - "difficulty" : 0.055, - "description": [ - "Delete the following from your style tag: .red-text, p, .smaller-image. Delete the p element with the dead link. Remove your red-text class from your h2 element and instead apply the text-primary Bootstrap class. Replace the smaller-image class on your top image with the img-responsive class." - ], - "tests": [ - "assert(!$('h2').hasClass('red-text'), 'You h2 element should no longer have the class \"red-text\".')", - "assert($('h2').hasClass('text-primary'), 'You h2 element should now have the class \"text-primary\".')", - "assert(!$('p').css('font-family').match(/monospace/i), 'Your paragraph elements should no longer use the font \"Monospace\".')", - "assert($('.img-responsive').length > 1, 'Remove the \"smaller-image\" class from your top image and replace it with the \"img-responsive\" class.')" - ], - "challengeSeed": [ - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "

        Click here for cat photos.

        ", - "", - "", - "", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aede08845", - "name": "Create a Custom Heading", - "difficulty" : 0.056, - "description": [ - "Wrap your first image and your h2 element in a <div class='row'> element. Wrap your h2 text in a <div class='col-xs-8'> and your image in a <div class='col-xs-4'> so that they are on the same line." - ], - "tests": [ - "assert($('.row').length > 1, 'Your h2 and top image elements should both be wrapped together within a div with the class \"row\".')", - "assert($('.col-xs-4').length > 3, 'Wrap your top image inside a div with the class \"col-xs-4\".')", - "assert($('.col-xs-8').length > 0, 'Wrap your h2 element inside a div with the class \"col-xs-8\".')" - ], - "challengeSeed": [ - "", - "", - "", - "", - "

        CatPhotoApp

        ", - "", - "", - "", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedd08845", - "name": "Add Font Awesome Icons to our Buttons", - "difficulty" : 0.057, - "description": [ - "Use Font Awesome to add a \"like\" icon to your like button.", - "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." - ], - "tests": [ - "assert($('.fa-thumbs-up').length > 0, 'You should add a <i class=\"fa fa-thumbs-up\"><i> within your like button element.')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedc08845", - "name": "Add Font Awesome Icons all of our Buttons", - "difficulty" : 0.058, - "description": [ - "Use Font Awesome to add a \"info-circle\" icon to your info button and a \"trash\" button to your delete button.", - "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." - ], - "tests": [ - "assert($('.fa-trash').length > 0, 'You should add a <i class=\"fa fa-trash\"><i> within your like button element.')", - "assert($('.fa-info-circle').length > 0, 'You should add a <i class=\"fa fa-info-circle\"><i> within your like button element.')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aedb08845", - "name": "Use Bootstrap to Responsively Style a Radio Buttons", - "difficulty" : 0.059, - "description": [ - "Wrap all of your radio buttons in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-6'> element." - ], - "tests": [ - "assert($('.row').length > 2, 'Wrap your all of your radio buttons inside one div with the class \"row\".')", - "assert($('.col-xs-6').length > 3, 'Wrap each of your radio buttons inside its own div with the class \"col-xs-6\".')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - " ", - " ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aeda08845", - "name": "Use Bootstrap to Responsively Style Checkboxes", - "difficulty" : 0.060, - "description": [ - "Wrap all your checkboxes in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-4'> element." - ], - "tests": [ - "assert($('.row').length > 3, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", - "assert($('.col-xs-4').length > 6, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - " ", - " ", - " ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aed908845", - "name": "Style a Text Input with the Bootstrap Form Control Class", - "difficulty" : 0.061, - "description": [ - "Give your form's text input field in a class of \"form-control\". Give your form's submit button the classes \"btn btn-primary\" and give it the Font Awesome icon of \"fa-paper-plane\"." - ], - "tests": [ - "assert($('.btn-primary').length > 1, 'Give your form's submit button the classes \"btn btn-primary\".')", - "assert($('.fa-paper-plane').length > 0, 'You should add a <i class=\"fa fa-paper-plane\"><i> within your submit button element.')", - "assert($('.form-control').length > 0, 'Give your form's text input field in a class of \"form-control\".')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id" : "bad87fee1348bd9aec908845", - "name": "Line up Form Elements Responsively with Bootstrap", - "difficulty" : 0.062, - "description": [ - "Wrap both your form's text input field and submit button within a div with the class \"row\". Wrap your form's text input field within a div with the class of \"col-xs-7\". Wrap your form's submit button the in a div with the class \"col-xs-5\"." - ], - "tests": [ - "assert($('.row').length > 4, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", - "assert($('.col-xs-5').length > 0, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')", - "assert($('.col-xs-7').length > 0, 'Wrap each of your checkboxes inside its own div with the class \"col-xs-4\".')" - ], - "challengeSeed": [ - "", - "", - "", - "
        ", - "
        ", - "

        CatPhotoApp

        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "

        Things cats love:

        ", - "
          ", - "
        • cat nip
        • ", - "
        • laser pointers
        • ", - "
        • lasagna
        • ", - "
        ", - "

        Top 3 things cats hate:

        ", - "
          ", - "
        1. flea treatment
        2. ", - "
        3. thunder
        4. ", - "
        5. other cats
        6. ", - "
        ", - "
        ", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - " ", - "
        ", - "
        ", - "
        ", - " ", - " ", - "" - ] - }, - - { - "_id": "bad88fee1348bd9aedf08825", - "name": "Adjusting the Padding of an Element", - "difficulty": 0.064, - "description": [ - "Change the padding of the green box to match that of the red box.", - "An element's padding controls the amount of space between an element and its border.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", - "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding', '20px')" - ], - "challengeSeed": [ - "", - "
        margin
        ", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08822", - "name": "Adjust the Margin of an Element", - "difficulty": 0.065, - "description": [ - "Change the margin of the green box to match that of the red box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", - "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '20px')" - ], - "challengeSeed": [ - "", - "
        margin
        ", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08823", - "name": "Add a Negative Margin to an Element", - "difficulty": 0.066, - "description": [ - "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "If you set an element's margin to a negative value, the element will grow larger.", - "Try to set the margin to a negative value like the one for the red box." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '-15px')" - ], - "challengeSeed": [ - "", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08824", - "name": "Add Different Padding to Each Side of an Element TEST", - "difficulty": 0.067, - "description": [ - "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has different padding on each of its sides.", - "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding-bottom', '20px')", - "expect($('.green-box')).to.have.css('padding-left', '40px')" - ], - "challengeSeed": [ - "", - "
        margin
        ", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - { - "_id": "bad87fee1248bd9aedf08824", - "name": "Add Different a Margin to Each Side of an Element TEST", - "difficulty": 0.068, - "description": [ - "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", - "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
        margin
        ", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - { - "_id": "bad87fee1348bd9aedf08826", - "name": "Use Clockwise Notation to Specify an Element's Padding", - "difficulty": 0.069, - "description": [ - "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", - "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", - "You can also use this notation for margins!" - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
        margin
        ", - "", - "
        ", - "
        padding
        ", - "
        padding
        ", - "
        " - ] - }, - - { - "_id": "bad87fee1348bd9aede08826", - "name": "Use Hex Codes for Precise Colors", - "difficulty": 0.070, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aedd08826", - "name": "Use Shortened Hex Codes for Colors", - "difficulty": 0.071, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9acdd08826", - "name": "Learn how Script Tags and Document Ready Work", - "difficulty": 0.072, - "description": [ - "Test" - ], - "tests": [ - "assert($('#target').hasClass('disabled'), 'The button with the ID of \"target\" should continue to have the \"disabled\" class.')", - "assert(!!$('#target[disabled]'), 'Enable the button with the ID of \"target\" by using jQuery.')", - "expect($('#target')).to.exist()" - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $('#target').attr('disabled', true)", - " });", - "fcces", - "" - ] - }, - - { - "_id": "bad87fee1348bd9aedc08826", - "name": "Target Elements by Selectors Using jQuery", - "difficulty": 0.073, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aedb08826", - "name": "Target Elements by Class Using jQuery", - "difficulty": 0.074, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aeda08826", - "name": "Target an element by ID Using jQuery", - "difficulty": 0.075, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed908826", - "name": "Change the CSS of an Element Using jQuery", - "difficulty": 0.076, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed808826", - "name": "Disable an Element Using jQuery", - "difficulty": 0.077, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed708826", - "name": "Remove an Element Using jQuery", - "difficulty": 0.078, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed608826", - "name": "Move an Element Using jQuery", - "difficulty": 0.079, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed508826", - "name": "Clone an Element Using jQuery", - "difficulty": 0.080, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed408826", - "name": "Animate an Element Using jQuery", - "difficulty": 0.081, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed308826", - "name": "Target the Parent of an Element Using jQuery", - "difficulty": 0.082, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed208826", - "name": "Target the Children of an Element Using jQuery", - "difficulty": 0.083, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - - { - "_id": "bad87fee1348bd9aed108826", - "name": "Target a Specific Child of an Element Using jQuery", - "difficulty": 0.084, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aed008826", - "name": "Target Even Numbered Elements Using jQuery", - "difficulty": 0.085, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aecc08826", - "name": "Read Data from an Element Using jQuery", - "difficulty": 0.086, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9aebc08826", - "name": "Get Data from an URL Using jQuery", - "difficulty": 0.087, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9ae9c08826", - "name": "Loop through JSON Data Using jQuery", - "difficulty": 0.089, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bad87fee1348bd9ae8c08826", - "name": "Setup Click Events Using jQuery", - "difficulty": 0.089, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] - }, - - { - "_id": "bd7123d8c441eddfaeb5bdef", - "name": "Learn Basic Computer Science", - "difficulty": 0.90, - "challengeSeed": "114628241", - "description": [ - "Stanford has an excellent free online Computer Science curriculum. This interactive course uses a modified version of JavaScript. It will cover a lot of concepts quickly.", - "Note that Harvard also has an excellent introduction to computer science course called CS50, but it takes more than 100 hours to complete, and doesn't use JavaScript.", - "Despite being completely self-paced, Stanford's CS101 course is broken up into weeks. Each of the following challenges will address one of those weeks.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z54/z1/ and complete the first week's course work." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd8124d8c441eddfaeb5bdef", - "name": "Learn Loops", - "difficulty": 0.19, - "challengeSeed": "114597348", - "description": [ - "Now let's tackle week 2 of Stanford's Intro to Computer Science course.", - "This will introduce us to loops, a fundamental feature of every programming language.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z100/a7a70ce6e4724c58862ee6007284face/ and complete Week 2." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd8125d8c441eddfaeb5bdef", - "name": "Learn Computer Hardware", - "difficulty": 0.20, - "challengeSeed": "114597347", - "description": [ - "Week 3 of Stanford's Intro to Computer Science covers computer hardware and explains Moore's law of exponential growth in the price-performance of processors.", - "This challenge will also give you an understanding of how bits and bytes work.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z143/z101/ and complete Week 3." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd8126d8c441eddfaeb5bdef", - "name": "Learn Computer Networking", - "difficulty": 0.21, - "challengeSeed": "114604811", - "description": [ - "Now that you've learned about computer hardware, it's time to learn about the software that runs on top of it.", - "Particularly important, you will learn about networks and TCP/IP - the protocol that powers the internet.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z187/z144/ and complete Week 4." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd8127d8c441eddfaeb5bdef", - "name": "Learn Boolean Logic", - "difficulty": 0.22, - "challengeSeed": "114604812", - "description": [ - "Now we'll do some more table exercises and learn boolean logic.", - "We'll also learn the difference between digital data and analog data.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z208/z188/ and complete Week 5." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd8128d8c441eddfaeb5bdef", - "name": "Learn Computer Security", - "difficulty": 0.23, - "challengeSeed": "114604813", - "description": [ - "We're almost done with Stanford's Introduction to Computer Science course!", - "We'll learn about one of the most important inventions of the 20th century - spreadsheets.", - "We'll also learn about Computer Security and some of the more common vulnerabilities software systems have.", - "Go to https://class.stanford.edu/courses/Engineering/CS101/Summer2014/courseware/z229/z213/ and complete Week 6, the final week of the course." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7129d8c441eddfaeb5bdef", - "name": "Build an Adventure Game", - "difficulty": 0.24, - "challengeSeed": "114604814", - "description": [ - "Now that you understand some Computer Science fundamentals, let's focus on programming JavaScript!", - "We're going to work through Codecademy's famous interactive JavaScript course.", - "This course will teach us some JavaScript fundamentals while guiding us through the process of building interesting web apps, all within Codecademy's learner-friendly environment!", - "Go to http://www.codecademy.com/courses/getting-started-v2/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-x9DnD/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7130d8c441eddfaeb5bdef", - "name": "Build Rock Paper Scissors", - "difficulty": 0.25, - "challengeSeed": "114604815", - "description": [ - "Now we'll learn how JavaScript functions work, and use them to build a simple Rock Paper Scissors game.", - "Go to http://www.codecademy.com/courses/javascript-beginner-en-6LzGd/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-Bthev-mskY8/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7131d8c441eddfaeb5bdef", - "name": "Learn JavaScript For Loops", - "difficulty": 0.26, - "challengeSeed": "114614220", - "description": [ - "Let's learn more about the loops that make virtually all programs possible - the \"For Loop\" and \"While Loop\". First, we'll learn the For Loop.", - "Go to http://www.codecademy.com/courses/javascript-beginner-en-NhsaT/0/1web and complete both the both For and While loop section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-XEDZA/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7132d8c441eddfaeb5bdef", - "name": "Learn JavaScript While Loops", - "difficulty": 0.27, - "challengeSeed": "114612889", - "description": [ - "Go to http://www.codecademy.com/courses/javascript-beginner-en-ASGIv/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-mrTNH-6VIZ9/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7133d8c441eddfaeb5bdef", - "name": "Learn Control Flow", - "difficulty": 0.28, - "challengeSeed": "114612888", - "description": [ - "Much of human reasoning can be broken down into what we call Boolean Logic. Lucky for us, computers can think the same way! Let's learn how to instruct our computers by writing \"If Statements\" and \"Else Statements\".", - "We'll also learn some advanced \"Control Flow\" principals, such as ways we can exit loops early.", - "Go to http://www.codecademy.com/courses/javascript-beginner-en-qDwp0/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-ZA2rb/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7134d8c441eddfaeb5bdef", - "name": "Build a Contact List", - "difficulty": 0.29, - "challengeSeed": "114612887", - "description": [ - "Up to this point, you've been working mostly with strings and numbers. Now we're going to learn more complicated data structures, like \"Arrays\" and \"Objects\".", - "Go to http://www.codecademy.com/courses/javascript-beginner-en-9Sgpi/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-3bmfN/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7135d8c441eddfaeb5bdef", - "name": "Build an Address Book", - "difficulty": 0.30, - "challengeSeed": "114612885", - "description": [ - "Let's learn more about objects.", - "Go to http://www.codecademy.com/courses/spencer-sandbox/0/1 and complete the section.", - "Be sure to also complete this section: http://www.codecademy.com/courses/building-an-address-book/0/1?curriculum_id=506324b3a7dffd00020bf661." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7136d8c441eddfaeb5bdef", - "name": "Build a Cash Register", - "difficulty": 0.31, - "challengeSeed": "114612882", - "description": [ - "In this final Codecademy section, we'll learn even more about JavaScript objects.", - "Go to http://www.codecademy.com/courses/objects-ii/0/1 and complete this section.", - "Be sure to also complete the final section: http://www.codecademy.com/courses/close-the-super-makert/0/1." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7118d8c441eddfaeb5bdef", - "name": "Discover Chrome's DevTools", - "difficulty": 0.32, - "challengeSeed": "110752743", - "description": [ - "It's time to learn the most powerful tool your browser has - the Development Tools!", - "If you aren't already using Chrome, you'll want to download it here: http://www.google.com/chrome/. While it's true that Firefox has a tool called Firebug that is very similar to Chrome's DevTools, we will use Chrome for this challenge.", - "Note that this course, jointly produced by Google and Code School, is technologically impressive, but occasionally buggy. If you encounter a bug, just ignore it and keep going.", - "Go to http://discover-devtools.codeschool.com and complete this short course." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7138d8c441eddfaeb5bdef", - "name": "Learn Regular Expressions", - "difficulty": 0.33, - "challengeSeed": "112547802", - "description": [ - "You can use a Regular Expression, or \"Regex\", to select specific types of characters in text.", - "Check out http://www.regexr.com. It's a Regular Expression Sandbox.", - "Now go to http://www.regexone.com and complete the tutorial and exercises 1 - 6.", - "Note that you can click \"continue\" to move on to the next step as soon as all the tasks have green check marks beside them. You can often do this just by using the wildcard \"dot\" operator, but try to use the techniques that each lesson recommends." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7154d8c441eddfaeb5bdef", - "name": "Get Started with Angular.js", - "difficulty": 0.34, - "challengeSeed": "114684726", - "description": [ - "Code School has a short, free Angular.js course. This will give us a quick tour of Angular.js's mechanics and features.", - "In this course, we'll build a virtual shop entirely in Angular.js.", - "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/1/section/1/video/1 and complete the section." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7155d8c441eddfaeb5bdef", - "name": "Apply Angular.js Directives", - "difficulty": 0.35, - "challengeSeed": "114684727", - "description": [ - "Directives serve as markers in your HTML. When Angular.js compiles your HTML, it will can alter the behavior of DOM elements based on the directives you've used.", - "Let's learn how these powerful directives work, and how to use them to make your web apps more dynamic", - "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/2/section/1/video/1 and complete the section." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7156d8c441eddfaeb5bdef", - "name": "Power Forms with Angular.js", - "difficulty": 0.36, - "challengeSeed": "114684729", - "description": [ - "One area where Angular.js really shines is its powerful web forms.", - "Learn how to create reactive Angular.js forms, including real-time form validation.", - "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/3/section/1/video/1 and complete the section." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7157d8c441eddfaeb5bdef", - "name": "Customize Angular.js Directives", - "difficulty": 0.37, - "challengeSeed": "114685062", - "description": [ - "Now we'll learn how to modify existing Angular.js directives, and even build directives of your own.", - "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/4/section/1/video/1 and complete the section." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7158d8c441eddfaeb5bdef", - "name": "Create Angular.js Services", - "difficulty": 0.38, - "challengeSeed": "114685060", - "description": [ - "Services are functions that you can use and reuse throughout your Angular.js app to get things done.", - "We'll learn how to use services in this final Code School Angular.js challenge.", - "Go to http://campus.codeschool.com/courses/shaping-up-with-angular-js/level/5/section/1/video/1 and complete the section." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7153d8c441eddfaeb5bd0f", - "name": "Manage Packages with NPM", - "difficulty": 0.39, - "challengeSeed": "126433450", - "description": [ - "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", - "If you don't already have Cloud 9 account, create one now at http://c9.io.", - "Open up http://c9.io and sign in to your account.", - "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", - "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", - "Click the \"Start Editing\" button.", - "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", - "Run this command: sudo npm install how-to-npm -g", - "Now start this tutorial by running how-to-npm", - "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through all of the the tutorial's steps before moving on." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7153d8c441eddfaeb5bdff", - "name": "Start a Node.js Server", - "difficulty": 0.40, - "challengeSeed": "126411561", - "description": [ - "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", - "If you don't already have Cloud 9 account, create one now at http://c9.io.", - "Open up http://c9.io and sign in to your account.", - "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", - "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", - "Click the \"Start Editing\" button.", - "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", - "Run this command: sudo npm install learnyounode -g", - "Now start this tutorial by running learnyounode", - "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through all of the the tutorial's steps before moving on." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7153d8c441eddfaeb5bd1f", - "name": "Build Web Apps with Express.js", - "difficulty": 0.41, - "challengeSeed": "126411559", - "description": [ - "We'll build this Waypoint on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", - "If you don't already have Cloud 9 account, create one now at http://c9.io.", - "Open up http://c9.io and sign in to your account.", - "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", - "Give your workspace a name.", - "Choose Node.js in the selection area below the name field", - "Click the Create button", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button", - "Click the \"Start Editing\" button.", - "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", - "Run this command: git clone http://github.com/reddock/fcc_express && chmod 744 fcc_express/setup.sh && fcc_express/setup.sh && source ~/.profile", - "Now start this tutorial by running expressworks", - "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through all of the the tutorial's steps before moving on." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7140d8c441eddfaeb5bdef", - "name": "Manage Source Code with Git", - "difficulty": 0.43, - "challengeSeed": "114635309", - "description": [ - "Version Control Systems like Git ensure that, no matter how you experiment with your code, you can always roll back your app to a stable previous state.", - "Git is also a great way to share and contribute to open source software.", - "Go to https://www.codeschool.com/courses/try-git and complete this short interactive course." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7139d8c441eddfaeb5bdef", - "name": "Pair Program on Bonfires", - "difficulty": 0.44, - "challengeSeed": "119657641", - "description": [ - "OK, we're finally ready to start pair programming!", - "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", - "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", - "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", - "We have a special chat room for people ready to pair program. Go to our Slack chatroom and navigate to the #letspair channel and type \"Hello Pair Programmers!\"", - "If someone is available, they will be your \"pair\" - the person you pair programming with.", - "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", - "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", - "Add them as a new contact in Screen Hero, then click the monitor-looking button to attempt to share your screen with them.", - "Once the Screen Hero session starts, your screen's margins will glow orange. You are now sharing your screen.", - "Your pair will have their own cursor, and will be able to type text on his or her and keyboard.", - "Now it's time to tackle our Bonfires.", - "Go to http://freecodecamp.com/bonfires and start working through our Bonfire challenges.", - "Once you you finish pair programming, end the session in Screen Hero session.", - "Congratulations! You have completed your first pair programming session.", - "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", - "Mark this challenge as complete and move on to the Bonfires." - ], - "challengeType": 2, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfbeb5bd1f", - "name": "Get Set for Ziplines", - "difficulty": 1.00, - "challengeSeed": "125658022", - "description": [ - "Now you're ready to start our Zipline challenges. These front-end development challenges will give you many opportunities to apply the HTML, CSS, jQuery and JavaScript you've learned to build static (database-less) applications.", - "For many of these challenges, you will be using JSON data from external API endpoints, such as Twitch.tv and Twitter. Note that you don't need to have a database to use these data.", - "The easiest way to manipulate these data is with jQuery $.getJSON().", - "Whatever you do, don't get discouraged! Remember to use RSAP if you get stuck.", - "We'll build these challenges using CodePen, a popular tool for creating, sharing, and discovering static web applications.", - "Go to http://codepen.io and create an account.", - "Click your user image in the top right corner, then click the \"New pen\" button that drops down.", - "Drag the windows around and press the buttons in the lower-right hand corner to change the orientation to suit your preference.", - "Click the gear next to CSS. Then in the \"External CSS File or Another Pen\" text field, type \"bootstrap\" and scroll down until you see the latest version of Bootstrap. Click it.", - "Verify that bootstrap is active by adding the following code to your HTML: <h1 class='text-primary'>Hello CodePen!</h1>. The text's color should be Bootstrap blue.", - "Click the gear next the JavaScript. Click the \"Latest version of...\" select box and choose jQuery.", - "Now add the following code to your JavaScript: $(document).ready(function() { $('.text-primary').text('Hi CodePen!') });. Click the \"Save\" button at the top. Your \"Hello CodePen!\" should change to \"Hi CodePen!\". This means that jQuery is working.", - "Now you're ready for your first Zipline. 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." - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd1f", - "name": "Zipline: Use the Twitch.tv JSON API", - "difficulty": 1.01, - "challengeSeed": "126411564", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/GJKRxZ.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can see whether Free Code Camp is currently streaming on Twitch.tv.", - "User Story: As a user, I can click the status output and be sent directly to the Free Code Camp's Twitch.tv channel.", - "User Story: As a user, if Free Code Camp is streaming, I can see additional details about what they are streaming.", - "Bonus User Story: As a user, I can search through the streams listed.", - "Hint: Here's an example call to Twitch.tv's JSON API: https://api.twitch.tv/kraken/streams/freecodecamp.", - "Hint: The relevant documentation about this API call is here: https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel.", - "Hint: Here's an array of the Twitch.tv usernames of people who regularly stream coding: [\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd13", - "name": "Zipline: Build a Random Quote Machine", - "difficulty": 1.02, - "challengeSeed": "126415122", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/vEoVMw.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can click a button to show me a new random quote.", - "Bonus User Story: As a user, I can press a button to tweet out a quote.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd10", - "name": "Zipline: Show the Local Weather", - "difficulty": 1.03, - "challengeSeed": "126415127", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/AdventureBear/full/yNBJRj.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can see the weather in my current location.", - "Bonus User Story: As a user, I can see an icon depending on the temperature..", - "Bonus User Story: As a user, I see a different background image depending on the temperature (e.g. snowy mountain, hot desert).", - "Bonus User Story: As a user, I can push a button to toggle between Fahrenheit and Celsius.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd18", - "name": "Zipline: Stylize Stories on Camper News", - "difficulty": 1.04, - "challengeSeed": "126415129", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/Wveezv.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can browse recent posts from Camper News.", - "User Story: As a user, I can click on a post to be taken to the story's original URL.", - "User Story: As a user, I can click a link to go directly to the post's discussion page.", - "Bonus User Story: As a user, I can see how many upvotes each story has.", - "Hint: Here's the Camper News Hot Stories API endpoint: http://www.freecodecamp.com/stories/hotStories.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd19", - "name": "Zipline: Wikipedia Viewer", - "difficulty": 1.05, - "challengeSeed": "126415131", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/MwgQea.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can search Wikipedia entries in a search box and see the resulting Wikipedia entries.", - "Bonus User Story:As a user, I can click a button to see a random Wikipedia entry.", - "Bonus User Story:As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.", - "Hint: Here's an entry on using Wikipedia's API: http://www.mediawiki.org/wiki/API:Main_page.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd0f", - "name": "Zipline: Build a Pomodoro Clock", - "difficulty": 1.06, - "challengeSeed": "126411567", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/RPbGxZ/.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can start a 25 minute pomodoro, and the timer will go off once 25 minutes has elapsed.", - "Bonus User Story: As a user, I can reset the clock for my next pomodoro.", - "Bonus User Story: As a user, I can customize the length of each pomodoro.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd17", - "name": "Zipline: Build a JavaScript Calculator", - "difficulty": 1.07, - "challengeSeed": "126411565", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/GeoffStorbeck/full/zxgaqw.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can add, subtract, multiply and divide two numbers.", - "Bonus User Story: I can clear the input field with a clear button.", - "Bonus User Story: I can keep chaining mathematical operations together until I hit the clear button, and the calculator will tell me the correct output.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c442eddfaeb5bd1c", - "name": "Zipline: Build a Tic Tac Toe Game", - "difficulty": 1.08, - "challengeSeed": "126415123", - "description": [ - "Objective: Build a CodePen.io that successfully reverse-engineers this: http://codepen.io/alex-dixon/full/JogOpQ/.", - "Rule #1: Don't look at the example project's code. 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.", - "Here are the user stories you must enable, and optional bonus user stories:", - "User Story: As a user, I can play a game of Tic Tac Toe with the computer.", - "Bonus User Story: As a user, I can never actually win against the computer - at best I can tie.", - "Bonus User Story: As a user, my game will reset as soon as it's over so I can play again.", - "Bonus User Story: As a user, I can choose whether I want to play as X or O.", - "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" - ], - "challengeType": 3, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bcef", - "name": "Get Set for Basejumps", - "difficulty": 2.00, - "challengeSeed": "128451852", - "description": [ - "Objective: Get the MEAN stack running on Cloud 9, push your code to GitHub, and deploy it to Heroku.", - "We'll build our Basejumps on Cloud 9, a powerful online code editor with a full Ubuntu Linux workspace, all running in the cloud.", - "If you don't already have Cloud 9 account, create one now at http://c9.io.", - "Now let's get your development environment ready for a new Angular-Fullstack application provided by Yeoman.", - "Open up http://c9.io and sign in to your account.", - "Click on Create New Workspace at the top right of the c9.io page, then click on the \"Create a new workspace\" popup that appears below it the button after you click on it.", - "Give your workspace a name.", - "Choose Node.js in the selection area below the name field.", - "Click the Create button.", - "Wait for the workspace to finish processing and select it on the left sidebar, below the Create New Workspace button.", - "Click the \"Start Editing\" button.", - "In the lower right hand corner you should see a terminal window. In this window use the following commands. You don't need to know what these mean at this point.", - "Never run this command on your local machine. But in your Cloud 9 terminal window, run: rm -rf * && echo \"export NODE_PATH=$NODE_PATH:/home/ubuntu/.nvm/v0.10.35/lib/node_modules\" >> ~/.bashrc && source ~/.bashrc && npm install -g yo grunt grunt-cli generator-angular-fullstack && yo angular-fullstack", - "Yeoman will prompt you to answer some questions. Answer them like this:", - "What would you like to write scripts with? JavaScript", - "What would you like to write markup with? HTML", - "What would you like to write stylesheets with? CSS", - "What Angular router would you like to use? ngRoute", - "Would you like to include Bootstrap? Yes", - "Would you like to include UI Bootstrap? Yes", - "Would you like to use MongoDB with Mongoose for data modeling? Yes", - "Would you scaffold out an authentication boilerplate? Yes", - "Would you like to include additional oAuth strategies? Twitter", - "Would you like to use socket.io? No", - "May bower anonymously report usage statistics to improve the tool over time? (Y/n) Y", - "You may get an error similar to ERR! EEXIST, open ‘/home/ubuntu/.npm. This is caused when Cloud9 runs out of memory and kills an install. If you get this, simply re-run this process with the command yo angular-fullstack. You will then be asked a few questions regarding the re-install. Answer them as follows:", - "Existing .yo-rc configuration found, would you like to use it? (Y/n) Y", - "Overwrite client/favicon.ico? (Ynaxdh) Y", - "To finish the installation run the commands: bower install && npm install", - "To start MongoDB, run the following commands in your terminal: mkdir data && echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest \"$@\"' > mongod && chmod a+x mongod && ./mongod", - "You will want to open up a new terminal to work from by clicking on the + icon and select New Terminal", - "Start the application by running the following command in your new terminal window: grunt serve", - "Wait for the following message to appear: xdg-open: no method available for opening 'http://localhost:8080' . Now you can open the internal Cloud9 browser. To launch the browser select Preview in the toolbar then select the dropdown option Preview Running Application.", - "Turn the folder in which your application is running into a Git repository by running the following commands: git init && git add . && git commit -am 'initial commit'.", - "Create a new GitHub repository by signing in to http://github.com and clicking on the + button next to your username in the upper-right hand side of your screen, then selecting \"New Repository\".", - "Enter a project name, then click the \"Create Repository\" button.", - "Find the \"...or push an existing repository from the command line\" section and click the Copy to Clipboard button beside it.", - "Paste the commands from your clipboard into the Cloud9 terminal prompt. This will push your changes to your repository on Cloud 9 up to GitHub.", - "Check back on your GitHub profile to verify the changes were successfully pushed up to GitHub.", - "Now let's push your code to Heroku. If you don't already have a Heroku account, create one at http://heroku.com. You shouldn't be charged for anything, but you will need to add your credit card information to your Heroku before you will be able to use Heroku's free MongoLab add on.", - "Before you publish to Heroku, you should free up as much memory as possible on Cloud9. In each of the Cloud9 terminal prompt tabs where MongoDB and Grunt are running, press the control + c hotkey to shut down these processes.", - "Run the following command in a Cloud9 terminal prompt tab: npm install grunt-contrib-imagemin --save-dev && npm install --save-dev && heroku login. At this point, the terminal will prompt you to log in to Heroku from the command line.", - "Now run yo angular-fullstack:heroku. You can choose a name for your Heroku project, or Heroku will create a random one for you. You can choose whether you want to deploy to servers the US or the EU.", - "Set the config flag for your Heroku environment and add MongoLab for your MongoDB instance by running the following command: cd ~/workspace/dist && heroku config:set NODE_ENV=production && heroku addons:add mongolab.", - "As you build your app, you should frequently commit changes to your codebase. Make sure you're in the ~/workspace directory by running cd ~/workspace. Then you can this code to stage the changes to your changes and commit them: git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a short summary of the changes you made to your code, such as \"added a records controller and corresponding routes\".", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Now you're ready to move on to your first Basejump. Click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it." - ], - "challengeType": 4, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bdef", - "name": "Basejump: Build a Voting App", - "difficulty": 2.01, - "challengeSeed": "128451852", - "description": [ - "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://voteplex.herokuapp.com/ and deploy it to Heroku.", - "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", - "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Here are the specific User Stories you should implement for this Basejump:", - "User Story: As an authenticated user, I can keep my polls and come back later to access them.", - "User Story: As an authenticated user, I can share my polls with my friends.", - "User Story: As an authenticated user, I can see the aggregate results of my polls.", - "User Story: As an authenticated user, I can delete polls that I decide I don't want anymore.", - "User Story: As an authenticated user, I can create a poll with any number of possible items.", - "Bonus User Story: As an unauthenticated user, I can see everyone's polls, but I can't vote on anything.", - "Bonus User Story: As an unauthenticated or authenticated user, I can see the results of polls in chart form. (This could be implemented using Chart.js or Google Charts.)", - "Bonus User Story: As an authenticated user, if I don't like the options on a poll, I can create a new option.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", - "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

        Click here then add your link to your tweet's text" - ], - "challengeType": 4, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bdff", - "name": "Basejump: Build a Nightlife Coordination App", - "difficulty": 2.02, - "challengeSeed": "128451852", - "description": [ - "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://sociallife.herokuapp.com/ and deploy it to Heroku.", - "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", - "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Here are the specific User Stories you should implement for this Basejump:", - "User Story: As an unauthenticated user, I can view all bars in my area.", - "User Story: As an authenticated user, I can add myself to a bar to indicate I am going there tonight.", - "User Story: As an authenticated user, I can remove myself from a bar if I no longer want to go there.", - "Bonus User Story: As an unauthenticated user, when I login I should not have to search again.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", - "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

        Click here then add your link to your tweet's text" - ], - "challengeType": 4, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bd0e", - "name": "Basejump: Chart the Stock Market", - "difficulty": 2.03, - "challengeSeed": "128451852", - "description": [ - "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://stockjump.herokuapp.com/ and deploy it to Heroku.", - "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", - "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Here are the specific User Stories you should implement for this Basejump:", - "User Story: As a user, I can view a graph displaying the recent trend lines for each added stock.", - "User Story: As a user, I can add new stocks by their symbol name.", - "User Story: As a user, I can remove stocks.", - "Bonus User Story: As a user, I can see changes in real-time when any other user adds or removes a stock.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", - "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

        Click here then add your link to your tweet's text" - ], - "challengeType": 4, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bd0f", - "name": "Basejump: Manage a Book Trading Club", - "difficulty": 2.04, - "challengeSeed": "128451852", - "description": [ - "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://bookoutpost.herokuapp.com/ and deploy it to Heroku.", - "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", - "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Here are the specific User Stories you should implement for this Basejump:", - "User Story: As an authenticated user, I can view all books posted by every user.", - "User Story: As an authenticated user, I can add a new book.", - "User Story: As an authenticated user, I can update my settings to store my full name, city, and state.", - "Bonus User Story: As an authenticated user, I can propose a trade and wait for the other user to accept the trade.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", - "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

        Click here then add your link to your tweet's text" - ], - "challengeType": 4, - "tests": [] - }, - { - "_id": "bd7158d8c443eddfaeb5bdee", - "name": "Basejump: Build a Pinterest Clone", - "difficulty": 2.05, - "challengeSeed": "128451852", - "description": [ - "Objective: Build a full stack JavaScript app that successfully reverse-engineers this: http://linkterest.herokuapp.com/ and deploy it to Heroku.", - "Note that for each Basejump, you should create a new GitHub repository and a new Heroku project. If you can't remember how to do this, revisit http://freecodecamp.com/challenges/get-set-for-basejumps.", - "As you build your app, you should frequently commit changes to your codebase. You can do this by running git commit -am \"your commit message\". Note that you should replace \"your commit message\" with a brief summary of the changes you made to your code.", - "You can push these new commits to GitHub by running git push origin master, and to Heroku by running grunt --force && grunt buildcontrol:heroku.", - "Here are the specific User Stories you should implement for this Basejump:", - "User Story: As an unauthenticated user, I can login with Twitter.", - "User Story: As an authenticated user, I can link to images.", - "User Story: As an authenticated user, I can delete images that I've linked to.", - "User Story: As an authenticated user, I can see a Pinterest-style wall of all the images I've linked to.", - "User Story: As an unauthenticated user, I can browse other users' walls of images.", - "Bonus User Story: As an authenticated user, if I upload an image that is broken, it will be replaced by a placeholder image. (can use jQuery broken image detection)", - "Hint: Masonry.js is a library that allows for Pinterest-style image grids.", - "Once you've finished implementing these user stories, click the \"I've completed this challenge\" button and enter the URLs for both your GitHub repository and your live app running on Heroku. If you pair programmed with a friend, enter his or her Free Code Camp username as well so that you both get credit for completing it.", - "If you'd like immediate feedback on your project, click this button and paste in a link to your Heroku project. Otherwise, we'll review it before you start your nonprofit projects.

        Click here then add your link to your tweet's text" - ], - "challengeType": 4, - "tests": [] - } -] diff --git a/seed_data/future-coursewares.json b/seed_data/future-coursewares.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/seed_data/future-coursewares.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/views/challengeMap/show.jade b/views/challengeMap/show.jade index 91a06a9146..43f06a04d3 100644 --- a/views/challengeMap/show.jade +++ b/views/challengeMap/show.jade @@ -14,7 +14,7 @@ block content img.img-responsive.img-center.border-radius-5(src='https://s3.amazonaws.com/freecodecamp/wide-social-banner-dino.png') else img.img-responsive.img-center.border-radius-5(src='https://s3.amazonaws.com/freecodecamp/wide-social-banner.png') - .col-xs-12.col-md-8.col-md-offset-2 + .col-xs-12.col-md-10.col-md-offset-1 h2.text-center span.text-primary #{camperCount}   | campers have joined our community @@ -22,88 +22,25 @@ block content | since we launched   span.text-primary #{daysRunning}   | days ago. - h2 - span.fa.fa-flag - |   Waypoints (200 hours of lessons) + .spacer + h3.negative-15 + ol + for challenge in challengeList + if completedChallengeList.indexOf(challenge._id) > -1 + .row + .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center + .col-xs-12.col-sm-9.col-md-10 + li.faded + a(href="/challenges/#{challenge.name}")= challenge.name - .col-xs-12.no-right-padding - h3.negative-15 - ol - for waypoint in waypoints - if completedChallengeList.indexOf(waypoint._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center - .col-xs-12.col-sm-9.col-md-10 - li.faded - a(href="/challenges/#{waypoint.name}")= waypoint.name + else + .row + .hidden-xs.col-sm-3.col-md-2 + span + .col-xs-12.col-sm-9.col-md-10 + li + a(href="/challenges/#{challenge.name}")= challenge.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/challenges/#{waypoint.name}")= waypoint.name - h2 - span.ion-bonfire - |   Bonfires (200 hours of JavaScript algorithm practice) - .col-xs-12 - h3.negative-15 - ol - for bonfire in bonfires - if completedChallengeList.indexOf(bonfire._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center - .col-xs-12.col-sm-9.col-md-10 - li.faded - a(href="/challenges/#{bonfire.name}")= bonfire.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/challenges/#{bonfire.name}")= bonfire.name - h2 - span.fa.fa-angle-double-right - |   Ziplines (200 hours of front end development) - .col-xs-12 - h3.negative-15 - ol - for zipline in ziplines - if completedChallengeList.indexOf(zipline._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center - .col-xs-12.col-sm-9.col-md-10 - li.faded - a(href="/challenges/#{zipline.name}")= zipline.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/challenges/#{zipline.name}")= zipline.name - h2 - span.fa.fa-level-down - |   Basejumps (200 hours of full stack development) - .col-xs-12 - h3.negative-15 - ol - for basejump in basejumps - if completedChallengeList.indexOf(basejump._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center - .col-xs-12.col-sm-9.col-md-10 - li.faded - a(href="/challenges/#{basejump.name}")= basejump.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/challenges/#{basejump.name}")= basejump.name h2 span.ion-ios-heart   Nonprofit Projects (800 hours of real-world experience)* h3.negative-15 From 31e10444a51196f695682d29874c7c26ee7247ec Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 00:42:32 -0700 Subject: [PATCH 58/81] improve field guide look and add cracking code interview article --- public/css/main.less | 2 +- seed_data/field-guides.json | 248 +++++++++++++++------------- views/field-guide/all-articles.jade | 2 +- 3 files changed, 133 insertions(+), 119 deletions(-) diff --git a/public/css/main.less b/public/css/main.less index c9337072f3..932e87bc73 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -247,7 +247,7 @@ ul { } .large-p { - font-size: 24px; + font-size: 18px; } .text-success { diff --git a/seed_data/field-guides.json b/seed_data/field-guides.json index 5b4edb5ac3..77f0e10600 100644 --- a/seed_data/field-guides.json +++ b/seed_data/field-guides.json @@ -17,7 +17,7 @@ "
        ", "

        We're a community of busy people who learn to code by building projects for nonprofits.

        ", "

        We help our campers (students):

        ", - "

        ", + "

        ", "

          ", "
        1. Learn full stack JavaScript
        2. ", "
        3. Build a portfolio of real apps that real people are using
        4. ", @@ -34,13 +34,13 @@ "
          ", "

          Learning to code is hard.

          ", "

          Most people who successfully learn to code:

          ", - "

          ", + "

          ", "

            ", "
          1. Make friends with people who code
          2. ", "
          3. Code a little every day
          4. ", "
          ", "

          ", - "

          We give you the structure and the community you need so you can successfully learn to code.

          ", + "

          We give you the structure and the community you need so you can successfully learn to code.

          ", "
          " ] }, @@ -50,7 +50,7 @@ "description": [ "
          ", "

          Our main advantage is that we're accessible to busy adults who want to change careers. Specifically, we're:

          ", - "

          ", + "

          ", "

            ", "
          • • Free
          • ", "
          • • Self-paced
          • ", @@ -89,7 +89,7 @@ "

            If you complete this program, you will be able to get a coding job. Many of our campers have already gotten coding jobs.

            ", " ", "

            Here are the facts:

            ", - "

            ", + "

            ", "

              ", "
            • • There are hundreds of thousands of unfilled coding jobs.
            • ", "
            • • Employers and the US government have joined together to promote nontraditional coding programs like Free Code Camp.
            • ", @@ -106,7 +106,7 @@ "description": [ "
              ", "

              First, you'll learn basic web design tools like:

              ", - "

              ", + "

              ", "

                ", "
              • • HTML - the structure of web pages
              • ", "
              • • CSS - the visual style of web pages
              • ", @@ -116,14 +116,14 @@ "
              ", "

              ", "

              Then you'll learn computer science and the art of programming:

              ", - "

              ", + "

              ", "

                ", "
              • • JavaScript - the one programming language that all web browsers use
              • ", "
              • • Algorithms - step-by-step recipes for getting things done
              • ", "
              ", "

              ", "

              Finally you'll learn Agile Methodologies and Full Stack JavaScript to build projects for nonprofits:

              ", - "

              ", + "

              ", "

                ", "
              • • Agile - a set of software development principles that focus the design and production of a project on the needs of its users
              • ", "
              • • Git - a version control system for saving and sharing your projects
              • ", @@ -142,7 +142,7 @@ "description": [ "
                ", "

                It takes about 1,600 hours of coding to develop the skills you'll need to get an entry level software engineering job.

                ", - "

                Most coding bootcamps try to jam all this into 3 or 4 months of intensive study. Free Code Camp is fully online, and there will always be other people at your skill level that you can pair program with, so you can learn at your own pace. Here are some example coding schedules:

                ", + "

                Most coding bootcamps try to jam all this into 3 or 4 months of intensive study. Free Code Camp is fully online, and there will always be other people at your skill level that you can pair program with, so you can learn at your own pace. Here are some example coding schedules:

                ", "
    Time budgeted
    ", " ", " ", @@ -178,9 +178,9 @@ "name": "Why does Free Code Camp use JavaScript instead of Ruby or Python?", "description": [ "
    ", - "

    Like JavaScript, Ruby and Python are high-level scripting languages that can be used for full stack web development.

    ", - "

    But even if you learned these languages, you'd still need to learn JavaScript. That's because JavaScript is the only language that runs in web browsers. JavaScript has been around for 20 years, and it is still growing in popularity.

    ", - "

    Because of this, JavaScript has more tools and online learning resources than any other language.

    ", + "

    Like JavaScript, Ruby and Python are high-level scripting languages that can be used for full stack web development.

    ", + "

    But even if you learned these languages, you'd still need to learn JavaScript. That's because JavaScript is the only language that runs in web browsers. JavaScript has been around for 20 years, and it is still growing in popularity.

    ", + "

    Because of this, JavaScript has more tools and online learning resources than any other language.

    ", " \"A", "
    ", "
    " @@ -193,8 +193,8 @@ "
    ", "

    Pair programming is where two people code together on one computer.

    ", " ", - "

    You discuss different approaches to solving problems, and keep each other motivated. The result is better code than either of you could have written by yourselves. Because of its benefits, many engineers pair program full time. And it's the best way to learn coding. Thanks to tools that allow two people to share mouse and keyboard inputs, you can pair program with a friend without needing to be in the same room.

    ", - "

    By pair programming with other Free Code Camp students on our coding challenges. Eventually, you'll work with people at nonprofits to build real-life software solutions.

    ", + "

    You discuss different approaches to solving problems, and keep each other motivated. The result is better code than either of you could have written by yourselves. Because of its benefits, many engineers pair program full time. And it's the best way to learn coding. Thanks to tools that allow two people to share mouse and keyboard inputs, you can pair program with a friend without needing to be in the same room.

    ", + "

    By pair programming with other Free Code Camp students on our coding challenges. Eventually, you'll work with people at nonprofits to build real-life software solutions.

    ", "
    " ] }, @@ -204,7 +204,7 @@ "description": [ "
    ", "

    When you get stuck, remember: RSAP.

    ", - "

    ", + "

    ", "

      ", "
    1. Read the documentation or error
    2. ", "
    3. Search Google
    4. ", @@ -212,11 +212,11 @@ "
    5. Post on Stack Overflow
    6. ", "
    ", "

    ", - "

    This is the most time-efficient way to handle being stuck, and it's the most respectful of other people's time, too.

    ", - "

    Most of the time, you'll solve your problem after just one or two steps of this algorithm.

    ", - "

    We have a special chat room just for getting help: https://freecode.slack.com/messages/help/

    ", - "

    Also, if you need to post on Stack Overflow, be sure to read their guide to asking good questions: http://stackoverflow.com/help/how-to-ask.

    ", - "

    Learning to code is hard. But it's a lot easier if you ask for help when you need it!

    ", + "

    This is the most time-efficient way to handle being stuck, and it's the most respectful of other people's time, too.

    ", + "

    Most of the time, you'll solve your problem after just one or two steps of this algorithm.

    ", + "

    We have a special chat room just for getting help: https://freecode.slack.com/messages/help/

    ", + "

    Also, if you need to post on Stack Overflow, be sure to read their guide to asking good questions: http://stackoverflow.com/help/how-to-ask.

    ", + "

    Learning to code is hard. But it's a lot easier if you ask for help when you need it!

    ", "
    " ] }, @@ -226,8 +226,8 @@ "description": [ "
    ", "

    This guide was designed as a reference for you. You shouldn't try to read it all today.

    ", - "

    Feel free to come back any time and jump around, reading any articles that seem interesting to you at the time.

    ", - "

    If you're currently doing our \"Browse our Field Guide\" Waypoint, go ahead and mark that challenge complete and move on to your next Waypoint.

    ", + "

    Feel free to come back any time and jump around, reading any articles that seem interesting to you at the time.

    ", + "

    If you're currently doing our \"Browse our Field Guide\" Waypoint, go ahead and mark that challenge complete and move on to your next Waypoint.

    ", "
    " ] }, @@ -237,9 +237,9 @@ "description": [ "
    ", "

    We are completely free for both students and for nonprofits.

    ", - "

    Our name is Free Code Camp. We are a free code camp. If you had to pay us (or sign over future earnings), we'd have to change our name. And we are not going to do that.

    ", - "

    Everyone working on our community and our open source projects is a volunteer.

    ", - "

    We plan to eventually cover our operational costs by earning job placement bonuses from companies who hire our graduates. Note that we will not actually garnish any wages from our graduates - employers are already paying recruiters thousands of dollars to find successful candidates. Employers will simply pay the recruitment bonus to Free Code Camp instead of paying a recruiter.

    ", + "

    Our name is Free Code Camp. We are a free code camp. If you had to pay us (or sign over future earnings), we'd have to change our name. And we are not going to do that.

    ", + "

    Everyone working on our community and our open source projects is a volunteer.

    ", + "

    We plan to eventually cover our operational costs by earning job placement bonuses from companies who hire our graduates. Note that we will not actually garnish any wages from our graduates - employers are already paying recruiters thousands of dollars to find successful candidates. Employers will simply pay the recruitment bonus to Free Code Camp instead of paying a recruiter.

    ", "
    " ] }, @@ -249,8 +249,8 @@ "description": [ "
    ", "

    Unlike coding bootcamps, anyone can study at Free Code Camp.

    ", - "

    We're not going to tell you that you can't become a software engineer. We believe the only person who should be able to tell you that is you.

    ", - "

    If you persevere, and keep working through our challenges and nonprofit projects, you will become an employable software engineer.

    ", + "

    We're not going to tell you that you can't become a software engineer. We believe the only person who should be able to tell you that is you.

    ", + "

    If you persevere, and keep working through our challenges and nonprofit projects, you will become an employable software engineer.

    ", "
    " ] }, @@ -260,17 +260,17 @@ "description": [ "
    ", "

    If you're interested in coding JavaScript live in front of dozens of people on our popular twitch.tv channel, we'd love to have you.

    ", - "

    Please follow these steps to get started:

    ", - "

    ", + "

    Please follow these steps to get started:

    ", + "

    ", "

      ", "
    1. Follow this tutorial to set up your computer for streaming.
    2. ", "
    3. Contact Jason Ruekert - he's @jsonify in Slack. He's in charge of our Twitch.tv channel. Tell him what you'd like to stream, and when you're available to stream.
    4. ", "
    5. Jason will pair with you using Screen Hero to verify your computer is configured properly to stream.
    6. ", "
    ", "

    ", - "

    Be respectful of your audience. Everything you stream should be related to coding JavaScript, and should be acceptable for children. (Yes, children do sometimes watch our Twitch stream to learn to code).

    ", - "

    While you're streaming, keep the chat room open so you can respond to questions from your viewers. If someone follows Free Code Camp on Twitch, try to thank them.

    ", - "

    If you do a good job, we'll invite you back to stream some more. Who knows, you might become one of our regular streamers!

    ", + "

    Be respectful of your audience. Everything you stream should be related to coding JavaScript, and should be acceptable for children. (Yes, children do sometimes watch our Twitch stream to learn to code).

    ", + "

    While you're streaming, keep the chat room open so you can respond to questions from your viewers. If someone follows Free Code Camp on Twitch, try to thank them.

    ", + "

    If you do a good job, we'll invite you back to stream some more. Who knows, you might become one of our regular streamers!

    ", "
    " ] }, @@ -382,7 +382,7 @@ " ", " ", "

    If you didn't see your city on this list, you should create your own Facebook group for your city. Please follow these steps:

    ", - "

    ", + "

    ", "

      ", "
    1. Sign in to Facebook.
    2. ", "
    3. Click the down arrow in the upper right corner of the screen, then choose \"Create Group\" from the options.", @@ -410,8 +410,8 @@ "
    4. Join our #local-group-leaders channel on Slack, where we share ideas about involving campers in your city.
    5. ", "
    ", "

    ", - "

    If you don't have a Facebook page, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.

    ", - "

    If Facebook is blocked in your country, feel free to use social network with a similar group functionality that's popular in your region.

    ", + "

    If you don't have a Facebook page, we strongly recommend you create one, even if it's just for the purpose of coordinating with campers in your city through this group.

    ", + "

    If Facebook is blocked in your country, feel free to use social network with a similar group functionality that's popular in your region.

    ", "" ] }, @@ -424,6 +424,20 @@ "" ] }, + { + "_id": "bd7158d9c442eddfaeb5b2ef", + "name": "Why doesn't Free Code Camp teach technical interviewing skills?", + "description": [ + "
    ", + "

    The skills you need to successfully interview for a job are quite different from the skills you'll need on the job.


    ", + "

    More and more employers are moving to a pair-programming-centric interview style. If you apply to these places, you don't need to make special preparations your interview - just pair program like you would on any Free Code Camp project.

    ", + "

    If you intend to apply for a job at a larger tech company like Apple, Microsoft, Google, Facebook or Amazon, you can prepare for your interviews by simply working through this single authoritative book. Many of the questions you'll be asked during your interviews will come straight out of this book, which is standard-issue in Silicon Valley.

    ", + " ", + "

    You can download the 4th edition of this book in PDF form for free here or buy the 5th edition of the book here.", + "

    We may focus more on interview preparation in the future if we determine that it's necessary. In the mean time, Free Code Camp will continue to focus skills that are directly related to becoming a job-ready software engineer.", + "

    " + ] + }, { "_id": "bd7158d9c442eddfaeb5bdef", "name": "How do I best use the Global Control Shortcuts for Mac?", @@ -431,8 +445,8 @@ "
    ", "

    These Global Control Shortcuts for Mac will save you hours by speeding up your typing.


    ", "
    ", - "

    These global shortcuts work everywhere on a Mac:

    ", - "

    ", + "

    These global shortcuts work everywhere on a Mac:

    ", + "

    ", "

      ", "
    • Control + F = Forward
    • ", "
    • Control + B = Backward
    • ", @@ -457,8 +471,8 @@ "
      ", " ", "
      ", - "

      The shortcuts:

      ", - "

      ", + "

      The shortcuts:

      ", + "

      ", "

        ", "
      • j - move down
      • ", "
      • k - move up
      • ", @@ -485,8 +499,8 @@ "
        ", " ", "
        ", - "

        Here are the technologies we used here:

        ", - "

        ", + "

        Here are the technologies we used here:

        ", + "

        ", "

          ", "
        • atom.io - a free code editor
        • ", "
        • startbootstrap.com - a collection of free responsive (Bootstrap) templates
        • ", @@ -494,7 +508,7 @@ "
        • bitballoon.com - a tool for drag and drop website deployment
        • ", "
        ", "

        ", - "

        You will quickly reach the limits of what you can do without actually coding, but it's nice to be able to rapidly build working prototype websites like this.

        ", + "

        You will quickly reach the limits of what you can do without actually coding, but it's nice to be able to rapidly build working prototype websites like this.

        ", "
    " ] }, @@ -503,15 +517,15 @@ "name": "How do Free Code Camp's Nonprofit Projects work?", "description": [ "
    ", - "

    Building nonprofit projects is the main way that our campers learn full stack JavaScript and agile software development. Once you complete the Free Code Camp Waypoints, Bonfires, Ziplines and Basejumps, you'll begin this process.

    ", + "

    Building nonprofit projects is the main way that our campers learn full stack JavaScript and agile software development. Once you complete the Free Code Camp Waypoints, Bonfires, Ziplines and Basejumps, you'll begin this process.

    ", "

    Starting with the end in mind

    ", - "

    Our goal at Free Code Camp is to help you land a job as a junior software developer (or, if you prefer, a 'pivot job' that leads your current career in a more technical direction).

    ", - "

    You'll continue to work on nonprofit projects until you've built a sufficiently impressive portfolio and references to start your job search. Your portfolio will ultimately have three to five nonprofit projects. We estimate that the 900 hours of nonprofit projects you're going to complete, in addition to the 100 hours of challenges you've already completed, will be enough to qualify you for your first coding job. This will produce a much broader portfolio than a traditional coding bootcamp, which generally only has one or two capstone projects.

    ", + "

    Our goal at Free Code Camp is to help you land a job as a junior software developer (or, if you prefer, a 'pivot job' that leads your current career in a more technical direction).

    ", + "

    You'll continue to work on nonprofit projects until you've built a sufficiently impressive portfolio and references to start your job search. Your portfolio will ultimately have three to five nonprofit projects. We estimate that the 900 hours of nonprofit projects you're going to complete, in addition to the 100 hours of challenges you've already completed, will be enough to qualify you for your first coding job. This will produce a much broader portfolio than a traditional coding bootcamp, which generally only has one or two capstone projects.

    ", "

    Choosing your first Nonprofit Project

    ", - "

    We've categorized all the nonprofit projects by estimated time investment per camper: 100 hours, 200 hours, and 300 hours. These are only rough estimates.

    ", - "

    Example: if you and the camper you're paired up with (your pair) each stated you could work 20 hours per week. If the project is a 100 hour per camper project, you should be able to complete it in about 5 weeks.

    ", - "

    Our team of nonprofit project camp counselors will match you and your pair based on:

    ", - "

    ", + "

    We've categorized all the nonprofit projects by estimated time investment per camper: 100 hours, 200 hours, and 300 hours. These are only rough estimates.

    ", + "

    Example: if you and the camper you're paired up with (your pair) each stated you could work 20 hours per week. If the project is a 100 hour per camper project, you should be able to complete it in about 5 weeks.

    ", + "

    Our team of nonprofit project camp counselors will match you and your pair based on:

    ", + "

    ", "

      ", "
    1. Your estimated time commitment (10, 20 or 40 hours per week)
    2. ", "
    3. Your time zone
    4. ", @@ -519,11 +533,11 @@ "
    5. Prior coding experience (we'd like both campers to be able to contribute equally)
    6. ", "
    ", "

    ", - "

    We won't take age or gender into account. This will provide you with valuable experience in meshing with diverse teams, which is a reality of the contemporary workplace.

    ", - "

    You'll only work on one project at a time. Once you start a nonprofit project, we'll remove you from all other nonprofit project you've expressed interest in. There's a good chance those projects will no longer be available when you finish your current project, anyway. Don't worry, though - we get new nonprofit project requests every day, so there will be plenty more projects for you to consider after you finish your current one.

    ", + "

    We won't take age or gender into account. This will provide you with valuable experience in meshing with diverse teams, which is a reality of the contemporary workplace.

    ", + "

    You'll only work on one project at a time. Once you start a nonprofit project, we'll remove you from all other nonprofit project you've expressed interest in. There's a good chance those projects will no longer be available when you finish your current project, anyway. Don't worry, though - we get new nonprofit project requests every day, so there will be plenty more projects for you to consider after you finish your current one.

    ", "

    Finalizing the Project

    ", - "

    Before you can start working on the project, our team of Nonprofit Project Coordinators will go through the following process:

    ", - "

    ", + "

    Before you can start working on the project, our team of Nonprofit Project Coordinators will go through the following process:

    ", + "

    ", "

      ", "
    1. We'll wait until there are two campers who have chosen the same project and look like they're a good match for one another based on the factors mentioned above.
    2. ", "
    3. We'll call the stakeholder to confirm once again that he or she agrees with our  terms  and has signed our  Nonprofit Project Stakeholder Pledge.
    4. ", @@ -531,27 +545,27 @@ "
    5. If the stakeholder and both campers shows up promptly, and seem enthusiastic and professional, we'll start the project.
    6. ", "
    ", "

    ", - "

    This lengthy process serves an important purpose: it reduces the likelihood that any of our campers or stakeholders will waste their precious time.

    ", + "

    This lengthy process serves an important purpose: it reduces the likelihood that any of our campers or stakeholders will waste their precious time.

    ", "

    Nonprofit Stakeholders

    ", - "

    Each nonprofit project was submitted by a nonprofit. A representative from this nonprofit has agreed to serve as a \"stakeholder\" - an authorative person who understands the organization and its needs for this particular project.

    ", - "

    Stakeholders have a deep understanding of their organizations' needs. Campers will work with them to figure out the best solutions to these needs.

    ", - "

    When you and your pair first speak with your nonprofit stakeholder, you'll:

    ", - "

    ", + "

    Each nonprofit project was submitted by a nonprofit. A representative from this nonprofit has agreed to serve as a \"stakeholder\" - an authorative person who understands the organization and its needs for this particular project.

    ", + "

    Stakeholders have a deep understanding of their organizations' needs. Campers will work with them to figure out the best solutions to these needs.

    ", + "

    When you and your pair first speak with your nonprofit stakeholder, you'll:

    ", + "

    ", "

      ", "
    • talk at length to better understand their needs.
    • ", "
    • create a new Trello board and use it to prioritize what needs to be built.
    • ", "
    • and establish deadlines based on your weekly time commitment, and how long you think each task will take.
    • ", "
    ", "

    ", - "

    It's notoriously difficult to estimate how long building software projects will take, so feel free to ask camp counselors for help.

    ", - "

    You'll continue to meet with your stakeholder at least twice a month in your project's Slack channel.

    ", - "

    You should also ask questions in your project's Slack channel as they come up throughout the week, and your stakeholder can answer them asynchronously.

    ", - "

    Getting \"blocked\" on a task can take away your sense of forward momentum, so be sure to proactively seek answers to any ambiguities you encounter.

    ", - "

    Ultimately, the project will be considered complete once both the stakeholder's needs have been met, and you and your pair are happy with the project. Then you can add it to your portfolio!

    ", + "

    It's notoriously difficult to estimate how long building software projects will take, so feel free to ask camp counselors for help.

    ", + "

    You'll continue to meet with your stakeholder at least twice a month in your project's Slack channel.

    ", + "

    You should also ask questions in your project's Slack channel as they come up throughout the week, and your stakeholder can answer them asynchronously.

    ", + "

    Getting \"blocked\" on a task can take away your sense of forward momentum, so be sure to proactively seek answers to any ambiguities you encounter.

    ", + "

    Ultimately, the project will be considered complete once both the stakeholder's needs have been met, and you and your pair are happy with the project. Then you can add it to your portfolio!

    ", "

    Working with your Pair

    ", - "

    You and your pair will pair program (code together on the same computer virtually) about half of the time, and work independently the other half of the time.

    ", - "

    Here are our recommended ways of collaborating:

    ", - "

    ", + "

    You and your pair will pair program (code together on the same computer virtually) about half of the time, and work independently the other half of the time.

    ", + "

    Here are our recommended ways of collaborating:

    ", + "

    ", "

      ", "
    • • Slack has robust private messaging functionality. It's the main way our team communicates, and we recommend it over email.
    • ", "
    • • Trello is great for managing projects. Work with your stakeholder to create Trello cards, and update these cards regularly as you make progress on them.
    • ", @@ -560,15 +574,15 @@ "
    ", "

    ", "

    Hosting Apps

    ", - "

    Unless your stakeholder has an existing modern host (AWS, Digital Ocean), you'll need to transition them over to a new platform. We believe Heroku is the best choice for a vast majority of web projects. It's free, easy to use, and has both browser and command line interfaces. It's owned by Salesforce and used by a ton of companies, so it's accountable and unlikely to go away.

    ", - "

    If you need help convincing your stakeholder that Heroku is the ideal platform, we'll be happy to talk with them.

    ", + "

    Unless your stakeholder has an existing modern host (AWS, Digital Ocean), you'll need to transition them over to a new platform. We believe Heroku is the best choice for a vast majority of web projects. It's free, easy to use, and has both browser and command line interfaces. It's owned by Salesforce and used by a ton of companies, so it's accountable and unlikely to go away.

    ", + "

    If you need help convincing your stakeholder that Heroku is the ideal platform, we'll be happy to talk with them.

    ", "

    Maintaining Apps

    ", - "

    Once you complete a nonprofit project, your obligation to its stakeholder is finished. You goal is to leave behind a well documented solution that can be easily maintained by a contract JavaScript developer (or even a less-technical \"super user\").

    ", - "

    While you will no longer need to help with feature development, we encourage you to consider helping your stakeholder with occasional patches down the road. After all, this project will be an important piece of your portfolio, and you'll want it to remain in good shape for curious future employers.

    ", + "

    Once you complete a nonprofit project, your obligation to its stakeholder is finished. You goal is to leave behind a well documented solution that can be easily maintained by a contract JavaScript developer (or even a less-technical \"super user\").

    ", + "

    While you will no longer need to help with feature development, we encourage you to consider helping your stakeholder with occasional patches down the road. After all, this project will be an important piece of your portfolio, and you'll want it to remain in good shape for curious future employers.

    ", "

    Pledging to finish the project

    ", - "

    Your nonprofit stakeholder, your pair, and the volunteer camp counselor team are all counting on you to finish your nonprofit project. If you walk away from an unfinished nonprofit project, you'll become ineligible to ever be assigned another one.

    ", - "

    To confirm that you understand the seriousness of this commitment, we require that all campers  sign this pledge  before starting on their nonprofit projects.

    ", - "

    There will likely be times of confusion or frustration. This is normal in software development. The most important thing is that you do not give up and instead persevere through these setbacks. As Steve Jobs famously said, \"Real artists ship.\" And you are going to ship one successful nonprofit project after another until you feel ready to take the next step in your promising career.

    ", + "

    Your nonprofit stakeholder, your pair, and the volunteer camp counselor team are all counting on you to finish your nonprofit project. If you walk away from an unfinished nonprofit project, you'll become ineligible to ever be assigned another one.

    ", + "

    To confirm that you understand the seriousness of this commitment, we require that all campers  sign this pledge  before starting on their nonprofit projects.

    ", + "

    There will likely be times of confusion or frustration. This is normal in software development. The most important thing is that you do not give up and instead persevere through these setbacks. As Steve Jobs famously said, \"Real artists ship.\" And you are going to ship one successful nonprofit project after another until you feel ready to take the next step in your promising career.

    ", "
    " ] }, @@ -579,7 +593,7 @@ "
    ", "

    Download for Mac

    ", "

    Download for Windows

    ", - "

    You'll use Screen Hero to pair program starting with http://freecodecamp.com/challenges/pair-program-on-bonfires

    ", + "

    You'll use Screen Hero to pair program starting with http://freecodecamp.com/challenges/pair-program-on-bonfires

    ", "
    " ] }, @@ -589,7 +603,7 @@ "description": [ "
    ", "

    Writing Bonfire challenges is a great way to exercise your own problem solving and testing abilities. Follow this process closely to maximize the chances of us accepting your bonfire.

    ", - "

    ", + "

    ", "

      ", "
    1. Fork the Free Code Camp repository and open seed_data/bonfires.json to become familiar with the format of our bonfires.
    2. ", "
    3. Regardless of your bonfire's difficulty, put it as the last bonfire in the JSON file. Change one of the numbers in the ID to ensure that your bonfire has a unique ID.
    4. ", @@ -600,21 +614,21 @@ "

      ", "

      Here is a description of each of the Bonfires' fields.

      ", "

      Name

      ", - "

      The name of your challenge. It's OK for this to be humorous but it must be brief and relevant to the task.

      ", + "

      The name of your challenge. It's OK for this to be humorous but it must be brief and relevant to the task.

      ", "

      Difficulty

      ", - "

      Attempt to rate difficulty compared against existing bonfire challenges. A good proxy for the difficulty of a bonfire is how long it takes you to solve it. For every 15 minutes it takes, increase the difficulty. For example, a one-hour bonfire should probably be a 4.

      ", + "

      Attempt to rate difficulty compared against existing bonfire challenges. A good proxy for the difficulty of a bonfire is how long it takes you to solve it. For every 15 minutes it takes, increase the difficulty. For example, a one-hour bonfire should probably be a 4.

      ", "

      Description

      ", - "

      Separate paragraphs with a line break. Only the first paragraph is visible prior to a user before they click the the 'More information' button.

      ", - "

      All necessary information must be included in the first paragraph. Write this first paragraph as succinctly as possible. Subsequent paragraphs should offer hints or details if needed.

      ", - "

      If your subject matter warrants deeper understanding, you may link to Wikipedia.

      ", + "

      Separate paragraphs with a line break. Only the first paragraph is visible prior to a user before they click the the 'More information' button.

      ", + "

      All necessary information must be included in the first paragraph. Write this first paragraph as succinctly as possible. Subsequent paragraphs should offer hints or details if needed.

      ", + "

      If your subject matter warrants deeper understanding, you may link to Wikipedia.

      ", "

      Challenge Seed

      ", - "

      This is where you set up what will be in the editor when the camper starts the bonfire.

      ", + "

      This is where you set up what will be in the editor when the camper starts the bonfire.

      ", "

      Tests

      ", - "

      These tests are what bring your challenge to life. Without them, we cannot confirm the accuracy of a user's submitted answer. Choose your tests wisely.

      ", - "

      Bonfire tests are written using the Chai.js assertion library. Please use the should and expect syntax for end user readability. As an example of what not do to, many of the original Bonfire challenges are written with assert syntax and many of the test cases are difficult to read.

      ", - "

      If your bonfire question has a lot of edge cases, you will need to write many tests for full coverage. If you find yourself writing more tests than you desire, you may consider simplifying the requirements of your bonfire challenge. For difficulty level 1 through 3, you will generally only need 2 to 4 tests.

      ", + "

      These tests are what bring your challenge to life. Without them, we cannot confirm the accuracy of a user's submitted answer. Choose your tests wisely.

      ", + "

      Bonfire tests are written using the Chai.js assertion library. Please use the should and expect syntax for end user readability. As an example of what not do to, many of the original Bonfire challenges are written with assert syntax and many of the test cases are difficult to read.

      ", + "

      If your bonfire question has a lot of edge cases, you will need to write many tests for full coverage. If you find yourself writing more tests than you desire, you may consider simplifying the requirements of your bonfire challenge. For difficulty level 1 through 3, you will generally only need 2 to 4 tests.

      ", "

      MDNlinks

      ", - "

      Take a look at seed_data/bonfireMDNlinks.js. If any of these concepts are relevant to your bonfire, be sure to include them. If you know of an MDN article that isn't linked here, you can add it to the bonfireMDNlinks.js file before adding it to your bonfire.

      ", + "

      Take a look at seed_data/bonfireMDNlinks.js. If any of these concepts are relevant to your bonfire, be sure to include them. If you know of an MDN article that isn't linked here, you can add it to the bonfireMDNlinks.js file before adding it to your bonfire.

      ", "
    " ] }, @@ -624,21 +638,21 @@ "description": [ "
    ", "

    Free Code Camp is friendly place to learn to code. We're committed to keeping it that way.

    ", - "

    All campers are required to agree with the following code of conduct. We'll enforce this code. We're expecting cooperation from all campers in ensuring a friendly environment for everybody.

    ", + "

    All campers are required to agree with the following code of conduct. We'll enforce this code. We're expecting cooperation from all campers in ensuring a friendly environment for everybody.

    ", "

    In short: be nice to your fellow campers.

    ", "

    Remember these 3 things and your fellow campers will like you:

    ", - "

    ", + "

    ", "

      ", "
    1. Compliment your fellow campers when they do good work. Congratulate them when they accomplish something (like finishing a nonprofit project or getting a job).
    2. ", "
    3. Critique the work, not the camper doing it.
    4. ", "
    5. Only argue about something if it's important to the greater discussion.
    6. ", "
    ", "

    ", - "

    Free Code Camp should be a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, national origin, or religion (or lack thereof).

    ", - "

    We do not tolerate harassment of campers in any form, anywhere on Free Code Camp's online media (Slack, Twitch, etc.) or during pair programming. Harassment includes sexual language and imagery, deliberate intimidation, stalking, unwelcome sexual attention, libel, and any malicious hacking or social engineering.

    ", - "

    If a camper engages in harassing behavior, our team will take any action we deem appropriate, up to and including banning them from Free Code Camp.

    ", - "

    We want everyone to feel safe and respected. If you are being harassed or notice that someone else is being harassed, say something! Message @quincylarson, @terakilobyte and @codenonprofit in Slack (preferably with a screen shot of the offending language) so we can take fast action.

    ", - "

    If you have questions about this code of conduct, email us at team@freecodecamp.com.

    ", + "

    Free Code Camp should be a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, national origin, or religion (or lack thereof).

    ", + "

    We do not tolerate harassment of campers in any form, anywhere on Free Code Camp's online media (Slack, Twitch, etc.) or during pair programming. Harassment includes sexual language and imagery, deliberate intimidation, stalking, unwelcome sexual attention, libel, and any malicious hacking or social engineering.

    ", + "

    If a camper engages in harassing behavior, our team will take any action we deem appropriate, up to and including banning them from Free Code Camp.

    ", + "

    We want everyone to feel safe and respected. If you are being harassed or notice that someone else is being harassed, say something! Message @quincylarson, @terakilobyte and @codenonprofit in Slack (preferably with a screen shot of the offending language) so we can take fast action.

    ", + "

    If you have questions about this code of conduct, email us at team@freecodecamp.com.

    ", "
    " ] }, @@ -647,39 +661,39 @@ "name": "What is the Free Code Camp Privacy Policy?", "description": [ "
    ", - "

    Free Code Camp is committed to respecting the privacy of visitors to our web sites and web applications. The guidelines below explain how we protect the privacy of visitors to FreeCodeCamp.com and its features.

    ", + "

    Free Code Camp is committed to respecting the privacy of visitors to our web sites and web applications. The guidelines below explain how we protect the privacy of visitors to FreeCodeCamp.com and its features.

    ", "

    Personally Identifiable Information

    ", - "

    Free Code Camp protects the identity of visitors to FreeCodeCamp.com by limiting the collection of personally identifiable information.

    ", - "

    Free Code Camp does not knowingly collect or solicit personally identifiable information from or about children under 13, except as permitted by law. If we discover we have received any information from a child under 13 in violation of this policy, we will delete that information immediately. If you believe Free Code Camp has any information from or about anyone under 13, please email us at team@freecodecamp.com.

    ", - "

    All personally identifiable information you provide to us is used by Free Code Camp and its team to process and manage your account, analyze the demographic of our users, or to deliver services through the site.

    ", - "

    If you choose to provide personally identifiable information to us, you may receive occasional emails from us that are relevant to Free Code Camp, getting a job, or learning to code in general.

    ", - "

    Free Code Camp may also use other third-party providers to facilitate the delivery of the services described above, and these third-party providers may be supplied with or have access to personally identifiable information for the sole purpose of providing these services, to you on behalf of Free Code Camp.

    ", - "

    Free Code Camp may also disclose personally identifiable information in special legal circumstances. For instance, such information may be used where it is necessary to protect our copyright or intellectual property rights, or if the law requires us to do so.

    ", + "

    Free Code Camp protects the identity of visitors to FreeCodeCamp.com by limiting the collection of personally identifiable information.

    ", + "

    Free Code Camp does not knowingly collect or solicit personally identifiable information from or about children under 13, except as permitted by law. If we discover we have received any information from a child under 13 in violation of this policy, we will delete that information immediately. If you believe Free Code Camp has any information from or about anyone under 13, please email us at team@freecodecamp.com.

    ", + "

    All personally identifiable information you provide to us is used by Free Code Camp and its team to process and manage your account, analyze the demographic of our users, or to deliver services through the site.

    ", + "

    If you choose to provide personally identifiable information to us, you may receive occasional emails from us that are relevant to Free Code Camp, getting a job, or learning to code in general.

    ", + "

    Free Code Camp may also use other third-party providers to facilitate the delivery of the services described above, and these third-party providers may be supplied with or have access to personally identifiable information for the sole purpose of providing these services, to you on behalf of Free Code Camp.

    ", + "

    Free Code Camp may also disclose personally identifiable information in special legal circumstances. For instance, such information may be used where it is necessary to protect our copyright or intellectual property rights, or if the law requires us to do so.

    ", "

    Anonymous Information

    ", - "

    Anonymous aggregated data may be provided to other organizations we associate with for statistical purposes. For example, we may report to an organization that a certain percentage of our site's visitors are adults between the ages of 25 and 35.

    ", + "

    Anonymous aggregated data may be provided to other organizations we associate with for statistical purposes. For example, we may report to an organization that a certain percentage of our site's visitors are adults between the ages of 25 and 35.

    ", "

    Cookies and Beacons—Use by Free Code Camp; Opting Out

    ", - "

    We use cookies and software logs to monitor the use of FreeCodeCamp.com and to gather non-personal information about visitors to the site. Cookies are small files that Free Code Camp transfers to the hard drives of visitors for record-keeping purposes. These monitoring systems allow us to track general information about our visitors, such as the type of browsers (for example, Firefox or Internet Explorer), the operating systems (for instance, Windows or Macintosh), or the Internet providers (for instance, Comcast) they use. This information is used for statistical and market research purposes to tailor content to usage patterns and to provide services requested by our customers. To delete these cookies, please see your browser's privacy settings.

    ", - "

    A beacon is an electronic file object (typically a transparent image) placed in the code of a Web page. We use third party beacons to monitor the traffic patterns of visitors from one Free Code Camp.com page to another and to improve site performance.

    ", - "

    None of the information we gather in this way can be used to identify any individual who visits our site.

    ", + "

    We use cookies and software logs to monitor the use of FreeCodeCamp.com and to gather non-personal information about visitors to the site. Cookies are small files that Free Code Camp transfers to the hard drives of visitors for record-keeping purposes. These monitoring systems allow us to track general information about our visitors, such as the type of browsers (for example, Firefox or Internet Explorer), the operating systems (for instance, Windows or Macintosh), or the Internet providers (for instance, Comcast) they use. This information is used for statistical and market research purposes to tailor content to usage patterns and to provide services requested by our customers. To delete these cookies, please see your browser's privacy settings.

    ", + "

    A beacon is an electronic file object (typically a transparent image) placed in the code of a Web page. We use third party beacons to monitor the traffic patterns of visitors from one Free Code Camp.com page to another and to improve site performance.

    ", + "

    None of the information we gather in this way can be used to identify any individual who visits our site.

    ", "

    Security

    ", - "

    Any personally identifiable information collected through this site is stored on limited-access servers. We will maintain safeguards to protect these servers and the information they store.

    ", + "

    Any personally identifiable information collected through this site is stored on limited-access servers. We will maintain safeguards to protect these servers and the information they store.

    ", "

    Surveys

    ", - "

    We may occasionally conduct on-line surveys. All surveys are voluntary and you may decline to participate.

    ", + "

    We may occasionally conduct on-line surveys. All surveys are voluntary and you may decline to participate.

    ", "

    Copyright

    ", - "

    All of the content on FreeCodeCamp.com is copyrighted by Free Code Camp. If you'd like to redistribute it beyond simply sharing it through social media, please contact us at team@freecodecamp.com.

    ", + "

    All of the content on FreeCodeCamp.com is copyrighted by Free Code Camp. If you'd like to redistribute it beyond simply sharing it through social media, please contact us at team@freecodecamp.com.

    ", "

    Contacting Us

    ", - "

    If you have questions about Free Code Camp, or to correct, update, or remove personally identifiable information, please email us at team@freecodecamp.com.

    ", + "

    If you have questions about Free Code Camp, or to correct, update, or remove personally identifiable information, please email us at team@freecodecamp.com.

    ", "

    Links to Other Web sites

    ", - "

    Free Code Camp's sites each contain links to other Web sites. Free Code Camp is not responsible for the privacy practices or content of these third-party Web sites. We urge all FreeCodeCamp.com visitors to follow safe Internet practices: Do not supply Personally Identifiable Information to these Web sites unless you have verified their security and privacy policies.

    ", + "

    Free Code Camp's sites each contain links to other Web sites. Free Code Camp is not responsible for the privacy practices or content of these third-party Web sites. We urge all FreeCodeCamp.com visitors to follow safe Internet practices: Do not supply Personally Identifiable Information to these Web sites unless you have verified their security and privacy policies.

    ", "

    Data Retention

    ", - "

    We retain your information for as long as necessary to permit us to use it for the purposes that we have communicated to you and comply with applicable law or regulations.

    ", + "

    We retain your information for as long as necessary to permit us to use it for the purposes that we have communicated to you and comply with applicable law or regulations.

    ", "

    Business Transfers

    ", - "

    As we continue to develop our business, we might sell or buy subsidiaries, or business units. In such transactions, customer information generally is one of the transferred business assets but remains subject to the promises made in any pre-existing Privacy Policy (unless, of course, the customer consents otherwise). Also, in the unlikely event that Free Code Camp, or substantially all of its assets are acquired, customer information will be one of the transferred assets, and will remain subject to our Privacy Policy.

    ", + "

    As we continue to develop our business, we might sell or buy subsidiaries, or business units. In such transactions, customer information generally is one of the transferred business assets but remains subject to the promises made in any pre-existing Privacy Policy (unless, of course, the customer consents otherwise). Also, in the unlikely event that Free Code Camp, or substantially all of its assets are acquired, customer information will be one of the transferred assets, and will remain subject to our Privacy Policy.

    ", "

    Your California Privacy Rights

    ", - "

    If you are a California resident, you are entitled to prevent sharing of your personal information with third parties for their own marketing purposes through a cost-free means. If you send a request to the address above, Free Code Camp will provide you with a California Customer Choice Notice that you may use to opt-out of such information sharing. To receive this notice, submit a written request to team@freecodecamp.com, specifying that you seek your "California Customer Choice Notice." Please allow at least thirty (30) days for a response.

    ", + "

    If you are a California resident, you are entitled to prevent sharing of your personal information with third parties for their own marketing purposes through a cost-free means. If you send a request to the address above, Free Code Camp will provide you with a California Customer Choice Notice that you may use to opt-out of such information sharing. To receive this notice, submit a written request to team@freecodecamp.com, specifying that you seek your "California Customer Choice Notice." Please allow at least thirty (30) days for a response.

    ", "

    Acceptance of Privacy Policy Terms and Conditions

    ", - "

    By using this site, you signify your agreement to the terms and conditions of this FreeCodeCamp.com Privacy Policy. If you do not agree to these terms, please do not use this site. We reserve the right, at our sole discretion, to change, modify, add, or remove portions of this policy at any time. All amended terms automatically take effect 30 days after they are initially posted on the site. Please check this page periodically for any modifications. Your continued use of FreeCodeCamp.com following the posting of any changes to these terms shall mean that you have accepted those changes.

    ", - "

    If you have any questions or concerns, please send an email to team@freecodecamp.com.

    ", + "

    By using this site, you signify your agreement to the terms and conditions of this FreeCodeCamp.com Privacy Policy. If you do not agree to these terms, please do not use this site. We reserve the right, at our sole discretion, to change, modify, add, or remove portions of this policy at any time. All amended terms automatically take effect 30 days after they are initially posted on the site. Please check this page periodically for any modifications. Your continued use of FreeCodeCamp.com following the posting of any changes to these terms shall mean that you have accepted those changes.

    ", + "

    If you have any questions or concerns, please send an email to team@freecodecamp.com.

    ", "
    " ] }, @@ -689,7 +703,7 @@ "description": [ "
    ", "

    We're happy to do a quick interview for your publication or show. Here's whom you should contact about what, and how to best reach them:

    ", - "

    ", + "

    ", "

      ", "
    1. Want to talk to about Free Code Camp's curriculum or long-term vision? Reach out to Quincy Larson. He's @ossia on Twitter and @quincylarson on Slack.
    2. ", "
    3. Want to talk about Free Code Camp's open source codebase, infrastructure, or JavaScript in general? Talk to Nathan Leniz. He's @terakilobyte on Twitter and @terakilobyte on Slack.
    4. ", @@ -697,7 +711,7 @@ "
    5. Want to get a camper's perspective on our community? Talk with Bianca Mihai (@biancamihai on Slack and @bubuslubu on Twitter) or Suzanne Atkinson (@adventurebear on Slack and @steelcitycoach on Twitter).", "
    ", "

    ", - "

    We strive to be helpful and transparent in everything we do. We'll do what we can to help you share our community with your audience.

    ", + "

    We strive to be helpful and transparent in everything we do. We'll do what we can to help you share our community with your audience.

    ", "
    " ] }, @@ -706,8 +720,8 @@ "name": "How can I contribute to this guide?", "description": [ "
    ", - "

    Contributing to our field guide is a great way to establish your history on GitHub, add to your portfolio, and help other campers. If you have a question about JavaScript or programming in general that you'd like us to add to the field guide, here are two ways to get it into the guide:

    ", - "

    ", + "

    Contributing to our field guide is a great way to establish your history on GitHub, add to your portfolio, and help other campers. If you have a question about JavaScript or programming in general that you'd like us to add to the field guide, here are two ways to get it into the guide:

    ", + "

    ", "

      ", "
    1. You can message @alex-dixon in Slack with your question.
    2. ", "
    3. You can also contribute to this field guide directly via GitHub pull request, by cloning Free Code Camp's main repository and modifying field-guides.json.
    4. ", diff --git a/views/field-guide/all-articles.jade b/views/field-guide/all-articles.jade index 32dc9d600b..80bc2f9091 100644 --- a/views/field-guide/all-articles.jade +++ b/views/field-guide/all-articles.jade @@ -4,7 +4,7 @@ block content .panel.panel-info .panel-heading.text-center Read our Field Guide in any order .panel-body - .col-xs-12.col-md-8.col-md-offset-2 + .col-xs-12.col-md-10.col-md-offset-1 .col-xs-12.no-right-padding h3 ol From f9386d1291f77c9b7932d5bf50190aa1c6db35ef Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 12:20:20 -0700 Subject: [PATCH 59/81] switching to Terakilobyte's computer --- controllers/resources.js | 2 ++ seed_data/challenges/bonfires.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/resources.js b/controllers/resources.js index 8a9fa041c1..8d852292a4 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -67,6 +67,8 @@ Array.zip = function(left, right, combinerFunction) { }); challengeMap = _.cloneDeep(localChallengeMap); } + //todo remove this debug + debug(challengeMap); })(); diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/bonfires.json index 9f7289e409..7f0c6fd1c1 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/bonfires.json @@ -606,7 +606,7 @@ }, { "_id": "af7588ade1100bde429baf20", - "name" : "Missing letters", + "name" : "Bonfire: Missing letters", "difficulty": "2.05", "description" : [ "Find the missing letter in the passed letter range and return it.", From fb3447c366f648d7154874fb8b2652729bd5680f Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 16:02:25 -0400 Subject: [PATCH 60/81] Update challengeMap display, more consistent dasherization --- controllers/challenge.js | 13 +++++-- controllers/challengeMap.js | 2 +- controllers/fieldGuide.js | 15 +++++--- controllers/resources.js | 17 ++++++++-- seed_data/challenges/basic-html5-and-css.json | 2 +- views/challengeMap/show.jade | 34 ++++++++++--------- 6 files changed, 54 insertions(+), 29 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index bbda541e63..06f33e704a 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -135,7 +135,8 @@ exports.returnCurrentChallenge = function(req, res, next) { } var nameString = req.user.currentChallenge.challengeName.trim() .toLowerCase() - .replace(/\s/g, '-'); + .replace(/\s/g, '-') + .replace(/[^a-z0-9\-]/gi, ''); req.user.save(function(err) { if (err) { return next(err); @@ -147,7 +148,10 @@ exports.returnCurrentChallenge = function(req, res, next) { exports.returnIndividualChallenge = function(req, res, next) { var dashedName = req.params.challengeName; - var challengeName = dashedName.replace(/\-/g, ' '); + var challengeName = dashedName.replace(/\-/g, ' ') + .split(' ') + .slice(1) + .join(' '); Challenge.find({'name': new RegExp(challengeName, 'i')}, function(err, challengeFromMongo) { @@ -164,7 +168,10 @@ exports.returnIndividualChallenge = function(req, res, next) { } var challenge = challengeFromMongo.pop(); // Redirect to full name if the user only entered a partial - var dashedNameFull = challenge.name.toLowerCase().replace(/\s/g, '-'); + var dashedNameFull = challenge.name + .toLowerCase() + .replace(/\s/g, '-') + .replace(/[^a-z0-9\-]/gi, ''); if (dashedNameFull !== dashedName) { return res.redirect('../challenges/' + dashedNameFull); } else { diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index 945c5e9aee..aef68cc4ce 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -23,7 +23,7 @@ module.exports = { var noDuplicatedChallenges = R.uniq(completedList); - var challengeList = resources.allChallenges(); + var challengeList = resources.getChallengeMapForDisplay(); var completedChallengeList = noDuplicatedChallenges .map(function(challenge) { return challenge._id; diff --git a/controllers/fieldGuide.js b/controllers/fieldGuide.js index 2d0809b6a3..49e4d80dab 100644 --- a/controllers/fieldGuide.js +++ b/controllers/fieldGuide.js @@ -5,7 +5,8 @@ var R = require('ramda'), exports.returnIndividualFieldGuide = function(req, res, next) { var dashedName = req.params.fieldGuideName; - var fieldGuideName = dashedName.replace(/\-/g, ' '); + var fieldGuideName = dashedName.replace(/\-/g, ' ') + .replace(/[^a-z0-9\s]/gi, ''); if (req.user) { var completed = req.user.completedFieldGuides; @@ -39,7 +40,9 @@ exports.returnIndividualFieldGuide = function(req, res, next) { var fieldGuide = R.head(fieldGuideFromMongo); var dashedNameFull = - fieldGuide.name.toLowerCase().replace(/\s/g, '-').replace(/\?/g, ''); + fieldGuide.name.toLowerCase() + .replace(/\s/g, '-') + .replace(/[^a-z0-9\-]/gi, ''); if (dashedNameFull !== dashedName) { return res.redirect('../field-guide/' + dashedNameFull); @@ -68,7 +71,7 @@ exports.showAllFieldGuides = function(req, res) { exports.returnNextFieldGuide = function(req, res, next) { if (!req.user) { - return res.redirect('/field-guide/how-do-i-use-this-guide?'); + return res.redirect('/field-guide/how-do-i-use-this-guide'); } var displayedFieldGuides = @@ -89,9 +92,11 @@ exports.returnNextFieldGuide = function(req, res, next) { ].join('') }); } - return res.redirect('../field-guide/how-do-i-use-this-guide?'); + return res.redirect('../field-guide/how-do-i-use-this-guide'); } - var nameString = fieldGuide.name.toLowerCase().replace(/\s/g, '-'); + var nameString = fieldGuide.name.toLowerCase() + .replace(/\s/g, '-') + .replace(/[^a-z0-9\-]/gi, ''); return res.redirect('../field-guide/' + nameString); }); }; diff --git a/controllers/resources.js b/controllers/resources.js index 8d852292a4..0fcef198ab 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -28,7 +28,7 @@ var async = require('async'), * Cached values */ var allFieldGuideIds, allFieldGuideNames, allNonprofitNames, - challengeMap, challengeMapWithIds, + challengeMap, challengeMapForDisplay, challengeMapWithIds, challengeMapWithNames, allChallengeIds, allChallenges; /** @@ -67,13 +67,24 @@ Array.zip = function(left, right, combinerFunction) { }); challengeMap = _.cloneDeep(localChallengeMap); } - //todo remove this debug - debug(challengeMap); })(); module.exports = { + getChallengeMapForDisplay: function() { + if (!challengeMapForDisplay) { + challengeMapForDisplay = {}; + Object.keys(challengeMap).forEach(function(key) { + challengeMapForDisplay[key] = { + name: challengeMap[key].name, + challenges: challengeMap[key].challenges + } + }); + } + return challengeMapForDisplay; + }, + getChallengeMapWithIds: function() { if (!challengeMapWithIds) { challengeMapWithIds = {}; diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json index a3827c4395..1ba903a877 100644 --- a/seed_data/challenges/basic-html5-and-css.json +++ b/seed_data/challenges/basic-html5-and-css.json @@ -1,5 +1,5 @@ { - "name": "Waypoint: Basic HTML5 and CSS", + "name": "Basic HTML5 and CSS", "order" : 0.002, "challenges": [ { diff --git a/views/challengeMap/show.jade b/views/challengeMap/show.jade index 43f06a04d3..0cb1ace524 100644 --- a/views/challengeMap/show.jade +++ b/views/challengeMap/show.jade @@ -23,23 +23,25 @@ block content span.text-primary #{daysRunning}   | days ago. .spacer - h3.negative-15 - ol - for challenge in challengeList - if completedChallengeList.indexOf(challenge._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center - .col-xs-12.col-sm-9.col-md-10 - li.faded - a(href="/challenges/#{challenge.name}")= challenge.name + .negative-15 + for challengeBlock in challengeList + h3 #{challengeBlock.name} + ol + for challenge in challengeBlock.challenges + if completedChallengeList.indexOf(challenge._id) > -1 + .row + .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.large-p + .col-xs-12.col-sm-9.col-md-10 + li.faded.large-p + a(href="/challenges/#{challenge.name}")= challenge.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/challenges/#{challenge.name}")= challenge.name + else + .row + .hidden-xs.col-sm-3.col-md-2 + span + .col-xs-12.col-sm-9.col-md-10 + li.large-p + a(href="/challenges/#{challenge.name}")= challenge.name h2 span.ion-ios-heart   Nonprofit Projects (800 hours of real-world experience)* From 1c4b40c8e6ee616aa60cf25d900d5670d8c6bd9a Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 17:27:27 -0400 Subject: [PATCH 61/81] Update to bonfires. Successfully completing triggers a save. "Paired with" form field moved to bonfire view. Controller hardened for checking pair as button is no longer disabled for unfound username --- controllers/challenge.js | 72 ++++++++++++------- .../coursewaresJSFramework_0.0.2.js | 28 ++++++-- public/js/main.js | 21 +----- views/coursewares/showBonfire.jade | 28 ++++---- 4 files changed, 84 insertions(+), 65 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 06f33e704a..76e273f681 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -324,44 +324,62 @@ exports.completedBonfire = function (req, res, next) { req.user.uncompletedChallenges.splice(index, 1); } pairedWith = pairedWith.pop(); + if (pairedWith) { - index = pairedWith.uncompletedChallenges.indexOf(challengeId); - if (index > -1) { - pairedWith.progressTimestamps.push(Date.now() || 0); - pairedWith.uncompletedChallenges.splice(index, 1); + index = pairedWith.uncompletedChallenges.indexOf(challengeId); + if (index > -1) { + pairedWith.progressTimestamps.push(Date.now() || 0); + pairedWith.uncompletedChallenges.splice(index, 1); + } + + pairedWith.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: req.user._id, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); + + req.user.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: pairedWith._id, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); } + // User said they paired, but pair wasn't found + req.user.completedChallenges.push({ + _id: challengeId, + name: challengeName, + completedWith: null, + completedDate: isCompletedDate, + solution: isSolution, + challengeType: 5 + }); - pairedWith.completedChallenges.push({ - _id: challengeId, - name: challengeName, - completedWith: req.user._id, - completedDate: isCompletedDate, - solution: isSolution, - challengeType: 5 - }); - - req.user.completedChallenges.push({ - _id: challengeId, - name: challengeName, - completedWith: pairedWith._id, - completedDate: isCompletedDate, - solution: isSolution, - challengeType: 5 - }); req.user.save(function (err, user) { if (err) { return next(err); } - pairedWith.save(function (err, paired) { - if (err) { - return next(err); - } - if (user && paired) { + if (pairedWith) { + pairedWith.save(function (err, paired) { + if (err) { + return next(err); + } + if (user && paired) { + res.send(true); + } + }); + } else { + if (user) { res.send(true); } - }); + } }); } }); diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js index 01f09d8f19..3abe01c1dc 100644 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js +++ b/public/js/lib/coursewares/coursewaresJSFramework_0.0.2.js @@ -239,10 +239,28 @@ var runTests = function(err, data) { function showCompletion() { var time = Math.floor(Date.now()) - started; ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time +', Attempts: ' + attempts); - $('#complete-courseware-dialog').modal('show'); - $('#complete-courseware-dialog').keydown(function(e) { - if (e.ctrlKey && e.keyCode == 13) { - $('#next-courseware-button').click(); + var bonfireSolution = myCodeMirror.getValue(); + var didCompleteWith = $('#completed-with').val() || null; + $.post( + '/completed-bonfire/', + { + challengeInfo: { + challengeId: challenge_Id, + challengeName: challenge_Name, + completedWith: didCompleteWith, + challengeType: challengeType, + solution: bonfireSolution + } + }, function(res) { + if (res) { + $('#complete-courseware-dialog').modal('show'); + $('#complete-courseware-dialog').keydown(function (e) { + if (e.ctrlKey && e.keyCode == 13) { + $('#next-courseware-button').click(); + } + }); + } } - }); + ); + } diff --git a/public/js/main.js b/public/js/main.js index ef692b4d42..ed6c881f99 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -215,29 +215,10 @@ $(document).ready(function() { }); break; case challengeTypes.BONFIRE: - var bonfireSolution = myCodeMirror.getValue(); - var didCompleteWith = $('#completed-with').val() || null; - $.post( - '/completed-bonfire/', - { - challengeInfo: { - challengeId: challenge_Id, - challengeName: challenge_Name, - completedWith: didCompleteWith, - challengeType: challengeType, - solution: bonfireSolution - } - }, - function(res) { - if (res) { - window.location.href = '/challenges/next-challenge'; - } - } - ); + window.location.href = '/challenges/next-challenge'; default: break; } - } }); diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index e68b9d4115..00787fee1d 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -16,7 +16,7 @@ block content script(type='text/javascript', src='/js/lib/jailed/jailed.js') script(type='text/javascript', src='/js/lib/coursewares/sandbox.js') - .row + .row(ng-controller="pairedWithController") .col-xs-12.col-sm-12.col-md-4.bonfire-top #testCreatePanel h1#bonfire-name.text-center= name @@ -79,6 +79,18 @@ block content span.ion-arrow-up-b | Less information + if (user) + form.form-horizontal(novalidate='novalidate', name='completedWithForm') + .form-group.text-center + .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn + // extra field to distract password tools like lastpass from injecting css into our username field + input.form-control(ng-show="false") + label(for="existingUser") If you're pairing with someone, enter their FreeCodeCamp username here + input.form-control#completed-with(name="existingUser", placeholder="Pair Username", existing-username='', ng-model="existingUser", autofocus) + .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") + alert(type='danger') + span.ion-close-circled + | Username not found #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) .button-spacer .btn-group.input-group.btn-group-justified @@ -122,23 +134,13 @@ block content .modal-content .modal-header.challenge-list-header= compliment a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body(ng-controller="pairedWithController") + .modal-body .text-center .animated.zoomInDown.delay-half span.completion-icon.ion-checkmark-circled.text-primary - if (user) - form.form-horizontal(novalidate='novalidate', name='completedWithForm') - .form-group.text-center - .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn - // extra field to distract password tools like lastpass from injecting css into our username field - input.form-control(ng-show="false") - input.form-control#completed-with(name="existingUser", placeholder="If you paired, enter your pair's username here", existing-username='', ng-model="existingUser", autofocus) - .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") - alert(type='danger') - span.ion-close-circled - | Username not found - a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next bonfire (ctrl + enter) + a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) Go to my next challenge (ctrl + enter) - if (user.progressTimestamps.length > 2) From f7252be9daa3026dc629090fdb584fe1efc500be Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 17:30:10 -0400 Subject: [PATCH 62/81] Minor view cleanup. Closes #478 --- views/coursewares/showBonfire.jade | 2 -- 1 file changed, 2 deletions(-) diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index 00787fee1d..560a9d3008 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -127,8 +127,6 @@ block content textarea#codeEditor(autofocus=true, style='display: none;') script(src='/js/lib/coursewares/coursewaresJSFramework_0.0.2.js') - - #complete-courseware-dialog.modal(tabindex='-1') .modal-dialog.animated.zoomIn.fast-animation .modal-content From 8fb2f9d2e0fd9ec8e94f8f6b5b754fb4c65a0403 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 15:17:04 -0700 Subject: [PATCH 63/81] continue fleshing out waypoints --- seed_data/challenges/advanced-bonfires.json | 219 ++++++++++++++++++ .../{bonfires.json => basic-bonfires.json} | 2 +- seed_data/challenges/basic-javascript.json | 29 ++- .../challenges/full-stack-javascript.json | 51 +++- .../challenges/functional-programming.json | 23 ++ .../challenges/intermediate-bonfires.json | 99 ++++++++ .../object-oriented-javascript.json | 131 +++++++++++ 7 files changed, 541 insertions(+), 13 deletions(-) create mode 100644 seed_data/challenges/advanced-bonfires.json rename seed_data/challenges/{bonfires.json => basic-bonfires.json} (99%) create mode 100644 seed_data/challenges/functional-programming.json create mode 100644 seed_data/challenges/intermediate-bonfires.json create mode 100644 seed_data/challenges/object-oriented-javascript.json diff --git a/seed_data/challenges/advanced-bonfires.json b/seed_data/challenges/advanced-bonfires.json new file mode 100644 index 0000000000..93d247b1f5 --- /dev/null +++ b/seed_data/challenges/advanced-bonfires.json @@ -0,0 +1,219 @@ +{ + "name": "Advanced Bonfires", + "order" : 0.007, + "challenges": [ + { + "_id": "aff0395860f5d3034dc0bfc9", + "name": "Bonfire: Validate US Telephone Numbers", + "difficulty": "4.01", + "description": [ + "Return true if the passed string is a valid US phone number", + "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", + "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", + "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "tests": [ + "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", + "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", + "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", + "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", + "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", + "assert.deepEqual(telephoneCheck(\"55555555\"), false);", + "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", + "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", + "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", + "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", + "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" + ], + "challengeSeed": [ + "function telephoneCheck(str) {", + " // Good luck!", + " return true;", + "}", + "", + "", + "", + "telephoneCheck(\"555-555-5555\");" + ], + "MDNlinks" : ["RegExp"], + "challengeType": 5 + }, + { + "_id": "a3f503de51cf954ede28891d", + "name": "Bonfire: Symmetric Difference", + "difficulty": "4.02", + "description": [ + "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", + "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function sym(args) {", + " return arguments;", + "}", + "", + "sym([1, 2, 3], [5, 2, 1, 4]);" + ], + "tests": [ + "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", + "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", + "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", + "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" + ], + "MDNlinks" : ["Array.reduce()"], + "challengeType": 5 + }, + { + "_id": "aa2e6f85cab2ab736c9a9b24", + "name": "Bonfire: Cash Register", + "difficulty": "4.03", + "description": [ + "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function drawer(price, cash, cid) {", + " var change;", + " // Here is your change, ma'am.", + " return change;", + "}", + "", + "// Example cash-in-drawer array:", + "// [['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]]", + "", + "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" + ], + "tests": [ + "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "expect(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", + "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", + "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" + ], + "MDNlinks" : ["Global Object"], + "challengeType": 5 + }, + { + "_id": "a56138aff60341a09ed6c480", + "name": "Bonfire: Inventory Update", + "difficulty": "4.04", + "description": [ + "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function inventory(arr1, arr2) {", + " // All inventory must be accounted for or you're fired!", + " return arr1;", + "}", + "", + "// Example inventory lists", + "var curInv = [", + " [21, 'Bowling Ball'],", + " [2, 'Dirty Sock'],", + " [1, 'Hair Pin'],", + " [5, 'Microphone']", + "];", + "", + "var newInv = [", + " [2, 'Hair Pin'],", + " [3, 'Half-Eaten Apple'],", + " [67, 'Bowling Ball'],", + " [7, 'Toothpaste']", + "];", + "", + "inventory(curInv, newInv);" + ], + "tests": [ + "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", + "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", + "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", + "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" + ], + "MDNlinks" : ["Global Array Object"], + "challengeType": 5 + }, + { + "_id": "a7bf700cd123b9a54eef01d5", + "name": "Bonfire: No repeats please", + "difficulty": "4.05", + "description": [ + "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", + "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function permAlone(str) {", + " return str;", + "}", + "", + "permAlone('aab');" + ], + "tests": [ + "expect(permAlone('aab')).to.be.a.number;", + "expect(permAlone('aab')).to.equal(2);", + "expect(permAlone('aaa')).to.equal(0);", + "expect(permAlone('aabb')).to.equal(8);", + "expect(permAlone('abcdefa')).to.equal(3600);", + "expect(permAlone('abfdefa')).to.equal(2640);", + "expect(permAlone('zzzzzzzz')).to.equal(0);" + ], + "MDNlinks" : ["Permutations", "RegExp"], + "challengeType": 5 + }, + { + "_id": "a19f0fbe1872186acd434d5a", + "name": "Bonfire: Friendly Date Ranges", + "difficulty": "4.06", + "description": [ + "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", + "It must not show any redundant information in the date range.", + "For example, if the year and month are the same then only the day range should be displayed.", + "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", + "Input date is formatted as YYYY-MM-DD", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function friendly(str) {", + " return str;", + "}", + "", + "friendly(['2015-07-01', '2015-07-04']);" + ], + "tests": [ + "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", + "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", + "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", + "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th, 2016']);", + "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", + "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" + ], + "MDNlinks": ["String.split()", "String.substr()", "parseInt()"], + "challengeType": 5 + } + ] +} diff --git a/seed_data/challenges/bonfires.json b/seed_data/challenges/basic-bonfires.json similarity index 99% rename from seed_data/challenges/bonfires.json rename to seed_data/challenges/basic-bonfires.json index 7f0c6fd1c1..c4852dbc90 100644 --- a/seed_data/challenges/bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -1,5 +1,5 @@ { - "name": "Bonfires", + "name": "Basic Bonfires", "order" : 0.007, "challenges": [ { diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index 1f18b89bc7..9129466cfd 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -1,5 +1,5 @@ { - "name": "Waypoint: Basic JavaScript", + "name": "Basic JavaScript", "order" : 0.006, "challenges": [ { @@ -125,7 +125,14 @@ "It's time to learn the most powerful tool your browser has - the Development Tools!", "If you aren't already using Chrome, you'll want to download it here: http://www.google.com/chrome/. While it's true that Firefox has a tool called Firebug that is very similar to Chrome's DevTools, we will use Chrome for this challenge.", "Note that this course, jointly produced by Google and Code School, is technologically impressive, but occasionally buggy. If you encounter a bug, just ignore it and keep going.", - "Go to http://discover-devtools.codeschool.com and complete this short course." + "Go to http://discover-devtools.codeschool.com.", + "Complete \"Chapter 1: Getting Started & Basic DOM and Styles\".", + "Complete \"Chapter 2: Advanced DOM and Styles\".", + "Complete \"Chapter 3: Working with the Console\".", + "Complete \"Chapter 4: Debugging JavaScript\".", + "Complete \"Chapter 5: Improving Network Performance\".", + "Complete \"Chapter 6: Improving Performance\".", + "Complete \"Chapter 7: Memory Profiling\".", ], "challengeType": 2, "tests": [], @@ -138,9 +145,17 @@ "challengeSeed": "112547802", "description": [ "You can use a Regular Expression, or \"Regex\", to select specific types of characters in text.", - "Check out http://www.regexr.com. It's a Regular Expression Sandbox.", - "Now go to http://www.regexone.com and complete the tutorial and exercises 1 - 6.", - "Note that you can click \"continue\" to move on to the next step as soon as all the tasks have green check marks beside them. You can often do this just by using the wildcard \"dot\" operator, but try to use the techniques that each lesson recommends." + "Check out http://www.regexr.com. It's a Regular Expression Sandbox for experimenting with Regular Expressions.", + "Now go to http://www.regexone.com.", + "Note that you can click \"continue\" to move on to the next step as soon as all the tasks have green check marks beside them. You can often do this just by using the wildcard \"dot\" operator, but try to use the techniques that each lesson recommends.", + "Complete \"Complete the 15-lesson tutorial\"", + "Complete \"Complete Practical Example 1: Matching a scientific or decimal number\"", + "Complete \"Complete Practical Example 2: Matching phone numbers\"", + "Complete \"Complete Practical Example 3: Matching emails\"", + "Complete \"Complete Practical Example 4: Matching HTML\"", + "Complete \"Complete Practical Example 5: Matching specific filenames\"", + "Complete \"Complete Practical Example 6: Trimming whitespace from start and end of line\"", + "Once you've completed these challenges, move on to our next Waypoint." ], "challengeType": 2, "tests": [], @@ -156,7 +171,7 @@ "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", - "We have a special chat room for people ready to pair program. Go to our Slack chatroom and navigate to the #letspair channel and type \"Hello Pair Programmers!\"", + "We have a special chat room for people ready to pair program. Go to our Slack chat room, navigate to the #letspair channel and type \"Hello Pair Programmers!\"", "If someone is available, they will be your \"pair\" - the person you pair programming with.", "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", @@ -168,7 +183,7 @@ "Once you you finish pair programming, end the session in Screen Hero session.", "Congratulations! You have completed your first pair programming session.", "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", - "Mark this challenge as complete and move on to the Bonfires." + "Mark this Waypoint complete and move on." ], "challengeType": 2, "tests": [], diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index 4a9b880ff9..d63a12552b 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -85,7 +85,25 @@ "Run this command: sudo npm install how-to-npm -g", "Now start this tutorial by running how-to-npm", "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through all of the the tutorial's steps before moving on." + "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.", + "Complete \"Install NPM\"", + "Complete \"Dev Environment\"", + "Complete \"Login\"", + "Complete \"Start a Project\"", + "Complete \"Install a Module\"", + "Complete \"Listing Dependencies\"", + "Complete \"NPM Test\"", + "Complete \"Package Niceties\"", + "Complete \"Publish\"", + "Complete \"Version\"", + "Complete \"Publish Again\"", + "Complete \"Dist Tag\"", + "Complete \"Dist Tag Removal\"", + "Complete \"Outdated\"", + "Complete \"Update\"", + "Complete \"RM\"", + "Complete \"Finale\"", + "Once you've completed these first 7 challenges, move on to our next waypoint.", ], "challengeType": 2, "tests": [] @@ -109,7 +127,15 @@ "Run this command: sudo npm install learnyounode -g", "Now start this tutorial by running learnyounode", "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through the tutorial's steps 1 through 7 before moving on." + "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.", + "Complete \"Hello World\"", + "Complete \"Baby Steps\"", + "Complete \"My First I/O\"", + "Complete \"My First Async I/O\"", + "Complete \"Filtered LS\"", + "Complete \"Make it Modular\"", + "Complete \"HTTP Client\"", + "Once you've completed these first 7 challenges, move on to our next waypoint.", ], "challengeType": 2, "tests": [] @@ -121,8 +147,12 @@ "challengeSeed": "126411561", "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 8 through 10.", + "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.", "Return to the c9.io workspace you created Now start this tutorial by running learnyounode", - "Follow the directions and work through all of the the tutorial's steps before moving on." + "Complete \"HTTP Collect\"", + "Complete \"Juggling Async\"", + "Complete \"Time Server\"", + "Once you've completed these 3 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] @@ -134,8 +164,12 @@ "challengeSeed": "126411561", "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 11 through 13.", + "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.", "Return to the c9.io workspace you created for the previous LearnYouNode challenges and start the tutorial by running learnyounode", - "Follow the directions and work through all of the the tutorial's steps before moving on." + "Complete \"HTTP File Server\"", + "Complete \"HTTP Uppercaserer\"", + "Complete \"HTTP JSON API Server\"", + "Once you've completed these final 3 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] @@ -159,7 +193,14 @@ "Run this command: git clone http://github.com/reddock/fcc_express && chmod 744 fcc_express/setup.sh && fcc_express/setup.sh && source ~/.profile", "Now start this tutorial by running expressworks", "Note that you can resize the c9.io's windows by dragging their borders.", - "Follow the directions and work through all of the the tutorial's steps before moving on." + "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.", + "Complete \"Hello World\"", + "Complete \"Juggling Async\"", + "Complete \"Time Server\"", + "Complete \"HTTP Collect\"", + "Complete \"Juggling Async\"", + "Complete \"Time Server\"", + "Once you've completed these challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] diff --git a/seed_data/challenges/functional-programming.json b/seed_data/challenges/functional-programming.json new file mode 100644 index 0000000000..64252068d2 --- /dev/null +++ b/seed_data/challenges/functional-programming.json @@ -0,0 +1,23 @@ +{ + "name": "Functional Programming", + "order" : 0.006, + "challenges": [ + { + "_id": "bd7129d8c441eddfaeb5bedf", + "name": "Waypoint: Practice Functional Programming", + "difficulty": 0.01, + "challengeSeed": "114604814", + "description": [ + "Functional programming holds the key to unlocking JavaScript's powerful asynchronous features.", + "Functional programming in JavaScript involves using five key functions: \"map\", \"reduce\", \"filter\", \"concatAll\", and \"zip\".", + "Jafar Husain's 42-step interactive Functional Programming course will familiarize you with the various ways you can recombine these functions.", + "Click here to go to the challenge: http://jhusain.github.io/learnrx/.", + "This challenge will take several hours, but don't worry. Husain's website will save your progress (using your browser's local storage) so you don't need to finish it in one sitting.", + "If you've spent several minutes on one of these challenges, and still can't figure out its correct answer, you can click \"show answer\", then click \"run\" to advance to the next challenge. Be sure to read the correct answer and make sure you understand it before moving on." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + } + ] +} diff --git a/seed_data/challenges/intermediate-bonfires.json b/seed_data/challenges/intermediate-bonfires.json new file mode 100644 index 0000000000..efcd5b3606 --- /dev/null +++ b/seed_data/challenges/intermediate-bonfires.json @@ -0,0 +1,99 @@ +{ + "name": "Bonfires", + "order" : 0.007, + "challenges": [ + { + "_id": "a2f1d72d9b908d0bd72bb9f6", + "name": "Bonfire: Make a Person", + "difficulty": "3.01", + "description": [ + "Fill in the object constructor with the methods specified in the tests.", + "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", + "All functions that take an argument have an arity of 1, and the argument will be a string.", + "These methods must be the only available means for interacting with the object.", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "var Person = function(firstAndLast) {", + " return firstAndLast;", + "};", + "", + "var bob = new Person('Bob Ross');", + "bob.getFullName();" + ], + "tests": [ + "expect(Object.keys(bob).length).to.eql(6);", + "expect(bob instanceof Person).to.be.true;", + "expect(bob.firstName).to.be.undefined();", + "expect(bob.lastName).to.be.undefined();", + "expect(bob.getFirstName()).to.eql('Bob');", + "expect(bob.getLastName()).to.eql('Ross');", + "expect(bob.getFullName()).to.eql('Bob Ross');", + "bob.setFirstName('Happy');", + "expect(bob.getFirstName()).to.eql('Happy');", + "bob.setLastName('Trees');", + "expect(bob.getLastName()).to.eql('Trees');", + "bob.setFullName('George Carlin');", + "expect(bob.getFullName()).to.eql('George Carlin');", + "bob.setFullName('Bob Ross');" + ], + "MDNlinks": ["Closures", "Details of the Object Model"], + "challengeType": 5 + }, + { + "_id": "af4afb223120f7348cdfc9fd", + "name": "Bonfire: Map the Debris", + "difficulty": "3.02", + "description": [ + "Return a new array that transforms the element's average altitude into their orbital periods.", + "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", + "You can read about orbital periods on wikipedia.", + "The values should be rounded to the nearest whole number. The body being orbited is Earth.", + "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function orbitalPeriod(arr) {", + " var GM = 398600.4418;", + " var earthRadius = 6367.4447;", + " return arr;", + "}", + "", + "orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);" + ], + "tests": [ + "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", + "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" + ], + "MDNlinks": ["Math.pow()"], + "challengeType": 5 + }, + { + "_id" : "a3f503de51cfab748ff001aa", + "name": "Bonfire: Pairwise", + "difficulty": "3.03", + "description": [ + "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", + "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", + "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!", + "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." + ], + "challengeSeed": [ + "function pairwise(arr, arg) {", + " return arg;", + "}", + "", + "pairwise([1,4,2,3,0,5], 7);" + ], + "tests": [ + "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", + "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", + "expect(pairwise([1,1,1], 2)).to.equal(1);", + "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", + "expect(pairwise([], 100)).to.equal(0);" + ], + "MDNlinks" : ["Array.reduce()"], + "challengeType": 5 + } + ] +} diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json new file mode 100644 index 0000000000..6696b68e4d --- /dev/null +++ b/seed_data/challenges/object-oriented-javascript.json @@ -0,0 +1,131 @@ +{ + "name": "Object Oriented JavaScript", + "order" : 0.006, + "challenges": [ + { + "_id": "bd7129d8c441eddfaeb5bddf", + "name": "Waypoint: Scope Your Variables", + "difficulty": 0.01, + "challengeSeed": "114604814", + "description": [ + "Objects will allow you to build applications more efficiently by using small, reusable blocks of code.", + "This course for Udacity will help you learn Object-Oriented Programming in JavaScript.", + "First, we'll learn how JavaScript works in terms of scopes. You'll learn the difference between a \"Lexical Scope\" and an Execution Context.", + "This theoretical foundation is useful for understanding when an a variable can be accessed and when it can't.", + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668697/m-2541189051 and start the course.", + "Once you've completed this first section of scopes, mark this Waypoint complete and move on to the next one." + ], + "_id": "bd7131d8c441eddfaeb5bdbf", + "name": "Waypoint: Reference your Current Object with This", + "difficulty": 0.03, + "challengeSeed": "114614220", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668699/m-2780408563 and start the course.", + "Once you've completed this section of using the keyword \"this\", mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7132d8c441eddfaeb5bdaf", + "name": "Waypoint: Traverse the Prototype Chain", + "difficulty": 0.04, + "challengeSeed": "114612889", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668700/m-2616738615 and start the course.", + "Once you've completed this section on prototype chain traversal, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7133d8c441eddfaeb5bd0f", + "name": "Waypoint: Reuse Code with Decorators", + "difficulty": 0.05, + "challengeSeed": "114612888", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468536/m-2697628561 and start the course.", + "Once you've completed this section of decorators, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7134d8c441eddfaeb5bd1f", + "name": "Waypoint: Build Objects with Functional Classes", + "difficulty": 0.06, + "challengeSeed": "114612887", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468537/m-2961989110 and start the course.", + "Once you've completed this section of functional classes, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7135d8c441eddfaeb5bd2f", + "name": "Waypoint: Build Objects with Prototypal Classes", + "difficulty": 0.07, + "challengeSeed": "114612885", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468538/m-3034538557 and start the course.", + "Once you've completed this section of prototypal classes, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7136d8c441eddfaeb5bd3f", + "name": "Waypoint: Understand Pseudoclassical Patterns", + "difficulty": 0.08, + "challengeSeed": "114612882", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468539/e-2783098540/m-2695768694 and start the course.", + "Once you've completed this section pseudoclasses, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7136d8c441eddfaeb5bd4f", + "name": "Waypoint: Subclass one Object to Another", + "difficulty": 0.09, + "challengeSeed": "114612882", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468540/m-2785128536 and start the course.", + "Once you've completed this section on subclassing, mark this Waypoint complete and move on to the next one." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, + { + "_id": "bd7136d8c441eddfaeb5bd5f", + "name": "Waypoint: Use Pseudoclassical Subclasses", + "difficulty": 0.10, + "challengeSeed": "114612882", + "description": [ + "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468541/e-2693158566/m-2688408703 and start the course.", + "Once you've completed this final section on pseudoclassical subclassing, mark this Waypoint complete and move on." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + } + ] +} From 0debdc5fd694033491fa780fbe0ae974a794c90e Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 19:02:09 -0400 Subject: [PATCH 64/81] Use middleware to migrate users --- app.js | 4 ++ controllers/user.js | 43 ++++++++++++++++++++++ seed_data/challenges/basic-javascript.json | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 55dc7bdb90..0c5012265b 100755 --- a/app.js +++ b/app.js @@ -216,6 +216,10 @@ app.use(function (req, res, next) { next(); }); +// User migration middleware + +app.use(userController.userMigration); + /** * Main routes. */ diff --git a/controllers/user.js b/controllers/user.js index 20e69b1825..57e581bd59 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -10,6 +10,49 @@ var _ = require('lodash'), resources = require('./resources'), R = require('ramda'); + + +/** + * + * @param req + * @param res + * @returns null + * Middleware to migrate users from fragmented challenge structure to unified + * challenge structure + */ +exports.userMigration = function(req, res, next) { + debug('user migration called'); + var user = req.user; + if (!user.migratedToUnifiedChallengeStructure && user) { + user.migratedToUnifiedChallengeStructure = true; + user.completedChallenges = R.filter(function (elem) { + return elem; // getting rid of undefined + }, R.concat( + user.completedCoursewares, + user.completedBonfires.map(function (bonfire) { + return ({ + completedDate: bonfire.completedDate, + _id: bonfire._id, + name: bonfire.name, + completedWith: bonfire.completedWith, + solution: bonfire.solution, + githubLink: '', + verified: false, + challengeType: 5 + }); + }) + )); + user.save(function (err) { + if (err) { + next(err); + } else { + next(req, res); + } + }) + } + next(req, res); +}; + /** * GET /signin * Siginin page. diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index 9129466cfd..4865ed9af2 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -132,7 +132,7 @@ "Complete \"Chapter 4: Debugging JavaScript\".", "Complete \"Chapter 5: Improving Network Performance\".", "Complete \"Chapter 6: Improving Performance\".", - "Complete \"Chapter 7: Memory Profiling\".", + "Complete \"Chapter 7: Memory Profiling\"." ], "challengeType": 2, "tests": [], From 08cf4407acb986372a1f5ab3800f291b41d019cc Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 16:26:04 -0700 Subject: [PATCH 65/81] further improvements to challenges --- seed_data/challenges/bootstrap.json | 2 +- .../object-oriented-javascript.json | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index cc5aba1e81..fb75777f7f 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -1,6 +1,6 @@ { "name": "Bootstrap", - "order" : 0.003, + "order" : 0.004, "challenges": [ { "_id": "bad87fee1348bd9acde08812", diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json index 6696b68e4d..6f30751a96 100644 --- a/seed_data/challenges/object-oriented-javascript.json +++ b/seed_data/challenges/object-oriented-javascript.json @@ -15,12 +15,17 @@ "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668697/m-2541189051 and start the course.", "Once you've completed this first section of scopes, mark this Waypoint complete and move on to the next one." - ], + ] + }, + { "_id": "bd7131d8c441eddfaeb5bdbf", "name": "Waypoint: Reference your Current Object with This", "difficulty": 0.03, "challengeSeed": "114614220", "description": [ + "In this section, you'll learn how you can use \"this\" to dynamically point to your current object.", + "For example, if we were inside the function camper.completeCourse(), \"this\" would refer to the specific camper we were running the function on.", + "Note that this section has several trick questions, designed to make you think. Don't get hung up on them, just keep moving forward.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668699/m-2780408563 and start the course.", "Once you've completed this section of using the keyword \"this\", mark this Waypoint complete and move on to the next one." @@ -35,6 +40,8 @@ "difficulty": 0.04, "challengeSeed": "114612889", "description": [ + "Next we'll learn about the multiple ways you can create a copy of an object.", + "We'll also learn how an object's missing attributes can traverse the \"prototype chain\".", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668700/m-2616738615 and start the course.", "Once you've completed this section on prototype chain traversal, mark this Waypoint complete and move on to the next one." @@ -49,6 +56,9 @@ "difficulty": 0.05, "challengeSeed": "114612888", "description": [ + "In this section, we'll learn about the Decorator Pattern.", + "The Decorator pattern will help you \"decorate\" an existing object with additional attributes. This pattern helps you reuse code, reducing the total amount of code you'll need to write and maintain.", + "It's a convenient way to add functionality to objects without changing their underlying structure.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468536/m-2697628561 and start the course.", "Once you've completed this section of decorators, mark this Waypoint complete and move on to the next one." @@ -63,6 +73,8 @@ "difficulty": 0.06, "challengeSeed": "114612887", "description": [ + "Now we'll go over the simplest way to implement a JavaScript class.", + "A class is a set of functions that you can use to easily produce similar objects.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468537/m-2961989110 and start the course.", "Once you've completed this section of functional classes, mark this Waypoint complete and move on to the next one." @@ -77,6 +89,9 @@ "difficulty": 0.07, "challengeSeed": "114612885", "description": [ + "Now we'll learn how one object can be prototyped off of another object.", + "Prototype objects delegate their \"failed lookups\" up the \"prototype chain\".", + "This means that if I create a second object based off another object, then try to access an attribute the second object doesn't have, JavaScript will \"fall through\" to the original object to see whether it has that attribute.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468538/m-3034538557 and start the course.", "Once you've completed this section of prototypal classes, mark this Waypoint complete and move on to the next one." @@ -91,6 +106,9 @@ "difficulty": 0.08, "challengeSeed": "114612882", "description": [ + "JavaScript doesn't have the traditional \"classes\" that lower-level languages like C and Java have.", + "Instead, JavaScript does some tricks to allow you to write code as though it had these traditional classes. We call these \"pseudo-classes\".", + "In this section, we'll learn how to build these pseudo-classes, and some tricks for later figuring out where these objects came from.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468539/e-2783098540/m-2695768694 and start the course.", "Once you've completed this section pseudoclasses, mark this Waypoint complete and move on to the next one." @@ -105,6 +123,8 @@ "difficulty": 0.09, "challengeSeed": "114612882", "description": [ + "Now we know the three ways of creating objects (through functions, prototyping and pseudo classing).", + "Let's learn how to subclass one object to another. This will give our new object the attributes of the original object. It will allow us to make further modifications new object without affecting the original object.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468540/m-2785128536 and start the course.", "Once you've completed this section on subclassing, mark this Waypoint complete and move on to the next one." @@ -119,6 +139,7 @@ "difficulty": 0.10, "challengeSeed": "114612882", "description": [ + "This final section will teach us how to create subclasses from pseudo classes.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468541/e-2693158566/m-2688408703 and start the course.", "Once you've completed this final section on pseudoclassical subclassing, mark this Waypoint complete and move on." From c115bc355af324b062c8259c345f50d24aea4c10 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 16:37:21 -0700 Subject: [PATCH 66/81] resequence and retitle challenge sections --- seed_data/challenges/advanced-bonfires.json | 4 +- seed_data/challenges/basejumps.json | 4 +- seed_data/challenges/basic-bonfires.json | 2 +- seed_data/challenges/bootstrap.json | 4 +- .../challenges/full-stack-javascript.json | 2 +- .../challenges/functional-programming.json | 2 +- .../challenges/intermediate-bonfires.json | 4 +- .../challenges/jquery-ajax-and-json.json | 324 +++--------------- .../object-oriented-javascript.json | 2 +- seed_data/challenges/ziplines.json | 4 +- seed_data/future-jquery-ajax-json.json | 300 ++++++++++++++++ 11 files changed, 363 insertions(+), 289 deletions(-) create mode 100644 seed_data/future-jquery-ajax-json.json diff --git a/seed_data/challenges/advanced-bonfires.json b/seed_data/challenges/advanced-bonfires.json index 93d247b1f5..50829b7473 100644 --- a/seed_data/challenges/advanced-bonfires.json +++ b/seed_data/challenges/advanced-bonfires.json @@ -1,6 +1,6 @@ { - "name": "Advanced Bonfires", - "order" : 0.007, + "name": "Advanced Algorithm Scripting", + "order" : 0.011, "challenges": [ { "_id": "aff0395860f5d3034dc0bfc9", diff --git a/seed_data/challenges/basejumps.json b/seed_data/challenges/basejumps.json index d47df7972c..c96b49c00a 100644 --- a/seed_data/challenges/basejumps.json +++ b/seed_data/challenges/basejumps.json @@ -1,6 +1,6 @@ { - "name": "Basejumps", - "order" : 0.010, + "name": "Full Stack JavaScript Projects", + "order" : 0.014, "challenges": [ { "_id": "bd7158d8c443eddfaeb5bcef", diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index c4852dbc90..6c934a3965 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -1,5 +1,5 @@ { - "name": "Basic Bonfires", + "name": "Basic Algorithm Scripting", "order" : 0.007, "challenges": [ { diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index fb75777f7f..c0e282451e 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -1,6 +1,6 @@ { - "name": "Bootstrap", - "order" : 0.004, + "name": "Responsive Design with Bootstrap", + "order" : 0.003, "challenges": [ { "_id": "bad87fee1348bd9acde08812", diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index d63a12552b..48a1e29826 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -1,6 +1,6 @@ { "name": "Full Stack JavaScript", - "order" : 0.008, + "order" : 0.012, "challenges": [ { "_id": "bd7154d8c441eddfaeb5bdef", diff --git a/seed_data/challenges/functional-programming.json b/seed_data/challenges/functional-programming.json index 64252068d2..1142214af9 100644 --- a/seed_data/challenges/functional-programming.json +++ b/seed_data/challenges/functional-programming.json @@ -1,6 +1,6 @@ { "name": "Functional Programming", - "order" : 0.006, + "order" : 0.010, "challenges": [ { "_id": "bd7129d8c441eddfaeb5bedf", diff --git a/seed_data/challenges/intermediate-bonfires.json b/seed_data/challenges/intermediate-bonfires.json index efcd5b3606..1645449670 100644 --- a/seed_data/challenges/intermediate-bonfires.json +++ b/seed_data/challenges/intermediate-bonfires.json @@ -1,6 +1,6 @@ { - "name": "Bonfires", - "order" : 0.007, + "name": "Intermediate Algorithm Scripting", + "order" : 0.009, "challenges": [ { "_id": "a2f1d72d9b908d0bd72bb9f6", diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json index 23bfa3c991..a68fa144bc 100644 --- a/seed_data/challenges/jquery-ajax-and-json.json +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -1,300 +1,74 @@ { - "name": "jQuery, Ajax and JSON", + "name": "jQuery", "order" : 0.004, "challenges": [ { - "_id": "bad87fee1348bd9acdd08826", - "name": "Waypoint: Learn how Script Tags and Document Ready Work", - "difficulty": 0.072, + "_id": "bd7112d8c441eddfaeb5bded", + "name": "Get Started with jQuery", + "difficulty": 0.13, + "challengeSeed": "125671865", "description": [ - "Test" + "jQuery is a powerful library built in Javascript for manipulating HTML elements.", + "It's a lot easier to use than Javascript itself, so we'll learn it first.", + "It's also extremely popular with employers, so we're going to learn it well.", + "Codecademy has an excellent free course that will walk us through the basics of jQuery.", + "Go to http://www.codecademy.com/courses/web-beginner-en-bay3D/0/1 and complete the first section." ], - "tests": [ - "assert(typeof $('#target').attr('disabled') === 'undefined', 'Change the disabled attribute of the \"target\" button to false');", - "expect($('#target')).to.exist()" - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $('#target').attr('disabled', true)", - " });", - "fcces", - "" - ], - "challengeType": 0 + "challengeType": 2, + "tests": [] }, - { - "_id": "bad87fee1348bd9aedc08826", - "name": "Waypoint: Target Elements by Selectors Using jQuery", - "difficulty": 0.073, + "_id": "bd7113d8c441eddfaeb5bdef", + "name": "Write Functions with jQuery", + "difficulty": 0.14, + "challengeSeed": "125658029", "description": [ - + "Now we're ready to write your first jQuery functions.", + "Functions are little sub-programs. You can call a function and ask it to do something. Then it will return an answer.", + "First, you'll learn about one of the most important jQuery functions of all: $(document).ready().", + "Go to http://www.codecademy.com/courses/web-beginner-en-GfjC6/0/1 and complete the second section." ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 + "challengeType": 2, + "tests": [] }, - { - "_id": "bad87fee1348bd9aedb08826", - "name": "Waypoint: Target Elements by Class Using jQuery", - "difficulty": 0.074, + "_id": "bd7114d8c441eddfaeb5bdef", + "name": "Harness Dynamic HTML", + "difficulty": 0.15, + "challengeSeed": "125658028", "description": [ - + "Did you know that you can create HTML elements using jQuery?", + "Let's learn some more advanced ways to use jQuery to manipulate the DOM.", + "Go to http://www.codecademy.com/courses/web-beginner-en-v6phg/0/1 and complete the third section." ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 + "challengeType": 2, + "tests": [] }, - { - "_id": "bad87fee1348bd9aeda08826", - "name": "Waypoint: Target an element by ID Using jQuery", - "difficulty": 0.075, + "_id": "bd7115d8c441eddfaeb5bdef", + "name": "Listen for jQuery Events", + "difficulty": 0.16, + "challengeSeed": "125658027", "description": [ - + "jQuery can listen for events, such as clicking a button, and respond to them.", + "Here we'll learn how to use the jQuery click() function to respond to events in the browser.", + "Go to http://www.codecademy.com/courses/web-beginner-en-JwhI1/0/1 and complete the fourth section." ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 + "challengeType": 2, + "tests": [] }, - { - "_id": "bad87fee1348bd9aed908826", - "name": "Waypoint: Change the CSS of an Element Using jQuery", - "difficulty": 0.076, + "_id": "bd7116d8c441eddfaeb5bdef", + "name": "Trigger jQuery Effects", + "difficulty": 0.17, + "challengeSeed": "125658025", "description": [ - + "We can use jQuery to do all kinds of visual effects and transitions.", + "Let's explore some of the fun ways we can manipulate DOM elements with jQuery.", + "Go to http://www.codecademy.com/courses/web-beginner-en-jtFIC/0/1 and complete the fifth section." ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed808826", - "name": "Waypoint: Disable an Element Using jQuery", - "difficulty": 0.077, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed708826", - "name": "Waypoint: Remove an Element Using jQuery", - "difficulty": 0.078, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed608826", - "name": "Waypoint: Move an Element Using jQuery", - "difficulty": 0.079, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed508826", - "name": "Waypoint: Clone an Element Using jQuery", - "difficulty": 0.080, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed408826", - "name": "Waypoint: Animate an Element Using jQuery", - "difficulty": 0.081, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed308826", - "name": "Waypoint: Target the Parent of an Element Using jQuery", - "difficulty": 0.082, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed208826", - "name": "Waypoint: Target the Children of an Element Using jQuery", - "difficulty": 0.083, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - - { - "_id": "bad87fee1348bd9aed108826", - "name": "Waypoint: Target a Specific Child of an Element Using jQuery", - "difficulty": 0.084, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aed008826", - "name": "Waypoint: Target Even Numbered Elements Using jQuery", - "difficulty": 0.085, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aecc08826", - "name": "Waypoint: Read Data from an Element Using jQuery", - "difficulty": 0.086, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aebc08826", - "name": "Waypoint: Get Data from an URL Using jQuery", - "difficulty": 0.087, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9ae9c08826", - "name": "Waypoint: Loop through JSON Data Using jQuery", - "difficulty": 0.089, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9ae8c08826", - "name": "Waypoint: Setup Click Events Using jQuery", - "difficulty": 0.089, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 + "challengeType": 2, + "tests": [] } ] } diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json index 6f30751a96..55bfadb4ae 100644 --- a/seed_data/challenges/object-oriented-javascript.json +++ b/seed_data/challenges/object-oriented-javascript.json @@ -1,6 +1,6 @@ { "name": "Object Oriented JavaScript", - "order" : 0.006, + "order" : 0.008, "challenges": [ { "_id": "bd7129d8c441eddfaeb5bddf", diff --git a/seed_data/challenges/ziplines.json b/seed_data/challenges/ziplines.json index 9efe5bdd35..972d7c2a4b 100644 --- a/seed_data/challenges/ziplines.json +++ b/seed_data/challenges/ziplines.json @@ -1,6 +1,6 @@ { - "name": "Ziplines", - "order" : 0.009, + "name": "Front End Development Projects", + "order" : 0.013, "challenges": [ { "_id": "bd7158d8c442eddfbeb5bd1f", diff --git a/seed_data/future-jquery-ajax-json.json b/seed_data/future-jquery-ajax-json.json new file mode 100644 index 0000000000..23bfa3c991 --- /dev/null +++ b/seed_data/future-jquery-ajax-json.json @@ -0,0 +1,300 @@ +{ + "name": "jQuery, Ajax and JSON", + "order" : 0.004, + "challenges": [ + { + "_id": "bad87fee1348bd9acdd08826", + "name": "Waypoint: Learn how Script Tags and Document Ready Work", + "difficulty": 0.072, + "description": [ + "Test" + ], + "tests": [ + "assert(typeof $('#target').attr('disabled') === 'undefined', 'Change the disabled attribute of the \"target\" button to false');", + "expect($('#target')).to.exist()" + ], + "challengeSeed": [ + "fccss", + " $(document).ready(function() {", + " $('#target').attr('disabled', true)", + " });", + "fcces", + "" + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aedc08826", + "name": "Waypoint: Target Elements by Selectors Using jQuery", + "difficulty": 0.073, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aedb08826", + "name": "Waypoint: Target Elements by Class Using jQuery", + "difficulty": 0.074, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aeda08826", + "name": "Waypoint: Target an element by ID Using jQuery", + "difficulty": 0.075, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed908826", + "name": "Waypoint: Change the CSS of an Element Using jQuery", + "difficulty": 0.076, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed808826", + "name": "Waypoint: Disable an Element Using jQuery", + "difficulty": 0.077, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed708826", + "name": "Waypoint: Remove an Element Using jQuery", + "difficulty": 0.078, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed608826", + "name": "Waypoint: Move an Element Using jQuery", + "difficulty": 0.079, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed508826", + "name": "Waypoint: Clone an Element Using jQuery", + "difficulty": 0.080, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed408826", + "name": "Waypoint: Animate an Element Using jQuery", + "difficulty": 0.081, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed308826", + "name": "Waypoint: Target the Parent of an Element Using jQuery", + "difficulty": 0.082, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed208826", + "name": "Waypoint: Target the Children of an Element Using jQuery", + "difficulty": 0.083, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + + { + "_id": "bad87fee1348bd9aed108826", + "name": "Waypoint: Target a Specific Child of an Element Using jQuery", + "difficulty": 0.084, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aed008826", + "name": "Waypoint: Target Even Numbered Elements Using jQuery", + "difficulty": 0.085, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aecc08826", + "name": "Waypoint: Read Data from an Element Using jQuery", + "difficulty": 0.086, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9aebc08826", + "name": "Waypoint: Get Data from an URL Using jQuery", + "difficulty": 0.087, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9ae9c08826", + "name": "Waypoint: Loop through JSON Data Using jQuery", + "difficulty": 0.089, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + + { + "_id": "bad87fee1348bd9ae8c08826", + "name": "Waypoint: Setup Click Events Using jQuery", + "difficulty": 0.089, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + } + ] +} From dec227582d66c9bfc54f2775f5434fb00d221ec1 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 16:42:35 -0700 Subject: [PATCH 67/81] fix issues with json discovered after attempting to seed --- seed_data/challenges/basic-bonfires.json | 306 ------------------ seed_data/challenges/basic-javascript.json | 2 +- .../challenges/full-stack-javascript.json | 4 +- .../challenges/functional-programming.json | 2 +- 4 files changed, 4 insertions(+), 310 deletions(-) diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index 6c934a3965..cfa9d1f87d 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -958,312 +958,6 @@ ], "MDNlinks": ["Global Function Object", "Arguments object"], "challengeType": 5 - }, - { - "_id": "a2f1d72d9b908d0bd72bb9f6", - "name": "Bonfire: Make a Person", - "difficulty": "3.12", - "description": [ - "Fill in the object constructor with the methods specified in the tests.", - "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", - "All functions that take an argument have an arity of 1, and the argument will be a string.", - "These methods must be the only available means for interacting with the object.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "var Person = function(firstAndLast) {", - " return firstAndLast;", - "};", - "", - "var bob = new Person('Bob Ross');", - "bob.getFullName();" - ], - "tests": [ - "expect(Object.keys(bob).length).to.eql(6);", - "expect(bob instanceof Person).to.be.true;", - "expect(bob.firstName).to.be.undefined();", - "expect(bob.lastName).to.be.undefined();", - "expect(bob.getFirstName()).to.eql('Bob');", - "expect(bob.getLastName()).to.eql('Ross');", - "expect(bob.getFullName()).to.eql('Bob Ross');", - "bob.setFirstName('Happy');", - "expect(bob.getFirstName()).to.eql('Happy');", - "bob.setLastName('Trees');", - "expect(bob.getLastName()).to.eql('Trees');", - "bob.setFullName('George Carlin');", - "expect(bob.getFullName()).to.eql('George Carlin');", - "bob.setFullName('Bob Ross');" - ], - "MDNlinks": ["Closures", "Details of the Object Model"], - "challengeType": 5 - }, - { - "_id": "af4afb223120f7348cdfc9fd", - "name": "Bonfire: Map the Debris", - "difficulty": "3.50", - "description": [ - "Return a new array that transforms the element's average altitude into their orbital periods.", - "The array will contain objects in the format {name: 'name', avgAlt: avgAlt}.", - "You can read about orbital periods on wikipedia.", - "The values should be rounded to the nearest whole number. The body being orbited is Earth.", - "The radius of the earth is 6367.4447 kilometers, and the GM value of earth is 398600.4418", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function orbitalPeriod(arr) {", - " var GM = 398600.4418;", - " var earthRadius = 6367.4447;", - " return arr;", - "}", - "", - "orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);" - ], - "tests": [ - "expect(orbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}])).to.eqls([{name: \"sputkin\", orbitalPeriod: 86400}]);", - "expect(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}])).to.eqls([{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}]);" - ], - "MDNlinks": ["Math.pow()"], - "challengeType": 5 - }, - { - "_id" : "a3f503de51cfab748ff001aa", - "name": "Bonfire: Pairwise", - "difficulty": "3.51", - "description": [ - "Return the sum of all indices of elements of 'arr' that can be paired with one other element to form a sum that equals the value in the second argument 'arg'. If multiple sums are possible, return the smallest sum. Once an element has been used, it cannot be reused to pair with another.", - "For example, pairwise([1, 4, 2, 3, 0, 5], 7) should return 11 because 4, 2, 3 and 5 can be paired with each other to equal 7.", - "pairwise([1, 3, 2, 4], 4) would only equal 1, because only the first two elements can be paired to equal 4, and the first element has an index of 0!", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function pairwise(arr, arg) {", - " return arg;", - "}", - "", - "pairwise([1,4,2,3,0,5], 7);" - ], - "tests": [ - "expect(pairwise([1, 4, 2, 3, 0, 5], 7)).to.equal(11);", - "expect(pairwise([1, 3, 2, 4], 4)).to.equal(1);", - "expect(pairwise([1,1,1], 2)).to.equal(1);", - "expect(pairwise([0, 0, 0, 0, 1, 1], 1)).to.equal(10);", - "expect(pairwise([], 100)).to.equal(0);" - ], - "MDNlinks" : ["Array.reduce()"], - "challengeType": 5 - }, - { - "_id": "aff0395860f5d3034dc0bfc9", - "name": "Bonfire: Validate US Telephone Numbers", - "difficulty": "4.01", - "description": [ - "Return true if the passed string is a valid US phone number", - "The user may fill out the form field any way they choose as long as it is a valid US number. The following are all valid formats for US numbers:", - "555-555-5555, (555)555-5555, (555) 555-5555, 555 555 5555, 5555555555, 1 555 555 5555", - "For this challenge you will be presented with a string such as \"800-692-7753\" or \"8oo-six427676;laskdjf\". Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is \"1\". Return true if the string is a valid US phone number; otherwise false.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "tests": [ - "expect(telephoneCheck(\"555-555-5555\")).to.be.a(\"boolean\");", - "assert.deepEqual(telephoneCheck(\"1 555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 (555) 555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"5555555555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1(555)555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 555 555 5555\"), true);", - "assert.deepEqual(telephoneCheck(\"555-555-5555\"), true);", - "assert.deepEqual(telephoneCheck(\"1 456 789 4444\"), true);", - "assert.deepEqual(telephoneCheck(\"123**&!!asdf#\"), false);", - "assert.deepEqual(telephoneCheck(\"55555555\"), false);", - "assert.deepEqual(telephoneCheck(\"(6505552368)\"), false);", - "assert.deepEqual(telephoneCheck(\"2 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"0 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"-1 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"2 757 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"10 (757) 622-7382\"), false);", - "assert.deepEqual(telephoneCheck(\"27576227382\"), false);", - "assert.deepEqual(telephoneCheck(\"(275)76227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)6227382\"), false);", - "assert.deepEqual(telephoneCheck(\"2(757)622-7382\"), false);" - ], - "challengeSeed": [ - "function telephoneCheck(str) {", - " // Good luck!", - " return true;", - "}", - "", - "", - "", - "telephoneCheck(\"555-555-5555\");" - ], - "MDNlinks" : ["RegExp"], - "challengeType": 5 - }, - { - "_id": "a3f503de51cf954ede28891d", - "name": "Bonfire: Symmetric Difference", - "difficulty": "4.02", - "description": [ - "Create a function that takes two or more arrays and returns an array of the symmetric difference of the provided arrays.", - "The mathematical term symmetric difference refers to the elements in two sets that are in either the first or second set, but not in both.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function sym(args) {", - " return arguments;", - "}", - "", - "sym([1, 2, 3], [5, 2, 1, 4]);" - ], - "tests": [ - "expect(sym([1, 2, 3], [5, 2, 1, 4])).to.eqls([3, 5, 4])", - "assert.deepEqual(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5], 'should return the symmetric difference of the given arrays');", - "assert.deepEqual(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5], 'should return an array of unique values');", - "assert.deepEqual(sym([1, 1]), [1], 'should return an array of unique values');" - ], - "MDNlinks" : ["Array.reduce()"], - "challengeType": 5 - }, - { - "_id": "aa2e6f85cab2ab736c9a9b24", - "name": "Bonfire: Cash Register", - "difficulty": "4.03", - "description": [ - "Design a cash register drawer function that accepts purchase price as the first argument, payment as the second argument, and cash-in-drawer (cid) as the third argument.", "cid is a 2d array listing available currency.", "Return the string \"Insufficient Funds\" if cash-in-drawer is less than the change due. Return the string \"Closed\" if cash-in-drawer is equal to the change due.", "Otherwise, return change in coin and bills, sorted in highest to lowest order.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function drawer(price, cash, cid) {", - " var change;", - " // Here is your change, ma'am.", - " return change;", - "}", - "", - "// Example cash-in-drawer array:", - "// [['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]]", - "", - "drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]);" - ], - "tests": [ - "expect(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]])).to.be.a('array');", - "expect(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", - "expect(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]])).to.be.a('string');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['QUARTER', 0.50]], 'return correct change');", - "assert.deepEqual(drawer(3.26, 100.00, [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.10], ['QUARTER', 4.25], ['ONE', 90.00], ['FIVE', 55.00], ['TEN', 20.00], ['TWENTY', 60.00], ['ONE HUNDRED', 100.00]]), [['TWENTY', 60.00], ['TEN', 20.00], ['FIVE', 15], ['ONE', 1], ['QUARTER', 0.50], ['DIME', 0.20], ['PENNY', 0.04] ], 'return correct change with multiple coins and bills');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), 'Insufficient Funds', 'insufficient funds');", - "assert.deepEqual(drawer(19.50, 20.00, [['PENNY', 0.50], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]]), \"Closed\", 'cash-in-drawer equals change');" - ], - "MDNlinks" : ["Global Object"], - "challengeType": 5 - }, - { - "_id": "a56138aff60341a09ed6c480", - "name": "Bonfire: Inventory Update", - "difficulty": "4.04", - "description": [ - "Compare and update inventory stored in a 2d array against a second 2d array of a fresh delivery. Update current inventory item quantity, and if an item cannot be found, add the new item and quantity into the inventory array in alphabetical order.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function inventory(arr1, arr2) {", - " // All inventory must be accounted for or you're fired!", - " return arr1;", - "}", - "", - "// Example inventory lists", - "var curInv = [", - " [21, 'Bowling Ball'],", - " [2, 'Dirty Sock'],", - " [1, 'Hair Pin'],", - " [5, 'Microphone']", - "];", - "", - "var newInv = [", - " [2, 'Hair Pin'],", - " [3, 'Half-Eaten Apple'],", - " [67, 'Bowling Ball'],", - " [7, 'Toothpaste']", - "];", - "", - "inventory(curInv, newInv);" - ], - "tests": [ - "expect(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']])).to.be.a('array');", - "assert.equal(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]).length, 6);", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[88, 'Bowling Ball'], [2, 'Dirty Sock'], [3, 'Hair Pin'], [3, 'Half-Eaten Apple'], [5, 'Microphone'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']], []), [[21, 'Bowling Ball'], [2, 'Dirty Sock'], [1, 'Hair Pin'], [5, 'Microphone']]);", - "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[67, 'Bowling Ball'], [2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [7, 'Toothpaste']]);", - "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair Pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [0, 'Dirty Sock'], [1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [0, 'Microphone'], [1, 'Toothpaste']]);" - ], - "MDNlinks" : ["Global Array Object"], - "challengeType": 5 - }, - { - "_id": "a7bf700cd123b9a54eef01d5", - "name": "Bonfire: No repeats please", - "difficulty": "4.05", - "description": [ - "Return the number of total permutations of the provided string that don't have repeated consecutive letters.", - "For example, 'aab' should return 2 because it has 6 total permutations, but only 2 of them don't have the same letter (in this case 'a') repeating.", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function permAlone(str) {", - " return str;", - "}", - "", - "permAlone('aab');" - ], - "tests": [ - "expect(permAlone('aab')).to.be.a.number;", - "expect(permAlone('aab')).to.equal(2);", - "expect(permAlone('aaa')).to.equal(0);", - "expect(permAlone('aabb')).to.equal(8);", - "expect(permAlone('abcdefa')).to.equal(3600);", - "expect(permAlone('abfdefa')).to.equal(2640);", - "expect(permAlone('zzzzzzzz')).to.equal(0);" - ], - "MDNlinks" : ["Permutations", "RegExp"], - "challengeType": 5 - }, - { - "_id": "a19f0fbe1872186acd434d5a", - "name": "Bonfire: Friendly Date Ranges", - "difficulty": "4.06", - "description": [ - "Implement a way of converting two dates into a more friendly date range that could be presented to a user.", - "It must not show any redundant information in the date range.", - "For example, if the year and month are the same then only the day range should be displayed.", - "Secondly, if the starting year is the current year, and the ending year can be inferred by the reader, the year should be omitted.", - "Input date is formatted as YYYY-MM-DD", - "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function friendly(str) {", - " return str;", - "}", - "", - "friendly(['2015-07-01', '2015-07-04']);" - ], - "tests": [ - "assert.deepEqual(friendly(['2015-07-01', '2015-07-04']), ['July 1st','4th'], 'ending month should be omitted since it is already mentioned');", - "assert.deepEqual(friendly(['2015-12-01', '2016-02-03']), ['December 1st','February 3rd'], 'one month apart can be inferred it is the next year');", - "assert.deepEqual(friendly(['2015-12-01', '2017-02-03']), ['December 1st, 2015','February 3rd, 2017']);", - "assert.deepEqual(friendly(['2016-03-01', '2016-05-05']), ['March 1st','May 5th, 2016']);", - "assert.deepEqual(friendly(['2017-01-01', '2017-01-01']), ['January 1st, 2017'], 'since we do not duplicate only return once');", - "assert.deepEqual(friendly(['2022-09-05', '2023-09-04']), ['September 5th, 2022','September 4th, 2023']);" - ], - "MDNlinks": ["String.split()", "String.substr()", "parseInt()"], - "challengeType": 5 } ] } diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index 9129466cfd..4865ed9af2 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -132,7 +132,7 @@ "Complete \"Chapter 4: Debugging JavaScript\".", "Complete \"Chapter 5: Improving Network Performance\".", "Complete \"Chapter 6: Improving Performance\".", - "Complete \"Chapter 7: Memory Profiling\".", + "Complete \"Chapter 7: Memory Profiling\"." ], "challengeType": 2, "tests": [], diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index 48a1e29826..38b3ac89f6 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -103,7 +103,7 @@ "Complete \"Update\"", "Complete \"RM\"", "Complete \"Finale\"", - "Once you've completed these first 7 challenges, move on to our next waypoint.", + "Once you've completed these first 7 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] @@ -135,7 +135,7 @@ "Complete \"Filtered LS\"", "Complete \"Make it Modular\"", "Complete \"HTTP Client\"", - "Once you've completed these first 7 challenges, move on to our next waypoint.", + "Once you've completed these first 7 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] diff --git a/seed_data/challenges/functional-programming.json b/seed_data/challenges/functional-programming.json index 1142214af9..f1b39cfd07 100644 --- a/seed_data/challenges/functional-programming.json +++ b/seed_data/challenges/functional-programming.json @@ -3,7 +3,7 @@ "order" : 0.010, "challenges": [ { - "_id": "bd7129d8c441eddfaeb5bedf", + "_id": "bd7129d8c441eddfbeb5bddf", "name": "Waypoint: Practice Functional Programming", "difficulty": 0.01, "challengeSeed": "114604814", From 060f0a3c36a644d526f8b95c1b2a7ea5c81f9c21 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 16:46:31 -0700 Subject: [PATCH 68/81] swap sequence of ziplines and full stack waypoints --- seed_data/challenges/full-stack-javascript.json | 2 +- seed_data/challenges/ziplines.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index 38b3ac89f6..62b9f36f9a 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -1,6 +1,6 @@ { "name": "Full Stack JavaScript", - "order" : 0.012, + "order" : 0.013, "challenges": [ { "_id": "bd7154d8c441eddfaeb5bdef", diff --git a/seed_data/challenges/ziplines.json b/seed_data/challenges/ziplines.json index 972d7c2a4b..98d7605096 100644 --- a/seed_data/challenges/ziplines.json +++ b/seed_data/challenges/ziplines.json @@ -1,6 +1,6 @@ { "name": "Front End Development Projects", - "order" : 0.013, + "order" : 0.012, "challenges": [ { "_id": "bd7158d8c442eddfbeb5bd1f", From 5f169001f600f41a4d444d43780b5d55f78a1d7a Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 19:55:18 -0400 Subject: [PATCH 69/81] Change migration middleware to not rely on boolean flag in User model --- app.js | 163 +++++++++--------- controllers/user.js | 30 ++-- models/User.js | 2 +- .../challenges/full-stack-javascript.json | 4 +- 4 files changed, 99 insertions(+), 100 deletions(-) diff --git a/app.js b/app.js index 0c5012265b..09fd2cf30f 100755 --- a/app.js +++ b/app.js @@ -33,9 +33,9 @@ var express = require('express'), forceDomain = require('forcedomain'), lessMiddleware = require('less-middleware'), - /** - * Controllers (route handlers). - */ + /** + * Controllers (route handlers). + */ homeController = require('./controllers/home'), resourcesController = require('./controllers/resources'), userController = require('./controllers/user'), @@ -44,9 +44,9 @@ var express = require('express'), challengeMapController = require('./controllers/challengeMap'), challengeController = require('./controllers/challenge'), - /** - * Stories - */ + /** + * Stories + */ storyController = require('./controllers/story'), /** @@ -65,9 +65,9 @@ var app = express(); */ mongoose.connect(secrets.db); mongoose.connection.on('error', function () { - console.error( - 'MongoDB Connection Error. Please make sure that MongoDB is running.' - ); + console.error( + 'MongoDB Connection Error. Please make sure that MongoDB is running.' + ); }); /** @@ -91,11 +91,11 @@ app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(expressValidator({ - customValidators: { - matchRegex: function (param, regex) { - return regex.test(param); - } + customValidators: { + matchRegex: function (param, regex) { + return regex.test(param); } + } })); app.use(methodOverride()); app.use(cookieParser()); @@ -117,11 +117,11 @@ app.use(helmet.xssFilter()); app.use(helmet.noSniff()); app.use(helmet.frameguard()); app.use(function(req, res, next) { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', - 'Origin, X-Requested-With, Content-Type, Accept' - ); - next(); + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Headers', + 'Origin, X-Requested-With, Content-Type, Accept' + ); + next(); }); var trusted = [ @@ -165,35 +165,35 @@ var trusted = [ ]; app.use(helmet.csp({ - defaultSrc: trusted, - scriptSrc: [ - '*.optimizely.com', - '*.aspnetcdn.com', - '*.d3js.org' - ].concat(trusted), - 'connect-src': [ - ].concat(trusted), - styleSrc: trusted, - imgSrc: [ - /* allow all input since we have user submitted images for public profile*/ - '*' - ].concat(trusted), - fontSrc: ['*.googleapis.com'].concat(trusted), - mediaSrc: [ - '*.amazonaws.com', - '*.twitter.com' - ].concat(trusted), - frameSrc: [ + defaultSrc: trusted, + scriptSrc: [ + '*.optimizely.com', + '*.aspnetcdn.com', + '*.d3js.org' + ].concat(trusted), + 'connect-src': [ + ].concat(trusted), + styleSrc: trusted, + imgSrc: [ + /* allow all input since we have user submitted images for public profile*/ + '*' + ].concat(trusted), + fontSrc: ['*.googleapis.com'].concat(trusted), + mediaSrc: [ + '*.amazonaws.com', + '*.twitter.com' + ].concat(trusted), + frameSrc: [ - '*.gitter.im', - '*.gitter.im https:', - '*.vimeo.com', - '*.twitter.com', - '*.ghbtns.com' - ].concat(trusted), - reportOnly: false, // set to true if you only want to report errors - setAllHeaders: false, // set to true if you want to set all headers - safari5: false // set to true if you want to force buggy CSP in Safari 5 + '*.gitter.im', + '*.gitter.im https:', + '*.vimeo.com', + '*.twitter.com', + '*.ghbtns.com' + ].concat(trusted), + reportOnly: false, // set to true if you only want to report errors + setAllHeaders: false, // set to true if you want to set all headers + safari5: false // set to true if you want to force buggy CSP in Safari 5 })); app.use(function (req, res, next) { @@ -205,21 +205,17 @@ app.use(function (req, res, next) { app.use(express.static(__dirname + '/public', {maxAge: 86400000 })); app.use(function (req, res, next) { - // Remember original destination before login. - var path = req.path.split('/')[1]; - if (/auth|login|logout|signin|signup|fonts|favicon/i.test(path)) { - return next(); - } else if (/\/stories\/comments\/\w+/i.test(req.path)) { - return next(); - } - req.session.returnTo = req.path; - next(); + // Remember original destination before login. + var path = req.path.split('/')[1]; + if (/auth|login|logout|signin|signup|fonts|favicon/i.test(path)) { + return next(); + } else if (/\/stories\/comments\/\w+/i.test(req.path)) { + return next(); + } + req.session.returnTo = req.path; + next(); }); -// User migration middleware - -app.use(userController.userMigration); - /** * Main routes. */ @@ -227,7 +223,7 @@ app.use(userController.userMigration); app.get('/', homeController.index); app.get('/nonprofit-project-instructions', function(req, res) { - res.redirect(301, '/field-guide/how-do-free-code-camp\'s-nonprofit-projects-work'); + res.redirect(301, '/field-guide/how-do-free-code-camp\'s-nonprofit-projects-work'); }); app.post('/get-help', resourcesController.getHelp); @@ -260,14 +256,14 @@ app.get('/cats.json', function(req, res) { // Agile Project Manager Onboarding app.get('/pmi-acp-agile-project-managers', - resourcesController.agileProjectManagers); + resourcesController.agileProjectManagers); app.get('/agile', function(req, res) { res.redirect(301, '/pmi-acp-agile-project-managers'); }); app.get('/pmi-acp-agile-project-managers-form', - resourcesController.agileProjectManagersForm); + resourcesController.agileProjectManagersForm); // Nonprofit Onboarding @@ -280,31 +276,31 @@ app.get('/nonprofits-form', resourcesController.nonprofitsForm); app.get('/map', challengeMapController.challengeMap); app.get('/live-pair-programming', function(req, res) { - res.redirect(301, '/field-guide/live-stream-pair-programming-on-twitch.tv'); + res.redirect(301, '/field-guide/live-stream-pair-programming-on-twitch.tv'); }); app.get('/install-screenhero', function(req, res) { - res.redirect(301, '/field-guide/install-screenhero'); + res.redirect(301, '/field-guide/install-screenhero'); }); app.get('/guide-to-our-nonprofit-projects', function(req, res) { - res.redirect(301, '/field-guide/a-guide-to-our-nonprofit-projects'); + res.redirect(301, '/field-guide/a-guide-to-our-nonprofit-projects'); }); app.get('/chromebook', function(req, res) { - res.redirect(301, '/field-guide/chromebook'); + res.redirect(301, '/field-guide/chromebook'); }); app.get('/deploy-a-website', function(req, res) { - res.redirect(301, '/field-guide/deploy-a-website'); + res.redirect(301, '/field-guide/deploy-a-website'); }); app.get('/gmail-shortcuts', function(req, res) { - res.redirect(301, '/field-guide/gmail-shortcuts'); + res.redirect(301, '/field-guide/gmail-shortcuts'); }); app.get('/nodeschool-challenges', function(req, res) { - res.redirect(301, '/field-guide/nodeschool-challenges'); + res.redirect(301, '/field-guide/nodeschool-challenges'); }); @@ -349,8 +345,8 @@ app.post('/email-signin', userController.postSignin); app.get('/nonprofits/directory', nonprofitController.nonprofitsDirectory); app.get( - '/nonprofits/:nonprofitName', - nonprofitController.returnIndividualNonprofit + '/nonprofits/:nonprofitName', + nonprofitController.returnIndividualNonprofit ); app.get( @@ -528,8 +524,8 @@ app.get('/api/codepen/twitter/:screenName', resourcesController.codepenResources app.get('/field-guide/all-articles', fieldGuideController.showAllFieldGuides); app.get('/field-guide/:fieldGuideName', - fieldGuideController.returnIndividualFieldGuide - ); + fieldGuideController.returnIndividualFieldGuide +); app.get('/field-guide/', fieldGuideController.returnNextFieldGuide); @@ -540,14 +536,19 @@ app.post('/completed-field-guide/', fieldGuideController.completedFieldGuide); * Challenge related routes */ -app.get('/challenges/next-challenge', challengeController.returnNextChallenge); +app.get('/challenges/next-challenge', + userController.userMigration, + challengeController.returnNextChallenge); app.get( - '/challenges/:challengeName', - challengeController.returnIndividualChallenge + '/challenges/:challengeName', + userController.userMigration, + challengeController.returnIndividualChallenge ); -app.get('/challenges/', challengeController.returnCurrentChallenge); +app.get('/challenges/', + userController.userMigration, + challengeController.returnCurrentChallenge); // todo refactor these routes app.post('/completed-challenge/', challengeController.completedChallenge); @@ -558,12 +559,12 @@ app.post('/completed-bonfire', challengeController.completedBonfire); // Unique Check API route app.get('/api/checkUniqueUsername/:username', - userController.checkUniqueUsername - ); + userController.checkUniqueUsername +); app.get('/api/checkExistingUsername/:username', - userController.checkExistingUsername - ); + userController.checkExistingUsername +); app.get('/api/checkUniqueEmail/:email', userController.checkUniqueEmail); diff --git a/controllers/user.js b/controllers/user.js index 57e581bd59..821648b5b2 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -6,7 +6,7 @@ var _ = require('lodash'), User = require('../models/User'), secrets = require('../config/secrets'), moment = require('moment'), - debug = require('debug')('freecc:cntr:challenges'), + debug = require('debug')('freecc:cntr:userController'), resources = require('./resources'), R = require('ramda'); @@ -21,15 +21,17 @@ var _ = require('lodash'), * challenge structure */ exports.userMigration = function(req, res, next) { - debug('user migration called'); - var user = req.user; - if (!user.migratedToUnifiedChallengeStructure && user) { - user.migratedToUnifiedChallengeStructure = true; - user.completedChallenges = R.filter(function (elem) { + if (req.user && req.user.completedChallenges.length === 0) { + debug('user migration called'); + debug('Completed coursewares', req.user.completedCoursewares); + debug('Completed bonfires', req.user.completedBonfires); + req.user.completedChallenges = R.filter(function (elem) { return elem; // getting rid of undefined }, R.concat( - user.completedCoursewares, - user.completedBonfires.map(function (bonfire) { + req.user.completedCoursewares, + req.user.completedBonfires.map(function (bonfire) { + debug('Completed coursewares', req.user.completedCoursewares); + debug('Completed bonfires', req.user.completedBonfires); return ({ completedDate: bonfire.completedDate, _id: bonfire._id, @@ -42,15 +44,11 @@ exports.userMigration = function(req, res, next) { }); }) )); - user.save(function (err) { - if (err) { - next(err); - } else { - next(req, res); - } - }) + debug(req.user.completedChallenges); + next(); + } else { + next(); } - next(req, res); }; /** diff --git a/models/User.js b/models/User.js index e47d75326f..a9ffe11ffb 100644 --- a/models/User.js +++ b/models/User.js @@ -168,7 +168,7 @@ var userSchema = new mongoose.Schema({ } } ], - uncompletedChallenges: Array + uncompletedChallenges: Array, }); /** diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index d63a12552b..e272948837 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -103,7 +103,7 @@ "Complete \"Update\"", "Complete \"RM\"", "Complete \"Finale\"", - "Once you've completed these first 7 challenges, move on to our next waypoint.", + "Once you've completed these first 7 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] @@ -135,7 +135,7 @@ "Complete \"Filtered LS\"", "Complete \"Make it Modular\"", "Complete \"HTTP Client\"", - "Once you've completed these first 7 challenges, move on to our next waypoint.", + "Once you've completed these first 7 challenges, move on to our next waypoint." ], "challengeType": 2, "tests": [] From 9c7746a9e860bb096999f58a66242c493a435610 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 17:09:49 -0700 Subject: [PATCH 70/81] improve challenge map view --- seed_data/challenges/basic-bonfires.json | 28 +++++++++ seed_data/challenges/basic-javascript.json | 28 --------- ...p.json => get-set-for-free-code-camp.json} | 2 +- views/challengeMap/show.jade | 60 ++++++++++--------- 4 files changed, 60 insertions(+), 58 deletions(-) rename seed_data/challenges/{getting-set-for-free-code-camp.json => get-set-for-free-code-camp.json} (99%) diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index cfa9d1f87d..aa9f46a4a5 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -2,6 +2,34 @@ "name": "Basic Algorithm Scripting", "order" : 0.007, "challenges": [ + { + "_id": "bd7139d8c441eddfaeb5bdef", + "name": "Waypoint: Pair Program on Bonfires", + "difficulty": 0.44, + "challengeSeed": "119657641", + "description": [ + "OK, we're finally ready to start pair programming!", + "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", + "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", + "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", + "We have a special chat room for people ready to pair program. Go to our Slack chat room, navigate to the #letspair channel and type \"Hello Pair Programmers!\"", + "If someone is available, they will be your \"pair\" - the person you pair programming with.", + "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", + "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", + "Add them as a new contact in Screen Hero, then click the monitor-looking button to attempt to share your screen with them.", + "Once the Screen Hero session starts, your screen's margins will glow orange. You are now sharing your screen.", + "Your pair will have their own cursor, and will be able to type text on his or her and keyboard.", + "Now it's time to tackle our Bonfires.", + "Go to http://freecodecamp.com/bonfires and start working through our Bonfire challenges.", + "Once you you finish pair programming, end the session in Screen Hero session.", + "Congratulations! You have completed your first pair programming session.", + "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", + "Mark this Waypoint complete and move on." + ], + "challengeType": 2, + "tests": [], + "challengeType": 0 + }, { "_id": "ad7123c8c441eddfaeb5bdef", "name": "Bonfire: Meet Bonfire", diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index 4865ed9af2..bd531192d7 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -160,34 +160,6 @@ "challengeType": 2, "tests": [], "challengeType": 0 - }, - { - "_id": "bd7139d8c441eddfaeb5bdef", - "name": "Waypoint: Pair Program on Bonfires", - "difficulty": 0.44, - "challengeSeed": "119657641", - "description": [ - "OK, we're finally ready to start pair programming!", - "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", - "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", - "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", - "We have a special chat room for people ready to pair program. Go to our Slack chat room, navigate to the #letspair channel and type \"Hello Pair Programmers!\"", - "If someone is available, they will be your \"pair\" - the person you pair programming with.", - "If no one gets back to you in the first few minutes, don't worry. There will be lots of opportunities to pair program in the future.", - "If someone does get back to you, private message them and ask for the email address they used to register Screen Hero.", - "Add them as a new contact in Screen Hero, then click the monitor-looking button to attempt to share your screen with them.", - "Once the Screen Hero session starts, your screen's margins will glow orange. You are now sharing your screen.", - "Your pair will have their own cursor, and will be able to type text on his or her and keyboard.", - "Now it's time to tackle our Bonfires.", - "Go to http://freecodecamp.com/bonfires and start working through our Bonfire challenges.", - "Once you you finish pair programming, end the session in Screen Hero session.", - "Congratulations! You have completed your first pair programming session.", - "Pair program as much as possible with different campers until you've completed all the Bonfire challenges. This is a big time investment, but the JavaScript practice you get will be well worth it!", - "Mark this Waypoint complete and move on." - ], - "challengeType": 2, - "tests": [], - "challengeType": 0 } ] } diff --git a/seed_data/challenges/getting-set-for-free-code-camp.json b/seed_data/challenges/get-set-for-free-code-camp.json similarity index 99% rename from seed_data/challenges/getting-set-for-free-code-camp.json rename to seed_data/challenges/get-set-for-free-code-camp.json index 3af8a0b0de..b1cfc7e22f 100644 --- a/seed_data/challenges/getting-set-for-free-code-camp.json +++ b/seed_data/challenges/get-set-for-free-code-camp.json @@ -1,5 +1,5 @@ { - "name": "Getting Set for Free Code Camp", + "name": "Get Set for Free Code Camp", "order" : 0.001, "challenges": [ { diff --git a/views/challengeMap/show.jade b/views/challengeMap/show.jade index 0cb1ace524..a83a74feab 100644 --- a/views/challengeMap/show.jade +++ b/views/challengeMap/show.jade @@ -23,37 +23,39 @@ block content span.text-primary #{daysRunning}   | days ago. .spacer - .negative-15 for challengeBlock in challengeList - h3 #{challengeBlock.name} - ol - for challenge in challengeBlock.challenges - if completedChallengeList.indexOf(challenge._id) > -1 - .row - .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.large-p - .col-xs-12.col-sm-9.col-md-10 - li.faded.large-p - a(href="/challenges/#{challenge.name}")= challenge.name + .row + .col-xs-12.col-sm-8.col-sm-offset-2 + h3 #{challengeBlock.name} + .row + .col-xs-12 + ol + for challenge in challengeBlock.challenges + if completedChallengeList.indexOf(challenge._id) > -1 + .row + .hidden-xs.col-sm-3.col-md-2.text-primary.ion-checkmark-circled.padded-ionic-icon.text-center.large-p.negative-10 + .col-xs-12.col-sm-9.col-md-10 + li.faded.large-p.negative-10 + a(href="/challenges/#{challenge.name}")= challenge.name - else - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li.large-p - a(href="/challenges/#{challenge.name}")= challenge.name - - h2 - span.ion-ios-heart   Nonprofit Projects (800 hours of real-world experience)* - h3.negative-15 - ul - .row - .hidden-xs.col-sm-3.col-md-2 - span - .col-xs-12.col-sm-9.col-md-10 - li - a(href="/nonprofits/directory") Browse our nonprofit projects - p * Complete all Waypoints, Bonfires, Ziplines and Basejumps to be assigned your first nonprofit project + else + .row + .hidden-xs.col-sm-3.col-md-2 + span.negative-10 + .col-xs-12.col-sm-9.col-md-10 + li.large-p.negative-10 + a(href="/challenges/#{challenge.name}")= challenge.name + h3.text-center Nonprofit Projects (800 hours of real-world experience)* + .row + .col-xs-12 + ul + .row + .hidden-xs.col-sm-3.col-md-2 + span.negative-10 + .col-xs-12.col-sm-9.col-md-10 + li.large-p.negative-10 + a(href="/nonprofits/directory") Browse our nonprofit projects + p * Complete all Waypoints, Bonfires, Ziplines and Basejumps to be assigned your first nonprofit project #announcementModal.modal(tabindex='-1') .modal-dialog.animated.fadeInUp.fast-animation From e941872176bf95e1d9ef177ad46db0d8a0f2fda5 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 17:27:56 -0700 Subject: [PATCH 71/81] improvements to nonprofit directory view --- .../challenges/jquery-ajax-and-json.json | 10 ++++---- views/nonprofits/directory.jade | 25 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/seed_data/challenges/jquery-ajax-and-json.json b/seed_data/challenges/jquery-ajax-and-json.json index a68fa144bc..d54806400e 100644 --- a/seed_data/challenges/jquery-ajax-and-json.json +++ b/seed_data/challenges/jquery-ajax-and-json.json @@ -4,7 +4,7 @@ "challenges": [ { "_id": "bd7112d8c441eddfaeb5bded", - "name": "Get Started with jQuery", + "name": "Waypoint: Get Started with jQuery", "difficulty": 0.13, "challengeSeed": "125671865", "description": [ @@ -19,7 +19,7 @@ }, { "_id": "bd7113d8c441eddfaeb5bdef", - "name": "Write Functions with jQuery", + "name": "Waypoint: Write Functions with jQuery", "difficulty": 0.14, "challengeSeed": "125658029", "description": [ @@ -33,7 +33,7 @@ }, { "_id": "bd7114d8c441eddfaeb5bdef", - "name": "Harness Dynamic HTML", + "name": "Waypoint: Harness Dynamic HTML", "difficulty": 0.15, "challengeSeed": "125658028", "description": [ @@ -46,7 +46,7 @@ }, { "_id": "bd7115d8c441eddfaeb5bdef", - "name": "Listen for jQuery Events", + "name": "Waypoint: Listen for jQuery Events", "difficulty": 0.16, "challengeSeed": "125658027", "description": [ @@ -59,7 +59,7 @@ }, { "_id": "bd7116d8c441eddfaeb5bdef", - "name": "Trigger jQuery Effects", + "name": "Waypoint: Trigger jQuery Effects", "difficulty": 0.17, "challengeSeed": "125658025", "description": [ diff --git a/views/nonprofits/directory.jade b/views/nonprofits/directory.jade index 8fb6d2c14b..61c5ff44ab 100644 --- a/views/nonprofits/directory.jade +++ b/views/nonprofits/directory.jade @@ -6,16 +6,15 @@ block content .panel.panel-info .panel-heading.text-center Nonprofits We Help .panel-body - .col-xs-12.col-md-8.col-md-offset-2 - .no-right-padding - for nonprofit in nonprofits - .spacer - .row - .col-xs-12.col-sm-3 - img.img-responsive.img-center(src=nonprofit.logoUrl) - .col-xs-12.col-sm-9 - h2.negative-15= nonprofit.name - h3.negative-15= nonprofit.whatDoesNonprofitDo - a.text-center.btn.btn-primary.btn-lg(href='/nonprofits/' + nonprofit.name.toLowerCase().replace(/\s/g, '-')) Read more - .spacer - .spacer + .col-xs-12.col-sm-12.col-md-10.col-md-offset-1 + for nonprofit in nonprofits + .spacer + .row + .col-xs-12.col-sm-3 + img.img-responsive.img-center(src=nonprofit.logoUrl) + .col-xs-12.col-sm-9 + h2.negative-15= nonprofit.name + h3.negative-15= nonprofit.whatDoesNonprofitDo + a.text-center.btn.btn-primary.btn-lg(href='/nonprofits/' + nonprofit.name.toLowerCase().replace(/\s/g, '-')) Read more + .spacer + .spacer From 95ab51986e181ac291b7f27d7b2334714cc46bae Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 17:52:00 -0700 Subject: [PATCH 72/81] challenges are working when authenticated --- app.js | 3 ++- controllers/challengeMap.js | 1 - controllers/user.js | 7 ----- .../challenges/functional-programming.json | 3 +-- .../object-oriented-javascript.json | 27 +++++++------------ views/coursewares/showBonfire.jade | 7 +++-- 6 files changed, 16 insertions(+), 32 deletions(-) diff --git a/app.js b/app.js index 09fd2cf30f..9e4a7686ba 100755 --- a/app.js +++ b/app.js @@ -538,7 +538,8 @@ app.post('/completed-field-guide/', fieldGuideController.completedFieldGuide); app.get('/challenges/next-challenge', userController.userMigration, - challengeController.returnNextChallenge); + challengeController.returnNextChallenge +); app.get( '/challenges/:challengeName', diff --git a/controllers/challengeMap.js b/controllers/challengeMap.js index aef68cc4ce..9c9eb36bac 100644 --- a/controllers/challengeMap.js +++ b/controllers/challengeMap.js @@ -40,7 +40,6 @@ module.exports = { User.count({}, function (err, camperCount) { if (err) { - debug('User err: ', err); return next(err); } res.render('challengeMap/show', { diff --git a/controllers/user.js b/controllers/user.js index 821648b5b2..ab000593ce 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -22,16 +22,11 @@ var _ = require('lodash'), */ exports.userMigration = function(req, res, next) { if (req.user && req.user.completedChallenges.length === 0) { - debug('user migration called'); - debug('Completed coursewares', req.user.completedCoursewares); - debug('Completed bonfires', req.user.completedBonfires); req.user.completedChallenges = R.filter(function (elem) { return elem; // getting rid of undefined }, R.concat( req.user.completedCoursewares, req.user.completedBonfires.map(function (bonfire) { - debug('Completed coursewares', req.user.completedCoursewares); - debug('Completed bonfires', req.user.completedBonfires); return ({ completedDate: bonfire.completedDate, _id: bonfire._id, @@ -44,7 +39,6 @@ exports.userMigration = function(req, res, next) { }); }) )); - debug(req.user.completedChallenges); next(); } else { next(); @@ -378,7 +372,6 @@ exports.returnUser = function(req, res, next) { moment(timeKeys[_i]).toString() ) { - debug(timeKeys[_i - 1], timeKeys[_i]); tmpLongest++; if (tmpLongest > user.currentStreak) { diff --git a/seed_data/challenges/functional-programming.json b/seed_data/challenges/functional-programming.json index f1b39cfd07..bf5a9a9666 100644 --- a/seed_data/challenges/functional-programming.json +++ b/seed_data/challenges/functional-programming.json @@ -16,8 +16,7 @@ "If you've spent several minutes on one of these challenges, and still can't figure out its correct answer, you can click \"show answer\", then click \"run\" to advance to the next challenge. Be sure to read the correct answer and make sure you understand it before moving on." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] } ] } diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json index 55bfadb4ae..f87fd7024a 100644 --- a/seed_data/challenges/object-oriented-javascript.json +++ b/seed_data/challenges/object-oriented-javascript.json @@ -15,7 +15,8 @@ "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668697/m-2541189051 and start the course.", "Once you've completed this first section of scopes, mark this Waypoint complete and move on to the next one." - ] + ], + "challengeType": 2 }, { "_id": "bd7131d8c441eddfaeb5bdbf", @@ -31,8 +32,7 @@ "Once you've completed this section of using the keyword \"this\", mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7132d8c441eddfaeb5bdaf", @@ -47,8 +47,7 @@ "Once you've completed this section on prototype chain traversal, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7133d8c441eddfaeb5bd0f", @@ -64,8 +63,7 @@ "Once you've completed this section of decorators, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7134d8c441eddfaeb5bd1f", @@ -80,8 +78,7 @@ "Once you've completed this section of functional classes, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7135d8c441eddfaeb5bd2f", @@ -97,8 +94,7 @@ "Once you've completed this section of prototypal classes, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7136d8c441eddfaeb5bd3f", @@ -114,8 +110,7 @@ "Once you've completed this section pseudoclasses, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7136d8c441eddfaeb5bd4f", @@ -130,8 +125,7 @@ "Once you've completed this section on subclassing, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7136d8c441eddfaeb5bd5f", @@ -145,8 +139,7 @@ "Once you've completed this final section on pseudoclassical subclassing, mark this Waypoint complete and move on." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] } ] } diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index 560a9d3008..feb1c90c5b 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -82,12 +82,11 @@ block content if (user) form.form-horizontal(novalidate='novalidate', name='completedWithForm') .form-group.text-center - .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn + .col-xs-12 // extra field to distract password tools like lastpass from injecting css into our username field input.form-control(ng-show="false") - label(for="existingUser") If you're pairing with someone, enter their FreeCodeCamp username here - input.form-control#completed-with(name="existingUser", placeholder="Pair Username", existing-username='', ng-model="existingUser", autofocus) - .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") + input.form-control#completed-with(name="existingUser", placeholder="Your pair's username if pairing", existing-username='', ng-model="existingUser") + .col-xs-12(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") alert(type='danger') span.ion-close-circled | Username not found From 08837304fdb14458b718eee6430883dfcd088674 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 18:00:45 -0700 Subject: [PATCH 73/81] fix unauthenticated challenge bug and hide pair, bug and help buttons when unauthenticated --- controllers/challenge.js | 44 +++++++++++++++++------------- views/coursewares/showBonfire.jade | 23 ++++++++-------- views/coursewares/showHTML.jade | 2 +- views/coursewares/showJS.jade | 23 ++++++++-------- views/coursewares/showVideo.jade | 19 +++++++------ 5 files changed, 60 insertions(+), 51 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 76e273f681..621d58ef41 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -175,20 +175,22 @@ exports.returnIndividualChallenge = function(req, res, next) { if (dashedNameFull !== dashedName) { return res.redirect('../challenges/' + dashedNameFull); } else { - req.user.currentChallenge = { - challengeId: challenge._id, - challengeName: challenge.name, - challengeBlock: R.head(R.flatten(Object.keys(challengeMapWithIds). - map(function(key) { - return challengeMapWithIds[key] - .filter(function(elem) { - return String(elem) === String(challenge._id); - }).map(function() { - return key; - }); - }) - )) - }; + if (req.user) { + req.user.currentChallenge = { + challengeId: challenge._id, + challengeName: challenge.name, + challengeBlock: R.head(R.flatten(Object.keys(challengeMapWithIds). + map(function (key) { + return challengeMapWithIds[key] + .filter(function (elem) { + return String(elem) === String(challenge._id); + }).map(function () { + return key; + }); + }) + )) + }; + } } var challengeType = { @@ -295,12 +297,16 @@ exports.returnIndividualChallenge = function(req, res, next) { }); } }; - req.user.save(function(err) { - if (err) { - return next(err); - } + if (req.user) { + req.user.save(function (err) { + if (err) { + return next(err); + } + return challengeType[challenge.challengeType](); + }); + } else { return challengeType[challenge.challengeType](); - }); + } }); }; diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index feb1c90c5b..bed66dc44f 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -91,17 +91,18 @@ block content span.ion-close-circled | Username not found #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) - .button-spacer - .btn-group.input-group.btn-group-justified - label.btn.btn-success#i-want-help - i.fa.fa-medkit - |   Help - label.btn.btn-success#i-want-to-pair - i.fa.fa-user-plus - |   Pair - label.btn.btn-success#report-issue - i.fa.fa-bug - |   Bug + if (user) + .button-spacer + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help + i.fa.fa-medkit + |   Help + label.btn.btn-success#i-want-to-pair + i.fa.fa-user-plus + |   Pair + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug .button-spacer form.code .form-group.codeMirrorView diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index ad9481e868..7979e0b8f2 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -37,8 +37,8 @@ block content #less-info.btn.btn-primary.btn-block.btn-primary-ghost span.ion-arrow-up-b | Less information - br - if (user) + br a.btn.btn-primary.btn-big.btn-block#next-courseware-button | Go to my next challenge br diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index d7b914005e..392f890121 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -36,17 +36,18 @@ block content | Less information #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) .button-spacer - .btn-group.input-group.btn-group-justified - label.btn.btn-success#i-want-help - i.fa.fa-medkit - |   Help - label.btn.btn-success#i-want-to-pair - i.fa.fa-user-plus - |   Pair - label.btn.btn-success#report-issue - i.fa.fa-bug - |   Bug - br + if (user) + .btn-group.input-group.btn-group-justified + label.btn.btn-success#i-want-help + i.fa.fa-medkit + |   Help + label.btn.btn-success#i-want-to-pair + i.fa.fa-user-plus + |   Pair + label.btn.btn-success#report-issue + i.fa.fa-bug + |   Bug + .spacer form.code .form-group.codeMirrorView textarea#codeOutput(style='display: none;') diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 277c5e1267..5b0843a08f 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -21,20 +21,21 @@ block content a.btn.btn-primary.btn-big.btn-block#completed-courseware I've completed this challenge (ctrl + enter) script. var userLoggedIn = true; + .button-spacer + .btn-group.input-group.btn-group-justified + .btn.btn-success.btn-big#i-want-help-editorless + i.fa.fa-medkit + |   Get help + .btn.btn-success.btn-big#report-issue + i.fa.fa-bug + |   Report a bug + .button-spacer - else a.btn.btn-big.signup-btn.btn-block(href='/login') Sign in so you can save your progress script. var userLoggedIn = false; br - .button-spacer - .btn-group.input-group.btn-group-justified - .btn.btn-success.btn-big#i-want-help-editorless - i.fa.fa-medkit - |   Get help - .btn.btn-success.btn-big#report-issue - i.fa.fa-bug - |   Report a bug - .button-spacer + script(type="text/javascript"). var controlEnterHandler = function(e) { From 406f4d17e5f8830658038657da59f0a82980edaa Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 21:23:52 -0400 Subject: [PATCH 74/81] Minor copy update for OOP portion of challenges --- seed_data/challenges/object-oriented-javascript.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json index f87fd7024a..c15d186f45 100644 --- a/seed_data/challenges/object-oriented-javascript.json +++ b/seed_data/challenges/object-oriented-javascript.json @@ -9,7 +9,7 @@ "challengeSeed": "114604814", "description": [ "Objects will allow you to build applications more efficiently by using small, reusable blocks of code.", - "This course for Udacity will help you learn Object-Oriented Programming in JavaScript.", + "This course on Udacity will help you learn Object-Oriented Programming in JavaScript.", "First, we'll learn how JavaScript works in terms of scopes. You'll learn the difference between a \"Lexical Scope\" and an Execution Context.", "This theoretical foundation is useful for understanding when an a variable can be accessed and when it can't.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", @@ -24,12 +24,12 @@ "difficulty": 0.03, "challengeSeed": "114614220", "description": [ - "In this section, you'll learn how you can use \"this\" to dynamically point to your current object.", - "For example, if we were inside the function camper.completeCourse(), \"this\" would refer to the specific camper we were running the function on.", + "In this section, you'll learn how you can use this to dynamically point to your current object.", + "For example, if we were inside the function camper.completeCourse(), this would refer to the specific camper we were running the function on.", "Note that this section has several trick questions, designed to make you think. Don't get hung up on them, just keep moving forward.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668699/m-2780408563 and start the course.", - "Once you've completed this section of using the keyword \"this\", mark this Waypoint complete and move on to the next one." + "Once you've completed this section of using the keyword this, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, "tests": [] @@ -73,6 +73,7 @@ "description": [ "Now we'll go over the simplest way to implement a JavaScript class.", "A class is a set of functions that you can use to easily produce similar objects.", + "You may have heard JavaScript doesn't have classes. This is technically true, but don't let it get in the way of the very important ideas in this section.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468537/m-2961989110 and start the course.", "Once you've completed this section of functional classes, mark this Waypoint complete and move on to the next one." @@ -87,7 +88,7 @@ "challengeSeed": "114612885", "description": [ "Now we'll learn how one object can be prototyped off of another object.", - "Prototype objects delegate their \"failed lookups\" up the \"prototype chain\".", + "Objects delegate their \"failed lookups\" up the \"prototype chain\".", "This means that if I create a second object based off another object, then try to access an attribute the second object doesn't have, JavaScript will \"fall through\" to the original object to see whether it has that attribute.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468538/m-3034538557 and start the course.", From eda9f17dfd5ce0095d5e24d0b075fcd33dfb9d7c Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 20:04:19 -0700 Subject: [PATCH 75/81] add new videos --- controllers/challenge.js | 4 +- seed_data/challenges/basic-bonfires.json | 3 +- seed_data/challenges/basic-javascript.json | 32 ++++------ .../challenges/full-stack-javascript.json | 4 +- .../challenges/functional-programming.json | 4 +- .../object-oriented-javascript.json | 64 +++++++++---------- 6 files changed, 50 insertions(+), 61 deletions(-) diff --git a/controllers/challenge.js b/controllers/challenge.js index 621d58ef41..d3af11c5be 100644 --- a/controllers/challenge.js +++ b/controllers/challenge.js @@ -136,7 +136,7 @@ exports.returnCurrentChallenge = function(req, res, next) { var nameString = req.user.currentChallenge.challengeName.trim() .toLowerCase() .replace(/\s/g, '-') - .replace(/[^a-z0-9\-]/gi, ''); + .replace(/[^a-z0-9\-\/.]/gi, ''); req.user.save(function(err) { if (err) { return next(err); @@ -171,7 +171,7 @@ exports.returnIndividualChallenge = function(req, res, next) { var dashedNameFull = challenge.name .toLowerCase() .replace(/\s/g, '-') - .replace(/[^a-z0-9\-]/gi, ''); + .replace(/[^a-z0-9\-\.]/gi, ''); if (dashedNameFull !== dashedName) { return res.redirect('../challenges/' + dashedNameFull); } else { diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index aa9f46a4a5..e9a01a9a3d 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -27,8 +27,7 @@ "Mark this Waypoint complete and move on." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "ad7123c8c441eddfaeb5bdef", diff --git a/seed_data/challenges/basic-javascript.json b/seed_data/challenges/basic-javascript.json index bd531192d7..6cd9fc39c2 100644 --- a/seed_data/challenges/basic-javascript.json +++ b/seed_data/challenges/basic-javascript.json @@ -15,8 +15,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-x9DnD/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7130d8c441eddfaeb5bdef", @@ -29,8 +28,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-Bthev-mskY8/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7131d8c441eddfaeb5bdef", @@ -43,8 +41,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-XEDZA/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7132d8c441eddfaeb5bdef", @@ -56,8 +53,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-mrTNH-6VIZ9/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7133d8c441eddfaeb5bdef", @@ -71,8 +67,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-ZA2rb/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7134d8c441eddfaeb5bdef", @@ -85,8 +80,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/javascript-beginner-en-3bmfN/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7135d8c441eddfaeb5bdef", @@ -99,8 +93,7 @@ "Be sure to also complete this section: http://www.codecademy.com/courses/building-an-address-book/0/1?curriculum_id=506324b3a7dffd00020bf661." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7136d8c441eddfaeb5bdef", @@ -113,12 +106,11 @@ "Be sure to also complete the final section: http://www.codecademy.com/courses/close-the-super-makert/0/1." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7118d8c441eddfaeb5bdef", - "name": "Waypoint: Discover Chrome's DevTools", + "name": "Waypoint: Discover Chrome DevTools", "difficulty": 0.32, "challengeSeed": "110752743", "description": [ @@ -135,8 +127,7 @@ "Complete \"Chapter 7: Memory Profiling\"." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] }, { "_id": "bd7138d8c441eddfaeb5bdef", @@ -158,8 +149,7 @@ "Once you've completed these challenges, move on to our next Waypoint." ], "challengeType": 2, - "tests": [], - "challengeType": 0 + "tests": [] } ] } diff --git a/seed_data/challenges/full-stack-javascript.json b/seed_data/challenges/full-stack-javascript.json index 62b9f36f9a..feeb71ba1b 100644 --- a/seed_data/challenges/full-stack-javascript.json +++ b/seed_data/challenges/full-stack-javascript.json @@ -144,7 +144,7 @@ "_id": "bd7153d8c441eddfaeb5bdfe", "name": "Waypoint: Continue working with Node.js Servers", "difficulty": 0.41, - "challengeSeed": "126411561", + "challengeSeed": "128836506", "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 8 through 10.", "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.", @@ -161,7 +161,7 @@ "_id": "bd7153d8c441eddfaeb5bdfd", "name": "Waypoint: Finish working with Node.js Servers", "difficulty": 0.42, - "challengeSeed": "126411561", + "challengeSeed": "128836507", "description": [ "Let's continue the LearnYouNode Node School challenge. For this Waypoint, we'll do challenges 11 through 13.", "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_data/challenges/functional-programming.json b/seed_data/challenges/functional-programming.json index bf5a9a9666..67f6a3b3f0 100644 --- a/seed_data/challenges/functional-programming.json +++ b/seed_data/challenges/functional-programming.json @@ -9,10 +9,10 @@ "challengeSeed": "114604814", "description": [ "Functional programming holds the key to unlocking JavaScript's powerful asynchronous features.", - "Functional programming in JavaScript involves using five key functions: \"map\", \"reduce\", \"filter\", \"concatAll\", and \"zip\".", "Jafar Husain's 42-step interactive Functional Programming course will familiarize you with the various ways you can recombine these functions.", + "Functional programming in JavaScript involves using five key functions: \"map\", \"reduce\", \"filter\", \"concatAll\", and \"zip\".", "Click here to go to the challenge: http://jhusain.github.io/learnrx/.", - "This challenge will take several hours, but don't worry. Husain's website will save your progress (using your browser's local storage) so you don't need to finish it in one sitting.", + "This challenge will take several hours, but don't worry. Jafar's website will save your progress (using your browser's local storage) so you don't need to finish it in one sitting.", "If you've spent several minutes on one of these challenges, and still can't figure out its correct answer, you can click \"show answer\", then click \"run\" to advance to the next challenge. Be sure to read the correct answer and make sure you understand it before moving on." ], "challengeType": 2, diff --git a/seed_data/challenges/object-oriented-javascript.json b/seed_data/challenges/object-oriented-javascript.json index c15d186f45..feee80d16c 100644 --- a/seed_data/challenges/object-oriented-javascript.json +++ b/seed_data/challenges/object-oriented-javascript.json @@ -6,14 +6,14 @@ "_id": "bd7129d8c441eddfaeb5bddf", "name": "Waypoint: Scope Your Variables", "difficulty": 0.01, - "challengeSeed": "114604814", + "challengeSeed": "128836683", "description": [ "Objects will allow you to build applications more efficiently by using small, reusable blocks of code.", "This course on Udacity will help you learn Object-Oriented Programming in JavaScript.", - "First, we'll learn how JavaScript works in terms of scopes. You'll learn the difference between a \"Lexical Scope\" and an Execution Context.", - "This theoretical foundation is useful for understanding when an a variable can be accessed and when it can't.", + "First, we'll learn how JavaScript works in terms of scopes. You'll learn the difference between a \"Lexical Scope\" and an \"Execution Context\".", + "This theoretical foundation is useful for understanding when a variable can be accessed and when it can't.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668697/m-2541189051 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668697/m-2541189051 and start the course.", "Once you've completed this first section of scopes, mark this Waypoint complete and move on to the next one." ], "challengeType": 2 @@ -22,13 +22,13 @@ "_id": "bd7131d8c441eddfaeb5bdbf", "name": "Waypoint: Reference your Current Object with This", "difficulty": 0.03, - "challengeSeed": "114614220", + "challengeSeed": "128836508", "description": [ - "In this section, you'll learn how you can use this to dynamically point to your current object.", - "For example, if we were inside the function camper.completeCourse(), this would refer to the specific camper we were running the function on.", - "Note that this section has several trick questions, designed to make you think. Don't get hung up on them, just keep moving forward.", + "In this section, you'll learn how you can use the keyword this to dynamically point to your current object.", + "For example, if we were inside the function camper.completeCourse(), this would refer to the specific camper upon which we were running the function.", + "Note that this section poses several trick questions that were designed to make you think. Don't get hung up on them, just keep moving forward.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668699/m-2780408563 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668699/m-2780408563 and start the course.", "Once you've completed this section of using the keyword this, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -38,12 +38,12 @@ "_id": "bd7132d8c441eddfaeb5bdaf", "name": "Waypoint: Traverse the Prototype Chain", "difficulty": 0.04, - "challengeSeed": "114612889", + "challengeSeed": "128836684", "description": [ "Next we'll learn about the multiple ways you can create a copy of an object.", "We'll also learn how an object's missing attributes can traverse the \"prototype chain\".", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668700/m-2616738615 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2593668700/m-2616738615 and start the course.", "Once you've completed this section on prototype chain traversal, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -53,13 +53,13 @@ "_id": "bd7133d8c441eddfaeb5bd0f", "name": "Waypoint: Reuse Code with Decorators", "difficulty": 0.05, - "challengeSeed": "114612888", + "challengeSeed": "128836681", "description": [ - "In this section, we'll learn about the Decorator Pattern.", - "The Decorator pattern will help you \"decorate\" an existing object with additional attributes. This pattern helps you reuse code, reducing the total amount of code you'll need to write and maintain.", + "In this section, we'll learn about the \"Decorator Pattern\".", + "The Decorator Pattern will help you \"decorate\" an existing object with additional attributes. This pattern helps you reuse code, reducing the total amount of code you'll need to write and maintain.", "It's a convenient way to add functionality to objects without changing their underlying structure.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468536/m-2697628561 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468536/m-2697628561 and start the course.", "Once you've completed this section of decorators, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -69,13 +69,13 @@ "_id": "bd7134d8c441eddfaeb5bd1f", "name": "Waypoint: Build Objects with Functional Classes", "difficulty": 0.06, - "challengeSeed": "114612887", + "challengeSeed": "128836503", "description": [ "Now we'll go over the simplest way to implement a JavaScript class.", "A class is a set of functions that you can use to easily produce similar objects.", - "You may have heard JavaScript doesn't have classes. This is technically true, but don't let it get in the way of the very important ideas in this section.", + "You may have heard JavaScript doesn't have classes. While this is technically true, don't let this fact prevent you from learning the important concepts in this section.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468537/m-2961989110 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468537/m-2961989110 and start the course.", "Once you've completed this section of functional classes, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -85,13 +85,13 @@ "_id": "bd7135d8c441eddfaeb5bd2f", "name": "Waypoint: Build Objects with Prototypal Classes", "difficulty": 0.07, - "challengeSeed": "114612885", + "challengeSeed": "128836505", "description": [ "Now we'll learn how one object can be prototyped off of another object.", - "Objects delegate their \"failed lookups\" up the \"prototype chain\".", - "This means that if I create a second object based off another object, then try to access an attribute the second object doesn't have, JavaScript will \"fall through\" to the original object to see whether it has that attribute.", + "Objects will delegate their \"failed lookups\" on up through the \"prototype chain\".", + "This means that when you create a second object based off another object, then try to access an attribute that the second object doesn't have, JavaScript will \"fall through\" to the original object to see whether it has that attribute.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468538/m-3034538557 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468538/m-3034538557 and start the course.", "Once you've completed this section of prototypal classes, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -101,13 +101,13 @@ "_id": "bd7136d8c441eddfaeb5bd3f", "name": "Waypoint: Understand Pseudoclassical Patterns", "difficulty": 0.08, - "challengeSeed": "114612882", + "challengeSeed": "128836689", "description": [ - "JavaScript doesn't have the traditional \"classes\" that lower-level languages like C and Java have.", + "JavaScript doesn't have the traditional \"classes\" that lower-level languages like C++ and Java have.", "Instead, JavaScript does some tricks to allow you to write code as though it had these traditional classes. We call these \"pseudo-classes\".", - "In this section, we'll learn how to build these pseudo-classes, and some tricks for later figuring out where these objects came from.", + "In this section, we'll learn how to build these pseudo-classes. We'll also learn some tricks for figuring out where these objects originally came from.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468539/e-2783098540/m-2695768694 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468539/e-2783098540/m-2695768694 and start the course.", "Once you've completed this section pseudoclasses, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -117,12 +117,12 @@ "_id": "bd7136d8c441eddfaeb5bd4f", "name": "Waypoint: Subclass one Object to Another", "difficulty": 0.09, - "challengeSeed": "114612882", + "challengeSeed": "128836686", "description": [ - "Now we know the three ways of creating objects (through functions, prototyping and pseudo classing).", - "Let's learn how to subclass one object to another. This will give our new object the attributes of the original object. It will allow us to make further modifications new object without affecting the original object.", + "Now we know the three ways that we can create objects. Through:
      1. functions
      2. prototyping
      3. pseudo classing
      ", + "Let's learn how to \"subclass\" one object to another. This will give our new object the attributes of the original object. It will allow us to make further modifications to the new object without affecting the original object.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468540/m-2785128536 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468540/m-2785128536 and start the course.", "Once you've completed this section on subclassing, mark this Waypoint complete and move on to the next one." ], "challengeType": 2, @@ -132,11 +132,11 @@ "_id": "bd7136d8c441eddfaeb5bd5f", "name": "Waypoint: Use Pseudoclassical Subclasses", "difficulty": 0.10, - "challengeSeed": "114612882", + "challengeSeed": "128836937", "description": [ "This final section will teach us how to create subclasses from pseudo classes.", "You can save your progress by creating a free Udacity account, but note that it's also possible to complete this entire course without an account by following the links we provide.", - "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468541/e-2693158566/m-2688408703 and start the course.", + "Go to https://www.udacity.com/course/viewer#!/c-ud015/l-2794468541/e-2693158566/m-2688408703 and start the course.", "Once you've completed this final section on pseudoclassical subclassing, mark this Waypoint complete and move on." ], "challengeType": 2, From c74a8a7fc0d9a5cb041a99500a77312e617799ce Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Mon, 25 May 2015 23:27:21 -0400 Subject: [PATCH 76/81] Consisten dasherization in stories. Updated story cleanup script. --- controllers/story.js | 7 +++---- seed_data/storyCleanup.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/controllers/story.js b/controllers/story.js index 233f929b69..3a34c7b883 100755 --- a/controllers/story.js +++ b/controllers/story.js @@ -137,7 +137,9 @@ exports.returnIndividualStory = function(req, res, next) { } story = story.pop(); - var dashedNameFull = story.storyLink.toLowerCase().replace(/\s/g, '-'); + var dashedNameFull = story.storyLink.toLowerCase() + .replace(/\s+/g, ' ') + .replace(/\s/g, '-'); if (dashedNameFull !== dashedName) { return res.redirect('../news/' + dashedNameFull); } @@ -328,9 +330,6 @@ exports.storySubmission = function(req, res, next) { return next(new Error('Not authorized')); } var storyLink = data.headline - .replace(/\'/g, '') - .replace(/\"/g, '') - .replace(/,/g, '') .replace(/\s+/g, ' ') .replace(/[^a-z0-9\s]/gi, '') .toLowerCase() diff --git a/seed_data/storyCleanup.js b/seed_data/storyCleanup.js index 2598526c8a..c216e67293 100644 --- a/seed_data/storyCleanup.js +++ b/seed_data/storyCleanup.js @@ -18,8 +18,8 @@ function storyLinkCleanup(cb) { console.log(i++); this.pause(); story.storyLink = story.storyLink. - replace(/[^a-z0-9\s]/gi, ''). replace(/\s+/g, ' '). + replace(/[^a-z0-9\s]/gi, ''). toLowerCase(). trim(); story.save(function (err) { From c121bbe3bbc0a5827bae61d7e85d6f49501e5804 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 20:28:34 -0700 Subject: [PATCH 77/81] make all directions in all challenge views wrap long stringsgs --- views/coursewares/showBonfire.jade | 2 +- views/coursewares/showHTML.jade | 2 +- views/coursewares/showJS.jade | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/views/coursewares/showBonfire.jade b/views/coursewares/showBonfire.jade index bed66dc44f..9c4a9d7c41 100644 --- a/views/coursewares/showBonfire.jade +++ b/views/coursewares/showBonfire.jade @@ -70,7 +70,7 @@ block content #long-instructions.row.hide .col-xs-12 for sentence in details - p!= sentence + p.wrappable!= sentence #MDN-links p Here are some helpful links: for link, index in MDNlinks diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 7979e0b8f2..4fecde91a9 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -33,7 +33,7 @@ block content #long-instructions.row.hide .col-xs-12 for sentence in details - p!= sentence + p.wrappable!= sentence #less-info.btn.btn-primary.btn-block.btn-primary-ghost span.ion-arrow-up-b | Less information diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index 392f890121..345ac1fab4 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -30,7 +30,7 @@ block content #long-instructions.row.hide .col-xs-12 for sentence in details - p!= sentence + p.wrappable!= sentence #less-info.btn.btn-primary.btn-block.btn-primary-ghost span.ion-arrow-up-b | Less information From 78f813bf186b491e4916e241fcd1bdfa6c5a18e6 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 20:28:57 -0700 Subject: [PATCH 78/81] make remaining directions in all challenge views wrap long strings --- views/coursewares/showVideo.jade | 3 +-- views/coursewares/showZiplineOrBasejump.jade | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 5b0843a08f..4ea1ad5011 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -11,8 +11,7 @@ block content .col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center input(type='checkbox' class='challenge-list-checkbox') .col-xs-9.col-sm-11.col-md-10 - li - .step-text!= step + li.step-text.wrappable!= step .col-xs-12.col-sm-12.col-md-8 .embed-responsive.embed-responsive-16by9 iframe.embed-responsive-item(src='//player.vimeo.com/video/#{video}') diff --git a/views/coursewares/showZiplineOrBasejump.jade b/views/coursewares/showZiplineOrBasejump.jade index bc890d9afc..1fe595c8d0 100644 --- a/views/coursewares/showZiplineOrBasejump.jade +++ b/views/coursewares/showZiplineOrBasejump.jade @@ -11,8 +11,7 @@ block content .col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center input(type='checkbox' class='challenge-list-checkbox') .col-xs-9.col-sm-11.col-md-10 - li - .step-text!= step + li.step-text.wrappable!= step .col-xs-12.col-sm-12.col-md-8 .embed-responsive.embed-responsive-16by9 iframe.embed-responsive-item(src='//player.vimeo.com/video/#{video}') From 47d350aa276185182aa6e6e4dcf312e0ad260426 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Tue, 26 May 2015 00:04:50 -0400 Subject: [PATCH 79/81] update instructions for Bonfire: Mutations --- seed_data/challenges/basic-bonfires.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index e9a01a9a3d..0e5ca681cc 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -349,10 +349,11 @@ "name": "Bonfire: Mutations", "difficulty": "1.12", "description": [ - "Return true if the string in the first element of the array contains the letters of the string in the second element of the array.", + "Return true if the string in the first element of the array contains the all of the letters of the string in the second element of the array.", "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'.", + "Lastly, ['Mary', 'Aarmy'] should return false because 'Mary' is only 4 letters while 'Aarmy' is 5, so 'Mary' can't possibly contain 'Aarmy'", "Remember to use RSAP if you get stuck. Try to pair program. Write your own code." ], "challengeSeed": [ @@ -367,6 +368,7 @@ "expect(mutation(['hello', 'Hello'])).to.be.true;", "expect(mutation(['zyxwvutsrqponmlkjihgfedcba', 'qrstu'])).to.be.true;", "expect(mutation(['Mary', 'Army'])).to.be.true;", + "expect(mutation(['Mary', 'Aarmy'])).to.be.false;", "expect(mutation(['Alien', 'line'])).to.be.true;" ], "MDNlinks": ["Array.sort()"], From ac304bd59c64d7185e312ce9fa9e3dbdf017c7d4 Mon Sep 17 00:00:00 2001 From: terakilobyte Date: Tue, 26 May 2015 00:07:10 -0400 Subject: [PATCH 80/81] Fix grammatical error in Mutations instructions --- seed_data/challenges/basic-bonfires.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seed_data/challenges/basic-bonfires.json b/seed_data/challenges/basic-bonfires.json index 0e5ca681cc..907fc7af9b 100644 --- a/seed_data/challenges/basic-bonfires.json +++ b/seed_data/challenges/basic-bonfires.json @@ -349,7 +349,7 @@ "name": "Bonfire: Mutations", "difficulty": "1.12", "description": [ - "Return true if the string in the first element of the array contains the all of the letters of the string in the second element of the array.", + "Return true if the string in the first element of the array contains all of the letters of the string in the second element of the array.", "For example, ['hello', 'Hello'], should return true because all of the letters in the second string are present in the first, ignoring case.", "The arguments ['hello', 'hey'] should return false because the string 'hello' does not contain a 'y'.", "Another example, ['Alien', 'line'], should return true because all of the letters in 'line' are present in 'Alien'.", From 77d3b5be9f098a3a2b87a87217d6cb565627b952 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Mon, 25 May 2015 22:46:47 -0700 Subject: [PATCH 81/81] finish html, css and bootstrap challenges --- seed_data/challenges/basic-html5-and-css.json | 364 +++++++++++++++ seed_data/challenges/bootstrap.json | 424 +++--------------- seed_data/future-jquery-ajax-json.json | 29 ++ views/coursewares/showHTML.jade | 4 +- 4 files changed, 445 insertions(+), 376 deletions(-) diff --git a/seed_data/challenges/basic-html5-and-css.json b/seed_data/challenges/basic-html5-and-css.json index 1ba903a877..8b773fb39c 100644 --- a/seed_data/challenges/basic-html5-and-css.json +++ b/seed_data/challenges/basic-html5-and-css.json @@ -1659,6 +1659,370 @@ "" ], "challengeType" : 0 + }, + { + "_id": "bad88fee1348bd9aedf08825", + "name": "Waypoint: Adjusting the Padding of an Element", + "difficulty": 0.064, + "description": [ + "These next few Waypoints will give you a brief tour of three important aspects of the space surrounding HTML elements: padding, margin, and border. Change the padding of your green box to match that of your red box.", + "An element's padding controls the amount of space between the element and its border.", + "Here, we can see that the green box and the red box are nested within the yellow box. Note that the red box has more padding than the green box.", + "When you increase the green box's padding, it will increase the distance between the text \"padding\" and the border around it." + ], + "tests": [ + "assert($('.green-box').css('padding-top') === '20px', 'Your green-box class should give elements 20px of padding.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08822", + "name": "Waypoint: Adjust the Margin of an Element", + "difficulty": 0.065, + "description": [ + "Change the margin of the green box to match that of the red box.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", + "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." + ], + "tests": [ + "assert($('.green-box').css('margin-top') === '20px', 'Your green-box class should give elements 20px of margin.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08823", + "name": "Waypoint: Add a Negative Margin to an Element", + "difficulty": 0.066, + "description": [ + "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the yellow box around it.", + "An element's margin controls the amount of space between an element's border and surrounding elements.", + "If you set an element's margin to a negative value, the element will grow larger.", + "Try to set the margin to a negative value like the one for the red box." + ], + "tests": [ + "assert($('.green-box').css('margin-top') === '-15px', 'Your green-box class should give elements -15px of margin.')" + ], + "challengeSeed": [ + "", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08824", + "name": "Waypoint: Add Different Padding to Each Side of an Element", + "difficulty": 0.067, + "description": [ + "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has different padding on each of its sides.", + "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." + ], + "tests": [ + "assert($('.green-box').css('padding-left') === '40px', 'Your green-box class should give the left of elements 40px of padding.')", + "assert($('.green-box').css('padding-bottom') === '20px', 'Your green-box class should give the bottom of elements 20px of padding.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1248bd9aedf08824", + "name": "Waypoint: Add Different a Margin to Each Side of an Element", + "difficulty": 0.068, + "description": [ + "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", + "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." + ], + "tests": [ + "assert($('.green-box').css('margin-left') === '40px', 'Your green-box class should give the left of elements 40px of margin.')", + "assert($('.green-box').css('margin-bottom') === '20px', 'Your green-box class should give the bottom of elements 20px of margin.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08826", + "name": "Waypoint: Use Clockwise Notation to Specify the Padding of an Element", + "difficulty": 0.069, + "description": [ + "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "assert($('.green-box').css('padding-left') === '40px', 'Your green-box class should give the left of elements 40px of padding.')", + "assert($('.green-box').css('padding-bottom') === '20px', 'Your green-box class should give the bottom of elements 20px of padding.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedf08726", + "name": "Waypoint: Use Clockwise Notation to Specify the Margin of an Element", + "difficulty": 0.070, + "description": [ + "Let's try this again, but with margin this time. Use Clockwise Notation to give an element a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", + "Instead of specifying an element's margin-top, margin-right, margin-bottom, and margin-left attributes, you can specify them all in one line, like this: margin: 10px 20px 10px 20px;.", + "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", + "You can also use this notation for margins!" + ], + "tests": [ + "assert($('.green-box').css('margin-left') === '40px', 'Your green-box class should give the left of elements 40px of margin.')", + "assert($('.green-box').css('margin-bottom') === '20px', 'Your green-box class should give the bottom of elements 20px of margin.')" + ], + "challengeSeed": [ + "", + "
      margin
      ", + "", + "
      ", + "
      padding
      ", + "
      padding
      ", + "
      " + ], + "challengeType": 0 } ] } diff --git a/seed_data/challenges/bootstrap.json b/seed_data/challenges/bootstrap.json index c0e282451e..480117ee2c 100644 --- a/seed_data/challenges/bootstrap.json +++ b/seed_data/challenges/bootstrap.json @@ -7,15 +7,16 @@ "name": "Waypoint: Mobile Responsive Images", "difficulty": 0.047, "description": [ - "Add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to the image.", - "Specifying a width of 200 pixels on our img element made it fit our phone's screen, but it's not a perfect fit. It would be great if the image could be exactly the width of our phone's screen.", - "Fortunately, there's a Responsive CSS Framework called written by Twitter called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML, but we've gone ahead and included it for you here.", + "Now let's go back to our Cat Photo App. This time, we'll style it using the popular Twitter Bootstrap responsive CSS framework. First, add a new image with the src attribute of \"http://bit.ly/fcc-kittens2\", and add the img-responsive Bootstrap class to that image.", + "It would be great if the image could be exactly the width of our phone's screen.", + "Fortunately, we have access to a Responsive CSS Framework called Bootstrap. You can add Bootstrap to any app just by including it with <link rel='stylesheet' href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'/> at the top of your HTML. But we've gone ahead and automatically added it to your Cat Photo App for you.", "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name Responsive Design.", + "With responsive design, there is no need to design a mobile version of your website. It will look good on devices with screens of any width.", "Now all you need to do is add the img-responsive class to your image." ], "tests": [ - "assert($('img').hasClass('img-responsive'), 'Your new image should have the class \"img-responsive\"')", - "assert($('img').length > 1, 'You should add an image with the src of \"http://bit.ly/fcc-kittens2\"')" + "assert($('img').hasClass('img-responsive'), 'Your new image should have the class \"img-responsive\".')", + "assert($('img').length > 1, 'You should add a second image with the src of http://bit.ly/fcc-kittens2.')" ], "challengeSeed": [ "", @@ -83,8 +84,8 @@ "difficulty": 0.048, "description": [ "Add Bootstrap's text-center class to your h2 element.", - "Now that we're using Bootstrap, we can center our heading elements (h2) to make them look better. All we need to do is add the class text-center to the h1 and h2 elements.", - "Note 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 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>." ], "tests": [ "assert($('h2').hasClass('text-center'), 'Your h2 element should be centered by applying the class \"text-center\"')" @@ -298,7 +299,7 @@ }, { "_id": "bad87fee1348cd8acef08811", - "name": "Waypoint: Rock Bootstrap Buttons", + "name": "Waypoint: Taste the Bootstrap Button Color Rainbow", "difficulty": 0.051, "description": [ "Add Bootstrap's btn-block class to both of your buttons.", @@ -372,11 +373,11 @@ }, { "_id": "bad87fee1348cd8acef08813", - "name": "Waypoint: Color a Bootstrap Button with Button Info", + "name": "Waypoint: Call out Optional Actions with Button Info", "difficulty": 0.052, "description": [ "Create a new block-level Bootstrap button below your \"like\" button with the text \"Info\", and add Bootstrap's btn-info class to it.", - "Bootstrap comes with several pre-defined colors for buttons. The btn-primary class is the main button color you'll use throughout your app.", + "Bootstrap comes with several pre-defined colors for buttons. The btn-info class is used to call attention to optional actions that the user can take.", "Note that these buttons still need the btn and btn-block classes." ], "tests": [ @@ -452,7 +453,7 @@ "description": [ "Create a button with the text \"delete\" and give it the class btn-danger.", "Bootstrap comes with several pre-defined colors for buttons. The btn-danger class is the button color you'll use to notify users that the button performs a destructive action, such as deleting a cat photo.", - "Note that this button still needs the btn and btn-block classes." + "Note that these buttons still need the btn and btn-block classes." ], "tests": [ "assert($('.btn-danger').length > 0, 'Your new button should have the class \"btn-danger\".')", @@ -526,9 +527,13 @@ "name": "Waypoint: Use the Bootstrap Grid to Put Elements Side By Side", "difficulty": 0.054, "description": [ - "Put the \"like\", \"Info\" and \"Delete\" buttons side-by-side by wrapping them in both in a <div class=\"row\"> element and each of them in a <div class=\"col-xs-4\"> element.", + "Put the \"like\", \"Info\" and \"Delete\" buttons side-by-side by wrapping all three of them within one <div class=\"row\"> element, then each of them within a <div class=\"col-xs-4\"> element.", "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.", - "The row class is applied to a div, and the buttons themselves can be nested within it." + "Here's a diagram of how Bootstrap's 12-column grid layout works:", + "", + "Note that in this illustration, we use the col-md-* class. Here, \"md\" means \"medium\", and \"*\" is a number specifying how many columns wide the element should be. In this case, we're specifying how many columns wide an element should be on a medium-sized screen, such as a laptop.", + "In the Cat Photo App that we're building, we'll use col-xs-*, where \"*\" is the number of columns wide the element should be, and \"xs\" means \"extra small\", like an extra-small mobile phone screen.", + "The row class is applied to a div, and the buttons themselves can be wrapped within it." ], "tests": [ "assert($('.row').length > 0, 'Your new button should be wrapped within a div with the class \"row\".')", @@ -604,7 +609,9 @@ "name": "Waypoint: Ditch Custom CSS for Bootstrap", "difficulty" : 0.055, "description": [ - "Delete the following from your style tag: .red-text, p, .smaller-image. Delete the p element with the dead link. Remove your red-text class from your h2 element and instead apply the text-primary Bootstrap class. Replace the smaller-image class on your top image with the img-responsive class." + "Delete the following from your style tag: .red-text, p, .smaller-image. Delete the p element with the dead link. Remove your red-text class from your h2 element and instead apply the text-primary Bootstrap class. Replace the smaller-image class on your top image with the img-responsive class.", + "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." ], "tests": [ "assert(!$('h2').hasClass('red-text'), 'You h2 element should no longer have the class \"red-text\".')", @@ -691,7 +698,14 @@ "name": "Waypoint: Create a Custom Heading", "difficulty" : 0.056, "description": [ - "Wrap your first image and your h2 element in a <div class='row'> element. Wrap your h2 text in a <div class='col-xs-8'> and your image in a <div class='col-xs-4'> so that they are on the same line." + "Wrap your first image and your h2 element within a single <div class='row'> element. Wrap 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.", + "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, we use the col-md-* class. Here, \"md\" means \"medium\", and \"*\" is a number specifying how many columns wide the element should be. In this case, we're specifying how many columns wide an element should be on a medium-sized screen, such as a laptop.", + "In the Cat Photo App that we're building, we'll use col-xs-*, where \"*\" is the number of columns wide the element should be, and \"xs\" means \"extra small\", like an extra-small mobile phone screen.", + "Notice how the image is now just the right size to fit along the text?" ], "tests": [ "assert($('.row').length > 1, 'Your h2 and top image elements should both be wrapped together within a div with the class \"row\".')", @@ -716,7 +730,7 @@ "", "

      CatPhotoApp

      ", "", - "", + "", "", "", "
      ", @@ -764,10 +778,11 @@ "difficulty" : 0.057, "description": [ "Use Font Awesome to add a \"like\" icon to your like button.", - "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." + "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.", + "Go ahead and add a <i class=\"fa fa-thumbs-up\"></i> within your like button's element." ], "tests": [ - "assert($('.fa-thumbs-up').length > 0, 'You should add a <i class=\"fa fa-thumbs-up\"><i> within your like button element.')" + "assert($('.fa-thumbs-up').length > 0, 'You should add a <i class=\"fa fa-thumbs-up\"></i> within your like button element.')" ], "challengeSeed": [ "", @@ -838,12 +853,13 @@ "name": "Waypoint: Add Font Awesome Icons all of our Buttons", "difficulty" : 0.058, "description": [ - "Use Font Awesome to add a \"info-circle\" icon to your info button and a \"trash\" button to your delete button.", - "You should add a <i class=\"fa fa-thumbs-up\"> within your like button's element." + "Use Font Awesome to add a \"info-circle\" icon to your info button and a \"trash\" icon to your delete button.", + "Font Awesome is a convenient library of icons. These icons are vector graphics, stored in the .svg file format. These icons are treated just like fonts. You can specify their size using pixels, and they will assume the font size of their parent HTML elements.", + "Add <i class=\"fa fa-info-circle\"></i> within your info button's element, and a <i class=\"fa fa-trash\"></i> within your delete button." ], "tests": [ - "assert($('.fa-trash').length > 0, 'You should add a <i class=\"fa fa-trash\"><i> within your like button element.')", - "assert($('.fa-info-circle').length > 0, 'You should add a <i class=\"fa fa-info-circle\"><i> within your like button element.')" + "assert($('.fa-trash').length > 0, 'You should add a <i class=\"fa fa-trash\"></i> within your like button element.')", + "assert($('.fa-info-circle').length > 0, 'You should add a <i class=\"fa fa-info-circle\"></i> within your like button element.')" ], "challengeSeed": [ "", @@ -914,11 +930,12 @@ "name": "Waypoint: Responsively Style a Radio Buttons", "difficulty" : 0.059, "description": [ - "Wrap all of your radio buttons in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-6'> element." + "Wrap all of your radio buttons within a <div class='row'> element. Then wrap each of them within a <div class='col-xs-6'> element.", + "You can use Bootstrap's col-xs-* classes on form elements, too! This way, our radio buttons will be evenly spread out across the page, regardless of how wide the screen resolution is." ], "tests": [ "assert($('.row').length > 2, 'Wrap your all of your radio buttons inside one div with the class \"row\".')", - "assert($('.col-xs-6').length > 3, 'Wrap each of your radio buttons inside its own div with the class \"col-xs-6\".')" + "assert($('.col-xs-6').length > 1, 'Wrap each of your radio buttons inside its own div with the class \"col-xs-6\".')" ], "challengeSeed": [ "", @@ -989,7 +1006,8 @@ "name": "Waypoint: Responsively Style Checkboxes", "difficulty" : 0.060, "description": [ - "Wrap all your checkboxes in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-4'> element." + "Wrap all your checkboxes in a <div class='row'> element. Then wrap each of them in a <div class='col-xs-4'> element.", + "You can use Bootstrap's col-xs-* classes on form elements, too! This way, our checkboxes will be evenly spread out across the page, regardless of how wide the screen resolution is." ], "tests": [ "assert($('.row').length > 3, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", @@ -1068,15 +1086,15 @@ { "_id" : "bad87fee1348bd9aed908845", - "name": "Waypoint: Style a Text Input with the Bootstrap Form Control Class", + "name": "Waypoint: Style Text Inputs as Form Controls", "difficulty" : 0.061, "description": [ "Give your form's text input field in a class of \"form-control\". Give your form's submit button the classes \"btn btn-primary\" and give it the Font Awesome icon of \"fa-paper-plane\"." ], "tests": [ - "assert($('.btn-primary').length > 1, 'Give your form's submit button the classes \"btn btn-primary\".')", - "assert($('.fa-paper-plane').length > 0, 'You should add a <i class=\"fa fa-paper-plane\"><i> within your submit button element.')", - "assert($('.form-control').length > 0, 'Give your form's text input field in a class of \"form-control\".')" + "assert($('.btn-primary').length > 1, 'Give the submit button in your form the classes \"btn btn-primary\".')", + "assert($('.fa-paper-plane').length > 0, 'Add a <i class=\"fa fa-paper-plane\"></i> within your submit button element.')", + "assert($('.form-control').length > 0, 'Give the the text input field in your form the class \"form-control\".')" ], "challengeSeed": [ "", @@ -1163,7 +1181,9 @@ "name": "Waypoint: Line up Form Elements Responsively with Bootstrap", "difficulty" : 0.062, "description": [ - "Wrap both your form's text input field and submit button within a div with the class \"row\". Wrap your form's text input field within a div with the class of \"col-xs-7\". Wrap your form's submit button the in a div with the class \"col-xs-5\"." + "Wrap both your form's text input field and submit button within a div with the class \"row\". Wrap your form's text input field within a div with the class of \"col-xs-7\". Wrap your form's submit button the in a div with the class \"col-xs-5\".", + "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 \"row\" element with \"col-xs-*\" elements withing it.", + "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": [ "assert($('.row').length > 4, 'Wrap your all of your checkboxes inside one div with the class \"row\".')", @@ -1248,350 +1268,6 @@ "" ], "challengeType": 0 - }, - - { - "_id": "bad88fee1348bd9aedf08825", - "name": "Waypoint: Adjusting the Padding of an Element", - "difficulty": 0.064, - "description": [ - "Change the padding of the green box to match that of the red box.", - "An element's padding controls the amount of space between an element and its border.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more padding than the green box.", - "When you increase the green box's padding, it will increase the distance between the word \"padding\" and the border around the text." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding', '20px')" - ], - "challengeSeed": [ - "", - "
      margin
      ", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9aedf08822", - "name": "Waypoint: Adjust the Margin of an Element", - "difficulty": 0.065, - "description": [ - "Change the margin of the green box to match that of the red box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "Here, we can see that the green box and the red box and the green box are nested within the yellow box. Note that the red box has more margin than the green box, making it appear smaller.", - "When you increase the green box's padding, it will increase the distance between its border and surrounding elements." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '20px')" - ], - "challengeSeed": [ - "", - "
      margin
      ", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9aedf08823", - "name": "Waypoint: Add a Negative Margin to an Element", - "difficulty": 0.066, - "description": [ - "Change the margin of the green box to a negative value, so it fills the entire horizontal width of the blue box.", - "An element's margin controls the amount of space between an element's border and surrounding elements.", - "If you set an element's margin to a negative value, the element will grow larger.", - "Try to set the margin to a negative value like the one for the red box." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin', '-15px')" - ], - "challengeSeed": [ - "", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9aedf08824", - "name": "Waypoint: Add Different Padding to Each Side of an Element TEST", - "difficulty": 0.067, - "description": [ - "Give the green box a padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has different padding on each of its sides.", - "CSS allows you to control the padding of an element on all four sides with padding-top, padding-right, padding-bottom, and padding-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('padding-bottom', '20px')", - "expect($('.green-box')).to.have.css('padding-left', '40px')" - ], - "challengeSeed": [ - "", - "
      margin
      ", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1248bd9aedf08824", - "name": "Waypoint: Add Different a Margin to Each Side of an Element TEST", - "difficulty": 0.068, - "description": [ - "Give the green box a margin of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Sometimes you will want to customize an element so that it has a different margin on each of its sides.", - "CSS allows you to control the margin of an element on all four sides with margin-top, margin-right, margin-bottom, and margin-left attributes." - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
      margin
      ", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - { - "_id": "bad87fee1348bd9aedf08826", - "name": "Waypoint: Use Clockwise Notation to Specify an Element's Padding", - "difficulty": 0.069, - "description": [ - "Use Clockwise Notation to give an element padding of 40 pixels on its top and left side, but only 20 pixels on its bottom and right side.", - "Instead of specifying an element's padding-top, padding-right, padding-bottom, and padding-left attributes, you can specify them all in one line, like this: padding: 10px 20px 10px 20px;.", - "These four values work like a clock: top, right, bottom, left, and will produce the exact same result as using the side-specific padding instructions.", - "You can also use this notation for margins!" - ], - "tests": [ - "expect($('.green-box')).to.have.css('margin-bottom', '20px')", - "expect($('.green-box')).to.have.css('margin-left', '40px')" - ], - "challengeSeed": [ - "", - "
      margin
      ", - "", - "
      ", - "
      padding
      ", - "
      padding
      ", - "
      " - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aede08826", - "name": "Waypoint: Use Hex Codes for Precise Colors", - "difficulty": 0.070, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ], - "challengeType": 0 - }, - - { - "_id": "bad87fee1348bd9aedd08826", - "name": "Waypoint: Use Shortened Hex Codes for Colors", - "difficulty": 0.071, - "description": [ - - ], - "tests": [ - - ], - "challengeSeed": [ - - ] } ] } diff --git a/seed_data/future-jquery-ajax-json.json b/seed_data/future-jquery-ajax-json.json index 23bfa3c991..4ceea2fafc 100644 --- a/seed_data/future-jquery-ajax-json.json +++ b/seed_data/future-jquery-ajax-json.json @@ -295,6 +295,35 @@ ], "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aede08826", + "name": "Waypoint: Use Hex Codes for Precise Colors", + "difficulty": 0.071, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ], + "challengeType": 0 + }, + { + "_id": "bad87fee1348bd9aedd08826", + "name": "Waypoint: Use Shortened Hex Codes for Colors", + "difficulty": 0.071, + "description": [ + + ], + "tests": [ + + ], + "challengeSeed": [ + + ] } ] } diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index 4fecde91a9..ad9481e868 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -33,12 +33,12 @@ block content #long-instructions.row.hide .col-xs-12 for sentence in details - p.wrappable!= sentence + p!= sentence #less-info.btn.btn-primary.btn-block.btn-primary-ghost span.ion-arrow-up-b | Less information - - if (user) br + - if (user) a.btn.btn-primary.btn-big.btn-block#next-courseware-button | Go to my next challenge br
    Time budgeted