From 3fe97a8e20d1796bc3c60a78bf32d4d439f16eb5 Mon Sep 17 00:00:00 2001 From: Stuart Taylor Date: Fri, 6 Apr 2018 15:27:40 +0100 Subject: [PATCH] ignore local build files --- packages/learn/.gitignore | 3 +- .../basic-algorithm-scripting.json | 967 - .../basic-data-structures.json | 822 - .../basic-javascript.json | 5841 --- .../debugging.json | 423 - .../es6.json | 971 - .../functional-programming.json | 1276 - .../intermediate-algorithm-scripting.json | 1212 - ...gorithms-and-data-structures-projects.json | 389 - .../object-oriented-programming.json | 1062 - .../regular-expressions.json | 994 - .../tmp/03-front-end-libraries/bootstrap.json | 2542 - .../front-end-libraries-projects.json | 124 - .../tmp/03-front-end-libraries/jquery.json | 1549 - .../react-and-redux.json | 758 - .../tmp/03-front-end-libraries/react.json | 2965 -- .../tmp/03-front-end-libraries/redux.json | 930 - .../seed/tmp/03-front-end-libraries/sass.json | 480 - .../data-visualization-projects.json | 115 - .../data-visualization-with-d3.json | 1805 - .../json-apis-and-ajax.json | 693 - .../api-and-microservice-projects.json | 174 - .../basic-node-and-express.json | 310 - .../managing-packages-with-npm.json | 305 - .../mongodb-and-mongoose.json | 324 - .../advanced-express-tools.json | 740 - .../information-security-with-helmetjs.json | 373 - ...nce-and-information-security-projects.json | 298 - ...ality-assurance-and-testing-with-chai.json | 833 - ...te-to-open-source-and-help-nonprofits.json | 126 - .../coding-interview-algorithm-questions.json | 470 - ...ng-interview-data-structure-questions.json | 2829 -- .../project-euler-problems.json | 20811 -------- .../rosetta-code-problems.json | 42100 ---------------- .../system-design-and-concept-questions.json | 975 - .../take-home-interview-projects.json | 873 - .../apis-and-microservices-certificate.json | 37 - .../data-visualization-certificate.json | 37 - .../front-end-libraries-certificate.json | 37 - ...ity-and-quality-assurance-certificate.json | 37 - ...ithms-and-data-structures-certificate.json | 37 - .../legacy-back-end-certificate.json | 57 - ...legacy-data-visualization-certificate.json | 57 - .../legacy-front-end-certificate.json | 57 - .../responsive-web-design-certificate.json | 37 - 45 files changed, 2 insertions(+), 97853 deletions(-) delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json delete mode 100644 packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/jquery.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/react-and-redux.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/react.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/redux.json delete mode 100644 packages/learn/seed/tmp/03-front-end-libraries/sass.json delete mode 100644 packages/learn/seed/tmp/04-data-visualization/data-visualization-projects.json delete mode 100644 packages/learn/seed/tmp/04-data-visualization/data-visualization-with-d3.json delete mode 100644 packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json delete mode 100644 packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json delete mode 100644 packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json delete mode 100644 packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json delete mode 100644 packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json delete mode 100644 packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json delete mode 100644 packages/learn/seed/tmp/06-information-security-and-quality-assurance/information-security-with-helmetjs.json delete mode 100644 packages/learn/seed/tmp/06-information-security-and-quality-assurance/quality-assurance-and-information-security-projects.json delete mode 100644 packages/learn/seed/tmp/06-information-security-and-quality-assurance/quality-assurance-and-testing-with-chai.json delete mode 100644 packages/learn/seed/tmp/07-contribute-to-open-source-and-help-nonprofits/contribute-to-open-source-and-help-nonprofits.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/coding-interview-algorithm-questions.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/coding-interview-data-structure-questions.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/project-euler-problems.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/rosetta-code-problems.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/system-design-and-concept-questions.json delete mode 100644 packages/learn/seed/tmp/08-coding-interview-questions-and-take-home-assignments/take-home-interview-projects.json delete mode 100644 packages/learn/seed/tmp/09-certificates/apis-and-microservices-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/data-visualization-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/front-end-libraries-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/information-security-and-quality-assurance-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/javascript-algorithms-and-data-structures-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/legacy-back-end-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/legacy-data-visualization-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/legacy-front-end-certificate.json delete mode 100644 packages/learn/seed/tmp/09-certificates/responsive-web-design-certificate.json diff --git a/packages/learn/.gitignore b/packages/learn/.gitignore index b32784b612..e24e3b80d3 100644 --- a/packages/learn/.gitignore +++ b/packages/learn/.gitignore @@ -11,6 +11,7 @@ yarn-error.log /public static/js -seed/tmp/ +seed/ignore +seed/tmp seed/transformed seed/ready \ No newline at end of file diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.json deleted file mode 100644 index 0b3990f257..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.json +++ /dev/null @@ -1,967 +0,0 @@ -{ - "name": "Basic Algorithm Scripting", - "order": 6, - "time": "50 hours", - "helpRoom": "HelpJavaScript", - "challenges": [ - { - "id": "bd7158d2c442eddfbeb5bd1f", - "title": "Get Set for our Algorithm Lessons", - "description": [ - "", - "", - "freeCodeCamp's algorithm challenges will teach you how to think like a programmer.", - "", - "@@STEP@@", - "", - "", - "The previous lessons introduced you to programming concepts. But for these algorithm lessons, you'll now need to apply what you learned to solve open-ended problems.", - "", - "@@STEP@@", - "", - "", - "These algorithm lessons are hard. Some of them may take you several hours to solve. You may get frustrated. But don't quit.", - "", - "@@STEP@@", - "", - "", - "When you get stuck, just use the Read-Search-Ask methodology.
Don't worry - you've got this!", - "", - "@@STEP@@" - ], - "challengeSeed": [], - "tests": [], - "type": "Waypoint", - "challengeType": 7, - "isRequired": false, - "translations": { - "es": { - "title": "Prepárate para nuestros Desafíos sobre Algoritmos", - "description": [ - [ - "https://i.imgur.com/sJkp30a.png", - "Una imagen de un desafio sobre algoritmos que presenta instrucciones, pruebas y el editor de código.", - "Nuestros desafios sobre algoritmos te enseñarán como pensar como un programador.", - "" - ], - [ - "https://i.imgur.com/d8LuRNh.png", - "Una mamá pájaro saca un bebé pájaro fuer de su nido.", - "Nuestros desafios anteriores te introdujeron a los conceptos de programación. Pero para estos desafios sobre algoritmos, ahora necesitarás aplicar lo que has aprendido y resolver problemas de respuesta abierta", - "" - ], - [ - "https://i.imgur.com/WBetuBa.jpg", - "Un programador frustado golpeando la pantalla de su computador.", - "Nuestros desafíos sobre algortimos son difíciles. Algunos pueden requerir muchas horas para resolverse. Podrás frustarte, pero no te rindas.", - "" - ], - [ - "https://i.imgur.com/p2TpOQd.jpg", - "Un tierno perro que salta sobre un obstáculo, pica el ojo y te apunta con su pata.", - "Cuando te atasques, usa la metodología Leer-Buscar-Preguntar.
No te preocupes - ya lo has entendido.", - "" - ] - ] - }, - "pt-br": { - "title": "Prepare-se para nossos desafios de algoritmos", - "description": [ - [ - "https://i.imgur.com/sJkp30a.png", - "Uma imagem de um desafio de algoritmo mostrando instruções, testes e o editor de código.", - "Nossos desafios de algoritmos vão te ensinar a pensar como um programador.", - "" - ], - [ - "https://i.imgur.com/d8LuRNh.png", - "Uma mãe pássaro expulsa seu filhote do ninho.", - "Os desafios anteriores te apresentaram os conceitos de programação. Mas para esses desafios de algoritmos, você terá que aplicar o que aprendeu para resolver problemas abertos.", - "" - ], - [ - "https://i.imgur.com/WBetuBa.jpg", - "Um programador frustrado atravessando a tela de seu laptop com um soco.", - "Os desafios de algoritmos são difíceis. Você pode levar várias horas para resolver alguns deles. Você vai ficar frustado. Mas não desista.", - "" - ], - [ - "https://i.imgur.com/p2TpOQd.jpg", - "Um cachorro fofo pulando sobre um obstáculo, piscando e apontando a pata na sua direção.", - "Quando ficar travado, use a metodologia Ler-Pesquisar-Perguntar.
Não se preocupe - você consegue.", - "" - ] - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b3", - "title": "Convert Celsius to Fahrenheit", - "description": [ - "The algorithm to convert from Celsius to Fahrenheit is the temperature in Celsius times 9/5, plus 32.", - "You are given a variable celsius representing a temperature in Celsius. Use the variable fahrenheit already defined and assign it the Fahrenheit temperature equivalent to the given Celsius temperature. Use the algorithm mentioned above to help convert the Celsius temperature to Fahrenheit.", - "Don't worry too much about the function and return statements as they will be covered in future challenges. For now, only use operators that you have already learned." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function convertToF(celsius) {", - " let fahrenheit;", - " return fahrenheit;", - "}", - "", - "convertToF(30);" - ], - "solutions": [ - "function convertToF(celsius) {\n let fahrenheit = celsius * 9/5 + 32;\n\n return fahrenheit;\n}\n\nconvertToF(30);\n" - ], - "tests": [ - "assert(typeof convertToF(0) === 'number', 'message: convertToF(0) should return a number');", - "assert(convertToF(-30) === -22, 'message: convertToF(-30) should return a value of -22');", - "assert(convertToF(-10) === 14, 'message: convertToF(-10) should return a value of 14');", - "assert(convertToF(0) === 32, 'message: convertToF(0) should return a value of 32');", - "assert(convertToF(20) === 68, 'message: convertToF(20) should return a value of 68');", - "assert(convertToF(30) === 86, 'message: convertToF(30) should return a value of 86');" - ], - "type": "checkpoint", - "challengeType": 1, - "isRequired": true, - "translations": { - "es": { - "title": "Convierte celsius a fahrenheit", - "description": [ - "Para probar tu aprendizaje, crearás una solucion \"desde cero\". Coloca tu código entre las líneas indicadas y este será probado contra multiples casos de prueba.", - "El algoritmo para convertir de Celsius a Fahrenheit consiste en multiplicar la temperatura en grados Celsius por 9/5 y al resultado agregarle 32.", - "Se te da una variable celsius representando una temperatura en Celsius. Crea una variable fahrenheit y aplica el algoritmo para asignar la correspondiente temperatura en Fahrenheit." - ] - }, - "pt-br": { - "title": "Converta Celsius para Fahrenheit", - "description": [ - "O algoritmo para converter de Celsius para Fahrenheit é a temperatura em Celsius vezes 9/5 mais 32.", - "Você recebe uma variável celsius representando uma temperatura em Celsius. Use a variável fahrenheit já definida e aplique o algoritmo para atribuir a ela a temperatura correspondente em Fahrenheit." - ] - } - } - }, - { - "id": "a202eed8fc186c8434cb6d61", - "title": "Reverse a String", - "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.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function reverseString(str) {", - " return str;", - "}", - "", - "reverseString(\"hello\");" - ], - "tests": [ - "assert(typeof reverseString(\"hello\") === \"string\", 'message: reverseString(\"hello\") should return a string.');", - "assert(reverseString(\"hello\") === \"olleh\", 'message: reverseString(\"hello\") should become \"olleh\".');", - "assert(reverseString(\"Howdy\") === \"ydwoH\", 'message: reverseString(\"Howdy\") should become \"ydwoH\".');", - "assert(reverseString(\"Greetings from Earth\") === \"htraE morf sgniteerG\", 'message: reverseString(\"Greetings from Earth\") should return \"htraE morf sgniteerG\".');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function reverseString(str) {\n return str.split('').reverse().join('');\n}\n\nreverseString(\"hello\");\n" - ], - "MDNlinks": [ - "Global String Object", - "String.prototype.split()", - "Array.prototype.reverse()", - "Array.prototype.join()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Invierte el texto", - "description": [ - "Invierte la cadena de texto que se te provee", - "Puede que necesites convertir la cadena de texto en un arreglo antes de que puedas invertirla", - "El resultado debe ser una cadena de texto", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Inverta uma string", - "description": [ - "Inverta a string fornecida.", - "Talvez você tenha que transformar a string num array antes de invertê-la.", - "Seu resultado deve ser uma string.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a302f7aae1aa3152a5b413bc", - "title": "Factorialize a Number", - "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 = 120", - "Only integers greater than or equal to zero will be supplied to the function.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function factorialize(num) {", - " return num;", - "}", - "", - "factorialize(5);" - ], - "tests": [ - "assert(typeof factorialize(5) === 'number', 'message: factorialize(5) should return a number.');", - "assert(factorialize(5) === 120, 'message: factorialize(5) should return 120.');", - "assert(factorialize(10) === 3628800, 'message: factorialize(10) should return 3628800.');", - "assert(factorialize(20) === 2432902008176640000, 'message: factorialize(20) should return 2432902008176640000.');", - "assert(factorialize(0) === 1, 'message: factorialize(0) should return 1.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function factorialize(num) {\n return num < 1 ? 1 : num * factorialize(num - 1);\n}\n\nfactorialize(5);\n" - ], - "MDNlinks": [ - "Arithmetic Operators" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Factoriza un número", - "description": [ - "Crea una función que devuelva el factorial del número entero que se te provee", - "El factorial de un número entero positivo n es la multiplicación de todos los enteros positivos menores o iguales a n", - "Los factoriales son comúnmente representados con la notación n!", - "Por ejemplo: 5! = 1 * 2 * 3 * 4 * 5 = 120", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Determine o fatorial de um número", - "description": [ - "Retorne o fatorial do inteiro fornecido.", - "Se o inteiro é representado pela letra n, o seu fatorial é o produto de todos os inteiros positivos menores ou iguais a n.", - "Por exemplo: 5! = 1 * 2 * 3 * 4 * 5 = 120", - "Apenas inteiros maiores ou iguais a zero serão fornecidos à função.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a26cbbe9ad8655a977e1ceb5", - "title": "Find the Longest Word in a String", - "description": [ - "Return the length of the longest word in the provided sentence.", - "Your response should be a number.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function findLongestWordLength(str) {", - " return str.length;", - "}", - "", - "findLongestWordLength(\"The quick brown fox jumped over the lazy dog\");" - ], - "tests": [ - "assert(typeof findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") === \"number\", 'message: findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") should return a number.');", - "assert(findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") === 6, 'message: findLongestWordLength(\"The quick brown fox jumped over the lazy dog\") should return 6.');", - "assert(findLongestWordLength(\"May the force be with you\") === 5, 'message: findLongestWordLength(\"May the force be with you\") should return 5.');", - "assert(findLongestWordLength(\"Google do a barrel roll\") === 6, 'message: findLongestWordLength(\"Google do a barrel roll\") should return 6.');", - "assert(findLongestWordLength(\"What is the average airspeed velocity of an unladen swallow\") === 8, 'message: findLongestWordLength(\"What is the average airspeed velocity of an unladen swallow\") should return 8.');", - "assert(findLongestWordLength(\"What if we try a super-long word such as otorhinolaryngology\") === 19, 'message: findLongestWordLength(\"What if we try a super-long word such as otorhinolaryngology\") should return 19.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function findLongestWordLength(str) {\n return str.split(' ').sort((a, b) => b.length - a.length)[0].length;\n}\n\nfindLongestWordLength(\"The quick brown fox jumped over the lazy dog\");\n" - ], - "MDNlinks": [ - "String.prototype.split()", - "String.length" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Encuentra la palabra más larga", - "description": [ - "Crea una función que devuelva la longitud de la palabra más larga en una frase dada", - "El resultado debe ser un número", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Encontre a palavra mais longa de uma string", - "description": [ - "Retorne o tamanho da palavra mais longa da frase fornecida.", - "Sua resposta deve ser um número.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a789b3483989747d63b0e427", - "title": "Return Largest Numbers in Arrays", - "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].", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "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": [ - "assert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]).constructor === Array, 'message: largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return an array.');", - "assert.deepEqual(largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]), [27, 5, 39, 1001], 'message: largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return [27, 5, 39, 1001].');", - "assert.deepEqual(largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]), [9, 35, 97, 1000000], 'message: largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]) should return [9, 35, 97, 1000000].');", - "assert.deepEqual(largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]]), [25, 48, 21, -3], 'message: largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]]) should return [25, 48, 21, -3].');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function largestOfFour(arr) {\n return arr.map(subArr => Math.max.apply(null, subArr));\n}\n\nlargestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);\n" - ], - "MDNlinks": [ - "Comparison Operators" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Devuelve el mayor entero de cada arreglo", - "description": [ - "Crea una función que devuelva un arreglo que contenga el mayor de los números de cada sub-arreglo que recibe. Para simplificar las cosas, el arreglo que recibirá tendrá exactamente 4 sub-arreglos", - "Recuerda que puedes iterar a través de un arreglo con un búcle simple, y acceder a cada miembro utilizando la sintaxis arr[i].", - "Si escribes tu propio test con Chai.js, asegúrate de utilizar un operador de igualdad estricto en lugar de un operador de igualdad cuando compares arreglos. ", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Retorne os maiores números de arrays", - "description": [ - "Retorne um array contendo o maior número de cada sub-array fornecido. Para simplificar, o array fornecido conterá exatamente 4 sub-arrays.", - "Lembre-se, você pode iterar por um array com um simples for e acessar cada membro do array com a sintaxe arr[i].", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "acda2fb1324d9b0fa741e6b5", - "title": "Confirm the Ending", - "description": [ - "Check if a string (first argument, str) ends with the given target string (second argument, target).", - "This challenge can be solved with the .endsWith() method, which was introduced in ES2015. But for the purpose of this challenge, we would like you to use one of the JavaScript substring methods instead.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function confirmEnding(str, target) {", - " // \"Never give up and good luck will find you.\"", - " // -- Falcor", - " return str;", - "}", - "", - "confirmEnding(\"Bastian\", \"n\");" - ], - "tests": [ - "assert(confirmEnding(\"Bastian\", \"n\") === true, 'message: confirmEnding(\"Bastian\", \"n\") should return true.');", - "assert(confirmEnding(\"Congratulation\", \"on\") === true, 'message: confirmEnding(\"Congratulation\", \"on\") should return true.');", - "assert(confirmEnding(\"Connor\", \"n\") === false, 'message: confirmEnding(\"Connor\", \"n\") should return false.');", - "assert(confirmEnding(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") === false, 'message: confirmEnding(\"Walking on water and developing software from a specification are easy if both are frozen\", \"specification\") should return false.');", - "assert(confirmEnding(\"He has to give me a new name\", \"name\") === true, 'message: confirmEnding(\"He has to give me a new name\", \"name\") should return true.');", - "assert(confirmEnding(\"Open sesame\", \"same\") === true, 'message: confirmEnding(\"Open sesame\", \"same\") should return true.');", - "assert(confirmEnding(\"Open sesame\", \"pen\") === false, 'message: confirmEnding(\"Open sesame\", \"pen\") should return false.');", - "assert(confirmEnding(\"Open sesame\", \"game\") === false, 'message: confirmEnding(\"Open sesame\", \"game\") should return false.');", - "assert(confirmEnding(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") === false, 'message: confirmEnding(\"If you want to save our world, you must hurry. We dont know how much longer we can withstand the nothing\", \"mountain\") should return false.');", - "assert(confirmEnding(\"Abstraction\", \"action\") === true, 'message: confirmEnding(\"Abstraction\", \"action\") should return true.');", - "assert(!(/\\.endsWith\\(.*?\\)\\s*?;?/.test(code)) && !(/\\['endsWith'\\]/.test(code)), 'message: Do not use the built-in method .endsWith() to solve the challenge.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function confirmEnding(str, target) {\n return str.substring(str.length - target.length) === target;\n}\n\nconfirmEnding(\"Bastian\", \"n\");\n" - ], - "MDNlinks": [ - "String.prototype.substr()", - "String.prototype.substring()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Confirma la terminación", - "description": [ - "Verifica si una cadena de texto (primer argumento) termina con otra cadena de texto (segundo argumento).", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Confirme o final", - "description": [ - "Verifique se uma string (primeiro argumento, str) termina com a string alvo fornecida (segundo argumento, target).", - "Esse desafio pode ser resolvido com o método .endsWith(), que foi introduzido na ES2015. Mas para o propósito desse desafio, nós gostaríamos que, ao invés dele, você usasse algum dos métodos de substring do JavaScript.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "afcc8d540bea9ea2669306b6", - "title": "Repeat a String Repeat a String", - "description": [ - "Repeat a given string str (first argument) for num times (second argument). Return an empty string if num is not a positive number.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function repeatStringNumTimes(str, num) {", - " // repeat after me", - " return str;", - "}", - "", - "repeatStringNumTimes(\"abc\", 3);" - ], - "tests": [ - "assert(repeatStringNumTimes(\"*\", 3) === \"***\", 'message: repeatStringNumTimes(\"*\", 3) should return \"***\".');", - "assert(repeatStringNumTimes(\"abc\", 3) === \"abcabcabc\", 'message: repeatStringNumTimes(\"abc\", 3) should return \"abcabcabc\".');", - "assert(repeatStringNumTimes(\"abc\", 4) === \"abcabcabcabc\", 'message: repeatStringNumTimes(\"abc\", 4) should return \"abcabcabcabc\".');", - "assert(repeatStringNumTimes(\"abc\", 1) === \"abc\", 'message: repeatStringNumTimes(\"abc\", 1) should return \"abc\".');", - "assert(repeatStringNumTimes(\"*\", 8) === \"********\", 'message: repeatStringNumTimes(\"*\", 8) should return \"********\".');", - "assert(repeatStringNumTimes(\"abc\", -2) === \"\", 'message: repeatStringNumTimes(\"abc\", -2) should return \"\".');", - "assert(!/\\.repeat/g.test(code), 'message: The built-in repeat()-method should not be used');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function repeatStringNumTimes(str, num) {\n if (num < 0) return '';\n return num === 1 ? str : str + repeatStringNumTimes(str, num-1);\n}\n\nrepeatStringNumTimes(\"abc\", 3);\n" - ], - "MDNlinks": [ - "Global String Object" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Repite el Texto Repite el Texto", - "description": [ - "Repite una cadena de texto dada (primer argumento) num veces (segundo argumento). Retorna una cadena de texto vacía si num es un número negativo.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Repita uma string Repita uma string", - "description": [ - "Repita uma string str dada (primeiro argumento) num vezes (segundo argumento). Retorne uma string vazia se num não for um número positivo.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "ac6993d51946422351508a41", - "title": "Truncate a String", - "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.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function truncateString(str, num) {", - " // Clear out that junk in your trunk", - " return str;", - "}", - "", - "truncateString(\"A-tisket a-tasket A green and yellow basket\", 8);" - ], - "tests": [ - "assert(truncateString(\"A-tisket a-tasket A green and yellow basket\", 8) === \"A-tisket...\", 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", 8) should return \"A-tisket...\".');", - "assert(truncateString(\"Peter Piper picked a peck of pickled peppers\", 11) === \"Peter Piper...\", 'message: truncateString(\"Peter Piper picked a peck of pickled peppers\", 11) should return \"Peter Piper...\".');", - "assert(truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) === \"A-tisket a-tasket A green and yellow basket\", 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncateString('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2) === 'A-tisket a-tasket A green and yellow basket', 'message: truncateString(\"A-tisket a-tasket A green and yellow basket\", \"A-tisket a-tasket A green and yellow basket\".length + 2) should return \"A-tisket a-tasket A green and yellow basket\".');", - "assert(truncateString(\"A-\", 1) === \"A...\", 'message: truncateString(\"A-\", 1) should return \"A...\".');", - "assert(truncateString(\"Absolutely Longer\", 2) === \"Ab...\", 'message: truncateString(\"Absolutely Longer\", 2) should return \"Ab...\".');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function truncateString(str, num) {\n if (num >= str.length) {\n return str;\n }\n\n return str.slice(0, num) + '...';\n}\n\ntruncateString(\"A-tisket a-tasket A green and yellow basket\", 8);\n" - ], - "MDNlinks": [ - "String.prototype.slice()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Trunca una Cadena de Texto", - "description": [ - "Trunca una cadena de texto (primer argumento) si su longitud es mayor que un máximo de caracteres dado (segundo argumento). Devuelve la cadena de texto truncada con una terminación \"...\".", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Trunque uma string", - "description": [ - "Trunque uma string (primeiro argumento) se ela for mais longa do que o comprimento máximo dado (segundo argumento). Retorne a string truncada com um ... no final.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a6e40f1041b06c996f7b2406", - "title": "Finders Keepers", - "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). If no element passes the test, return undefined.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function findElement(arr, func) {", - " let num = 0;", - " return num;", - "}", - "", - "findElement([1, 2, 3, 4], num => num % 2 === 0);" - ], - "solutions": [ - "function findElement(arr, func) {\n let num;\n\n arr.some(e => {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n\n return num;\n}\n\nfindElement([1, 2, 3, 4], num => num % 2 === 0);\n" - ], - "tests": [ - "assert.strictEqual(findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'message: findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }) should return 8.');", - "assert.strictEqual(findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; }) should return undefined.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Array.prototype.filter()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Buscando la verdad", - "description": [ - "Crea una función que busque dentro de un vector (primer argumento) y que devuelva el primer elemento que pase una prueba de verdad (segundo argumento).", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Achado não é roubado", - "description": [ - "Crie uma função que itera sobre um array (primeiro argumento) e retorna o primeiro elemento do array que retornar true para uma função de teste (segundo argumento). Se nenhum elemento passar no teste, retorne undefined.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - }, - "fr": { - "title": "Détecteur de mensonges", - "description": [ - "Crée une fonction qui parcourt un tableau (premier argument) et renvoie le premier élément du tableau qui passe le test (second argument).", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a77dbc43c33f39daa4429b4f", - "title": "Boo who", - "description": [ - "Check if a value is classified as a boolean primitive. Return true or false.", - "Boolean primitives are true and false.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function booWho(bool) {", - " // What is the new fad diet for ghost developers? The Boolean.", - " return bool;", - "}", - "", - "booWho(null);" - ], - "solutions": [ - "function booWho(bool) {\n return typeof bool === \"boolean\";\n}\n\nbooWho(null);" - ], - "tests": [ - "assert.strictEqual(booWho(true), true, 'message: booWho(true) should return true.');", - "assert.strictEqual(booWho(false), true, 'message: booWho(false) should return true.');", - "assert.strictEqual(booWho([1, 2, 3]), false, 'message: booWho([1, 2, 3]) should return false.');", - "assert.strictEqual(booWho([].slice), false, 'message: booWho([].slice) should return false.');", - "assert.strictEqual(booWho({ \"a\": 1 }), false, 'message: booWho({ \"a\": 1 }) should return false.');", - "assert.strictEqual(booWho(1), false, 'message: booWho(1) should return false.');", - "assert.strictEqual(booWho(NaN), false, 'message: booWho(NaN) should return false.');", - "assert.strictEqual(booWho(\"a\"), false, 'message: booWho(\"a\") should return false.');", - "assert.strictEqual(booWho(\"true\"), false, 'message: booWho(\"true\") should return false.');", - "assert.strictEqual(booWho(\"false\"), false, 'message: booWho(\"false\") should return false.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Boolean Objects" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "¡Bu!", - "description": [ - "Crea una función que verifique si el valor que se le pasa es de tipo booleano. Haz que la función devuelva true o false según corresponda.", - "Los primitivos booleanos primitivos son: true y false", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Bu!", - "description": [ - "Verifique se um valor é classificado como um primitivo booleano. Retorne true ou false.", - "Primitivos booleanos são true e false.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Tente programar em par. Escreva seu próprio código." - ] - }, - "fr": { - "title": "Boo !", - "description": [ - "Crée une fonction qui vérifie qu'une valeur est de type booléen. Renvoie true ou false.", - "Les primitives booléennes sont true ou false.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "ab6137d4e35944e21037b769", - "title": "Title Case a Sentence", - "description": [ - "Return the provided string with the first letter of each word capitalized. Make sure the rest of the word is in lower case.", - "For the purpose of this exercise, you should also capitalize connecting words like \"the\" and \"of\".", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function titleCase(str) {", - " return str;", - "}", - "", - "titleCase(\"I'm a little tea pot\");" - ], - "tests": [ - "assert(typeof titleCase(\"I'm a little tea pot\") === \"string\", 'message: titleCase(\"I'm a little tea pot\") should return a string.');", - "assert(titleCase(\"I'm a little tea pot\") === \"I'm A Little Tea Pot\", 'message: titleCase(\"I'm a little tea pot\") should return I'm A Little Tea Pot.');", - "assert(titleCase(\"sHoRt AnD sToUt\") === \"Short And Stout\", 'message: titleCase(\"sHoRt AnD sToUt\") should return Short And Stout.');", - "assert(titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") === \"Here Is My Handle Here Is My Spout\", 'message: titleCase(\"HERE IS MY HANDLE HERE IS MY SPOUT\") should return Here Is My Handle Here Is My Spout.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function titleCase(str) {\n return str.split(' ').map(word => word.charAt(0).toUpperCase() + word.substring(1).toLowerCase()).join(' ');\n}\n\ntitleCase(\"I'm a little tea pot\");\n" - ], - "MDNlinks": [ - "String.prototype.split()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Aplica formato de título", - "description": [ - "Crea una función que devuelva la cadena de texto que recibe con la primera letra de cada palabra en mayúscula. Asegúrate de que el resto de las letras sean minúsculas", - "Para este ejercicio, también debes poner en mayúscula conectores como \"the\" y \"of\".", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Transforme Uma String Num Título", - "description": [ - "Retorne a string fornecida com a primeira letra de cada palavra em maiúsculo. Certifique-se de que o resto da palavra esteja minúsculo.", - "Para o propósito desse exercício, você também deve deixar maiúscula a primeira letra das palavras de ligação como \"the\" e \"of\".", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "579e2a2c335b9d72dd32e05c", - "title": "Slice and Splice", - "description": [ - "You are given two arrays and an index.", - "Use the array methods slice and splice to copy each element of the first array into the second array, in order.", - "Begin inserting elements at index n of the second array.", - "Return the resulting array. The input arrays should remain the same after the function runs.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function frankenSplice(arr1, arr2, n) {", - " // It's alive. It's alive!", - " return arr2;", - "}", - "", - "frankenSplice([1, 2, 3], [4, 5, 6], 1);" - ], - "tail": [ - "let testArr1 = [1, 2];", - "let testArr2 = [\"a\", \"b\"];" - ], - "tests": [ - "assert.deepEqual(frankenSplice([1, 2, 3], [4, 5], 1), [4, 1, 2, 3, 5], 'message: frankenSplice([1, 2, 3], [4, 5], 1) should return [4, 1, 2, 3, 5].');", - "assert.deepEqual(frankenSplice(testArr1, testArr2, 1), [\"a\", 1, 2, \"b\"], 'message: frankenSplice([1, 2], [\"a\", \"b\"], 1) should return [\"a\", 1, 2, \"b\"].');", - "assert.deepEqual(frankenSplice([\"claw\", \"tentacle\"], [\"head\", \"shoulders\", \"knees\", \"toes\"], 2), [\"head\", \"shoulders\", \"claw\", \"tentacle\", \"knees\", \"toes\"], 'message: frankenSplice([\"claw\", \"tentacle\"], [\"head\", \"shoulders\", \"knees\", \"toes\"], 2) should return [\"head\", \"shoulders\", \"claw\", \"tentacle\", \"knees\", \"toes\"].');", - "assert.deepEqual(frankenSplice([1, 2, 3, 4], [], 0), [1, 2, 3, 4], 'message: All elements from the first array should be added to the second array in their original order.');", - "assert(testArr1[0] === 1 && testArr1[1] === 2, 'message: The first array should remain the same after the function runs.');", - "assert(testArr2[0] === \"a\" && testArr2[1] === \"b\", 'message: The second array should remain the same after the function runs.');" - ], - "type": "bonfire", - "isRequired": true, - "isBeta": true, - "solutions": [ - "function frankenSplice(arr1, arr2, n) {\n // It's alive. It's alive!\n let result = arr2.slice();\n for (let i = 0; i < arr1.length; i++) {\n result.splice(n+i, 0, arr1[i]);\n }\n return result;\n}\n\nfrankenSplice([1, 2, 3], [4, 5], 1);\n" - ], - "MDNlinks": [ - "Array.prototype.slice()", - "Array.prototype.splice()" - ], - "challengeType": 5, - "translations": { - "pt-br": { - "title": "Slice e splice", - "description": [ - "Você recebe dois arrays e um índice.", - "Use os métodos de array slice e splice para copiar cada elemento do primeiro array para o segundo array, em ordem.", - "Comece a inserir elementos no índice n do segundo array.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "adf08ec01beb4f99fc7a68f2", - "title": "Falsy Bouncer", - "description": [ - "Remove all falsy values from an array.", - "Falsy values in JavaScript are false, null, 0, \"\", undefined, and NaN.", - "Hint: Try converting each value to a Boolean.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "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], 'message: bouncer([7, \"ate\", \"\", false, 9]) should return [7, \"ate\", 9].');", - "assert.deepEqual(bouncer([\"a\", \"b\", \"c\"]), [\"a\", \"b\", \"c\"], 'message: bouncer([\"a\", \"b\", \"c\"]) should return [\"a\", \"b\", \"c\"].');", - "assert.deepEqual(bouncer([false, null, 0, NaN, undefined, \"\"]), [], 'message: bouncer([false, null, 0, NaN, undefined, \"\"]) should return [].');", - "assert.deepEqual(bouncer([1, null, NaN, 2, undefined]), [1, 2], 'message: bouncer([1, null, NaN, 2, undefined]) should return [1, 2].');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function bouncer(arr) {\n return arr.filter(e => e);\n}\n\nbouncer([7, \"ate\", \"\", false, 9]);\n" - ], - "MDNlinks": [ - "Boolean Objects", - "Array.prototype.filter()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Detector de Mentiras", - "description": [ - "Remueve todos los valores falsy de un arreglo dado", - "En JavaScript, los valores falsy son los siguientes: false, null, 0, \"\", undefined, y NaN.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Detector de mentiras", - "description": [ - "Remova todos os valores falsos de um array.", - "Valores falsos em JavaScript são false, null, 0, \"\", undefined e NaN.", - "Dica: Tente converter cada valor para um booleano.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a24c1a4622e3c05097f71d67", - "title": "Where do I Belong", - "description": [ - "Return the lowest index at which a value (second argument) should be inserted into an array (first argument) once it has been sorted. The returned value should be a number.", - "For example, getIndexToIns([1,2,3,4], 1.5) should return 1 because it is greater than 1 (index 0), but less than 2 (index 1).", - "Likewise, getIndexToIns([20,3,5], 19) should return 2 because once the array has been sorted it will look like [3,5,20] and 19 is less than 20 (index 2) and greater than 5 (index 1).", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function getIndexToIns(arr, num) {", - " // Find my place in this sorted array.", - " return num;", - "}", - "", - "getIndexToIns([40, 60], 50);" - ], - "tests": [ - "assert(getIndexToIns([10, 20, 30, 40, 50], 35) === 3, 'message: getIndexToIns([10, 20, 30, 40, 50], 35) should return 3.');", - "assert(typeof(getIndexToIns([10, 20, 30, 40, 50], 35)) === \"number\", 'message: getIndexToIns([10, 20, 30, 40, 50], 35) should return a number.');", - "assert(getIndexToIns([10, 20, 30, 40, 50], 30) === 2, 'message: getIndexToIns([10, 20, 30, 40, 50], 30) should return 2.');", - "assert(typeof(getIndexToIns([10, 20, 30, 40, 50], 30)) === \"number\", 'message: getIndexToIns([10, 20, 30, 40, 50], 30) should return a number.');", - "assert(getIndexToIns([40, 60], 50) === 1, 'message: getIndexToIns([40, 60], 50) should return 1.');", - "assert(typeof(getIndexToIns([40, 60], 50)) === \"number\", 'message: getIndexToIns([40, 60], 50) should return a number.');", - "assert(getIndexToIns([3, 10, 5], 3) === 0, 'message: getIndexToIns([3, 10, 5], 3) should return 0.');", - "assert(typeof(getIndexToIns([3, 10, 5], 3)) === \"number\", 'message: getIndexToIns([3, 10, 5], 3) should return a number.');", - "assert(getIndexToIns([5, 3, 20, 3], 5) === 2, 'message: getIndexToIns([5, 3, 20, 3], 5) should return 2.');", - "assert(typeof(getIndexToIns([5, 3, 20, 3], 5)) === \"number\", 'message: getIndexToIns([5, 3, 20, 3], 5) should return a number.');", - "assert(getIndexToIns([2, 20, 10], 19) === 2, 'message: getIndexToIns([2, 20, 10], 19) should return 2.');", - "assert(typeof(getIndexToIns([2, 20, 10], 19)) === \"number\", 'message: getIndexToIns([2, 20, 10], 19) should return a number.');", - "assert(getIndexToIns([2, 5, 10], 15) === 3, 'message: getIndexToIns([2, 5, 10], 15) should return 3.');", - "assert(typeof(getIndexToIns([2, 5, 10], 15)) === \"number\", 'message: getIndexToIns([2, 5, 10], 15) should return a number.');", - "assert(getIndexToIns([], 1) === 0, 'message: getIndexToIns([], 1) should return 0.');", - "assert(typeof(getIndexToIns([], 1)) === \"number\", 'message: getIndexToIns([], 1) should return a number.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function getIndexToIns(arr, num) {\n arr = arr.sort((a, b) => a - b);\n\n for (let i = 0; i < arr.length; i++) {\n if (arr[i] >= num) {\n return i;\n }\n }\n\n return arr.length;\n}\n\ngetIndexToIns([40, 60], 50);\n" - ], - "MDNlinks": [ - "Array.prototype.sort()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "¿Cuál es mi Asiento?", - "description": [ - "Devuelve el menor índice en el que un valor (segundo argumento) debe ser insertado en un arreglo (primer argumento) una vez ha sido ordenado.", - "Por ejemplo, where([1,2,3,4], 1.5) debe devolver 1 porque el segundo argumento de la función (1.5) es mayor que 1 (con índice 0 en el arreglo), pero menor que 2 (con índice 1).", - "Mientras que where([20,3,5], 19) debe devolver 2 porque una vez ordenado el arreglo se verá com [3,5,20] y 19 es menor que 20 (índice 2) y mayor que 5 (índice 1).", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Onde é meu lugar?", - "description": [ - "Retorne o menor índice no qual um valor (segundo argumento) deve ser inserido num array (primeiro argumento) depois que ele foi ordenado. O valor retornado deve ser um número.", - "Por exemplo, getIndexToIns([1,2,3,4], 1.5) deve retornar 1 porque 1.5 é maior que 1 (índice 0), mas menor que 2 (índice 1).", - "Da mesma forma, getIndexToIns([20,3,5], 19) deve retornar 2 porque, depois de ordenado, o array será [3,5,20] e 19 é menor que 20 (índice 2) e maior que 5 (index 1).", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "af2170cad53daa0770fabdea", - "title": "Mutations", - "description": [ - "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\".", - "Lastly, [\"Alien\", \"line\"], should return true because all of the letters in \"line\" are present in \"Alien\".", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function mutation(arr) {", - " return arr;", - "}", - "", - "mutation([\"hello\", \"hey\"]);" - ], - "tests": [ - "assert(mutation([\"hello\", \"hey\"]) === false, 'message: mutation([\"hello\", \"hey\"]) should return false.');", - "assert(mutation([\"hello\", \"Hello\"]) === true, 'message: mutation([\"hello\", \"Hello\"]) should return true.');", - "assert(mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) === true, 'message: mutation([\"zyxwvutsrqponmlkjihgfedcba\", \"qrstu\"]) should return true.');", - "assert(mutation([\"Mary\", \"Army\"]) === true, 'message: mutation([\"Mary\", \"Army\"]) should return true.');", - "assert(mutation([\"Mary\", \"Aarmy\"]) === true, 'message: mutation([\"Mary\", \"Aarmy\"]) should return true.');", - "assert(mutation([\"Alien\", \"line\"]) === true, 'message: mutation([\"Alien\", \"line\"]) should return true.');", - "assert(mutation([\"floor\", \"for\"]) === true, 'message: mutation([\"floor\", \"for\"]) should return true.');", - "assert(mutation([\"hello\", \"neo\"]) === false, 'message: mutation([\"hello\", \"neo\"]) should return false.');", - "assert(mutation([\"voodoo\", \"no\"]) === false, 'message: mutation([\"voodoo\", \"no\"]) should return false.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function mutation(arr) {\n let hash = Object.create(null);\n\n arr[0].toLowerCase().split('').forEach(c => hash[c] = true);\n\n return !arr[1].toLowerCase().split('').filter(c => !hash[c]).length;\n}\n\nmutation([\"hello\", \"hey\"]);\n" - ], - "MDNlinks": [ - "String.prototype.indexOf()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Mutaciones", - "description": [ - "Crea una función que devuelva true si la cadena de texto del primer elemento de un arreglo contiene todas las letras de la cadena de texto del segundo elemento del arreglo.", - "Por ejemplo, [\"hello\", \"Hello\"], debe devolver true porque todas las letras en la segunda cadena de texto están presentes en la primera, sin distinguir entre mayúsculas y minúsculas.", - "En el caso de [\"hello\", \"hey\"] la función debe devolver false porque la cadena de texto \"hello\" no contiene una \"y\".", - "Finalmente, [\"Alien\", \"line\"], la función debe devolver true porque todas las letras en \"line\" están presentes en \"Alien\".", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Mutações", - "description": [ - "Retorne true se a string no primeiro elemento do array contiver todas as letras da string no segundo elemento do array.", - "Por exemplo, para os argumentos [\"hello\", \"Hello\"], sua função deve retornar true, porque todas as letras da segunda string estão presentes na primeira, ignorando maiúsculas e minúsculas.", - "Para os argumentos [\"hello\", \"hey\"], sua função deve retornar false porque a string \"hello\" não contém um \"y\".", - "Finalmente, para [\"Alien\", \"line\"], sua função deve retornar true porque todas as letras em \"line\" estão presentes em \"Alien\".", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a9bd25c716030ec90084d8a1", - "title": "Chunky Monkey", - "description": [ - "Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a two-dimensional array.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function chunkArrayInGroups(arr, size) {", - " // Break it up.", - " return arr;", - "}", - "", - "chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2);" - ], - "tests": [ - "assert.deepEqual(chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2), [[\"a\", \"b\"], [\"c\", \"d\"]], 'message: chunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2) should return [[\"a\", \"b\"], [\"c\", \"d\"]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3) should return [[0, 1, 2], [3, 4, 5]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 2), [[0, 1], [2, 3], [4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 2) should return [[0, 1], [2, 3], [4, 5]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 4), [[0, 1, 2, 3], [4, 5]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5], 4) should return [[0, 1, 2, 3], [4, 5]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3), [[0, 1, 2], [3, 4, 5], [6]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3) should return [[0, 1, 2], [3, 4, 5], [6]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4), [[0, 1, 2, 3], [4, 5, 6, 7], [8]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4) should return [[0, 1, 2, 3], [4, 5, 6, 7], [8]].');", - "assert.deepEqual(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2), [[0, 1], [2, 3], [4, 5], [6, 7], [8]], 'message: chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2) should return [[0, 1], [2, 3], [4, 5], [6, 7], [8]].');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function chunkArrayInGroups(arr, size) {\n let out = [];\n\n for (let i = 0; i < arr.length; i += size) {\n out.push(arr.slice(i, i + size));\n }\n\n return out;\n}\n\nchunkArrayInGroups([\"a\", \"b\", \"c\", \"d\"], 2);\n" - ], - "MDNlinks": [ - "Array.prototype.push()", - "Array.prototype.slice()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "En mil Pedazos", - "description": [ - "Escribe una función que parta un arreglo (primer argumento) en fragmentos de una longitud dada (segundo argumento) y los devuelva en forma de un arreglo bidimensional.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Em pedaços", - "description": [ - "Escreva uma função que divide um array (primeiro argumento) em grupos de comprimento size (segundo argumento) e retorna esses grupos num array bidimensional.", - "Lembre-se de Ler-Pesquisar-Perguntar se ficar travado. Escreva seu próprio código." - ] - } - } - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json deleted file mode 100644 index 3694741c81..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-data-structures.json +++ /dev/null @@ -1,822 +0,0 @@ -{ - "name": "Basic Data Structures", - "order": 5, - "time": "1 hour", - "helpRoom": "Help", - "challenges": [ - { - "id": "5a61985d9bb0a3540e49dc9f", - "title": "Introduction to Arrays", - "description": [ - "", - "", - "Arrays are one of JavaScript's most fundamental built-in data structures, and probably the data structure that you will work with most often throughout the course of the freeCodeCamp curriculum. The array is by no means unique to JavaScript, however — in fact, it’s probably safe to say that arrays are utilized by almost every complex program... ever.

In computer science, an array is a linear collection of elements characterized by the fact that each element has a unique index, or address, that can be computed and used to look up an element's position at run-time.", - "", - "@@STEP@@", - "", - "", - "In JavaScript, arrays are written as comma-separated lists and are enclosed in brackets [element1, element2, element3]. They can be any length, and store any type of data supported by JavaScript.

Arrays can sometimes be simple and serve very basic functionalities, but they can also be complex and very powerful - all of which depends on how the programmer chooses to utilize them

From this point forward, whenever we refer to the term array, it will be strictly within the context of JavaScript.", - "", - "@@STEP@@", - "", - "", - "JavaScript offers many array methods, which are a sort of built in function, that allow us to access, traverse, and mutate arrays as needed, depending on our purpose.

In the coming challenges, we will discuss several of the most common and useful methods, and a few other key techniques, that will help you to better understand and utilize arrays as data structures in JavaScript.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7b7e367417b2b2512b20", - "title": "Use an Array to Store a Collection of Data", - "description": [ - "The below is an example of the simplest implementation of an array data structure. This is known as a one-dimensional array, meaning it only has one level, or that it does not have any other arrays nested within it. Notice it contains booleans, strings, and numbers, among other valid JavaScript data types:", - "
let simpleArray = ['one', 2, 'three’, true, false, undefined, null];
console.log(simpleArray.length);
// logs 7
", - "All array's have a length property, which as shown above, can be very easily accessed with the syntax Array.length.", - "A more complex implementation of an array can be seen below. This is known as a multi-dimensional array, or an array that contains other arrays. Notice that this array also contains JavaScript objects, which we will examine very closely in our next section, but for now, all you need to know is that arrays are also capable of storing complex objects.", - "
let complexArray = [
[
{
one: 1,
two: 2
},
{
three: 3,
four: 4
}
],
[
{
a: \"a\",
b: \"b\"
},
{
c: \"c\",
d: “d”
}
]
];
", - "
", - "We have defined a variable called yourArray. Complete the statement by assigning an array of at least 5 elements in length to the yourArray variable. Your array should contain at least one string, one number, and one boolean." - ], - "challengeSeed": [ - "let yourArray; // change this line" - ], - "tests": [ - "assert.strictEqual(Array.isArray(yourArray), true, 'message: yourArray is an array');", - "assert.isAtLeast(yourArray.length, 5, 'message: yourArray is at least 5 elements long');", - "assert(yourArray.filter( el => typeof el === 'boolean').length >= 1, 'message: yourArray contains at least one boolean');", - "assert(yourArray.filter( el => typeof el === 'number').length >= 1, 'message: yourArray contains at least one number');", - "assert(yourArray.filter( el => typeof el === 'string').length >= 1, 'message: yourArray contains at least one string');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "5a661e0f1068aca922b3ef17", - "title": "Access an Array's Contents Using Bracket Notation", - "description": [ - "The fundamental feature of any data structure is, of course, the ability to not only store data, but to be able to retrieve that data on command. So, now that we've learned how to create an array, let's begin to think about how we can access that array's information.", - "When we define a simple array as seen below, there are 3 items in it:", - "
let ourArray = [\"a\", \"b\", \"c\"];
", - "In an array, each array item has an index. This index doubles as the position of that item in the array, and how you reference it. However, it is important to note, that JavaScript arrays are zero-indexed, meaning that the first element of an array is actually at the zeroth position, not the first.", - "In order to retrieve an element from an array we can enclose an index in brackets and append it to the end of an array, or more commonly, to a variable which references an array object. This is known as bracket notation.", - "For example, if we want to retrieve the \"a\" from ourArray and assign it to a variable, we can do so with the following code:", - "
let ourVariable = ourArray[0];
// ourVariable equals \"a\"
", - "In addition to accessing the value associated with an index, you can also set an index to a value using the same notation:", - "
ourArray[1] = \"not b anymore\";
// ourArray now equals [\"a\", \"not b anymore\", \"c\"];
", - "Using bracket notation, we have now reset the item at index 1 from \"b\", to \"not b anymore\".", - "
", - "In order to complete this challenge, set the 2nd position (index 1) of myArray to anything you want, besides \"b\"." - ], - "challengeSeed": [ - "let myArray = [\"a\", \"b\", \"c\", \"d\"];", - "// change code below this line", - "", - "//change code above this line", - "console.log(myArray);" - ], - "tests": [ - "assert.strictEqual(myArray[0], \"a\", 'message: myArray[0] is equal to \"a\"');", - "assert.notStrictEqual(myArray[1], \"b\", 'message: myArray[1] is no longer set to \"b\"');", - "assert.strictEqual(myArray[2], \"c\", 'message: myArray[2] is equal to \"c\"');", - "assert.strictEqual(myArray[3], \"d\", 'message: myArray[3] is equal to \"d\"');" - ], - "type": "waypoint", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d78b2367417b2b2512b0e", - "title": "Add Items to an Array with push() and unshift()", - "description": [ - "An array's length, like the data types it can contain, is not fixed. Arrays can be defined with a length of any number of elements, and elements can be added or removed over time; in other words, arrays are mutable. In this challenge, we will look at two methods with which we can programmatically modify an array: Array.push() and Array.unshift(). ", - "Both methods take one or more elements as parameters and add those elements to the array the method is being called on; the push() method adds elements to the end of an array, and unshift() adds elements to the beginning. Consider the following:", - "
let twentyThree = 'XXIII';
let romanNumerals = ['XXI', 'XXII'];

romanNumerals.unshift('XIX', 'XX');
// now equals ['XIX', 'XX', 'XXI', 'XXII']

romanNumerals.push(twentyThree);
// now equals ['XIX', 'XX', 'XXI', 'XXII', 'XXIII']", - "Notice that we can also pass variables, which allows us even greater flexibility in dynamically modifying our array's data.", - "
", - "We have defined a function, mixedNumbers, which we are passing an array as an argument. Modify the function by using push() and unshift() to add 'I', 2, 'three' to the beginning of the array and 7, 'VIII', 9 to the end so that the returned array contains representations of the numbers 1-9 in order." - ], - "challengeSeed": [ - "function mixedNumbers(arr) {", - " // change code below this line", - "", - " // change code above this line", - " return arr;", - "}", - "", - "// do not change code below this line", - "console.log(mixedNumbers(['IV', 5, 'six']));" - ], - "tests": [ - "assert.deepEqual(mixedNumbers(['IV', 5, 'six']), ['I', 2, 'three', 'IV', 5, 'six', 7, 'VIII', 9], 'message: mixedNumbers([\"IV\", 5, \"six\"]) should now return [\"I\", 2, \"three\", \"IV\", 5, \"six\", 7, \"VIII\", 9]');", - "assert.notStrictEqual(mixedNumbers.toString().search(/\\.push\\(/), -1, 'message: The mixedNumbers function should utilize the push() method');", - "assert.notStrictEqual(mixedNumbers.toString().search(/\\.unshift\\(/), -1, 'message: The mixedNumbers function should utilize the unshift() method');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d78b2367417b2b2512b0f", - "title": "Remove Items from an Array with pop() and shift()", - "description": [ - "Both push() and unshift() have corresponding methods that are nearly functional opposites: pop() and shift(). As you may have guessed by now, instead of adding, pop() removes an element from the end of an array, while shift() removes an element from the beginning. The key difference between pop() and shift() and their cousins push() and unshift(), is that neither method takes parameters, and each only allows an array to be modified by a single element at a time.", - "Let's take a look:", - "
let greetings = ['whats up?', 'hello', 'see ya!'];

greetings.pop();
// now equals ['whats up?', 'hello']

greetings.shift();
// now equals ['hello']
", - "We can also return the value of the removed element with either method like this:", - "
let popped = greetings.pop();
// returns 'hello'
// greetings now equals []
", - "
", - "We have defined a function, popShift, which takes an array as an argument and returns a new array. Modify the function, using pop() and shift(), to remove the first and last elements of the argument array, and assign the removed elements to their corresponding variables, so that the returned array contains their values." - ], - "challengeSeed": [ - "function popShift(arr) {", - " let popped; // change this line", - " let shifted; // change this line", - " return [shifted, popped];", - "}", - "", - "// do not change code below this line", - "console.log(popShift(['challenge', 'is', 'not', 'complete']));" - ], - "tests": [ - "assert.deepEqual(popShift(['challenge', 'is', 'not', 'complete']), [\"challenge\", \"complete\"], 'message: popShift([\"challenge\", \"is\", \"not\", \"complete\"]) should return [\"challenge\", \"complete\"]');", - "assert.notStrictEqual(popShift.toString().search(/\\.pop\\(/), -1, 'message: The popShift function should utilize the pop() method');", - "assert.notStrictEqual(popShift.toString().search(/\\.shift\\(/), -1, 'message: The popShift function should utilize the shift() method');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d78b2367417b2b2512b10", - "title": "Remove Items Using splice()", - "description": [ - "Ok, so we've learned how to remove elements from the beginning and end of arrays using shift() and pop(), but what if we want to remove an element from somewhere in the middle? Or remove more than one element at once? Well, that's where splice() comes in. splice() allows us to do just that: remove any number of consecutive elements from anywhere in an array.", - "splice() can take up to 3 parameters, but for now, we'll focus on just the first 2. The first two parameters of splice() are integers which represent indexes, or positions, of the array that splice() is being called upon. And remember, arrays are zero-indexed, so to indicate the first element of an array, we would use 0. splice()'s first parameter represents the index on the array from which to begin removing elements, while the second parameter indicates the number of elements to delete. For example:", - "
let array = ['today', 'was', 'not', 'so', 'great'];

array.splice(2, 2);
// remove 2 elements beginning with the 3rd element
// array now equals ['today', 'was', 'great']
", - "splice() not only modifies the array it's being called on, but it also returns a new array containing the value of the removed elements:", - "
let array = ['I', 'am', 'feeling', 'really', 'happy'];

let newArray = array.splice(3, 2);
// newArray equals ['really', 'happy']
", - "
", - "We've defined a function, sumOfTen, which takes an array as an argument and returns the sum of that array's elements. Modify the function, using splice(), so that it returns a value of 10." - ], - "challengeSeed": [ - "function sumOfTen(arr) {", - " // change code below this line", - " ", - " // change code above this line", - " return arr.reduce((a, b) => a + b);", - "}", - "", - "// do not change code below this line", - "console.log(sumOfTen([2, 5, 1, 5, 2, 1]));" - ], - "tests": [ - "assert.strictEqual(sumOfTen([2, 5, 1, 5, 2, 1]), 10, 'message: sumOfTen should return 10');", - "assert.notStrictEqual(sumOfTen.toString().search(/\\.splice\\(/), -1, 'message: The sumOfTen function should utilize the splice() method');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d78b3367417b2b2512b11", - "title": "Add Items Using splice()", - "description": [ - "Remember in the last challenge we mentioned that splice() can take up to three parameters? Well, we can go one step further with splice() — in addition to removing elements, we can use that third parameter, which represents one or more elements, to add them as well. This can be incredibly useful for quickly switching out an element, or a set of elements, for another. For instance, let's say you're storing a color scheme for a set of DOM elements in an array, and want to dynamically change a color based on some action:", - "
function colorChange(arr, index, newColor) {
  arr.splice(index, 1, newColor);
  return arr;
}

let colorScheme = ['#878787', '#a08794', '#bb7e8c', '#c9b6be', '#d1becf'];

colorScheme = colorChange(colorScheme, 2, '#332327');
// we have removed '#bb7e8c' and added '#332327' in its place
// colorScheme now equals ['#878787', '#a08794', '#332327', '#c9b6be', '#d1becf']
", - "This function takes an array of hex values, an index at which to remove an element, and the new color to replace the removed element with. The return value is an array containing a newly modified color scheme! While this example is a bit oversimplified, we can see the value that utilizing splice() to its maximum potential can have.", - "
", - "We have defined a function, htmlColorNames, which takes an array of HTML colors as an argument. Modify the function using splice() to remove the first two elements of the array and add 'DarkSalmon' and 'BlanchedAlmond' in their respective places." - ], - "challengeSeed": [ - "function htmlColorNames(arr) {", - " // change code below this line", - " ", - " // change code above this line", - " return arr;", - "} ", - " ", - "// do not change code below this line", - "console.log(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurqoise', 'FireBrick']));" - ], - "tests": [ - "assert.deepEqual(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurqoise', 'FireBrick']), ['DarkSalmon', 'BlanchedAlmond', 'LavenderBlush', 'PaleTurqoise', 'FireBrick'], 'message: htmlColorNames should return [\"DarkSalmon\", \"BlanchedAlmond\", \"LavenderBlush\", \"PaleTurqoise\", \"FireBrick\"]');", - "assert(/.splice/.test(code), 'message: The htmlColorNames function should utilize the splice() method');", - "assert(!/shift|unshift/.test(code), 'message: You should not use shift() or unshift().');", - "assert(!/\\[\\d\\]\\s*=/.test(code), 'message: You should not use array bracket notation.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7a367417b2b2512b12", - "title": "Copy Array Items Using slice()", - "description": [ - "The next method we will cover is slice(). slice(), rather than modifying an array, copies, or extracts, a given number of elements to a new array, leaving the array it is called upon untouched. slice() takes only 2 parameters — the first is the index at which to begin extraction, and the second is the index at which to stop extraction (extraction will occur up to, but not including the element at this index). Consider this:", - "
let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];

let todaysWeather = weatherConditions.slice(1, 3);
// todaysWeather equals ['snow', 'sleet'];
// weatherConditions still equals ['rain', 'snow', 'sleet', 'hail', 'clear']
", - "In effect, we have created a new array by extracting elements from an existing array.", - "
", - "We have defined a function, forecast, that takes an array as an argument. Modify the function using slice() to extract information from the argument array and return a new array that contains the elements 'warm' and 'sunny'." - ], - "challengeSeed": [ - "function forecast(arr) {", - " // change code below this line", - " ", - " return arr;", - "}", - "", - "// do not change code below this line", - "console.log(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']));" - ], - "tests": [ - "assert.deepEqual(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']), ['warm', 'sunny'], 'message: forecast should return [\"warm\", \"sunny\"]');", - "assert(/\\.slice\\(/.test(code), 'message: The forecast function should utilize the slice() method');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7b367417b2b2512b13", - "title": "Copy an Array with the Spread Operator", - "description": [ - "While slice() allows us to be selective about what elements of an array to copy, among several other useful tasks, ES6's new spread operator allows us to easily copy all of an array's elements, in order, with a simple and highly readable syntax. The spread syntax simply looks like this: ...", - "In practice, we can use the spread operator to copy an array like so:", - "
let thisArray = [true, true, undefined, false, null];
let thatArray = [...thisArray];
// thatArray equals [true, true, undefined, false, null]
// thisArray remains unchanged, and is identical to thatArray
", - "
", - "We have defined a function, copyMachine which takes arr (an array) and num (a number) as arguments. The function is supposed to return a new array made up of num copies of arr. We have done most of the work for you, but it doesn't work quite right yet. Modify the function using spread syntax so that it works correctly (hint: another method we have already covered might come in handy here!)." - ], - "challengeSeed": [ - "function copyMachine(arr, num) {", - " let newArr = [];", - " while (num >= 1) {", - " // change code below this line", - "", - " // change code above this line", - " num--;", - " }", - " return newArr;", - "}", - "", - "// change code here to test different cases:", - "console.log(copyMachine([true, false, true], 2));" - ], - "tests": [ - "assert.deepEqual(copyMachine([true, false, true], 2), [[true, false, true], [true, false, true]], 'message: copyMachine([true, false, true], 2) should return [[true, false, true], [true, false, true]]');", - "assert.deepEqual(copyMachine([1, 2, 3], 5), [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]], 'message: copyMachine([1, 2, 3], 5) should return [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]');", - "assert.deepEqual(copyMachine([true, true, null], 1), [[true, true, null]], 'message: copyMachine([true, true, null], 1) should return [[true, true, null]]');", - "assert.deepEqual(copyMachine(['it works'], 3), [['it works'], ['it works'], ['it works']], 'message: copyMachine([\"it works\"], 3) should return [[\"it works\"], [\"it works\"], [\"it works\"]]');", - "assert.notStrictEqual(copyMachine.toString().indexOf('.concat(_toConsumableArray(arr))'), -1, 'message: The copyMachine function should utilize the spread operator with array arr');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7b367417b2b2512b17", - "title": "Combine Arrays with the Spread Operator", - "description": [ - "Another huge advantage of the spread operator, is the ability to combine arrays, or to insert all the elements of one array into another, at any index. With more traditional syntaxes, we can concatenate arrays, but this only allows us to combine arrays at the end of one, and at the start of another. Spread syntax makes the following operation extremely simple:", - "
let thisArray = ['sage', 'rosemary', 'parsley', 'thyme'];

let thatArray = ['basil', 'cilantro', ...thisArray, 'coriander'];
// thatArray now equals ['basil', 'cilantro', 'sage', 'rosemary', 'parsley', 'thyme', 'coriander']
", - "Using spread syntax, we have just achieved an operation that would have been more more complex and more verbose had we used traditional methods.", - "
", - "We have defined a function spreadOut that returns the variable sentence, modify the function using the spread operator so that it returns the array ['learning', 'to', 'code', 'is', 'fun']." - ], - "challengeSeed": [ - "function spreadOut() {", - " let fragment = ['to', 'code'];", - " let sentence; // change this line", - " return sentence;", - "}", - "", - "// do not change code below this line", - "console.log(spreadOut());" - ], - "tests": [ - "assert.deepEqual(spreadOut(), ['learning', 'to', 'code', 'is', 'fun'], 'message: spreadOut should return [\"learning\", \"to\", \"code\", \"is\", \"fun\"]');", - "assert.notStrictEqual(spreadOut.toString().search(/[...]/), -1, 'message: The spreadOut function should utilize spread syntax');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7b367417b2b2512b14", - "title": "Check For The Presence of an Element With indexOf()", - "description": [ - "Since arrays can be changed, or mutated, at any time, there's no guarantee about where a particular piece of data will be on a given array, or if that element even still exists. Luckily, JavaScript provides us with another built-in method, indexOf(), that allows us to quickly and easily check for the presence of an element on an array. indexOf() takes an element as a parameter, and when called, it returns the position, or index, of that element, or -1 if the element does not exist on the array.", - "For example:", - "
let fruits = ['apples', 'pears', 'oranges', 'peaches', 'pears'];

fruits.indexOf('dates') // returns -1
fruits.indexOf('oranges') // returns 2
fruits.indexOf('pears') // returns 1, the first index at which the element exists
", - "
", - "indexOf() can be incredibly useful for quickly checking for the presence of an element on an array. We have defined a function, quickCheck, that takes an array and an element as arguments. Modify the function using indexOf() so that it returns true if the passed element exists on the array, and false if it does not." - ], - "challengeSeed": [ - "function quickCheck(arr, elem) {", - " // change code below this line", - "", - " // change code above this line", - "}", - "", - "// change code here to test different cases:", - "console.log(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'));" - ], - "tests": [ - "assert.strictEqual(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'), false, 'message: quickCheck([\"squash\", \"onions\", \"shallots\"], \"mushrooms\") should return false');", - "assert.strictEqual(quickCheck(['squash', 'onions', 'shallots'], 'onions'), true, 'message: quickCheck([\"squash\", \"onions\", \"shallots\"], \"onions\") should return true');", - "assert.strictEqual(quickCheck([3, 5, 9, 125, 45, 2], 125), true, 'message: quickCheck([3, 5, 9, 125, 45, 2], 125) should return true');", - "assert.strictEqual(quickCheck([true, false, false], undefined), false, 'message: quickCheck([true, false, false], undefined) should return false');", - "assert.notStrictEqual(quickCheck.toString().search(/\\.indexOf\\(/), -1, 'message: The quickCheck function should utilize the indexOf() method');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7b367417b2b2512b15", - "title": "Iterate Through All an Array's Items Using For Loops", - "description": [ - "Sometimes when working with arrays, it is very handy to be able to iterate through each item to find one or more elements that we might need, or to manipulate an array based on which data items meet a certain set of criteria. JavaScript offers several built in methods that each iterate over arrays in slightly different ways to achieve different results (such as every(), forEach(), map(), etc.), however the technique which is most flexible and offers us the greatest amount of control is a simple for loop.", - "Consider the following:", - "
function greaterThanTen(arr) {
  let newArr = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > 10) {
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

greaterThanTen([2, 12, 8, 14, 80, 0, 1]);
// returns [12, 14, 80]
", - "Using a for loop, this function iterates through and accesses each element of the array, and subjects it to a simple test that we have created. In this way, we have easily and programmatically determined which data items are greater than 10, and returned a new array containing those items.", - "
", - "We have defined a function, filteredArray, which takes arr, a nested array, and elem as arguments, and returns a new array. elem represents an element that may or may not be present on one or more of the arrays nested within arr. Modify the function, using a for loop, to return a filtered version of the passed array such that any array nested within arr containing elem has been removed." - ], - "challengeSeed": [ - "function filteredArray(arr, elem) {", - " let newArr = [];", - " // change code below this line", - "", - " // change code above this line", - " return newArr;", - "}", - "", - "// change code here to test different cases:", - "console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));" - ], - "tests": [ - "assert.deepEqual(filteredArray([ [10, 8, 3], [14, 6, 23], [3, 18, 6] ], 18), [[10, 8, 3], [14, 6, 23]], 'message: filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18) should return [ [10, 8, 3], [14, 6, 23] ]');", - "assert.deepEqual(filteredArray([ ['trumpets', 2], ['flutes', 4], ['saxophones', 2] ], 2), [['flutes', 4]], 'message: filteredArray([ [\"trumpets\", 2], [\"flutes\", 4], [\"saxophones\", 2] ], 2) should return [ [\"flutes\", 4] ]');", - "assert.deepEqual(filteredArray([['amy', 'beth', 'sam'], ['dave', 'sean', 'peter']], 'peter'), [['amy', 'beth', 'sam']], 'message: filteredArray([ [\"amy\", \"beth\", \"sam\"], [\"dave\", \"sean\", \"peter\"] ], \"peter\") should return [ [\"amy\", \"beth\", \"sam\"] ]');", - "assert.deepEqual(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3), [], 'message: filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3) should return [ ]');", - "assert.notStrictEqual(filteredArray.toString().search(/for/), -1, 'message: The filteredArray function should utilize a for loop');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7b367417b2b2512b16", - "title": "Create complex multi-dimensional arrays", - "description": [ - "Awesome! You have just learned a ton about arrays! This has been a fairly high level overview, and there is plenty more to learn about working with arrays, much of which you will see in later sections. But before moving on to looking at Objects, lets take one more look, and see how arrays can become a bit more complex than what we have seen in previous challenges.", - "One of the most powerful features when thinking of arrays as data structures, is that arrays can contain, or even be completely made up of other arrays. We have seen arrays that contain arrays in previous challenges, but fairly simple ones. However, arrays can contain an infinite depth of arrays that can contain other arrays, each with their own arbitrary levels of depth, and so on. In this way, an array can very quickly become very complex data structure, known as a multi-dimensional, or nested array. Consider the following example:", - "
let nestedArray = [ // top, or first level - the outer most array
  ['deep'], // an array within an array, 2 levels of depth
  [
    ['deeper'], ['deeper'] // 2 arrays nested 3 levels deep
  ],
  [
    [
      ['deepest'], ['deepest'] // 2 arrays nested 4 levels deep
    ],
    [
      [
        ['deepest-est?'] // an array nested 5 levels deep
      ]
    ]
  ]
];
", - "While this example may seem convoluted, this level of complexity is not unheard of, or even unusual, when dealing with large amounts of data.", - "However, we can still very easily access the deepest levels of an array this complex with bracket notation:", - "
console.log(nestedArray[2][1][0][0][0]);
// logs: deepest-est?
", - "And now that we know where that piece of data is, we can reset it if we need to:", - "
nestedArray[2][1][0][0][0] = 'deeper still';

console.log(nestedArray[2][1][0][0][0]);
// now logs: deeper still
", - "
", - "We have defined a variable, myNestedArray, set equal to an array. Modify myNestedArray, using any combination of strings, numbers, and booleans for data elements, so that it has exactly five levels of depth (remember, the outer-most array is level 1). Somewhere on the third level, include the string 'deep', on the fourth level, include the string 'deeper', and on the fifth level, include the string 'deepest'." - ], - "challengeSeed": [ - "let myNestedArray = [", - " // change code below this line", - " ['unshift', false, 1, 2, 3, 'complex', 'nested'],", - " ['loop', 'shift', 6, 7, 1000, 'method'],", - " ['concat', false, true, 'spread', 'array'],", - " ['mutate', 1327.98, 'splice', 'slice', 'push'],", - " ['iterate', 1.3849, 7, '8.4876', 'arbitrary', 'depth']", - " // change code above this line", - "];" - ], - "tests": [ - "assert.strictEqual((function(arr) { let flattened = (function flatten(arr) { const flat = [].concat(...arr); return flat.some (Array.isArray) ? flatten(flat) : flat; })(arr); for (let i = 0; i < flattened.length; i++) { if ( typeof flattened[i] !== 'number' && typeof flattened[i] !== 'string' && typeof flattened[i] !== 'boolean') { return false } } return true })(myNestedArray), true, 'message: myNestedArray should contain only numbers, booleans, and strings as data elements');", - "assert.strictEqual((function(arr) {let depth = 0;function arrayDepth(array, i, d) { if (Array.isArray(array[i])) { arrayDepth(array[i], 0, d + 1);} else { depth = (d > depth) ? d : depth;}if (i < array.length) { arrayDepth(array, i + 1, d);} }arrayDepth(arr, 0, 0);return depth;})(myNestedArray), 4, 'message: myNestedArray should have exactly 5 levels of depth');", - "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep')[0] === 2, 'message: myNestedArray should contain exactly one occurrence of the string \"deep\" on an array nested 3 levels deep');", - "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper')[0] === 3, 'message: myNestedArray should contain exactly one occurrence of the string \"deeper\" on an array nested 4 levels deep');", - "assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest')[0] === 4, 'message: myNestedArray should contain exactly one occurrence of the string \"deepest\" on an array nested 5 levels deep');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dac367417b2b25184d3", - "title": "Introduction to Objects", - "description": [ - [ - "", - "", - "The next data structure we will discuss is the JavaScript object. Like arrays, objects are a fundamental part of JavaScript. However, it is probably safe to say that objects surpass arrays in flexibility, usefulness and in their overall importance to the language — in fact, you may have heard this line before: 'In JavaScript, everything is an object.'

While an understanding of objects is important to understand the inner workings of JavaScript functions or JavaScript's object-oriented capabilities, JavaScript objects at a basic level are actually just key-value pair stores, a commonly used data structure across almost all programming languages. Here, we will confine our discussion to JavaScript objects in this capacity.", - "" - ], - [ - "", - "", - "Key-value pair data structures go by different names depending on the language and the specific details of the data structure. The terms dictionary, map, and hash table all refer to the notion of a data structure in which specific keys, or properties, are mapped to specific values.

Objects, and other similar key-value pair data structures, offer some very useful benefits. One clear benefit is that they allow us to structure our data in an intuitive way; properties can be nested to an arbitrary depth, and values can be anything, including arrays and even other objects.

Largely due to this flexibility, objects are also the foundation for JavaScript Object Notation, or JSON, which is a widely used method of sending data across the web.", - "" - ], - [ - "", - "", - "Another powerful advantage of key-value pair data structures is constant lookup time. What this means, is that when you request the value of a specific property, you will get the value back in the same amount of time (theoretically) regardless of the number of entries in the object. If you had an object with 5 entries or one that held a collection of 1,000,000, you could still retrieve property values or check if a key exists in the same amount of time.

The reason for this fast lookup time, is that internally, the object is storing properties using a hashing mechanism which allows it to know exactly where it has stored different property values. If you want to learn more about this please take a look at the optional Advanced Data Structures challenges. All you should remember for now is that performant access to flexibly structured data make key-value stores very attractive data structures useful in a wide variety of settings.", - "" - ], - [ - "", - "", - "

In JavaScript, objects are written as comma-separated lists of key-value pairs, wrapped in curly brackets, with each key and its assigned value separated by a colon:
{ key1: 'val-1', key2: 'val-2' }

In the next few challenges, we will examine JavaScript objects more closely, and take a look at methods and techniques that allow us to access, store, and manipulate an object's data.

Note that throughout the scope of this discussion, and in general when considering JavaScript objects, the terms key and property will be used interchangeably.", - "" - ] - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7b7c367417b2b2512b18", - "title": "Add Key-Value Pairs to JavaScript Objects", - "description": [ - "At their most basic, objects are just collections of key-value pairs, or in other words, pieces of data mapped to unique identifiers that we call properties or keys. Let's take a look at a very simple example:", - "
let FCC_User = {
username: 'awesome_coder',
followers: 572,
points: 1741,
completedProjects: 15
};
", - "The above code defines an object called FCC_User that has four properties, each of which map to a specific value. If we wanted to know the number of followers FCC_User has, we can access that property by writing:", - "
let userData = FCC_User.followers;
// userData equals 572
", - "This is called dot notation. Alternatively, we can also access the property with brackets, like so:", - "
let userData = FCC_User['followers']
// userData equals 572
", - "Notice that with bracket notation, we enclosed followers in quotes. This is because the brackets actually allow us to pass a variable in to be evaluated as a property name (hint: keep this in mind for later!). Had we passed followers in without the quotes, the JavaScript engine would have attempted to evaluate it as a variable, and a ReferenceError: followers is not defined would have been thrown.", - "
", - "Using the same syntax, we can also add new key-value pairs to objects. We've created a foods object with three entries. Add three more entries: bananas with a value of 13, grapes with a value of 35, and strawberries with a value of 27." - ], - "challengeSeed": [ - "let foods = {", - " apples: 25,", - " oranges: 32,", - " plums: 28", - "};", - "", - "// change code below this line", - "", - "// change code above this line", - "", - "console.log(foods);" - ], - "tests": [ - "assert(typeof foods === 'object', 'message: foods is an object');", - "assert(foods.bananas === 13, 'message: The foods object has a key \"bananas\" with a value of 13');", - "assert(foods.grapes === 35, 'message: The foods object has a key \"grapes\" with a value of 35');", - "assert(foods.strawberries === 27, 'message: The foods object has a key \"strawberries\" with a value of 27');", - "assert(code.search(/bananas:/) === -1 && code.search(/grapes:/) === -1 && code.search(/strawberries:/) === -1, 'message: The key-value pairs should be set using dot or bracket notation');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7c367417b2b2512b19", - "title": "Modify an Object Nested Within an Object", - "description": [ - "Now let's take a look at a slightly more complex object. Object properties can be nested to an arbitrary depth, and their values can be any type of data supported by JavaScript, including arrays and even other objects. Consider the following:", - "
let nestedObject = {
id: 28802695164,
date: 'December 31, 2016',
data: {
totalUsers: 99,
online: 80,
onlineStatus: {
active: 67,
away: 13
}
}
};
", - "nestedObject has three unique keys: id, whose value is a number, date whose value is a string, and data, whose value is an object which has yet another object nested within it. While structures can quickly become complex, we can still use the same notations to access the information we need.", - "
", - "Here we've defined an object, userActivity, which includes another object nested within it. You can modify properties on this nested object in the same way you modified properties in the last challenge. Set the value of the online key to 45." - ], - "challengeSeed": [ - "let userActivity = {", - " id: 23894201352,", - " date: 'January 1, 2017',", - " data: {", - " totalUsers: 51,", - " online: 42", - " }", - "};", - "", - "// change code below this line", - "", - "// change code above this line", - "", - "console.log(userActivity);" - ], - "tests": [ - "assert('id' in userActivity && 'date' in userActivity && 'data' in userActivity, 'message: userActivity has id, date and data properties');", - "assert('totalUsers' in userActivity.data && 'online' in userActivity.data, 'message: userActivity has a data key set to an object with keys totalUsers and online');", - "assert(userActivity.data.online === 45, 'message: The online property nested in the data key of userActivity should be set to 45');", - "assert.strictEqual(code.search(/online: 45/), -1, 'message: The online property is set using dot or bracket notation');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7c367417b2b2512b1a", - "title": "Access Property Names with Bracket Notation", - "description": [ - "In the first object challenge we mentioned the use of bracket notation as a way to access property values using the evaluation of a variable. For instance, imagine that our foods object is being used in a program for a supermarket cash register. We have some function that sets the selectedFood and we want to check our foods object for the presence of that food. This might look like:", - "
let selectedFood = getCurrentFood(scannedItem);
let inventory = foods[selectedFood];
", - "This code will evaluate the value stored in the selectedFood variable and return the value of that key in the foods object, or undefined if it is not present. Bracket notation is very useful because sometimes object properties are not known before runtime or we need to access them in a more dynamic way.", - "
", - "We've defined a function, checkInventory, which receives a scanned item as an argument. Return the current value of the scannedItem key in the foods object. You can assume that only valid keys will be provided as an argument to checkInventory." - ], - "challengeSeed": [ - "let foods = {", - " apples: 25,", - " oranges: 32,", - " plums: 28,", - " bananas: 13,", - " grapes: 35,", - " strawberries: 27", - "};", - "// do not change code above this line", - "", - "function checkInventory(scannedItem) {", - " // change code below this line", - "", - "}", - "", - "// change code below this line to test different cases:", - "console.log(checkInventory(\"apples\"));" - ], - "tests": [ - "assert.strictEqual(typeof checkInventory, 'function', 'message: checkInventory is a function');", - "assert.deepEqual(foods, {apples: 25, oranges: 32, plums: 28, bananas: 13, grapes: 35, strawberries: 27}, 'message: The foods object should have only the following key-value pairs: apples: 25, oranges: 32, plums: 28, bananas: 13, grapes: 35, strawberries: 27');", - "assert.strictEqual(checkInventory('apples'), 25, 'message: checkInventory(\"apples\") should return 25');", - "assert.strictEqual(checkInventory('bananas'), 13, 'message: checkInventory(\"bananas\") should return 13');", - "assert.strictEqual(checkInventory('strawberries'), 27, 'message: checkInventory(\"strawberries\") should return 27');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7c367417b2b2512b1b", - "title": "Use the delete Keyword to Remove Object Properties", - "description": [ - "Now you know what objects are and their basic features and advantages. In short, they are key-value stores which provide a flexible, intuitive way to structure data, and, they provide very fast lookup time. Throughout the rest of these challenges, we will describe several common operations you can perform on objects so you can become comfortable applying these useful data structures in your programs.", - "In earlier challenges, we have both added to and modified an object's key-value pairs. Here we will see how we can remove a key-value pair from an object.", - "Let's revisit our foods object example one last time. If we wanted to remove the apples key, we can remove it by using the delete keyword like this:", - "
delete foods.apples;
", - "
", - "Use the delete keyword to remove the oranges, plums, and strawberries keys from the foods object." - ], - "challengeSeed": [ - "let foods = {", - " apples: 25,", - " oranges: 32,", - " plums: 28,", - " bananas: 13,", - " grapes: 35,", - " strawberries: 27", - "};", - "", - "// change code below this line", - "", - "// change code above this line", - "", - "console.log(foods);" - ], - "tests": [ - "assert(!foods.hasOwnProperty('oranges') && !foods.hasOwnProperty('plums') && !foods.hasOwnProperty('strawberries') && Object.keys(foods).length === 3, 'message: The foods object only has three keys: apples, grapes, and bananas');", - "assert(code.search(/oranges:/) !== -1 && code.search(/plums:/) !== -1 && code.search(/strawberries:/) !== -1, 'message: The oranges, plums, and strawberries keys are removed using delete');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7d367417b2b2512b1c", - "title": "Check if an Object has a Property", - "description": [ - "Now we can add, modify, and remove keys from objects. But what if we just wanted to know if an object has a specific property? JavaScript provides us with two different ways to do this. One uses the hasOwnProperty() method and the other uses the in keyword. If we have an object users with a property of Alan, we could check for its presence in either of the following ways:", - "
users.hasOwnProperty('Alan');
'Alan' in users;
// both return true
", - "
", - "We've created an object, users, with some users in it and a function isEveryoneHere, which we pass the users object to as an argument. Finish writing this function so that it returns true only if the users object contains all four names, Alan, Jeff, Sarah, and Ryan, as keys, and false otherwise." - ], - "challengeSeed": [ - "let users = {", - " Alan: {", - " age: 27,", - " online: true", - " },", - " Jeff: {", - " age: 32,", - " online: true", - " },", - " Sarah: {", - " age: 48,", - " online: true", - " },", - " Ryan: {", - " age: 19,", - " online: true", - " }", - "};", - "", - "function isEveryoneHere(obj) {", - " // change code below this line", - "", - " // change code above this line", - "}", - "", - "console.log(isEveryoneHere(users));" - ], - "tests": [ - "assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4, 'message: The users object only contains the keys Alan, Jeff, Sarah, and Ryan');", - "assert(isEveryoneHere(users) === true, 'message: The function isEveryoneHere returns true if Alan, Jeff, Sarah, and Ryan are properties on the users object');", - "assert((function() { delete users.Alan; delete users.Jeff; delete users.Sarah; delete users.Ryan; return isEveryoneHere(users) })() === false, 'message: The function isEveryoneHere returns false if Alan, Jeff, Sarah, and Ryan are not properties on the users object');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7d367417b2b2512b1d", - "title": " Iterate Through the Keys of an Object with a for...in Statement", - "description": [ - "Sometimes you may need to iterate through all the keys within an object. This requires a specific syntax in JavaScript called a for...in statement. For our users object, this could look like:", - "
for (let user in users) {
console.log(user);
};

// logs:
Alan
Jeff
Sarah
Ryan
", - "In this statement, we defined a variable user, and as you can see, this variable was reset during each iteration to each of the object's keys as the statement looped through the object, resulting in each user's name being printed to the console.", - "NOTE:
Objects do not maintain an ordering to stored keys like arrays do; thus a keys position on an object, or the relative order in which it appears, is irrelevant when referencing or accessing that key.", - "
", - "We've defined a function, countOnline; use a for...in statement within this function to loop through the users in the users object and return the number of users whose online property is set to true." - ], - "challengeSeed": [ - "let users = {", - " Alan: {", - " age: 27,", - " online: false", - " },", - " Jeff: {", - " age: 32,", - " online: true", - " },", - " Sarah: {", - " age: 48,", - " online: false", - " },", - " Ryan: {", - " age: 19,", - " online: true", - " }", - "};", - "", - "function countOnline(obj) {", - " // change code below this line", - "", - " // change code above this line", - "}", - "", - "console.log(countOnline(users));" - ], - "tests": [ - "assert(users.Alan.online === false && users.Jeff.online === true && users.Sarah.online === false && users.Ryan.online === true, 'message: The users object contains users Jeff and Ryan with online set to true and users Alan and Sarah with online set to false');", - "assert((function() { users.Harry = {online: true}; users.Sam = {online: true}; users.Carl = {online: true}; return countOnline(users) })() === 5, 'message: The function countOnline returns the number of users with the online property set to true');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7d367417b2b2512b1e", - "title": "Generate an Array of All Object Keys with Object.keys()", - "description": [ - "We can also generate an array which contains all the keys stored in an object using the Object.keys() method and passing in an object as the argument. This will return an array with strings representing each property in the object. Again, there will be no specific order to the entries in the array.", - "
", - "Finish writing the getArrayOfUsers function so that it returns an array containing all the properties in the object it receives as an argument." - ], - "challengeSeed": [ - "let users = {", - " Alan: {", - " age: 27,", - " online: false", - " },", - " Jeff: {", - " age: 32,", - " online: true", - " },", - " Sarah: {", - " age: 48,", - " online: false", - " },", - " Ryan: {", - " age: 19,", - " online: true", - " }", - "};", - "", - "function getArrayOfUsers(obj) {", - " // change code below this line", - "", - " // change code above this line", - "}", - "", - "console.log(getArrayOfUsers(users));" - ], - "tests": [ - "assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4, 'message: The users object only contains the keys Alan, Jeff, Sarah, and Ryan');", - "assert((function() { users.Sam = {}; users.Lewis = {}; let R = getArrayOfUsers(users); return (R.indexOf('Alan') !== -1 && R.indexOf('Jeff') !== -1 && R.indexOf('Sarah') !== -1 && R.indexOf('Ryan') !== -1 && R.indexOf('Sam') !== -1 && R.indexOf('Lewis') !== -1); })() === true, 'message: The getArrayOfUsers function returns an array which contains all the keys in the users object');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b7d367417b2b2512b1f", - "title": "Modify an Array Stored in an Object", - "description": [ - "Now you've seen all the basic operations for JavaScript objects. You can add, modify, and remove key-value pairs, check if keys exist, and iterate over all the keys in an object. As you continue learning JavaScript you will see even more versatile applications of objects. Additionally, the optional Advanced Data Structures lessons later in the curriculum also cover the ES6 Map and Set objects, both of which are similar to ordinary objects but provide some additional features. Now that you've learned the basics of arrays and objects, you're fully prepared to begin tackling more complex problems using JavaScript!", - "
", - "Take a look at the object we've provided in the code editor. The user object contains three keys. The data key contains five keys, one of which contains an array of friends. From this, you can see how flexible objects are as data structures. We've started writing a function addFriend. Finish writing it so that it takes a user object and adds the name of the friend argument to the array stored in user.data.friends and returns that array." - ], - "challengeSeed": [ - "let user = {", - " name: 'Kenneth',", - " age: 28,", - " data: {", - " username: 'kennethCodesAllDay',", - " joinDate: 'March 26, 2016',", - " organization: 'freeCodeCamp',", - " friends: [", - " 'Sam',", - " 'Kira',", - " 'Tomo'", - " ],", - " location: {", - " city: 'San Francisco',", - " state: 'CA',", - " country: 'USA'", - " }", - " }", - "};", - "", - "function addFriend(userObj, friend) {", - " // change code below this line ", - "", - " // change code above this line", - "}", - "", - "console.log(addFriend(user, 'Pete'));" - ], - "tests": [ - "assert('name' in user && 'age' in user && 'data' in user, 'message: The user object has name, age, and data keys');", - "assert((function() { let L1 = user.data.friends.length; addFriend(user, 'Sean'); let L2 = user.data.friends.length; return (L2 === L1 + 1); })(), 'message: The addFriend function accepts a user object and a friend string as arguments and adds the friend to the array of friends in the user object');", - "assert.deepEqual((function() { delete user.data.friends; user.data.friends = ['Sam', 'Kira', 'Tomo']; return addFriend(user, 'Pete') })(), ['Sam', 'Kira', 'Tomo', 'Pete'], 'message: addFriend(user, \"Pete\") should return [\"Sam\", \"Kira\", \"Tomo\", \"Pete\"]');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "solutions": [], - "challengeType": 1, - "translations": {} - } - ] -} \ No newline at end of file diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json deleted file mode 100644 index c023da0c42..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/basic-javascript.json +++ /dev/null @@ -1,5841 +0,0 @@ -{ - "name": "Basic JavaScript", - "time": "10 hours", - "order": 1, - "helpRoom": "HelpJavaScript", - "challenges": [ - { - "id": "bd6123c9c441eddfaeb4bdef", - "title": "Introduction to JavaScript", - "description": [ - "", - "", - "JavaScript is a high-level programming language that all modern web browsers support. It is also one of the core technologies of the web, along with HTML and CSS that you may have learned previously. This section will cover basic programming concepts in JavaScript, which range from variables and arithemtic to objects and loops.", - "", - "@@STEP@@" - ], - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "bd7123c9c441eddfaeb4bdef", - "title": "Comment Your JavaScript Code", - "description": [ - "Comments are lines of code that JavaScript will intentionally ignore. Comments are a great way to leave notes to yourself and to other people who will later need to figure out what that code does.", - "There are two ways to write comments in JavaScript:", - "Using // will tell JavaScript to ignore the remainder of the text on the current line:", - "
// This is an in-line comment.
", - "You can make a multi-line comment beginning with /* and ending with */:", - "
/* This is a
multi-line comment */
", - "Best Practice
As you write code, you should regularly add comments to clarify the function of parts of your code. Good commenting can help communicate the intent of your code—both for others and for your future self.", - "
", - "Try creating one of each type of comment." - ], - "challengeSeed": [ - "" - ], - "solutions": [ - "// Fake Comment\n/* Another Comment */" - ], - "tests": [ - "assert(code.match(/(\\/\\/)...../g), 'message: Create a // style comment that contains at least five letters.');", - "assert(code.match(/(\\/\\*)([^\\*\\/]{5,})(?=\\*\\/)/gm), 'message: Create a /* */ style comment that contains at least five letters.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Agrega comentarios a tu código JavaScript", - "description": [ - "Los comentarios son líneas de código que el computador ignorará intencionalmente. Los comentarios son una gran forma de dejarte notas a ti mismo y a otras personas que luego tendrán que averiguar lo que hace que el código. ", - "Vamos a echar un vistazo a las dos maneras en las que puedes agregar tus comentarios en JavaScript.", - "El comentario de doble barra comentará el resto del texto en la línea donde se ubica:", - "// Este es un comentario.", - "El comentario de barra-estrella-estrella-barra, comentará todo lo que haya entre los caracteres /* y */:", - "/* Este es también un comentario */", - "Trata de crear uno de cada uno." - ] - }, - "fr": { - "title": "Commentez votre code JavaScript", - "description": [ - "Les commentaires sont des lignes de code que JavaScript va intentionnellement ignorer. Les commentaires sont un bon moyen de laisser des notes à votre intention ou pour d'autres personnes qui devront comprendre ce que fait votre code.", - "Il y a deux façons d'écrire des commentaires en JavaScript.", - "Utiliser // indiquera à JavaScript d'ignorer le reste du texte sur cette même ligne:", - "// Voici un commentaire sur une ligne.", - "Vous pouvez commenter plusieurs lignes en commençant par /* et en finissant par */:", - "/*Voici un commentaire
sur plusieurs lignes */
", - "Conseils", - "Lorsque vous écrivez votre code, vous devriez ajouter régulièrement des commentaires pour clarifier l'objectif de certaines parties de votre code. De bons commentaires peuvent aider les autres et vous-même à mieux comprendre votre code.", - "
", - "Essayez de créer un commentaire de chaque type." - ] - } - } - }, - { - "id": "bd7123c9c443eddfaeb5bdef", - "title": "Declare JavaScript Variables", - "description": [ - "In computer science, data is anything that is meaningful to the computer. JavaScript provides seven different data types which are undefined, null, boolean, string, symbol, number, and object.", - "For example, computers distinguish between numbers, such as the number 12, and strings, such as \"12\", \"dog\", or \"123 cats\", which are collections of characters. Computers can perform mathematical operations on a number, but not on a string.", - "Variables allow computers to store and manipulate data in a dynamic fashion. They do this by using a \"label\" to point to the data rather than using the data itself. Any of the seven data types may be stored in a variable.", - "Variables are similar to the x and y variables you use in mathematics, which means they're a simple name to represent the data we want to refer to. Computer variables differ from mathematical variables in that they can store different values at different times.", - "We tell JavaScript to create or declare a variable by putting the keyword var in front of it, like so:", - "
var ourName;
", - "creates a variable called ourName. In JavaScript we end statements with semicolons.", - "Variable names can be made up of numbers, letters, and $ or _, but may not contain spaces or start with a number.", - "
", - "Use the var keyword to create a variable called myName.", - "Hint
Look at the ourName example if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var ourName;", - "", - "// Declare myName below this line", - "" - ], - "tail": [ - "if(typeof myName !== \"undefined\"){(function(v){return v;})(myName);}" - ], - "solutions": [ - "var myName;" - ], - "tests": [ - "assert(/var\\s+myName\\s*;/.test(code), 'message: You should declare myName with the var keyword, ending with a semicolon');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Declara variables en JavaScript", - "description": [ - "Cuando almacenamos datos en una estructura de datos, la llamamos una variable. Estas variables no son diferentes de las variables x e y que utilizas en matemáticas. ", - "Vamos a crear nuestra primera variable y a llamarla \"myName\".", - "Te darás cuenta que en myName, no usamos un espacio, y que la \" N\"se escribe con mayúscula. Las variables en JavaScript se escriben con capitalización camello (camel case). Un ejemplo de capitalización camello: capitalizacionCamello.", - "Ahora, utiliza la palabra clave var para crear una variable llamada myName. Establecele como valor tu nombre, entre comillas dobles. ", - "Mira el ejemplo con ourName si te quedas atascado." - ] - }, - "fr": { - "title": "Déclarer des variables en JavaScript", - "description": [ - "En informatique, une donnée comporte tout ce qui peut avoir du sens pour l'ordinateur. JavaScript dispose de sept types de données différents qui sont undefined, null, boolean, string, symbol, number et object.", - "Par exemple, les ordinateurs font la différence entre les nombres tel que 12 et les strings, tels que \"12\", \"dog\", ou \"123 cats\", qui sont des collections de caractères. Les ordinateurs peuvent faire des opérations mathématiques sur un nombre, mais pas sur une chaîne de caractères.", - "Les variables permettent aux ordinateurs de stocker et manipuler les données de façon dynamique. Ils font cela en utilisant un
label
qui réfère à la donnée plutôt que d'utiliser la donnée elle-même. Les sept types de données peuvent être stockés dans une variable.", - "Les variables sont similaires aux x et y que vous utilisez en mathématiques, ce qui veut dire que ce sont des noms simples qui représentent les données que l'on veut utiliser. Les variables de l'ordinateur diffèrent de celles des mathématiques car elles peuvent stocker différentes valeurs à différents moments.", - "On peut dire à JavaScript de créer ou déclarer une variable en la précédant du mot-clé var, comme ceci:", - "var notreNom;", - "crée une variable appelée notreNom.On termine nos expressions avec un point virgule en JavaScript.", - "Le nom d'une variable peut être composé de nombres, lettres et $ ou _, mais ne peut contenir d'espaces ou commencer par un nombre.", - "
", - "Utilisez le mot-clé var pour créer une variable appelée monNom", - "Conseil
Regardez à l'exemple de notreNom si vous vous êtes bloqué." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244a8", - "title": "Storing Values with the Assignment Operator", - "description": [ - "In JavaScript, you can store a value in a variable with the assignment operator.", - "myVariable = 5;", - "This assigns the Number value 5 to myVariable.", - "Assignment always goes from right to left. Everything to the right of the = operator is resolved before the value is assigned to the variable to the left of the operator.", - "
myVar = 5;
myNum = myVar;
", - "This assigns 5 to myVar and then resolves myVar to 5 again and assigns it to myNum.", - "
", - "Assign the value 7 to variable a.", - "Assign the contents of a to variable b." - ], - "releasedOn": "January 1, 2016", - "head": [ - "if (typeof a != 'undefined') {", - " a = undefined;", - "}", - "if (typeof b != 'undefined') {", - " b = undefined;", - "}" - ], - "challengeSeed": [ - "// Setup", - "var a;", - "var b = 2;", - "", - "// Only change code below this line", - "" - ], - "tail": [ - "(function(a,b){return \"a = \" + a + \", b = \" + b;})(a,b);" - ], - "solutions": [ - "var a;\nvar b = 2;\na = 7;\nb = a;" - ], - "tests": [ - "assert(/var a;/.test(code) && /var b = 2;/.test(code), 'message: Do not change code above the line');", - "assert(typeof a === 'number' && a === 7, 'message: a should have a value of 7');", - "assert(typeof b === 'number' && b === 7, 'message: b should have a value of 7');", - "assert(/b\\s*=\\s*a\\s*;/g.test(code), 'message: a should be assigned to b with =');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Almacenar valores con el operador igual", - "description": [ - "En JavaScript, puedes almacenar un valor en una variable con la asignación o con el operador igual (=).", - "miVariable = 5;", - "Asigna el valor númerico de 5 a miVariable.", - "La asignación siempre va de derecha a izquierda. Todo a la derecha del operador = es resuelto antes que el valor es asignado a la variable a la izquierda del operador.", - "
miVar = 5;
miNum = miVar;
", - "Asigna 5 a miVar y entonces resuelve miVar a 5 otra vez y asigna esta a miNum.", - "

Instrucciones

", - "Asigna el valor 7 a la variable a.", - "Asigna el contenido de a a la variable b." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244a9", - "title": "Initializing Variables with the Assignment Operator", - "description": [ - "It is common to initialize a variable to an initial value in the same line as it is declared.", - "var myVar = 0;", - "Creates a new variable called myVar and assigns it an initial value of 0.", - "
", - "Define a variable a with var and initialize it to a value of 9." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var ourVar = 19;", - "", - "// Only change code below this line", - "" - ], - "tail": [ - "if(typeof a !== 'undefined') {(function(a){return \"a = \" + a;})(a);} else { (function() {return 'a is undefined';})(); }" - ], - "solutions": [ - "var a = 9;" - ], - "tests": [ - "assert(/var\\s+a\\s*=\\s*9\\s*/.test(code), 'message: Initialize a to a value of 9');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Inicializar variables con el operador igual", - "description": [ - "Es común inicializar una variable a un valor inicial en la misma línea que es declarada.", - "var miVar = 0;", - "Crea una nueva variable llamada miVar y le asigna un valor inicial de 0.", - "

Instrucciones

", - "Define una variable a con var e inicializala a un valor de 9." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244aa", - "title": "Understanding Uninitialized Variables", - "description": [ - "When JavaScript variables are declared, they have an initial value of undefined. If you do a mathematical operation on an undefined variable your result will be NaN which means \"Not a Number\". If you concatenate a string with an undefined variable, you will get a literal string of \"undefined\".", - "
", - "Initialize the three variables a, b, and c with 5, 10, and \"I am a\" respectively so that they will not be undefined." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Initialize these three variables", - "var a;", - "var b;", - "var c;", - "", - "// Do not change code below this line", - "", - "a = a + 1;", - "b = b + 5;", - "c = c + \" String!\";", - "" - ], - "tail": [ - "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = '\" + c + \"'\"; })(a,b,c);" - ], - "solutions": [ - "var a = 5;\nvar b = 10;\nvar c = \"I am a\";\na = a + 1;\nb = b + 5;\nc = c + \" String!\";" - ], - "tests": [ - "assert(typeof a === 'number' && a === 6, 'message: a should be defined and evaluated to have the value of 6');", - "assert(typeof b === 'number' && b === 15, 'message: b should be defined and evaluated to have the value of 15');", - "assert(!/undefined/.test(c) && c === \"I am a String!\", 'message: c should not contain undefined and should have a value of \"I am a String!\"');", - "assert(/a = a \\+ 1;/.test(code) && /b = b \\+ 5;/.test(code) && /c = c \\+ \" String!\";/.test(code), 'message: Do not change code below the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Entendiendo variables sin inicializar", - "description": [ - "Cuando las variables de JavaScript son declaradas, ellas tienen un valor inicial de undefined. Si tu haces una operación matematica sobre una variable undefined tu resultado sera NaN el cual significa \"Not a Number\" es decir \"No es un número\". Si tu concatenas una cadena con una variable undefined, vas a obtener una cadena literal de \"undefined\".", - "

Instrucciones

", - "Inicializa las tres variables a, b, y c con 5, 10, y \"I am a\" respectivamente de manera que no sean undefined." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ab", - "title": "Understanding Case Sensitivity in Variables", - "description": [ - "In JavaScript all variables and function names are case sensitive. This means that capitalization matters.", - "MYVAR is not the same as MyVar nor myvar. It is possible to have multiple distinct variables with the same name but different casing. It is strongly recommended that for the sake of clarity, you do not use this language feature.", - "

Best Practice

", - "Write variable names in JavaScript in camelCase. In camelCase, multi-word variable names have the first word in lowercase and the first letter of each subsequent word is capitalized.", - "Examples:", - "
var someVariable;
var anotherVariableName;
var thisVariableNameIsSoLong;
", - "
", - "Modify the existing declarations and assignments so their names use camelCase.
Do not create any new variables." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Declarations", - "var StUdLyCapVaR;", - "var properCamelCase;", - "var TitleCaseOver;", - "", - "// Assignments", - "STUDLYCAPVAR = 10;", - "PRoperCAmelCAse = \"A String\";", - "tITLEcASEoVER = 9000;" - ], - "solutions": [ - "var studlyCapVar;\nvar properCamelCase;\nvar titleCaseOver;\n\nstudlyCapVar = 10;\nproperCamelCase = \"A String\";\ntitleCaseOver = 9000;" - ], - "tests": [ - "assert(typeof studlyCapVar !== 'undefined' && studlyCapVar === 10, 'message: studlyCapVar is defined and has a value of 10');", - "assert(typeof properCamelCase !== 'undefined' && properCamelCase === \"A String\", 'message: properCamelCase is defined and has a value of \"A String\"');", - "assert(typeof titleCaseOver !== 'undefined' && titleCaseOver === 9000, 'message: titleCaseOver is defined and has a value of 9000');", - "assert(code.match(/studlyCapVar/g).length === 2, 'message: studlyCapVar should use camelCase in both declaration and assignment sections.');", - "assert(code.match(/properCamelCase/g).length === 2, 'message: properCamelCase should use camelCase in both declaration and assignment sections.');", - "assert(code.match(/titleCaseOver/g).length === 2, 'message: titleCaseOver should use camelCase in both declaration and assignment sections.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Entendiendo la distinción en variables", - "description": [ - "En JavaScript todas las variables y nombres de funciones distinguen entre mayúsculas y minúsculas. Esto significa que la capitalización importa.", - "MIVAR no es lo mismo que MiVar o mivar. Esto hace posible tener múltiples variables distintas con el mismo nombre pero de diferente manera. Es fuertemente recomendado por el bien de la claridad, que tu no uses esta característica del lenguaje.", - "

Mejor Práctica

", - "Escribe nombres de variables en JavaScript en capitalizaciónCamello (camelCase). En capitalizaciónCamello, los nombres de variables con múltiples palabras tienen la primera palabra en minúsculas y la primera letra de cada palabra subsecuente es capitalizada.", - "Ejemplos:", - "
var algunaVariable;
var otraVariable;
var esteNombreDeVariableEsMuyLargo;
", - "

Instrucciones

", - "Repara las declaraciones y asignaciones de variables de manera que sus nombres usen capitalizaciónCamello." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb3bdef", - "title": "Add Two Numbers with JavaScript", - "description": [ - "Number is a data type in JavaScript which represents numeric data.", - "Now let's try to add two numbers using JavaScript.", - "JavaScript uses the + symbol as addition operation when placed between two numbers.", - "Example", - "
myVar = 5 + 10; // assigned 15
", - "
", - "Change the 0 so that sum will equal 20." - ], - "challengeSeed": [ - "var sum = 10 + 0;", - "" - ], - "tail": [ - "(function(z){return 'sum = '+z;})(sum);" - ], - "solutions": [ - "var sum = 10 + 10;" - ], - "tests": [ - "assert(sum === 20, 'message: sum should equal 20');", - "assert(/\\+/.test(code), 'message: Use the + operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Suma dos números con JavaScript", - "description": [ - "Intentemos sumar dos números con JavaScript.", - "JavaScript utiliza el símbolo + para la adición.", - "Cambie el 0 para que la suma seá igual a 20." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb4bdef", - "title": "Subtract One Number from Another with JavaScript", - "description": [ - "We can also subtract one number from another.", - "JavaScript uses the - symbol for subtraction.", - "", - "Example", - "
myVar = 12 - 6; // assigned 6
", - "", - "
", - "Change the 0 so the difference is 12." - ], - "challengeSeed": [ - "var difference = 45 - 0;", - "", - "" - ], - "tail": [ - "(function(z){return 'difference = '+z;})(difference);" - ], - "solutions": [ - "var difference = 45 - 33;" - ], - "tests": [ - "assert(difference === 12, 'message: Make the variable difference equal 12.');", - "assert(/var\\s*difference\\s*=\\s*45\\s*-\\s*[0-9]*;(?!\\s*[a-zA-Z0-9]+)/.test(code),'message: Only subtract one number from 45.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Resta un número de otro con JavaScript", - "description": [ - "También podemos restar un número de otro.", - "JavaScript utiliza el símbolo - de sustracción", - "Cambia el 0 para que la diferencia sea 12." - ] - } - } - }, - { - "id": "cf1231c1c11feddfaeb5bdef", - "title": "Multiply Two Numbers with JavaScript", - "description": [ - "We can also multiply one number by another.", - "JavaScript uses the * symbol for multiplication of two numbers.", - "", - "Example", - "
myVar = 13 * 13; // assigned 169
", - "", - "
", - "Change the 0 so that product will equal 80." - ], - "challengeSeed": [ - "var product = 8 * 0;", - "", - "" - ], - "tail": [ - "(function(z){return 'product = '+z;})(product);" - ], - "solutions": [ - "var product = 8 * 10;" - ], - "tests": [ - "assert(product === 80,'message: Make the variable product equal 80');", - "assert(/\\*/.test(code), 'message: Use the * operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Multiplica dos números con JavaScript", - "description": [ - "También podemos multiplicar un número por otro.", - "JavaScript utiliza el símbolo * de la multiplicación.", - "Cambie el 0 para que el producto sea igual a 80." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb6bdef", - "title": "Divide One Number by Another with JavaScript", - "description": [ - "We can also divide one number by another.", - "JavaScript uses the / symbol for division.", - "", - "Example", - "
myVar = 16 / 2; // assigned 8
", - "", - "
", - "Change the 0 so that the quotient is equal to 2." - ], - "challengeSeed": [ - "var quotient = 66 / 0;", - "", - "" - ], - "tail": [ - "(function(z){return 'quotient = '+z;})(quotient);" - ], - "solutions": [ - "var quotient = 66 / 33;" - ], - "tests": [ - "assert(quotient === 2, 'message: Make the variable quotient equal to 2.');", - "assert(/\\d+\\s*\\/\\s*\\d+/.test(code), 'message: Use the / operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Divide un número por otro con JavaScript", - "description": [ - "También podemos dividir un número por otro.", - "JavaScript utiliza el símbolo / para dividir.", - "Cambia el 0 para que el cociente sea igual a 2." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ac", - "title": "Increment a Number with JavaScript", - "description": [ - "You can easily increment or add one to a variable with the ++ operator.", - "i++;", - "is the equivalent of", - "i = i + 1;", - "Note
The entire line becomes i++;, eliminating the need for the equal sign.", - "
", - "Change the code to use the ++ operator on myVar.", - "Hint
Learn more about Arithmetic operators - Increment (++)." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myVar = 87;", - "", - "// Only change code below this line", - "myVar = myVar + 1;", - "" - ], - "tail": [ - "(function(z){return 'myVar = ' + z;})(myVar);" - ], - "solutions": [ - "var myVar = 87;\nmyVar++;" - ], - "tests": [ - "assert(myVar === 88, 'message: myVar should equal 88');", - "assert(/var\\s*myVar\\s*=\\s*87;\\s*\\/*.*\\s*myVar\\+\\+;/.test(code), 'message: myVar = myVar + 1; should be changed');", - "assert(/[+]{2}\\s*myVar|myVar\\s*[+]{2}/.test(code), 'message: Use the ++ operator');", - "assert(/var myVar = 87;/.test(code), 'message: Do not change code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Incrementa un número con JavaScript", - "description": [ - "Tu puedes fácilmente incrementar o agregar uno a una variable con el operador ++.", - "i++", - "es el equivalente de", - "i = i + 1;", - "Nota
Toda la línea equivale a i++, sin necesidad del signo igual.", - "

Instrucciones

", - "Cambia el código para usar el operador ++ sobre myVar." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ad", - "title": "Decrement a Number with JavaScript", - "description": [ - "You can easily decrement or decrease a variable by one with the -- operator.", - "i--;", - "is the equivalent of", - "i = i - 1;", - "Note
The entire line becomes i--;, eliminating the need for the equal sign.", - "
", - "Change the code to use the -- operator on myVar." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myVar = 11;", - "", - "// Only change code below this line", - "myVar = myVar - 1;", - "" - ], - "tail": [ - "(function(z){return 'myVar = ' + z;})(myVar);" - ], - "solutions": [ - "var myVar = 11;\nmyVar--;" - ], - "tests": [ - "assert(myVar === 10, 'message: myVar should equal 10');", - "assert(/var\\s*myVar\\s*=\\s*11;\\s*\\/*.*\\s*myVar--;/.test(code), 'message: myVar = myVar - 1; should be changed');", - "assert(/[-]{2}\\s*myVar|myVar\\s*[-]{2}/.test(code), 'message: Use the -- operator on myVar');", - "assert(/var myVar = 11;/.test(code), 'message: Do not change code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Decrementar un número con JavaScript", - "description": [ - "Fácilmente puedes decrementar o disminuir una variable por uno con el operador --.", - "i--;", - "es el equivalente a", - "i = i - 1;", - "Nota
Toda la línea equivale a i--;, sin necesidad del signo igual.", - "

Instrucciones

", - "Cambia el código para usar el operador -- en myVar." - ] - } - } - }, - { - "id": "cf1391c1c11feddfaeb4bdef", - "title": "Create Decimal Numbers with JavaScript", - "description": [ - "We can store decimal numbers in variables too. Decimal numbers are sometimes referred to as floating point numbers or floats.", - "Note
Not all real numbers can accurately be represented in floating point. This can lead to rounding errors. Details Here.", - "
", - "Create a variable myDecimal and give it a decimal value with a fractional part (e.g. 5.7)." - ], - "challengeSeed": [ - "var ourDecimal = 5.7;", - "", - "// Only change code below this line", - "", - "" - ], - "tail": [ - "(function(){if(typeof myDecimal !== \"undefined\"){return myDecimal;}})();" - ], - "solutions": [ - "var myDecimal = 9.9;" - ], - "tests": [ - "assert(typeof myDecimal === \"number\", 'message: myDecimal should be a number.');", - "assert(myDecimal % 1 != 0, 'message: myDecimal should have a decimal point'); " - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Crea números decimales con JavaScript", - "description": [ - "Podemos almacenar números decimales en variables también. Los números decimales a veces son referidos como números de punto flotante o flotantes.", - "Nota
No todos los números reales pueden ser exactamente representados en punto flotante. Esto puede conducir a errores de redondeo. Detalles aquí.", - "

Instrucciones

", - "Crea una variable myDecimal y dale un valor decimal con una parte fraccional (p.e. 5.7)." - ] - } - } - }, - { - "id": "bd7993c9c69feddfaeb7bdef", - "title": "Multiply Two Decimals with JavaScript", - "description": [ - "In JavaScript, you can also perform calculations with decimal numbers, just like whole numbers.", - "Let's multiply two decimals together to get their product.", - "
", - "Change the 0.0 so that product will equal 5.0." - ], - "challengeSeed": [ - "var product = 2.0 * 0.0;", - "", - "" - ], - "tail": [ - "(function(y){return 'product = '+y;})(product);" - ], - "solutions": [ - "var product = 2.0 * 2.5;" - ], - "tests": [ - "assert(product === 5.0, 'message: The variable product should equal 5.0.');", - "assert(/\\*/.test(code), 'message: You should use the * operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Multiplicar dos decimales con JavaScript", - "description": [ - "En JavaScript, también puedes realizar cálculos con números decimales, al igual que con números enteros.", - "Vamos a multiplicar dos números decimales para obtener su producto.", - "

Instrucciones

", - "Cambia el 0.0 para que el producto sea igual a 5.0." - ] - } - } - }, - { - "id": "bd7993c9ca9feddfaeb7bdef", - "title": "Divide One Decimal by Another with JavaScript", - "description": [ - "Now let's divide one decimal by another.", - "
", - "Change the 0.0 so that quotient will equal to 2.2." - ], - "challengeSeed": [ - "var quotient = 0.0 / 2.0; // Fix this line", - "", - "" - ], - "tail": [ - "(function(y){return 'quotient = '+y;})(quotient);" - ], - "solutions": [], - "tests": [ - "assert(quotient === 2.2, 'message: The variable quotient should equal 2.2');", - "assert(/4\\.40*\\s*\\/\\s*2\\.*0*/.test(code), 'message: You should use the / operator to divide 4.4 by 2');", - "assert(code.match(/quotient/g).length === 1, 'message: The quotient variable should only be assigned once');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Divide un número decimal por otro con JavaScript", - "description": [ - "Ahora vamos a dividir un decimal por otro.", - "

Instrucciones

", - "Cambia el 0.0 para que tu cociente sea igual a 2.2." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ae", - "title": "Finding a Remainder in JavaScript", - "description": [ - "The remainder operator % gives the remainder of the division of two numbers.", - "Example", - "
5 % 2 = 1 because
Math.floor(5 / 2) = 2 (Quotient)
2 * 2 = 4
5 - 4 = 1 (Remainder)
", - "Usage
In mathematics, a number can be checked to be even or odd by checking the remainder of the division of the number by 2.", - "
17 % 2 = 1 (17 is Odd)
48 % 2 = 0 (48 is Even)
", - "Note
The remainder operator is sometimes incorrectly referred to as the \"modulus\" operator. It is very similar to modulus, but does not work properly with negative numbers.", - "
", - "Set remainder equal to the remainder of 11 divided by 3 using the remainder (%) operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Only change code below this line", - "", - "var remainder;", - "" - ], - "tail": [ - "(function(y){return 'remainder = '+y;})(remainder);" - ], - "solutions": [ - "var remainder = 11 % 3;" - ], - "tests": [ - "assert(/var\\s+?remainder/.test(code), 'message: The variable remainder should be initialized');", - "assert(remainder === 2, 'message: The value of remainder should be 2');", - "assert(/\\s+?remainder\\s*?=\\s*?.*%.*;/.test(code), 'message: You should use the % operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Encontrar un cociente en JavaScript", - "description": [ - "El operador residuo % da el residuo de la división de dos números.", - "Ejemplo", - "
5 % 2 = 1 por que
Math.floor(5 / 2) = 2 (Cociente)
2 * 2 = 4
5 - 4 = 1 (Residuo)
", - "Uso
En matemáticas, se puede comprobar si un número es par o impar revisando en residuo de la división del número por 2.", - "
17 % 2 = 1 (17 es Impar)
48 % 2 = 0 (48 es Par)
", - "Nota
El operador residuo es a veces incorrectamente referenciado como el operador \"módulo\". Este es muy parecido a módulo, pero no trabaja apropiadamente con números negativos.", - "

Instrucciones

", - "Asigna remainder igual al residuo de 11 dividido por 3 usando el operador residuo (%)." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244af", - "title": "Compound Assignment With Augmented Addition", - "description": [ - "In programming, it is common to use assignments to modify the contents of a variable. Remember that everything to the right of the equals sign is evaluated first, so we can say:", - "myVar = myVar + 5;", - "to add 5 to myVar. Since this is such a common pattern, there are operators which do both a mathematical operation and assignment in one step.", - "One such operator is the += operator.", - "
var myVar = 1;
myVar += 5;
console.log(myVar); // Returns 6
", - "
", - "Convert the assignments for a, b, and c to use the += operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var a = 3;", - "var b = 17;", - "var c = 12;", - "", - "// Only modify code below this line", - "", - "a = a + 12;", - "b = 9 + b;", - "c = c + 7;", - "" - ], - "tail": [ - "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);" - ], - "solutions": [ - "var a = 3;\nvar b = 17;\nvar c = 12;\n\na += 12;\nb += 9;\nc += 7;" - ], - "tests": [ - "assert(a === 15, 'message: a should equal 15');", - "assert(b === 26, 'message: b should equal 26');", - "assert(c === 19, 'message: c should equal 19');", - "assert(code.match(/\\+=/g).length === 3, 'message: You should use the += operator for each variable');", - "assert(/var a = 3;/.test(code) && /var b = 17;/.test(code) && /var c = 12;/.test(code), 'message: Do not modify the code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Asignación con más", - "description": [ - "En programación, es común usar asignaciones para modificar el contenido de una variable. Recuerda que todo lo de la derecha del signo igual es evaluado primero, así podemos decir que:", - "miVar = miVar + 5;", - "para agregar 5 a miVar. Dado que este es un patrón común, hay operadores que realizan tanto una operación matemática como una asignación en un paso.", - "Uno de tales operadores es el operador +=.", - "miVar += 5; añadirá 5 a miVar.", - "

Instrucciones

", - "Convierte las asignaciones para a, b y c usando el operador +=." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b0", - "title": "Compound Assignment With Augmented Subtraction", - "description": [ - "Like the += operator, -= subtracts a number from a variable.", - "myVar = myVar - 5;", - "will subtract 5 from myVar. This can be rewritten as: ", - "myVar -= 5;", - "
", - "Convert the assignments for a, b, and c to use the -= operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var a = 11;", - "var b = 9;", - "var c = 3;", - "", - "// Only modify code below this line", - "", - "a = a - 6;", - "b = b - 15;", - "c = c - 1;", - "", - "" - ], - "tail": [ - "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);" - ], - "solutions": [ - "var a = 11;\nvar b = 9;\nvar c = 3;\n\na -= 6;\nb -= 15;\nc -= 1;\n\n" - ], - "tests": [ - "assert(a === 5, 'message: a should equal 5');", - "assert(b === -6, 'message: b should equal -6');", - "assert(c === 2, 'message: c should equal 2');", - "assert(code.match(/-=/g).length === 3, 'message: You should use the -= operator for each variable');", - "assert(/var a = 11;/.test(code) && /var b = 9;/.test(code) && /var c = 3;/.test(code), 'message: Do not modify the code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Asignación con menos", - "description": [ - "Al igual que el operador +=, -= substrae un número de una variable.", - "miVar = miVar - 5;", - "substraerá 5 de miVar. Esto puede ser reescrito como: ", - "miVar -= 5;", - "

Instrucciones

", - "Convierte las asignaciones para a, b, y c para usar el operador -=." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b1", - "title": "Compound Assignment With Augmented Multiplication", - "description": [ - "The *= operator multiplies a variable by a number.", - "myVar = myVar * 5;", - "will multiply myVar by 5. This can be rewritten as: ", - "myVar *= 5;", - "
", - "Convert the assignments for a, b, and c to use the *= operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var a = 5;", - "var b = 12;", - "var c = 4.6;", - "", - "// Only modify code below this line", - "", - "a = a * 5;", - "b = 3 * b;", - "c = c * 10;", - "", - "" - ], - "tail": [ - "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);" - ], - "solutions": [ - "var a = 5;\nvar b = 12;\nvar c = 4.6;\n\na *= 5;\nb *= 3;\nc *= 10;" - ], - "tests": [ - "assert(a === 25, 'message: a should equal 25');", - "assert(b === 36, 'message: b should equal 36');", - "assert(c === 46, 'message: c should equal 46');", - "assert(code.match(/\\*=/g).length === 3, 'message: You should use the *= operator for each variable');", - "assert(/var a = 5;/.test(code) && /var b = 12;/.test(code) && /var c = 4\\.6;/.test(code), 'message: Do not modify the code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Asignación con veces igual", - "description": [ - "El operador *= multiplica una variable por un número.", - "miVar = miVar * 5;", - "multiplicará miVar por 5. Esto puede ser reescrito como: ", - "miVar *= 5;", - "

Instrucciones

", - "Convierte las asignaciones para a, b y c usando el operador *=." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b2", - "title": "Compound Assignment With Augmented Division", - "description": [ - "The /= operator divides a variable by another number.", - "myVar = myVar / 5;", - "Will divide myVar by 5. This can be rewritten as: ", - "myVar /= 5;", - "
", - "Convert the assignments for a, b, and c to use the /= operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var a = 48;", - "var b = 108;", - "var c = 33;", - "", - "// Only modify code below this line", - "", - "a = a / 12;", - "b = b / 4;", - "c = c / 11;", - "" - ], - "tail": [ - "(function(a,b,c){ return \"a = \" + a + \", b = \" + b + \", c = \" + c; })(a,b,c);" - ], - "solutions": [ - "var a = 48;\nvar b = 108;\nvar c = 33;\n\na /= 12;\nb /= 4;\nc /= 11;" - ], - "tests": [ - "assert(a === 4, 'message: a should equal 4');", - "assert(b === 27, 'message: b should equal 27');", - "assert(c === 3, 'message: c should equal 3');", - "assert(code.match(/\\/=/g).length === 3, 'message: You should use the /= operator for each variable');", - "assert(/var a = 48;/.test(code) && /var b = 108;/.test(code) && /var c = 33;/.test(code), 'message: Do not modify the code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Asignación con división", - "description": [ - "El operador /= divide una variable por otro número.", - "miVar = miVar / 5;", - "Dividirá miVar por 5. Esto puede ser reescrito como: ", - "miVar /= 5;", - "

Instrucciones

", - "Convierte las asignaciones para a, b y c para usar el operador /=." - ] - } - } - }, - { - "id": "bd7123c9c444eddfaeb5bdef", - "title": "Declare String Variables", - "description": [ - "Previously we have used the code", - "var myName = \"your name\";", - "\"your name\" is called a string literal. It is a string because it is a series of zero or more characters enclosed in single or double quotes.", - "
", - "Create two new string variables: myFirstName and myLastName and assign them the values of your first and last name, respectively." - ], - "challengeSeed": [ - "// Example", - "var firstName = \"Alan\";", - "var lastName = \"Turing\";", - "", - "// Only change code below this line", - "", - "" - ], - "tail": [ - "if(typeof myFirstName !== \"undefined\" && typeof myLastName !== \"undefined\"){(function(){return myFirstName + ', ' + myLastName;})();}" - ], - "solutions": [ - "var myFirstName = \"Alan\";\nvar myLastName = \"Turing\";" - ], - "tests": [ - "assert((function(){if(typeof myFirstName !== \"undefined\" && typeof myFirstName === \"string\" && myFirstName.length > 0){return true;}else{return false;}})(), 'message: myFirstName should be a string with at least one character in it.');", - "assert((function(){if(typeof myLastName !== \"undefined\" && typeof myLastName === \"string\" && myLastName.length > 0){return true;}else{return false;}})(), 'message: myLastName should be a string with at least one character in it.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Declara variables tipo cadena", - "description": [ - "En el reto anterior, se utilizó el código myName var = \"su nombre\". Esto es lo que llamamos una variable tipo cadena. No es nada más que una \"cadena\" de caracteres. Las cadenas en JavaScript siempre se encierran entre comillas. ", - "Ahora vamos a crear dos nuevas variables tipo cadena: myFirstName y myLastName y asignarles los valores de tu nombre y tu apellido, respectivamente." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b5", - "title": "Escaping Literal Quotes in Strings", - "description": [ - "When you are defining a string you must start and end with a single or double quote. What happens when you need a literal quote: \" or ' inside of your string?", - "In JavaScript, you can escape a quote from considering it as an end of string quote by placing a backslash (\\) in front of the quote.", - "var sampleStr = \"Alan said, \\\"Peter is learning JavaScript\\\".\";", - "This signals to JavaScript that the following quote is not the end of the string, but should instead appear inside the string. So if you were to print this to the console, you would get:", - "Alan said, \"Peter is learning JavaScript\".", - "
", - "Use backslashes to assign a string to the myStr variable so that if you were to print it to the console, you would see:", - "I am a \"double quoted\" string inside \"double quotes\"." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myStr = \"\"; // Change this line", - "", - "" - ], - "tail": [ - "(function(){", - " if(typeof myStr === 'string') {", - " console.log(\"myStr = \\\"\" + myStr + \"\\\"\");", - " } else {", - " console.log(\"myStr is undefined\");", - " }", - "})();" - ], - "solutions": ["var myStr = \"I am a \\\"double quoted\\\" string inside \\\"double quotes\\\".\";"], - "tests": [ - "assert(code.match(/\\\\\"/g).length === 4 && code.match(/[^\\\\]\"/g).length === 2, 'message: You should use two double quotes (") and four escaped double quotes (\").');", - "assert(myStr === \"I am a \\\"double quoted\\\" string inside \\\"double quotes\\\".\", 'message: Variable myStr should contain the string: I am a \"double quoted\" string inside \"double quotes\".');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Escapar comillas en cadenas de texto", - "description": [ - "Cuando estás definiendo una cadena debes iniciar y terminar con apóstrofes o comillas. ¿Qué pasa cuando necesitas una comilla: \" o ' dentro de tu cadena?", - "En JavaScript, tu puedes escapar unas comillas para diferenciarlas de las comillas del final de la cadena colocando una barra invertida (\\) antes de la cita.", - "var cadenaEjem = \"Alan dijo, \\\"Pedro está aprendiendo JavaScript\\\".\";", - "Esto le indica a JavaScript que la comilla siguiente no es el fin de la cadena, sino que debe aparecer dentro de la cadena. Así que si fueras a imprimir esto en la consola, tu obtendrías:", - "Alan dijo, \"Pedro está aprendiendo JavaScript\".", - "

Instructiones

", - "Usa barras invertidaspara asigar una cadena a la variable myStr de modo que si tu fueras a imprimirla en la consola, tu verías:", - "I am a \"double quoted\" string inside \"double quotes\"." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b4", - "title": "Quoting Strings with Single Quotes", - "description": [ - "String values in JavaScript may be written with single or double quotes, as long as you start and end with the same type of quote. Unlike some other programming languages, single and double quotes work the same in JavaScript.", - "
doubleQuoteStr = \"This is a string\";
singleQuoteStr = 'This is also a string';
", - "The reason why you might want to use one type of quote over the other is if you want to use both in a string. This might happen if you want to save a conversation in a string and have the conversation in quotes. Another use for it would be saving an <a> tag with various attributes in quotes, all within a string.", - "
conversation = 'Finn exclaims to Jake, \"Algebraic!\"';
", - "However, this becomes a problem if you need to use the outermost quotes within it. Remember, a string has the same kind of quote at the beginning and end. But if you have that same quote somewhere in the middle, the string will stop early and throw an error.", - "
goodStr = 'Jake asks Finn, \"Hey, let\\'s go on an adventure?\"';
badStr = 'Finn responds, \"Let's go!\"'; // Throws an error
", - "In the goodStr above, you can use both quotes safely by using the backslash \\ as an escape character.", - "Note
The backslash \\ should not be be confused with the forward slash /. They do not do the same thing.", - "
", - "Change the provided string to a string with single quotes at the beginning and end and no escape characters.", - "Right now, the <a> tag in the string uses double quotes everywhere. You will need to change the outer quotes to single quotes so you can remove the escape characters." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myStr = \"Link\";", - "", - "" - ], - "tail": [ - "(function() { return \"myStr = \" + myStr; })();" - ], - "solutions": ["var myStr = 'Link';"], - "tests": [ - "assert(!/\\\\/g.test(code) && myStr.match('\\\\s*\\\\s*Link\\\\s*\\\\s*'), 'message: Remove all the backslashes (\\)');", - "assert(code.match(/\"/g).length === 4 && code.match(/'/g).length === 2, 'message: You should have two single quotes ' and four double quotes "');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Citando cadenas con comillas simples", - "description": [ - "Los valores de Cadenas en JavaScript pueden ser escritos con comillas o apóstrofes, siempre y cuando inicien y terminen con el mismo tipo de cita. A diferencia de algunos lenguajes, apóstrofes y comillas son funcionalmente identicas en JavaScript.", - "\"Esta cadena tiene \\\"comillas\\\" en esta\"", - "La ventaja de usar una o la otra tiene que ver con la necesidad de escapar comillas. Si tu tienes una cadena con algunas comillas, esta puede ser difícil de leer y escribir. En su lugar, usa apóstrofes:", - "'Esta cadena tiene \"comillas\" en esta. Y \"probablemente\" muchas de ellas.'", - "

Instrucciones

", - "Cambia la cadena dada de comillas a apóstrofes y quita el escape." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b6", - "title": "Escape Sequences in Strings", - "description": [ - "Quotes are not the only characters that can be escaped inside a string. There are two reasons to use escaping characters: First is to allow you to use characters you might not otherwise be able to type out, such as a backspace. Second is to allow you to represent multiple quotes in a string without JavaScript misinterpreting what you mean. We learned this in the previous challenge.", - "
CodeOutput
\\'single quote
\\\"double quote
\\\\backslash
\\nnewline
\\rcarriage return
\\ttab
\\bbackspace
\\fform feed
", - "Note that the backslash itself must be escaped in order to display as a backslash.", - "
", - "Assign the following three lines of text into the single variable myStr using escape sequences.", - "
FirstLine
    \\SecondLine
ThirdLine
", - "You will need to use escape sequences to insert special characters correctly. You will also need to follow the spacing as it looks above, with no spaces between escape sequences or words.", - "Here is the text with the escape sequences written out.", - "FirstLinenewlinetabbackslashSecondLinenewlineThirdLine" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myStr; // Change this line", - "", - "" - ], - "tail": [ - "(function(){", - "if (myStr !== undefined){", - "console.log('myStr:\\n' + myStr);}})();" - ], - "solutions": [ - "var myStr = \"FirstLine\\n\\t\\\\SecondLine\\nThirdLine\";" - ], - "tests": [ - "assert(!/ /.test(myStr), 'message: myStr should not contain any spaces');", - "assert(/FirstLine/.test(myStr) && /SecondLine/.test(myStr) && /ThirdLine/.test(myStr), 'message: myStr should contain the strings FirstLine, SecondLine and ThirdLine (remember case sensitivity)');", - "assert(/FirstLine\\n/.test(myStr), 'message: FirstLine should be followed by the newline character \\n');", - "assert(/\\n\\t/.test(myStr), 'message: myStr should contain a tab character \\t which follows a newline character');", - "assert(/\\SecondLine/.test(myStr), 'message: SecondLine should be preceded by the backslash character \\\\');", - "assert(/SecondLine\\nThirdLine/.test(myStr), 'message: There should be a newline character between SecondLine and ThirdLine');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Secuencias de escape en cadenas", - "description": [ - "Las comillas no son el único caracter que puede ser escapado dentro de una cadena. Aquí ahí una tabla de secuencias de escape comunes:", - "
CódigoSalida
\\'apostrofe
\\\"comilla
\\\\barra invertida
\\nnueva línea
\\rretorno de carro
\\ttabulación
\\bretroceso
\\fsalto de página
", - "Nota que la barra invertida por si misma tiene que ser escapada con el fin de mostrarse como una barra invertida.", - "

Instrucciones

", - "Codifica la siguiente secuencia, separada por espacios:
FirstLinenueva líneatabulaciónbarra invertidaSecondLinenueva líneaThirdLine" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b7", - "title": "Concatenating Strings with Plus Operator", - "description": [ - "In JavaScript, when the + operator is used with a String value, it is called the concatenation operator. You can build a new string out of other strings by concatenating them together.", - "Example", - "
'My name is Alan,' + ' I concatenate.'
", - "Note
Watch out for spaces. Concatenation does not add spaces between concatenated strings, so you'll need to add them yourself.", - "
", - "Build myStr from the strings \"This is the start. \" and \"This is the end.\" using the + operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var ourStr = \"I come first. \" + \"I come second.\";", - "", - "// Only change code below this line", - "", - "var myStr;", - "", - "" - ], - "tail": [ - "(function(){", - " if(typeof myStr === 'string') {", - " return 'myStr = \"' + myStr + '\"';", - " } else {", - " return 'myStr is not a string';", - " }", - "})();" - ], - "solutions": [ - "var ourStr = \"I come first. \" + \"I come second.\";\nvar myStr = \"This is the start. \" + \"This is the end.\";" - ], - "tests": [ - "assert(myStr === \"This is the start. This is the end.\", 'message: myStr should have a value of This is the start. This is the end.');", - "assert(code.match(/([\"']).*([\"'])\\s*\\+\\s*([\"']).*([\"'])/g).length > 1, 'message: Use the + operator to build myStr');", - "assert(/var\\s+myStr/.test(code), 'message: myStr should be created using the var keyword.');", - "assert(/myStr\\s*=/.test(code), 'message: Make sure to assign the result to the myStr variable.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Concatenar cadenas con el operador más", - "description": [ - "En JavaScript, cuando el operador + es usado con un valor de Cadena, este es llamado el operador concatenación. Tu puedes construir una nueva cadena de otras cadenas concatenandolas juntas.", - "Ejemplo", - "
'Mi nombre es Alan,' + ' Yo concateno.'
", - "Nota
Cuidado con los espacios. La concatenación no agrega espacios entre cadenas concatenadas, así que necesitarás agregarlos tu mismo.", - "

Instrucciones

", - "Construye myStr con las cadenas \"This is the start. \" y \"This is the end.\" usando el operador+." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b8", - "title": "Concatenating Strings with the Plus Equals Operator", - "description": [ - "We can also use the += operator to concatenate a string onto the end of an existing string variable. This can be very helpful to break a long string over several lines.", - "Note
Watch out for spaces. Concatenation does not add spaces between concatenated strings, so you'll need to add them yourself.", - "
", - "Build myStr over several lines by concatenating these two strings: \"This is the first sentence. \" and \"This is the second sentence.\" using the += operator. Use the += operator similar to how it is shown in the editor. Start by assigning the first string to myStr, then add on the second string." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var ourStr = \"I come first. \";", - "ourStr += \"I come second.\";", - "", - "// Only change code below this line", - "", - "var myStr;", - "", - "" - ], - "tail": [ - "(function(){", - " if(typeof myStr === 'string') {", - " return 'myStr = \"' + myStr + '\"';", - " } else {", - " return 'myStr is not a string';", - " }", - "})();" - ], - "solutions": [ - "var ourStr = \"I come first. \";\nourStr += \"I come second.\";\n\nvar myStr = \"This is the first sentence. \";\nmyStr += \"This is the second sentence.\";" - ], - "tests": [ - "assert(myStr === \"This is the first sentence. This is the second sentence.\", 'message: myStr should have a value of This is the first sentence. This is the second sentence.');", - "assert(code.match(/\\w\\s*\\+=\\s*[\"']/g).length > 1 && code.match(/\\w\\s*\\=\\s*[\"']/g).length > 1, 'message: Use the += operator to build myStr');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Concatenar cadenas con el operador mas igual", - "description": [ - "Nosotros también podemos usar el operador += para concatenar una cadena al final de una variable de cadena existente. Esto puede ser muy útil para romper una cadena larga sobre varias líneas.", - "Nota
Cuidado con los espacios. La concatenación no agrega espacios entre cadenas concatenadas, así que necesitarás añadirlos tu mismo.", - "

Instrucciones

", - "Construye myStr sobre varias líneas concatenando estas dos cadenas:
\"This is the first sentence. \" y \"This is the second sentence.\" usando el operador +=." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244b9", - "title": "Constructing Strings with Variables", - "description": [ - "Sometimes you will need to build a string, Mad Libs style. By using the concatenation operator (+), you can insert one or more variables into a string you're building.", - "
", - "Set myName to a string equal to your name and build myStr with myName between the strings \"My name is \" and \" and I am well!\"" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var ourName = \"freeCodeCamp\";", - "var ourStr = \"Hello, our name is \" + ourName + \", how are you?\";", - "", - "// Only change code below this line", - "var myName;", - "var myStr;", - "", - "" - ], - "tail": [ - "(function(){", - " var output = [];", - " if(typeof myName === 'string') {", - " output.push('myName = \"' + myName + '\"');", - " } else {", - " output.push('myName is not a string');", - " }", - " if(typeof myStr === 'string') {", - " output.push('myStr = \"' + myStr + '\"');", - " } else {", - " output.push('myStr is not a string');", - " }", - " return output.join('\\n');", - "})();" - ], - "solutions": [ - "var myName = \"Bob\";\nvar myStr = \"My name is \" + myName + \" and I am well!\";" - ], - "tests": [ - "assert(typeof myName !== 'undefined' && myName.length > 2, 'message: myName should be set to a string at least 3 characters long');", - "assert(code.match(/[\"']\\s*\\+\\s*myName\\s*\\+\\s*[\"']/g).length > 0, 'message: Use two + operators to build myStr with myName inside it');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Construir cadenas con variables", - "description": [ - "A veces necesitarás construir una cadena, al estilo Mad Libs. Mediante el uso del operador concatenación (+), puedes insertar una o más variables dentro de una cadena que estés construyendo.", - "

Instrucciones

", - "Asigna myName a una cadena igual a tu nombre y construye myStr con myName entre las cadenas \"My name is \" and \" and I am well!\"" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ed", - "title": "Appending Variables to Strings", - "description": [ - "Just as we can build a string over multiple lines out of string literals, we can also append variables to a string using the plus equals (+=) operator.", - "
", - "Set someAdjective and append it to myStr using the += operator." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var anAdjective = \"awesome!\";", - "var ourStr = \"freeCodeCamp is \";", - "ourStr += anAdjective;", - "", - "// Only change code below this line", - "", - "var someAdjective;", - "var myStr = \"Learning to code is \";", - "" - ], - "tail": [ - "(function(){", - " var output = [];", - " if(typeof someAdjective === 'string') {", - " output.push('someAdjective = \"' + someAdjective + '\"');", - " } else {", - " output.push('someAdjective is not a string');", - " }", - " if(typeof myStr === 'string') {", - " output.push('myStr = \"' + myStr + '\"');", - " } else {", - " output.push('myStr is not a string');", - " }", - " return output.join('\\n');", - "})();" - ], - "solutions": [ - "var anAdjective = \"awesome!\";\nvar ourStr = \"freeCodeCamp is \";\nourStr += anAdjective;\n\nvar someAdjective = \"neat\";\nvar myStr = \"Learning to code is \";\nmyStr += someAdjective;" - ], - "tests": [ - "assert(typeof someAdjective !== 'undefined' && someAdjective.length > 2, 'message: someAdjective should be set to a string at least 3 characters long');", - "assert(code.match(/myStr\\s*\\+=\\s*someAdjective\\s*/).length > 0, 'message: Append someAdjective to myStr using the += operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Anexando variables a cadenas", - "description": [ - "Al igual que podemos construir una cadena en múltiples líneas a partir de cadenas literales, nosotros podemos ademas anexar variables a una cadena usando el operador más igual (+=).", - "

Instructiones

", - "Asigna someAdjective y anexalo a myStr usando el operador +=." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/appending-variables-to-strings" - }, - { - "id": "bd7123c9c448eddfaeb5bdef", - "title": "Find the Length of a String", - "description": [ - "You can find the length of a String value by writing .length after the string variable or string literal.", - "\"Alan Peter\".length; // 10", - "For example, if we created a variable var firstName = \"Charles\", we could find out how long the string \"Charles\" is by using the firstName.length property.", - "
", - "Use the .length property to count the number of characters in the lastName variable and assign it to lastNameLength." - ], - "challengeSeed": [ - "// Example", - "var firstNameLength = 0;", - "var firstName = \"Ada\";", - "", - "firstNameLength = firstName.length;", - "", - "// Setup", - "var lastNameLength = 0;", - "var lastName = \"Lovelace\";", - "", - "// Only change code below this line.", - "", - "lastNameLength = lastName;", - "", - "" - ], - "tail": [ - "if(typeof lastNameLength !== \"undefined\"){(function(){return lastNameLength;})();}" - ], - "solutions": [ - "var firstNameLength = 0;\nvar firstName = \"Ada\";\nfirstNameLength = firstName.length;\n\nvar lastNameLength = 0;\nvar lastName = \"Lovelace\";\nlastNameLength = lastName.length;" - ], - "tests": [ - "assert((function(){if(typeof lastNameLength !== \"undefined\" && typeof lastNameLength === \"number\" && lastNameLength === 8){return true;}else{return false;}})(), 'message: lastNameLength should be equal to eight.');", - "assert((function(){if(code.match(/\\.length/gi) && code.match(/\\.length/gi).length >= 2 && code.match(/var lastNameLength \\= 0;/gi) && code.match(/var lastNameLength \\= 0;/gi).length >= 1){return true;}else{return false;}})(), 'message: You should be getting the length of lastName by using .length like this: lastName.length.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Comprueba la propiedad longitud (length) de una variable tipo cadena", - "description": [ - "Las estructuras de datos tienen propiedades. Por ejemplo, las cadenas tienen una propiedad llamada .length que te dirá cuántos caracteres hay en la cadena.", - "Por ejemplo, si creamos una variable var firstName=\"Charles\", podemos averiguar la longitud de la cadena \"Charles\" usando la propiedad firstName.length. ", - "Usa la propiedad .length para contar el número de caracteres en el variable lastName." - ] - } - } - }, - { - "id": "bd7123c9c549eddfaeb5bdef", - "title": "Use Bracket Notation to Find the First Character in a String", - "description": [ - "Bracket notation is a way to get a character at a specific index within a string.", - "Most modern programming languages, like JavaScript, don't start counting at 1 like humans do. They start at 0. This is referred to as Zero-based indexing.", - "For example, the character at index 0 in the word \"Charles\" is \"C\". So if var firstName = \"Charles\", you can get the value of the first letter of the string by using firstName[0].", - "
", - "Use bracket notation to find the first character in the lastName variable and assign it to firstLetterOfLastName.", - "Hint
Try looking at the firstLetterOfFirstName variable declaration if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var firstLetterOfFirstName = \"\";", - "var firstName = \"Ada\";", - "", - "firstLetterOfFirstName = firstName[0];", - "", - "// Setup", - "var firstLetterOfLastName = \"\";", - "var lastName = \"Lovelace\";", - "", - "// Only change code below this line", - "firstLetterOfLastName = lastName;", - "", - "" - ], - "tail": [ - "(function(v){return v;})(firstLetterOfLastName);" - ], - "solutions": [ - "var firstLetterOfLastName = \"\";\nvar lastName = \"Lovelace\";\n\n// Only change code below this line\nfirstLetterOfLastName = lastName[0];" - ], - "tests": [ - "assert(firstLetterOfLastName === 'L', 'message: The firstLetterOfLastName variable should have the value of L.');", - "assert(code.match(/firstLetterOfLastName\\s*?=\\s*?lastName\\[.*?\\]/), 'message: You should use bracket notation.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usa la notación de corchetes para encontrar el primer carácter de una cadena", - "description": [ - "La notación de corchetes es una forma de obtener el caracter en un índice específico de una cadena.", - "Los computadoras no empiezan a contar desde 1 como hacen los humanos. Comienzan en 0 ", - "Por ejemplo, el caracter en el índice 0 en la palabra \"Charles \" es \"C\". Entonces si var firstName = \"Charles\", puedes obtener la primera letra de la cadena usando firstName[0] .", - "Usa la notación de corchetes para encontrar el primer caracter en la variable lastName y asignarlo a firstLetterOfLastName.", - "Si te atascas intenta mirar la declaración de la variable firstLetterOfFirstName." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ba", - "title": "Understand String Immutability", - "description": [ - "In JavaScript, String values are immutable, which means that they cannot be altered once created.", - "For example, the following code:", - "
var myStr = \"Bob\";
myStr[0] = \"J\";
", - "cannot change the value of myStr to \"Job\", because the contents of myStr cannot be altered. Note that this does not mean that myStr cannot be changed, just that the individual characters of a string literal cannot be changed. The only way to change myStr would be to assign it with a new string, like this:", - "
var myStr = \"Bob\";
myStr = \"Job\";
", - "
", - "Correct the assignment to myStr so it contains the string value of Hello World using the approach shown in the example above." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var myStr = \"Jello World\";", - "", - "// Only change code below this line", - "", - "myStr[0] = \"H\"; // Fix Me", - "", - "" - ], - "tail": [ - "(function(v){return \"myStr = \" + v;})(myStr);" - ], - "solutions": [ - "var myStr = \"Jello World\";\nmyStr = \"Hello World\";" - ], - "tests": [ - "assert(myStr === \"Hello World\", 'message: myStr should have a value of Hello World');", - "assert(/myStr = \"Jello World\"/.test(code), 'message: Do not change the code above the line');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Comprender la inmutabilidad de cadenas", - "description": [ - "En JavaScript, los valores de las Cadenas son inmutables, lo cual significa que ellos no pueden ser alterados una vez creados.", - "Por ejemplo, el siguiente código:", - "
var miCad = \"Bob\";
myCad[0] = \"J\";
", - "no puede cambiar el valor de miCad a \"Job\" porque el contenido de miCad no puede ser alterado. Nota que esto no significa que miCad no puede ser cambiado, solo que los valores individuales de una cadena literal no pueden ser cambiados. La única manera de cambiar miCad sería asignandola a una nueva cadena, como esta:", - "
var miCad = \"Bob\";
miCad = \"Job\";
", - "

Instrucciones

", - "Corrige la asignación de myStr para lograr el efecto deseado." - ] - } - } - }, - { - "id": "bd7123c9c450eddfaeb5bdef", - "title": "Use Bracket Notation to Find the Nth Character in a String", - "description": [ - "You can also use bracket notation to get the character at other positions within a string.", - "Remember that computers start counting at 0, so the first character is actually the zeroth character.", - "
", - "Let's try to set thirdLetterOfLastName to equal the third letter of the lastName variable using bracket notation.", - "Hint
Try looking at the secondLetterOfFirstName variable declaration if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var firstName = \"Ada\";", - "var secondLetterOfFirstName = firstName[1];", - "", - "// Setup", - "var lastName = \"Lovelace\";", - "", - "// Only change code below this line.", - "var thirdLetterOfLastName = lastName;", - "", - "" - ], - "tail": [ - "(function(v){return v;})(thirdLetterOfLastName);" - ], - "solutions": [ - "var lastName = \"Lovelace\";\nvar thirdLetterOfLastName = lastName[2];" - ], - "tests": [ - "assert(thirdLetterOfLastName === 'v', 'message: The thirdLetterOfLastName variable should have the value of v.');", - "assert(code.match(/thirdLetterOfLastName\\s*?=\\s*?lastName\\[.*?\\]/), 'message: You should use bracket notation.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usar la notación de corchetes para encontrar el n-ésimo caracter en una cadena", - "description": [ - "También puede usar notación de corchetes para obtener el caracter en otras posiciones dentro de una cadena.", - "Recuerda que los computadores empiezan a contar a 0, por lo que el primer caracter es en realidad el caracter cero.", - "

Instrucciones

", - "Vamos a tratar de asignar a thirdLetterOfLastName la tercera letra de la variable lastName.", - "Pista
Si te atascas intenta mirar la declaración de la variable secondLetterOfFirstName." - ] - } - } - }, - { - "id": "bd7123c9c451eddfaeb5bdef", - "title": "Use Bracket Notation to Find the Last Character in a String", - "description": [ - "In order to get the last letter of a string, you can subtract one from the string's length.", - "For example, if var firstName = \"Charles\", you can get the value of the last letter of the string by using firstName[firstName.length - 1].", - "
", - "Use bracket notation to find the last character in the lastName variable.", - "Hint
Try looking at the lastLetterOfFirstName variable declaration if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var firstName = \"Ada\";", - "var lastLetterOfFirstName = firstName[firstName.length - 1];", - "", - "// Setup", - "var lastName = \"Lovelace\";", - "", - "// Only change code below this line.", - "var lastLetterOfLastName = lastName;", - "", - "" - ], - "tail": [ - "(function(v){return v;})(lastLetterOfLastName);" - ], - "solutions": [ - "var firstName = \"Ada\";\nvar lastLetterOfFirstName = firstName[firstName.length - 1];\n\nvar lastName = \"Lovelace\";\nvar lastLetterOfLastName = lastName[lastName.length - 1];" - ], - "tests": [ - "assert(lastLetterOfLastName === \"e\", 'message: lastLetterOfLastName should be \"e\".');", - "assert(code.match(/\\.length/g).length === 2, 'message: You have to use .length to get the last letter.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usa notación de corchetes para encontrar el último caracter de una cadena", - "description": [ - "Con el fin de conseguir la última letra de una cadena, puedes restar uno a la longitud de la cadena.", - "Por ejemplo, si var firstName = \"Charles\", se puede obtener la última letra usando firstName[firstName.length - 1]. ", - "

Instrucciones

", - "Utiliza notación de corchetes para encontrar el último caracter de la variabel lastName.", - "Si te atascas intenta mirando la declaración de la variable lastLetterOfFirstName." - ] - } - } - }, - { - "id": "bd7123c9c452eddfaeb5bdef", - "title": "Use Bracket Notation to Find the Nth-to-Last Character in a String", - "description": [ - "You can use the same principle we just used to retrieve the last character in a string to retrieve the Nth-to-last character.", - "For example, you can get the value of the third-to-last letter of the var firstName = \"Charles\" string by using firstName[firstName.length - 3]", - "
", - "Use bracket notation to find the second-to-last character in the lastName string.", - "Hint
Try looking at the thirdToLastLetterOfFirstName variable declaration if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var firstName = \"Ada\";", - "var thirdToLastLetterOfFirstName = firstName[firstName.length - 3];", - "", - "// Setup", - "var lastName = \"Lovelace\";", - "", - "// Only change code below this line", - "var secondToLastLetterOfLastName = lastName;", - "", - "" - ], - "tail": [ - "(function(v){return v;})(secondToLastLetterOfLastName);" - ], - "solutions": [ - "var firstName = \"Ada\";\nvar thirdToLastLetterOfFirstName = firstName[firstName.length - 3];\n\nvar lastName = \"Lovelace\";\nvar secondToLastLetterOfLastName = lastName[lastName.length - 2];" - ], - "tests": [ - "assert(secondToLastLetterOfLastName === 'c', 'message: secondToLastLetterOfLastName should be \"c\".');", - "assert(code.match(/\\.length/g).length === 2, 'message: You have to use .length to get the second last letter.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usa notación de corchetes para encontrar el n-ésimo último caracter de una cadena", - "description": [ - "Puede utilizar el mismo principio utilizamos para recuperar el último caracter de una cadena para recuperar el n-ésimo último caracter.", - "Por ejemplo, se puede obtener el valor de la tercera última letra de la cadena var firstName = \"Charles\" utilizando firstName[firstName.length - 3] ", - "

Instrucciones

", - "Usa notación de corchete para encontrar el segundo último caracter de la cadena en lastName.", - "Pista
Si te atascas intenta mirando la declaración de la variable thirdToLastLetterOfFirstName." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244bb", - "title": "Word Blanks", - "description": [ - "We will now use our knowledge of strings to build a \"Mad Libs\" style word game we're calling \"Word Blanks\". You will create an (optionally humorous) \"Fill in the Blanks\" style sentence. Here's an example of an incomplete sentence.", - "In a \"Mad Libs\" game, you are provided sentences with some missing words, like nouns, verbs, adjectives and adverbs. You then fill in the missing pieces with words of your choice in a way that the completed sentence makes sense.", - "Consider this sentence - \"It was really ____, and we ____ ourselves ____\". This sentence has three missing pieces- an adjective, a verb and an adverb, and we can add words of our choice to complete it. We can then assign the completed sentence to a variable as follows:", - "
var sentence = \"It was really\" + \"hot\" + \", and we\" + \"laughed\" + \"ourselves\" + \"silly.\";
", - "
", - "In this challenge, we provide you with a noun, a verb, an adjective and an adverb. You need to form a complete sentence using words of your choice, along with the words we provide.", - "You will need to use the string concatenation operator + to build a new string, using the provided variables: myNoun, myAdjective, myVerb, and myAdverb. You will then assign the formed string to the result variable.", - "You will also need to account for spaces in your string, so that the final sentence has spaces between all the words. The result should be a complete sentence." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function wordBlanks(myNoun, myAdjective, myVerb, myAdverb) {", - " // Your code below this line", - " var result = \"\";", - "", - " // Your code above this line", - " return result;", - "}", - "", - "// Change the words here to test your function", - "wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\");" - ], - "tail": [ - "var test1 = wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\");", - "var test2 = wordBlanks(\"cat\", \"little\", \"hit\", \"slowly\");" - ], - "solutions": [ - "function wordBlanks(myNoun, myAdjective, myVerb, myAdverb) {\n var result = \"\";\n\n result = \"Once there was a \" + myNoun + \" which was very \" + myAdjective + \". \";\n result += \"It \" + myVerb + \" \" + myAdverb + \" around the yard.\";\n\n return result;\n}" - ], - "tests": [ - "assert(typeof wordBlanks(\"\",\"\",\"\",\"\") === 'string', 'message: wordBlanks(\"\",\"\",\"\",\"\") should return a string.');", - "assert(/\\bdog\\b/.test(test1) && /\\bbig\\b/.test(test1) && /\\bran\\b/.test(test1) && /\\bquickly\\b/.test(test1),'message: wordBlanks(\"dog\", \"big\", \"ran\", \"quickly\") should contain all of the passed in words separated by non-word characters (and any additional words in your madlib).');", - "assert(/\\bcat\\b/.test(test2) && /\\blittle\\b/.test(test2) && /\\bhit\\b/.test(test2) && /\\bslowly\\b/.test(test2),'message: wordBlanks(\"cat\", \"little\", \"hit\", \"slowly\") should contain all of the passed in words separated by non-word characters (and any additional words in your madlib).');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Espacios en blanco de palabras", - "description": [ - "Ahora usaremos nuestro conocimiento de cadenas para construir un juego de palabras estilo \"Mad Libs\" que llamaremos \"Espacios en Blanco de Palabras\". Vas a crear unas oraciones estilo (opcionalmente graciosa) \"Llena los espacios en blanco\".", - "Necesitarás usar operadores de cadenas para construir una nueva cadena result, usando las variables previstas: myNoun, myAdjective, myVerb y myAdverb.", - "Además, necesitarás proporcionar cadenas adicionales, las cuales no cambiarán entre las palabras proporcionadas.", - "Nosotros hemos proporcionado un marco de referencia para probar tus resultados con diferentes palabras. La prueba correrá tu función con varias palabras diferentes para asegurarse que todas las palabras proporcionadas aparezcan en la salida, así como en tus cadenas adicionales." - ] - } - } - }, - { - "id": "bd7993c9c69feddfaeb8bdef", - "title": "Store Multiple Values in one Variable using JavaScript Arrays", - "description": [ - "With JavaScript array variables, we can store several pieces of data in one place.", - "You start an array declaration with an opening square bracket, end it with a closing square bracket, and put a comma between each entry, like this: ", - "var sandwich = [\"peanut butter\", \"jelly\", \"bread\"].", - "
", - "Modify the new array myArray so that it contains both a string and a number (in that order).", - "Hint
Refer to the example code in the text editor if you get stuck." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [\"John\", 23];", - "", - "// Only change code below this line.", - "var myArray = [];", - "" - ], - "tail": [ - "(function(z){return z;})(myArray);" - ], - "solutions": [ - "var myArray = [\"The Answer\", 42];" - ], - "tests": [ - "assert(typeof myArray == 'object', 'message: myArray should be an array.');", - "assert(typeof myArray[0] !== 'undefined' && typeof myArray[0] == 'string', 'message: The first item in myArray should be a string.');", - "assert(typeof myArray[1] !== 'undefined' && typeof myArray[1] == 'number', 'message: The second item in myArray should be a number.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Almacena múltiples valores en una variable utilizando vectores en JavaScript", - "description": [ - "Con las variables tipo vector (o en inglés array) podemos almacenar diversos datos en un solo lugar.", - "Empiezas la declaración de un vector con un corchete de apertura, y terminas con un corchete de cierre, y pones una coma entre cada entrada, así: var sandwich = [\"mantequilla de maní\", \"jalea\" , \"pan\"]. ", - "

Instrucciones

", - "Ahora vamos a crear un nuevo vector llamado myArray que contenga una cadena y un número (en ese orden).", - "Consulta el código comentado en el editor de texto si te atascas." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb7bdef", - "title": "Nest one Array within Another Array", - "description": [ - "You can also nest arrays within other arrays, like this: [[\"Bulls\", 23], [\"White Sox\", 45]]. This is also called a Multi-dimensional Array.", - "
", - "Create a nested array called myArray." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [[\"the universe\", 42], [\"everything\", 101010]];", - "", - "// Only change code below this line.", - "var myArray = [];", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var myArray = [[1,2,3]];" - ], - "tests": [ - "assert(Array.isArray(myArray) && myArray.some(Array.isArray), 'message: myArray should have at least one array nested within another array.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Anida un vector dentro de otro vector", - "description": [ - "También puedes anidar vectores dentro de otros vectores, como este: [[\"Bulls\", 23], [\"White Sox\", 45]].", - "

Instrucciones

", - "Ahora vamos a crear un vector anidado llamado myArray." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392ca", - "title": "Access Array Data with Indexes", - "description": [ - "We can access the data inside arrays using indexes.", - "Array indexes are written in the same bracket notation that strings use, except that instead of specifying a character, they are specifying an entry in the array. Like strings, arrays use zero-based indexing, so the first element in an array is element 0.", - "Example", - "
var array = [50,60,70];
array[0]; // equals 50
var data = array[1]; // equals 60
", - "Note
There shouldn't be any spaces between the array name and the square brackets, like array [0]. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.", - "
", - "Create a variable called myData and set it to equal the first value of myArray using bracket notation." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [50,60,70];", - "var ourData = ourArray[0]; // equals 50", - "", - "// Setup", - "var myArray = [50,60,70];", - "", - "// Only change code below this line.", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\" && typeof myData !== \"undefined\"){(function(y,z){return 'myArray = ' + JSON.stringify(y) + ', myData = ' + JSON.stringify(z);})(myArray, myData);}" - ], - "solutions": [ - "var myArray = [50,60,70];\nvar myData = myArray[0];" - ], - "tests": [ - "assert((function(){if(typeof myArray !== 'undefined' && typeof myData !== 'undefined' && myArray[0] === myData){return true;}else{return false;}})(), 'message: The variable myData should equal the first value of myArray.');", - "assert((function(){if(code.match(/\\s*=\\s*myArray\\[0\\]/g)){return true;}else{return false;}})(), 'message: The data in variable myArray should be accessed using bracket notation.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Accede a los datos de un vector mediante índices", - "description": [ - "Podemos acceder a los datos dentro de los vectores usando índices.", - "Los índices del vector se escriben en la misma notación con corchetes usado con cadenas, excepto que en lugar de especificar un caracter, especifican un elemento del vector.", - "Por ejemplo:", - "var array = [1,2,3];", - "array[0]; //es igual a 1", - "var data = array[1];", - "

Instrucciones

", - "Crea una variable llamada myData y asignale el primer valor del vector myArray." - ] - } - }, - "guideUrl": "https://guide.freecodecamp.org/certificates/access-array-data-with-indexes" - }, - { - "id": "cf1111c1c11feddfaeb8bdef", - "title": "Modify Array Data With Indexes", - "description": [ - "Unlike strings, the entries of arrays are mutable and can be changed freely.", - "Example", - "
var ourArray = [50,40,30];
ourArray[0] = 15; // equals [15,40,30]
", - "Note
There shouldn't be any spaces between the array name and the square brackets, like array [0]. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.", - "
", - "Modify the data stored at index 0 of myArray to a value of 45." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [18,64,99];", - "ourArray[1] = 45; // ourArray now equals [18,45,99].", - "", - "// Setup", - "var myArray = [18,64,99];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var myArray = [18,64,99];\nmyArray[0] = 45;" - ], - "tests": [ - "assert((function(){if(typeof myArray != 'undefined' && myArray[0] == 45 && myArray[1] == 64 && myArray[2] == 99){return true;}else{return false;}})(), 'message: myArray should now be [45,64,99].');", - "assert((function(){if(code.match(/myArray\\[0\\]\\s*=\\s*/g)){return true;}else{return false;}})(), 'message: You should be using correct index to modify the value in myArray.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Modifica datos de un vector usando índices", - "description": [ - "También podemos modificar los datos almacenados en vectores usando índices.", - "Por ejemplo:", - "var ourArray = [3,2,1];", - "ourArray[0] = 1; // equals [1,2,1]", - "

Instrucciones

", - "Ahora establece el dato almacenado en el índice 0 de myArray para que sea el valor 3." - ] - } - } - }, - { - "id": "56592a60ddddeae28f7aa8e1", - "title": "Access Multi-Dimensional Arrays With Indexes", - "description": [ - "One way to think of a multi-dimensional array, is as an array of arrays. When you use brackets to access your array, the first set of brackets refers to the entries in the outer-most (the first level) array, and each additional pair of brackets refers to the next level of entries inside.", - "Example", - "
var arr = [
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12], 13, 14]
];
arr[3]; // equals [[10,11,12], 13, 14]
arr[3][0]; // equals [10,11,12]
arr[3][0][1]; // equals 11
", - "Note
There shouldn't be any spaces between the array name and the square brackets, like array [0][0] and even this array [0] [0] is not allowed. Although JavaScript is able to process this correctly, this may confuse other programmers reading your code.", - "
", - "Using bracket notation select an element from myArray such that myData is equal to 8." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var myArray = [[1,2,3], [4,5,6], [7,8,9], [[10,11,12], 13, 14]];", - "", - "// Only change code below this line.", - "var myData = myArray[0][0];", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return \"myData: \" + myData + \" myArray: \" + JSON.stringify(myArray);})();}" - ], - "solutions": [ - "var myArray = [[1,2,3],[4,5,6], [7,8,9], [[10,11,12], 13, 14]];\nvar myData = myArray[2][1];" - ], - "tests": [ - "assert(myData === 8, 'message: myData should be equal to 8.');", - "assert(/myArray\\[2\\]\\[1\\]/g.test(code) && !/myData\\s*=\\s*(?:.*[-+*/%]|\\d)/g.test(code), 'message: You should be using bracket notation to read the correct value from myArray.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a vectores multi-dimensionales con índices", - "description": [ - "Una manera de pensar un vector multi-dimensional, es como un vector de vectores. Cuando usas corchetes para acceder a tu vector, el primer conjunto de brackets se refiere a las entradas en el vector más externo y cada nivel subsecuente de brackets se refiere al siguiente nivel de vectores internos.", - "Ejemplo", - "
var vec = [
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12], 13, 14]
];
vec[0]; // es igual [1,2,3]
vec[1][2]; // es igual 6
vec[3][0][1]; // es igual 11
", - "

Instrucciones

", - "Lee de myArray usando la notación corchete de modo que myData sea igual a 8" - ] - } - }, - "guideUrl": "https://guide.freecodecamp.org/certificates/access-array-data-with-indexes" - }, - { - "id": "56bbb991ad1ed5201cd392cb", - "title": "Manipulate Arrays With push()", - "description": [ - "An easy way to append data to the end of an array is via the push() function.", - ".push() takes one or more parameters and \"pushes\" them onto the end of the array.", - "
var arr = [1,2,3];
arr.push(4);
// arr is now [1,2,3,4]
", - "
", - "Push [\"dog\", 3] onto the end of the myArray variable." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [\"Stimpson\", \"J\", \"cat\"];", - "ourArray.push([\"happy\", \"joy\"]); ", - "// ourArray now equals [\"Stimpson\", \"J\", \"cat\", [\"happy\", \"joy\"]]", - "", - "// Setup", - "var myArray = [[\"John\", 23], [\"cat\", 2]];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "(function(z){return 'myArray = ' + JSON.stringify(z);})(myArray);" - ], - "solutions": [ - "var myArray = [[\"John\", 23], [\"cat\", 2]];\nmyArray.push([\"dog\",3]);" - ], - "tests": [ - "assert((function(d){if(d[2] != undefined && d[0][0] == 'John' && d[0][1] === 23 && d[2][0] == 'dog' && d[2][1] === 3 && d[2].length == 2){return true;}else{return false;}})(myArray), 'message: myArray should now equal [[\"John\", 23], [\"cat\", 2], [\"dog\", 3]].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Manipula vectores con push()", - "description": [ - "No sólo se pueden sacar datos del final de un vector con pop(), también puedes empujar (push()) datos al final del vector.", - "

Instrucciones

", - "Empuja [\"dog\", 3] al final de la variable myArray." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392cc", - "title": "Manipulate Arrays With pop()", - "description": [ - "Another way to change the data in an array is with the .pop() function.", - ".pop() is used to \"pop\" a value off of the end of an array. We can store this \"popped off\" value by assigning it to a variable. In other words, .pop() removes the last element from an array and returns that element.", - "Any type of entry can be \"popped\" off of an array - numbers, strings, even nested arrays.", - "
var threeArr = [1, 4, 6];
var oneDown = threeArr.pop();
console.log(oneDown); // Returns 6
console.log(threeArr); // Returns [1, 4]
", - "
", - "Use the .pop() function to remove the last item from myArray, assigning the \"popped off\" value to removedFromMyArray." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [1,2,3];", - "var removedFromOurArray = ourArray.pop(); ", - "// removedFromOurArray now equals 3, and ourArray now equals [1,2]", - "", - "// Setup", - "var myArray = [[\"John\", 23], [\"cat\", 2]];", - "", - "// Only change code below this line.", - "var removedFromMyArray;", - "", - "" - ], - "tail": [ - "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removedFromMyArray = ' + JSON.stringify(z);})(myArray, removedFromMyArray);" - ], - "solutions": [ - "var myArray = [[\"John\", 23], [\"cat\", 2]];\nvar removedFromMyArray = myArray.pop();" - ], - "tests": [ - "assert((function(d){if(d[0][0] == 'John' && d[0][1] === 23 && d[1] == undefined){return true;}else{return false;}})(myArray), 'message: myArray should only contain [[\"John\", 23]].');", - "assert(/removedFromMyArray\\s*=\\s*myArray\\s*.\\s*pop\\s*(\\s*)/.test(code), 'message: Use pop() on myArray');", - "assert((function(d){if(d[0] == 'cat' && d[1] === 2 && d[2] == undefined){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray should only contain [\"cat\", 2].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Manipula vectores con pop()", - "description": [ - "Otra forma de cambiar los datos en un vector es con la función .pop().", - ".pop() se utiliza para \"sacar\" el valor final de un vector. Podemos almacenar el valor \"sacado\" asignando pop a una variable por ejemplo durante su declaración.", - "Todo tipo de datos puede ser \"sacado\" de un vector --números, cadenas, incluso los vectores anidadas.", - "

Instrucciones

", - "Usa la función .pop() para sacar el último elemento de myArray y asigna ese valor \"sacado\" a removedFromMyArray ." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392cd", - "title": "Manipulate Arrays With shift()", - "description": [ - "pop() always removes the last element of an array. What if you want to remove the first?", - "That's where .shift() comes in. It works just like .pop(), except it removes the first element instead of the last.", - "
", - "Use the .shift() function to remove the first item from myArray, assigning the \"shifted off\" value to removedFromMyArray." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [\"Stimpson\", \"J\", [\"cat\"]];", - "removedFromOurArray = ourArray.shift();", - "// removedFromOurArray now equals \"Stimpson\" and ourArray now equals [\"J\", [\"cat\"]].", - "", - "// Setup", - "var myArray = [[\"John\", 23], [\"dog\", 3]];", - "", - "// Only change code below this line.", - "var removedFromMyArray;", - "", - "" - ], - "tail": [ - "(function(y, z){return 'myArray = ' + JSON.stringify(y) + ' & removedFromMyArray = ' + JSON.stringify(z);})(myArray, removedFromMyArray);" - ], - "solutions": [ - "var myArray = [[\"John\", 23], [\"dog\", 3]];\n\n// Only change code below this line.\nvar removedFromMyArray = myArray.shift();" - ], - "tests": [ - "assert((function(d){if(d[0][0] == 'dog' && d[0][1] === 3 && d[1] == undefined){return true;}else{return false;}})(myArray), 'message: myArray should now equal [[\"dog\", 3]].');", - "assert((function(d){if(d[0] == 'John' && d[1] === 23 && typeof removedFromMyArray === 'object'){return true;}else{return false;}})(removedFromMyArray), 'message: removedFromMyArray should contain [\"John\", 23].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Manipula vectores con shift()", - "description": [ - "pop() siempre elimina el último elemento de un vector. ¿Qué pasa si quieres quitar el primero?", - "Ahí es donde entra .shift(). Funciona igual que .pop (), excepto que elimina el primer elemento en lugar del pasado. ", - "

Instrucciones

", - "Usa la función .shift() para eliminar el primer elemento de myArray, y el elemento que saques asignalo a removedFromMyArra" - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392ce", - "title": "Manipulate Arrays With unshift()", - "description": [ - "Not only can you shift elements off of the beginning of an array, you can also unshift elements to the beginning of an array i.e. add elements in front of the array.", - ".unshift() works exactly like .push(), but instead of adding the element at the end of the array, unshift() adds the element at the beginning of the array.", - "
", - "Add [\"Paul\",35] to the beginning of the myArray variable using unshift()." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [\"Stimpson\", \"J\", \"cat\"];", - "ourArray.shift(); // ourArray now equals [\"J\", \"cat\"]", - "ourArray.unshift(\"Happy\"); ", - "// ourArray now equals [\"Happy\", \"J\", \"cat\"]", - "", - "// Setup", - "var myArray = [[\"John\", 23], [\"dog\", 3]];", - "myArray.shift();", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "(function(y, z){return 'myArray = ' + JSON.stringify(y);})(myArray);" - ], - "solutions": [ - "var myArray = [[\"John\", 23], [\"dog\", 3]];\nmyArray.shift();\nmyArray.unshift([\"Paul\", 35]);" - ], - "tests": [ - "assert((function(d){if(typeof d[0] === \"object\" && d[0][0] == 'Paul' && d[0][1] === 35 && d[1][0] != undefined && d[1][0] == 'dog' && d[1][1] != undefined && d[1][1] == 3){return true;}else{return false;}})(myArray), 'message: myArray should now have [[\"Paul\", 35], [\"dog\", 3]].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Manipula vectores con unshift()", - "description": [ - "No sólo se puedes correr (shift) elementos del comienzo de un vector, también puedes descorrerlos (unshift) al comienzo.", - "unshift() funciona exactamente igual que push(), pero en lugar de añadir el elemento al final del vector, unshift() añade el elemento al comienzo del vector. ", - "

Instrucciones

", - "Añade \"Paul\" al comienzo de la variable myArray usando unshift()." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244bc", - "title": "Shopping List", - "description": [ - "Create a shopping list in the variable myList. The list should be a multi-dimensional array containing several sub-arrays.", - "The first element in each sub-array should contain a string with the name of the item. The second element should be a number representing the quantity i.e.", - "[\"Chocolate Bar\", 15]", - "There should be at least 5 sub-arrays in the list." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myList = [];", - "", - "" - ], - "tail": [ - "var count = 0;", - "var isArray = false;", - "var hasString = false;", - "var hasNumber = false;", - "(function(list){", - " if(Array.isArray(myList)) {", - " isArray = true;", - " if(myList.length > 0) {", - " hasString = true;", - " hasNumber = true;", - " myList.forEach(function(elem) {", - " if(typeof elem[0] !== 'string') {", - " hasString = false;", - " }", - " if(typeof elem[1] !== 'number') {", - " hasNumber = false;", - " }", - " });", - " }", - " count = myList.length;", - " return JSON.stringify(myList);", - " } else {", - " return \"myList is not an array\";", - " }", - "", - "})(myList);" - ], - "solutions": [ - "var myList = [\n [\"Candy\", 10],\n [\"Potatoes\", 12],\n [\"Eggs\", 12],\n [\"Catfood\", 1],\n [\"Toads\", 9]\n];" - ], - "tests": [ - "assert(isArray, 'message: myList should be an array');", - "assert(hasString, 'message: The first elements in each of your sub-arrays must all be strings');", - "assert(hasNumber, 'message: The second elements in each of your sub-arrays must all be numbers');", - "assert(count > 4, 'message: You must have at least 5 items in your list');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Lista de compras", - "description": [ - "Crea una lista de compras en la variable myList. La lista tiene que ser un vector multidimensional conteniendo varios sub-vectores.", - "El primer elemento en cada sub-vector debe contener una cadena con el nombre del elemento. El segundo elemento debe ser un número representando la cantidad i. e.", - "[\"Barra de Chocolate\", 15]", - "Tiene que haber por lo menos 5 sub-vectores en la lista." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392cf", - "title": "Write Reusable JavaScript with Functions", - "description": [ - "In JavaScript, we can divide up our code into reusable parts called functions.", - "Here's an example of a function:", - "
function functionName() {
console.log(\"Hello World\");
}
", - "You can call or invoke this function by using its name followed by parentheses, like this:", - "functionName();", - "Each time the function is called it will print out the message \"Hello World\" on the dev console. All of the code between the curly braces will be executed every time the function is called.", - "
", - "
  1. Create a function called reusableFunction which prints \"Hi World\" to the dev console.
  2. Call the function.
" - ], - "head": [ - "var logOutput = \"\";", - "var originalConsole = console", - "function capture() {", - " var nativeLog = console.log;", - " console.log = function (message) {", - " if(message && message.trim) logOutput = message.trim();", - " if(nativeLog.apply) {", - " nativeLog.apply(originalConsole, arguments);", - " } else {", - " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", - " nativeLog(nativeMsg);", - " }", - " };", - "}", - "", - "function uncapture() {", - " console.log = originalConsole.log;", - "}", - "", - "capture();" - ], - "challengeSeed": [ - "// Example", - "function ourReusableFunction() {", - " console.log(\"Heyya, World\");", - "}", - "", - "ourReusableFunction();", - "", - "// Only change code below this line", - "" - ], - "tail": [ - "uncapture();", - "", - "if (typeof reusableFunction !== \"function\") { ", - " (function() { return \"reusableFunction is not defined\"; })();", - "} else {", - " (function() { return logOutput || \"console.log never called\"; })();", - "}" - ], - "solutions": [ - "function reusableFunction() {\n console.log(\"Hi World\");\n}\nreusableFunction();" - ], - "tests": [ - "assert(typeof reusableFunction === 'function', 'message: reusableFunction should be a function');", - "assert(\"Hi World\" === logOutput, 'message: reusableFunction should output \"Hi World\" to the dev console');", - "assert(/^\\s*reusableFunction\\(\\)\\s*;/m.test(code), 'message: Call reusableFunction after you define it');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Escribe código JavaScript reutilizable con funciones", - "description": [ - "En JavaScript, podemos dividir nuestro código en partes reutilizables llamadas funciones.", - "He aquí un ejemplo de una función:", - "function nombreDeFuncion(a, b) {", - "& nbsp; & nbsp; return a + b;", - "}", - "Después de escribir las líneas anteriores en nuestro código, podemos pasar valores a nuestra función y el resultado que sigue a la instrucción return será retornado.", - "Por ejemplo, podemos pasar los números 4 y 2 al \"llamar\" la función más adelante en nuestro código, así: nombreDeFuncion(4, 2). ", - "En este ejemplo, la función devolverá el número 6, ya que es el resultado de 4 + 2.", - "Crea y llama una función de nombre myFunction que devuelva la suma de a y b." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244bd", - "title": "Passing Values to Functions with Arguments", - "description": [ - "Parameters are variables that act as placeholders for the values that are to be input to a function when it is called. When a function is defined, it is typically defined along with one or more parameters. The actual values that are input (or \"passed\") into a function when it is called are known as arguments.", - "Here is a function with two parameters, param1 and param2:", - "
function testFun(param1, param2) {
console.log(param1, param2);
}
", - "Then we can call testFun:", - "testFun(\"Hello\", \"World\");", - "We have passed two arguments, \"Hello\" and \"World\". Inside the function, param1 will equal \"Hello\" and param2 will equal \"World\". Note that you could call testFun again with different arguments and the parameters would take on the value of the new arguments.", - "
", - "
  1. Create a function called functionWithArgs that accepts two arguments and outputs their sum to the dev console.
  2. Call the function with two numbers as arguments.
" - ], - "releasedOn": "January 1, 2016", - "head": [ - "var logOutput = \"\";", - "var originalConsole = console", - "function capture() {", - " var nativeLog = console.log;", - " console.log = function (message) {", - " if(message) logOutput = JSON.stringify(message).trim();", - " if(nativeLog.apply) {", - " nativeLog.apply(originalConsole, arguments);", - " } else {", - " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", - " nativeLog(nativeMsg);", - " }", - " };", - "}", - "", - "function uncapture() {", - " console.log = originalConsole.log;", - "}", - "", - "capture();" - ], - "challengeSeed": [ - "// Example", - "function ourFunctionWithArgs(a, b) {", - " console.log(a - b);", - "}", - "ourFunctionWithArgs(10, 5); // Outputs 5", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "uncapture();", - "", - "if (typeof functionWithArgs !== \"function\") { ", - " (function() { return \"functionWithArgs is not defined\"; })();", - "} else {", - " (function() { return logOutput || \"console.log never called\"; })();", - "}" - ], - "solutions": [ - "function functionWithArgs(a, b) {\n console.log(a + b);\n}\nfunctionWithArgs(10, 5);" - ], - "tests": [ - "assert(typeof functionWithArgs === 'function', 'message: functionWithArgs should be a function');", - "if(typeof functionWithArgs === \"function\") { capture(); functionWithArgs(1,2); uncapture(); } assert(logOutput == 3, 'message: functionWithArgs(1,2) should output 3');", - "if(typeof functionWithArgs === \"function\") { capture(); functionWithArgs(7,9); uncapture(); } assert(logOutput == 16, 'message: functionWithArgs(7,9) should output 16');", - "assert(/^\\s*functionWithArgs\\s*\\(\\s*\\d+\\s*,\\s*\\d+\\s*\\)\\s*;/m.test(code), 'message: Call functionWithArgs with two numbers after you define it.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Pasando valores a funciones con argumentos", - "description": [ - "Los parámetros son variables que actúan como marcadores de lugar para los valores que han de ser entrada para una función cuando esta es llamada. Cuando una función es definida, es típicamente definida con uno o más parámetros. Los valores actuales que son entrada (or \"pasados\") dentro de una función cuando esta es llamada son concidos como argumentos.", - "Aquí hay una función con dos parámetros, param1 y param2:", - "
function testFun(param1, param2) {
console.log(param1, param2);
}
", - "Entonces nosotros podemos llamar testFun:", - "testFun(\"Hello\", \"World\");", - "Nosotros hemos pasado dos argumentos, \"Hello\" y \"World\". Dentro de la función, param1 será igual a \"Hello\" y param2 será igual a \"World\". Nota que puedes llamar testFun otra vez con argumentos diferentes y los parámetros asumirían el valor de los nuevos argumentos.", - "

Instrucciones

", - "
  1. Crea una función llamada functionWithArgs que acepte dos argumentos y da salida a su suma en la consola.
  2. Llama la función.
" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244be", - "title": "Global Scope and Functions", - "description": [ - "In JavaScript, scope refers to the visibility of variables. Variables which are defined outside of a function block have Global scope. This means, they can be seen everywhere in your JavaScript code.", - "Variables which are used without the var keyword are automatically created in the global scope. This can create unintended consequences elsewhere in your code or when running a function again. You should always declare your variables with var.", - "
", - "Using var, declare a global variable myGlobal outside of any function. Initialize it with a value of 10.", - "Inside function fun1, assign 5 to oopsGlobal without using the var keyword." - ], - "releasedOn": "January 1, 2016", - "head": [ - "var logOutput = \"\";", - "var originalConsole = console", - "function capture() {", - " var nativeLog = console.log;", - " console.log = function (message) {", - " logOutput = message;", - " if(nativeLog.apply) {", - " nativeLog.apply(originalConsole, arguments);", - " } else {", - " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", - " nativeLog(nativeMsg);", - " }", - " };", - "}", - "", - "function uncapture() {", - " console.log = originalConsole.log;", - "}", - "var oopsGlobal;", - "capture();" - ], - "challengeSeed": [ - "// Declare your variable here", - "", - "", - "function fun1() {", - " // Assign 5 to oopsGlobal Here", - " ", - "}", - "", - "// Only change code above this line", - "function fun2() {", - " var output = \"\";", - " if (typeof myGlobal != \"undefined\") {", - " output += \"myGlobal: \" + myGlobal;", - " }", - " if (typeof oopsGlobal != \"undefined\") {", - " output += \" oopsGlobal: \" + oopsGlobal;", - " }", - " console.log(output);", - "}" - ], - "tail": [ - "fun1();", - "fun2();", - "uncapture();", - "(function() { return logOutput || \"console.log never called\"; })();" - ], - "solutions": [ - "// Declare your variable here\nvar myGlobal = 10;\n\nfunction fun1() {\n // Assign 5 to oopsGlobal Here\n oopsGlobal = 5;\n}\n\n// Only change code above this line\nfunction fun2() {\n var output = \"\";\n if(typeof myGlobal != \"undefined\") {\n output += \"myGlobal: \" + myGlobal;\n }\n if(typeof oopsGlobal != \"undefined\") {\n output += \" oopsGlobal: \" + oopsGlobal;\n }\n console.log(output);\n}" - ], - "tests": [ - "assert(typeof myGlobal != \"undefined\", 'message: myGlobal should be defined');", - "assert(myGlobal === 10, 'message: myGlobal should have a value of 10');", - "assert(/var\\s+myGlobal/.test(code), 'message: myGlobal should be declared using the var keyword');", - "assert(typeof oopsGlobal != \"undefined\" && oopsGlobal === 5, 'message: oopsGlobal should be a global variable and have a value of 5');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Alcance global y funciones", - "description": [ - "En JavaScript, alcance se referiere a la visibilidad de variables. Las variables que definas fuera de un bloque de una función tienen alcance Global. Esto significa que ellas pueden ser vistas en todas partes en tu código JavaScript.", - "Las variables que pueden ser usadas sin la palabra clave var son automáticamente creadas en el alcance global. Esto puede tener consecuencias no deseadas en otras partes de tu código o cuando se ejecuta una función de nuevo. Tu siempre deberías declarar tus variables con var.", - "

Instrucciones

", - "Declara a variable global myGlobal fuera de cualquier función. Inicializala para tener un valor de 10 ", - "Dentro de la función fun1, asigna 5 a oopsGlobal sin usar la palabra clave var." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244bf", - "title": "Local Scope and Functions", - "description": [ - "Variables which are declared within a function, as well as the function parameters have local scope. That means, they are only visible within that function.", - "Here is a function myTest with a local variable called loc.", - "
function myTest() {
var loc = \"foo\";
console.log(loc);
}
myTest(); // logs \"foo\"
console.log(loc); // loc is not defined
", - "loc is not defined outside of the function.", - "
", - "Declare a local variable myVar inside myLocalScope. Run the tests and then follow the instructions commented out in the editor.", - "Hint
Refreshing the page may help if you get stuck." - ], - "releasedOn": "January 1, 2016", - "head": [ - "var logOutput = \"\";", - "var originalConsole = console", - "function capture() {", - " var nativeLog = console.log;", - " console.log = function (message) {", - " logOutput = message;", - " if(nativeLog.apply) {", - " nativeLog.apply(originalConsole, arguments);", - " } else {", - " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", - " nativeLog(nativeMsg);", - " }", - " };", - "}", - "", - "function uncapture() {", - " console.log = originalConsole.log;", - "}", - "" - ], - "challengeSeed": [ - "function myLocalScope() {", - " 'use strict'; // you shouldn't need to edit this line", - " ", - " console.log(myVar);", - "}", - "myLocalScope();", - "", - "// Run and check the console", - "// myVar is not defined outside of myLocalScope", - "console.log(myVar);", - "", - "// Now remove the console log line to pass the test", - "" - ], - "tail": [ - "typeof myLocalScope === 'function' && (capture(), myLocalScope(), uncapture());", - "(function() { return logOutput || \"console.log never called\"; })();" - ], - "solutions": [ - "function myLocalScope() {\n 'use strict';\n \n var myVar;\n console.log(myVar);\n}\nmyLocalScope();" - ], - "tests": [ - "assert(typeof myVar === 'undefined', 'message: No global myVar variable');", - "assert(/var\\s+myVar/.test(code), 'message: Add a local myVar variable');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Alcance local y funciones", - "description": [ - "Las variables que son declaradas dentro de una función, así como los parámetros de la función tienen alcance local. Eso significa que solo son visibles dentro de esa función.", - "Aquí está una función myTest con una variable local llamada loc.", - "
function myTest() {
var loc = \"foo\";
console.log(loc);
}
myTest(); // \"foo\"
console.log(loc); // \"undefined\"
", - "loc no está definida fuera de la función.", - "

Instrucciones

", - "Declara una variable local myVar dentro de myLocalScope" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244c0", - "title": "Global vs. Local Scope in Functions", - "description": [ - "It is possible to have both local and global variables with the same name. When you do this, the local variable takes precedence over the global variable.", - "In this example:", - "
var someVar = \"Hat\";
function myFun() {
var someVar = \"Head\";
return someVar;
}
", - "The function myFun will return \"Head\" because the local version of the variable is present.", - "
", - "Add a local variable to myOutfit function to override the value of outerWear with \"sweater\"." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var outerWear = \"T-Shirt\";", - "", - "function myOutfit() {", - " // Only change code below this line", - " ", - " ", - " ", - " // Only change code above this line", - " return outerWear;", - "}", - "", - "myOutfit();" - ], - "solutions": [ - "var outerWear = \"T-Shirt\";\nfunction myOutfit() {\n var outerWear = \"sweater\";\n return outerWear;\n}" - ], - "tests": [ - "assert(outerWear === \"T-Shirt\", 'message: Do not change the value of the global outerWear');", - "assert(myOutfit() === \"sweater\", 'message: myOutfit should return \"sweater\"');", - "assert(/return outerWear/.test(code), 'message: Do not change the return statement');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Alcance global vs. local en funciones", - "description": [ - "Es posible tener variables locales y globales con el mismo nombre. Cuando tu haces esto, la variable local toma precedencia sobre la variable global.", - "En este ejemplo:", - "
var algunaVar = \"Sombrero\";
function miFun() {
var algunaVar = \"Cabeza\";
return algunaVar;
}
", - "La función miFun regresará \"Cabeza\" porque la versión local de la variable tiene precedencia.", - "

Instrucciones

", - "Agrega una variable local a myOutfit para sobreescribir el valor de outerWear con \"sweater\"." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244c2", - "title": "Return a Value from a Function with Return", - "description": [ - "We can pass values into a function with arguments. You can use a return statement to send a value back out of a function.", - "Example", - "
function plusThree(num) {
return num + 3;
}
var answer = plusThree(5); // 8
", - "plusThree takes an argument for num and returns a value equal to num + 3.", - "
", - "Create a function timesFive that accepts one argument, multiplies it by 5, and returns the new value. See the last line in the editor for an example of how you can test your timesFive function." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "function minusSeven(num) {", - " return num - 7;", - "}", - "", - "// Only change code below this line", - "", - "", - "", - "console.log(minusSeven(10));" - ], - "tail": [], - "solutions": [ - "function timesFive(num) {\n return num * 5;\n}\ntimesFive(10);" - ], - "tests": [ - "assert(typeof timesFive === 'function', 'message: timesFive should be a function');", - "assert(code.match(/timesFive\\(\\s*\\d+\\s*\\)/g), 'message: function timesFive should be called with a number');", - "assert(timesFive(5) === 25, 'message: timesFive(5) should return 25');", - "assert(timesFive(2) === 10, 'message: timesFive(2) should return 10');", - "assert(timesFive(0) === 0, 'message: timesFive(0) should return 0');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Retorna un valor desde una función con return", - "description": [ - "Podemos pasar valores a una función mediante los argumentos. Puedes usar una sentencia return para enviar un valor de vuelta de una función.", - "Ejemplo", - "
function masTres(num) {
return num + 3;
}
var respuesta = masTres(5); // 8
", - "masTres toma un argumento que es num y retorna un valor igual a num + 3.", - "

Instrucciones

", - "Crea una función timesFive que acepte un argumento, lo multiplique por 5 y retorne el nuevo valor." - ] - } - } - }, - { - "id": "598e8944f009e646fc236146", - "title": "Understanding Undefined Value returned from a Function", - "description": [ - "A function can include the return statement but it does not have to. In the case that the function doesn't have a return statement, when you call it, the function processes the inner code but the returned value is undefined.", - "Example", - "
var sum = 0;
function addSum(num) {
sum = sum + num;
}
var returnedValue = addSum(3); // sum will be modified but returned value is undefined
", - "addSum is a function without a return statement. The function will change the global sum variable but the returned value of the function is undefined", - "
", - "Create a function addFive without any arguments. This function adds 5 to the sum variable, but its returned value is undefined." - ], - "releasedOn": "August 11, 2017", - "challengeSeed": [ - "// Example", - "var sum = 0;", - "function addThree() {", - " sum = sum + 3;", - "}", - "", - "// Only change code below this line", - "", - "", - "", - "// Only change code above this line", - "var returnedValue = addFive();" - ], - "tail": [ - "var sum = 0;", - "function addThree() {sum = sum + 3;}", - "addThree();", - "addFive();" - ], - "solutions": [ - "function addFive() {\n sum = sum + 5;\n}" - ], - "tests": [ - "assert(typeof addFive === 'function', 'message: addFive should be a function');", - "assert(sum === 8, 'message: sum should be equal to 8');", - "assert(addFive() === undefined, 'message: Returned value from addFive should be undefined');", - "assert(code.match(/(sum\\s*\\=\\s*sum\\s*\\+\\s*5)|(sum\\s*\\+\\=\\s*5)/g).length === 1, 'message: Inside of your functions, add 5 to the sum variable');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "56533eb9ac21ba0edf2244c3", - "title": "Assignment with a Returned Value", - "description": [ - "If you'll recall from our discussion of Storing Values with the Assignment Operator, everything to the right of the equal sign is resolved before the value is assigned. This means we can take the return value of a function and assign it to a variable.", - "Assume we have pre-defined a function sum which adds two numbers together, then: ", - "ourSum = sum(5, 12);", - "will call sum function, which returns a value of 17 and assigns it to ourSum variable.", - "
", - "Call the processArg function with an argument of 7 and assign its return value to the variable processed." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var changed = 0;", - "", - "function change(num) {", - " return (num + 5) / 3;", - "}", - "", - "changed = change(10);", - "", - "// Setup", - "var processed = 0;", - "", - "function processArg(num) {", - " return (num + 3) / 5;", - "}", - "", - "// Only change code below this line", - "", - "" - ], - "tail": [ - "(function(){return \"processed = \" + processed})();" - ], - "solutions": [ - "var processed = 0;\n\nfunction processArg(num) {\n return (num + 3) / 5;\n}\n\nprocessed = processArg(7);" - ], - "tests": [ - "assert(processed === 2, 'message: processed should have a value of 2');", - "assert(/processed\\s*=\\s*processArg\\(\\s*7\\s*\\)\\s*;/.test(code), 'message: You should assign processArg to processed');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Asignación con un valor retornado", - "description": [ - "Si recuerdas de nuestra discusión de Almacenar Valores con el Operador Igual, todo a la derecha del signo igual es resuelto antes que el valor sea asignado. Esto significa que nosotros podemos tomar el valor de retorno de una función y asignarlo a una variable.", - "Supongamos que tenemos una función pre-definida suma la cual suma dos números, entonces: ", - "nuestraSuma = suma(5, 12);", - "llamará la función suma, la cual retornará un valor de 17 y lo asignará a la variable nuestraSuma.", - "

Instrucciones

", - "Llama la función processArg con un argumento 7 y asigna su valor de retorno a la variable processed." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/assignment-with-a-returned-value" - }, - { - "id": "56533eb9ac21ba0edf2244c6", - "title": "Stand in Line", - "description": [ - "In Computer Science a queue is an abstract Data Structure where items are kept in order. New items can be added at the back of the queue and old items are taken off from the front of the queue.", - "Write a function nextInLine which takes an array (arr) and a number (item) as arguments.", - "Add the number to the end of the array, then remove the first element of the array.", - "The nextInLine function should then return the element that was removed." - ], - "releasedOn": "January 1, 2016", - "head": [ - "var logOutput = [];", - "var originalConsole = console", - "function capture() {", - " var nativeLog = console.log;", - " console.log = function (message) {", - " logOutput.push(message);", - " if(nativeLog.apply) {", - " nativeLog.apply(originalConsole, arguments);", - " } else {", - " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", - " nativeLog(nativeMsg);", - " }", - " };", - "}", - "", - "function uncapture() {", - " console.log = originalConsole.log;", - "}", - "", - "capture();" - ], - "challengeSeed": [ - "function nextInLine(arr, item) {", - " // Your code here", - " ", - " return item; // Change this line", - "}", - "", - "// Test Setup", - "var testArr = [1,2,3,4,5];", - "", - "// Display Code", - "console.log(\"Before: \" + JSON.stringify(testArr));", - "console.log(nextInLine(testArr, 6)); // Modify this line to test", - "console.log(\"After: \" + JSON.stringify(testArr));" - ], - "tail": [ - "uncapture();", - "testArr = [1,2,3,4,5];", - "(function() { return logOutput.join(\"\\n\");})();" - ], - "solutions": [ - "var testArr = [ 1,2,3,4,5];\n\nfunction nextInLine(arr, item) {\n arr.push(item);\n return arr.shift();\n}" - ], - "tests": [ - "assert.isNumber(nextInLine([],5), 'message: nextInLine([], 5) should return a number.');", - "assert(nextInLine([],1) === 1, 'message: nextInLine([], 1) should return 1');", - "assert(nextInLine([2],1) === 2, 'message: nextInLine([2], 1) should return 2');", - "assert(nextInLine([5,6,7,8,9],1) === 5, 'message: nextInLine([5,6,7,8,9], 1) should return 5');", - "nextInLine(testArr, 10); assert(testArr[4] === 10, 'message: After nextInLine(testArr, 10), testArr[4] should be 10');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Hacer cola", - "description": [ - "En Ciencias de la Computación una cola es una Estructura de Datos abstracta donde los elementos son mantenidos en orden. Nuevos elementos pueden ser agregados en la parte trasera de la cola y los elementos viejos son quitados desde el frente de la cola.", - "Escribe una función nextInLine la cual toma un vector (arr) y un número (item) como argumentos. Agrega el número al final del vector, entonces retira el primer elemento del vector. La función nextInLine debe entonces devolver el elemento que se ha eliminado." - ] - } - } - }, - { - "id": "bd7123c9c441eddfaeb5bdef", - "title": "Understanding Boolean Values", - "description": [ - "Another data type is the Boolean. Booleans may only be one of two values: true or false. They are basically little on-off switches, where true is \"on\" and false is \"off.\" These two states are mutually exclusive.", - "Note
Boolean values are never written with quotes. The strings \"true\" and \"false\" are not Boolean and have no special meaning in JavaScript.", - "
", - "Modify the welcomeToBooleans function so that it returns true instead of false when the run button is clicked." - ], - "challengeSeed": [ - "function welcomeToBooleans() {", - "", - "// Only change code below this line.", - "", - "return false; // Change this line", - "", - "// Only change code above this line.", - "}" - ], - "tail": [ - "welcomeToBooleans();" - ], - "solutions": [ - "function welcomeToBooleans() {\n return true; // Change this line\n}" - ], - "tests": [ - "assert(typeof welcomeToBooleans() === 'boolean', 'message: The welcomeToBooleans() function should return a boolean (true/false) value.');", - "assert(welcomeToBooleans() === true, 'message: welcomeToBooleans() should return true.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Entiende los valores booleanos", - "description": [ - "En informática las estructuras de datos son cosas que contienen datos. JavaScript tiene siete de estas. Por ejemplo, la estructura de datos Número contiene números. ", - "Vamos a aprender acerca de la estructura de datos más básica de todas: el Boolean. Los booleanos sólo puede contener el valor verdadero o el valor falso. Son básicamente pequeños interruptores de encendido y apagado. ", - "

Instrucciones

", - "Vamos a modificar nuestra función welcomeToBooleans para que devuelva true en lugar de false cuando se pulse el botón de ejecución." - ] - } - } - }, - { - "id": "cf1111c1c12feddfaeb3bdef", - "title": "Use Conditional Logic with If Statements", - "description": [ - "If statements are used to make decisions in code. The keyword if tells JavaScript to execute the code in the curly braces under certain conditions, defined in the parentheses. These conditions are known as Boolean conditions and they may only be true or false.", - "When the condition evaluates to true, the program executes the statement inside the curly braces. When the Boolean condition evaluates to false, the statement inside the curly braces will not execute.", - "Pseudocode", - "
if (condition is true) {
statement is executed
}
", - "Example", - "
function test (myCondition) {
if (myCondition) {
return \"It was true\";
}
return \"It was false\";
}
test(true); // returns \"It was true\"
test(false); // returns \"It was false\"
", - "When test is called with a value of true, the if statement evaluates myCondition to see if it is true or not. Since it is true, the function returns \"It was true\". When we call test with a value of false, myCondition is not true and the statement in the curly braces is not executed and the function returns \"It was false\".", - "
", - "Create an if statement inside the function to return \"Yes, that was true\" if the parameter wasThatTrue is true and return \"No, that was false\" otherwise." - ], - "challengeSeed": [ - "// Example", - "function ourTrueOrFalse(isItTrue) {", - " if (isItTrue) { ", - " return \"Yes, it's true\";", - " }", - " return \"No, it's false\";", - "}", - "", - "// Setup", - "function trueOrFalse(wasThatTrue) {", - "", - " // Only change code below this line.", - " ", - " ", - " ", - " // Only change code above this line.", - "", - "}", - "", - "// Change this value to test", - "trueOrFalse(true);" - ], - "solutions": [ - "function trueOrFalse(wasThatTrue) {\n if (wasThatTrue) {\n return \"Yes, that was true\";\n }\n return \"No, that was false\";\n}" - ], - "tests": [ - "assert(typeof trueOrFalse === \"function\", 'message: trueOrFalse should be a function');", - "assert(typeof trueOrFalse(true) === \"string\", 'message: trueOrFalse(true) should return a string');", - "assert(typeof trueOrFalse(false) === \"string\", 'message: trueOrFalse(false) should return a string');", - "assert(trueOrFalse(true) === \"Yes, that was true\", 'message: trueOrFalse(true) should return \"Yes, that was true\"');", - "assert(trueOrFalse(false) === \"No, that was false\", 'message: trueOrFalse(false) should return \"No, that was false\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usa lógica condicional con instrucciones if y else", - "description": [ - "Podemos usar instrucciones if (\"if\" es \"si\" en español) en JavaScript para ejecutar código sólo cuando cierta condición se cumpla.", - "Las instrucciones if requieren evaluar algún tipo de condición booleana.", - "Por ejemplo:", - "if (1 === 2) {", - "  return true;", - "} else {", - "  return false;", - "}", - "Vamos a usar la instrucción if con else (\"else\" puede traducirse como \"de lo contrario\") para hacer un juego de cara o sello.", - "

Instrucciones

", - "Crea una instrucción if con else que retorne la cadena \"heads\" si la variable flip es cero, o bien que retorne \"tails\" si la variable flip no es cero. " - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d0", - "title": "Comparison with the Equality Operator", - "description": [ - "There are many Comparison Operators in JavaScript. All of these operators return a boolean true or false value.", - "The most basic operator is the equality operator ==. The equality operator compares two values and returns true if they're equivalent or false if they are not. Note that equality is different from assignment (=), which assigns the value at the right of the operator to a variable in the left.", - "
function equalityTest(myVal) {
if (myVal == 10) {
return \"Equal\";
}
return \"Not Equal\";
}
", - "If myVal is equal to 10, the equality operator returns true, so the code in the curly braces will execute, and the function will return \"Equal\". Otherwise, the function will return \"Not Equal\".", - "In order for JavaScript to compare two different data types (for example, numbers and strings), it must convert one type to another. This is known as \"Type Coercion\". Once it does, however, it can compare terms as follows:", - "
1 == 1 // true
1 == 2 // false
1 == '1' // true
\"3\" == 3 // true
", - "
", - "Add the equality operator to the indicated line so that the function will return \"Equal\" when val is equivalent to 12" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function testEqual(val) {", - " if (val) { // Change this line", - " return \"Equal\";", - " }", - " return \"Not Equal\";", - "}", - "", - "// Change this value to test", - "testEqual(10);" - ], - "solutions": [ - "function testEqual(val) {\n if (val == 12) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}" - ], - "tests": [ - "assert(testEqual(10) === \"Not Equal\", 'message: testEqual(10) should return \"Not Equal\"');", - "assert(testEqual(12) === \"Equal\", 'message: testEqual(12) should return \"Equal\"');", - "assert(testEqual(\"12\") === \"Equal\", 'message: testEqual(\"12\") should return \"Equal\"');", - "assert(code.match(/==/g) && !code.match(/===/g), 'message: You should use the == operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador de igualdad", - "description": [ - "Hay muchos Operadores de Comparación en JavaScript. Todos estos operadores retornan un valor booleano true(verdadero) o false(falso).", - "El operador más básico es el operador de igualdad ==. El operador de igualdad compara dos valores y retorna true si son equivalentes o false si no lo son. Nota que la igualdad es diferente de la asignación (=), la cual asigna el valor a la derecha del operador a la variable en la izquierda.", - "
function pruebaIgualdad(miVal) {
if (miVal == 10) {
return \"Igual\";
}
return \"No Es Igual\";
}
", - "Si miVal es igual a 10, el operador de igualdad retornará true(verdadero), así el código entre llaves será ejecutado y la función retornará \"Equal\". De otra manera, la función retornará \"Not Equal\".", - "Para que JavaScript pueda comparar dos tipos de datos diferentes (por ejemplo, números y cadenas de texto), debe convertir un tipo a otro. Una vez que lo hace, sin embargo, puede comparar términos de la siguiente manera:", - "
1 == 1 // true
1 == 2 // false
1 == '1' // true
\"3\" == 3 // true
", - "

Instrucciones

", - "Agrega el operador de igualdad a la línea indicada de manera que la función retornará \"Equal\" cuando val sea equivalente a 12" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d1", - "title": "Comparison with the Strict Equality Operator", - "description": [ - "Strict equality (===) is the counterpart to the equality operator (==). However, unlike the equality operator, which attempts to convert both values being compared to a common type, the strict equality operator does not perform a type conversion.", - "If the values being compared have different types, they are considered unequal, and the strict equality operator will return false.", - "Examples", - "
3 === 3 // true
3 === '3' // false
", - "In the second example, 3 is a Number type and '3' is a String type.", - "
", - "Use the strict equality operator in the if statement so the function will return \"Equal\" when val is strictly equal to 7" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function testStrict(val) {", - " if (val) { // Change this line", - " return \"Equal\";", - " }", - " return \"Not Equal\";", - "}", - "", - "// Change this value to test", - "testStrict(10);" - ], - "solutions": [ - "function testStrict(val) {\n if (val === 7) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}" - ], - "tests": [ - "assert(testStrict(10) === \"Not Equal\", 'message: testStrict(10) should return \"Not Equal\"');", - "assert(testStrict(7) === \"Equal\", 'message: testStrict(7) should return \"Equal\"');", - "assert(testStrict(\"7\") === \"Not Equal\", 'message: testStrict(\"7\") should return \"Not Equal\"');", - "assert(code.match(/(val\\s*===\\s*\\d+)|(\\d+\\s*===\\s*val)/g).length > 0, 'message: You should use the === operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador de estricta igualdad", - "description": [ - "Igualdad estricta (===) es la contraparte del operador de igualdad (==). Diferente al operador de igualdad, igualdad estricta prueba los tipos de datos y el valor de los elementos comparados.", - "Ejemplos", - "
3 === 3 // true
3 === '3' // falso
", - "En el segundo ejemplo, 3 es de tipo Número y '3' es de tipo Cadena.", - "

Instrucciones

", - "Usa el operador de igualdad estricta en la sentencia if de manera que la función retorne \"Equal\" cuando val es estrictamente igual a 7" - ] - } - } - }, - { - "id": "599a789b454f2bbd91a3ff4d", - "title": "Practice comparing different values", - "description": [ - "In the last two challenges, we learned about the equality operator (==) and the strict equality operator (===). Let's do a quick review and practice using these operators some more.", - "If the values being compared are not of the same type, the equality operator will perform a type conversion, and then evaluate the values. However, the strict equalty operator will compare both the data type and value as-is, without converting one type to the other.", - "Examples", - "
3 == '3' // returns true because JavaScript performs type converstion from string to number
3 === '3' // returns false because the types are different and type conversion is not performed
", - "Note
In JavaScript, you can determine the type of a variable or a value with the typeof operator, as follows:", - "
typeof 3 // returns 'number'
typeof '3' // returns 'string'
", - "
", - "The compareEquality function in the editor compares two values using the equality operator. Modify the function so that it returns \"Equal\" only when the values are strictly equal." - ], - "releasedOn": "August 21, 2017", - "challengeSeed": [ - "// Setup", - "function compareEquality(a, b) {", - " if (a == b) { // Change this line", - " return \"Equal\";", - " }", - " return \"Not Equal\";", - "}", - "", - "// Change this value to test", - "compareEquality(10, \"10\");" - ], - "solutions": [ - "function compareEquality(a,b) {\n if (a === b) {\n return \"Equal\";\n }\n return \"Not Equal\";\n}" - ], - "tests": [ - "assert(compareEquality(10, \"10\") === \"Not Equal\", 'message: compareEquality(10, \"10\") should return \"Not Equal\"');", - "assert(compareEquality(\"20\", 20) === \"Not Equal\", 'message: compareEquality(\"20\", 20) should return \"Not Equal\"');", - "assert(code.match(/===/g), 'message: You should use the === operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "56533eb9ac21ba0edf2244d2", - "title": "Comparison with the Inequality Operator", - "description": [ - "The inequality operator (!=) is the opposite of the equality operator. It means \"Not Equal\" and returns false where equality would return true and vice versa. Like the equality operator, the inequality operator will convert data types of values while comparing.", - "Examples", - "
1 != 2 // true
1 != \"1\" // false
1 != '1' // false
1 != true // false
0 != false // false
", - "
", - "Add the inequality operator != in the if statement so that the function will return \"Not Equal\" when val is not equivalent to 99" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function testNotEqual(val) {", - " if (val) { // Change this line", - " return \"Not Equal\";", - " }", - " return \"Equal\";", - "}", - "", - "// Change this value to test", - "testNotEqual(10);" - ], - "solutions": [ - "function testNotEqual(val) {\n if (val != 99) {\n return \"Not Equal\";\n }\n return \"Equal\";\n}" - ], - "tests": [ - "assert(testNotEqual(99) === \"Equal\", 'message: testNotEqual(99) should return \"Equal\"');", - "assert(testNotEqual(\"99\") === \"Equal\", 'message: testNotEqual(\"99\") should return \"Equal\"');", - "assert(testNotEqual(12) === \"Not Equal\", 'message: testNotEqual(12) should return \"Not Equal\"');", - "assert(testNotEqual(\"12\") === \"Not Equal\", 'message: testNotEqual(\"12\") should return \"Not Equal\"');", - "assert(testNotEqual(\"bob\") === \"Not Equal\", 'message: testNotEqual(\"bob\") should return \"Not Equal\"');", - "assert(code.match(/(?!!==)!=/), 'message: You should use the != operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador de desigualdad", - "description": [ - "El operador de desigualdad (!=) es el opuesto al operador de igualdad. Esto significa \"No Igual a\" y retorna false cuando igualdad retornaría true y viceversa. Como el operador de igualdad, el operador de desigualdad convertirá tipos de datos mientras compara.", - "Ejemplos", - "
1 != 2 // true
1 != \"1\" // false
1 != '1' // false
1 != true // false
0 != false // false
", - "

Instrucciones

", - "Agrega el operador de desigualdad != en la sentencia if de manera que la función retorne \"Not Equal\" (No igual a) cuando val no es equivalente a 99" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d3", - "title": "Comparison with the Strict Inequality Operator", - "description": [ - "The strict inequality operator (!==) is the logical opposite of the strict equality operator. It means \"Strictly Not Equal\" and returns false where strict equality would return true and vice versa. Strict inequality will not convert data types.", - "Examples", - "
3 !== 3 // false
3 !== '3' // true
4 !== 3 // true
", - "
", - "Add the strict inequality operator to the if statement so the function will return \"Not Equal\" when val is not strictly equal to 17" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function testStrictNotEqual(val) {", - " // Only Change Code Below this Line", - " ", - " if (val) {", - "", - " // Only Change Code Above this Line", - "", - " return \"Not Equal\";", - " }", - " return \"Equal\";", - "}", - "", - "// Change this value to test", - "testStrictNotEqual(10);" - ], - "solutions": [ - "function testStrictNotEqual(val) {\n if (val !== 17) {\n return \"Not Equal\";\n }\n return \"Equal\";\n}" - ], - "MDNlinks": [ - "Strict Inequality Operator" - ], - "tests": [ - "assert(testStrictNotEqual(17) === \"Equal\", 'message: testStrictNotEqual(17) should return \"Equal\"');", - "assert(testStrictNotEqual(\"17\") === \"Not Equal\", 'message: testStrictNotEqual(\"17\") should return \"Not Equal\"');", - "assert(testStrictNotEqual(12) === \"Not Equal\", 'message: testStrictNotEqual(12) should return \"Not Equal\"');", - "assert(testStrictNotEqual(\"bob\") === \"Not Equal\", 'message: testStrictNotEqual(\"bob\") should return \"Not Equal\"');", - "assert(code.match(/(val\\s*!==\\s*\\d+)|(\\d+\\s*!==\\s*val)/g).length > 0, 'message: You should use the !== operator');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador de estricta desigualdad", - "description": [ - "El operador de estricta desigualdad (!==) es el opuesto al operador de estricta igualdad. Esto significa \"Estrictamente no Igual\" y retorna false(falso) donde igualdad estricta retornaría true(verdadero) y viceversa. Estricta desigualdad no convertirá tipos de datos.", - "Ejemplos", - "
3 !== 3 // false
3 !== '3' // true
4 !== 3 // true
", - "

Instrucciones

", - "Agrega el operador de estricta desigualdad a la sentencia if de manera que la función retorne \"Not Equal\" cuando val no es estrictamente igual a 17" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d4", - "title": "Comparison with the Greater Than Operator", - "description": [ - "The greater than operator (>) compares the values of two numbers. If the number to the left is greater than the number to the right, it returns true. Otherwise, it returns false.", - "Like the equality operator, greater than operator will convert data types of values while comparing.", - "Examples", - "
5 > 3 // true
7 > '3' // true
2 > 3 // false
'1' > 9 // false
", - "
", - "Add the greater than operator to the indicated lines so that the return statements make sense." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testGreaterThan(val) {", - " if (val) { // Change this line", - " return \"Over 100\";", - " }", - " ", - " if (val) { // Change this line", - " return \"Over 10\";", - " }", - "", - " return \"10 or Under\";", - "}", - "", - "// Change this value to test", - "testGreaterThan(10);" - ], - "solutions": [ - "function testGreaterThan(val) {\n if (val > 100) { // Change this line\n return \"Over 100\";\n }\n if (val > 10) { // Change this line\n return \"Over 10\";\n }\n return \"10 or Under\";\n}" - ], - "tests": [ - "assert(testGreaterThan(0) === \"10 or Under\", 'message: testGreaterThan(0) should return \"10 or Under\"');", - "assert(testGreaterThan(10) === \"10 or Under\", 'message: testGreaterThan(10) should return \"10 or Under\"');", - "assert(testGreaterThan(11) === \"Over 10\", 'message: testGreaterThan(11) should return \"Over 10\"');", - "assert(testGreaterThan(99) === \"Over 10\", 'message: testGreaterThan(99) should return \"Over 10\"');", - "assert(testGreaterThan(100) === \"Over 10\", 'message: testGreaterThan(100) should return \"Over 10\"');", - "assert(testGreaterThan(101) === \"Over 100\", 'message: testGreaterThan(101) should return \"Over 100\"');", - "assert(testGreaterThan(150) === \"Over 100\", 'message: testGreaterThan(150) should return \"Over 100\"');", - "assert(code.match(/val\\s*>\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the > operator at least twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador mayor que", - "description": [ - "El operador mayor que (>) compara los valores de dos números. Si el número a la izquierda es mayor que el número a la derecha, este returna true(verdadero). De otra manera, este retorna false(falso).", - "Al igual que el operador de igualdad, el operador mayor que convertirá tipos de datos de valores mientras los compara.", - "Ejemplos", - "
5 > 3 // true
7 > '3' // true
2 > 3 // false
'1' > 9 // false
", - "

Instrucciones

", - "Agrega el operador mayor que para las líneas indicadas de manera que las sentencias retornadas tengan sentido." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d5", - "title": "Comparison with the Greater Than Or Equal To Operator", - "description": [ - "The greater than or equal to operator (>=) compares the values of two numbers. If the number to the left is greater than or equal to the number to the right, it returns true. Otherwise, it returns false.", - "Like the equality operator, greater than or equal to operator will convert data types while comparing.", - "Examples", - "
6 >= 6 // true
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // false
", - "
", - "Add the greater than or equal to operator to the indicated lines so that the return statements make sense." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testGreaterOrEqual(val) {", - " if (val) { // Change this line", - " return \"20 or Over\";", - " }", - " ", - " if (val) { // Change this line", - " return \"10 or Over\";", - " }", - "", - " return \"Less than 10\";", - "}", - "", - "// Change this value to test", - "testGreaterOrEqual(10);" - ], - "solutions": [ - "function testGreaterOrEqual(val) {\n if (val >= 20) { // Change this line\n return \"20 or Over\";\n }\n \n if (val >= 10) { // Change this line\n return \"10 or Over\";\n }\n\n return \"Less than 10\";\n}" - ], - "tests": [ - "assert(testGreaterOrEqual(0) === \"Less than 10\", 'message: testGreaterOrEqual(0) should return \"Less than 10\"');", - "assert(testGreaterOrEqual(9) === \"Less than 10\", 'message: testGreaterOrEqual(9) should return \"Less than 10\"');", - "assert(testGreaterOrEqual(10) === \"10 or Over\", 'message: testGreaterOrEqual(10) should return \"10 or Over\"');", - "assert(testGreaterOrEqual(11) === \"10 or Over\", 'message: testGreaterOrEqual(11) should return \"10 or Over\"');", - "assert(testGreaterOrEqual(19) === \"10 or Over\", 'message: testGreaterOrEqual(19) should return \"10 or Over\"');", - "assert(testGreaterOrEqual(100) === \"20 or Over\", 'message: testGreaterOrEqual(100) should return \"20 or Over\"');", - "assert(testGreaterOrEqual(21) === \"20 or Over\", 'message: testGreaterOrEqual(21) should return \"20 or Over\"');", - "assert(code.match(/val\\s*>=\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the >= operator at least twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador mayor o ogual", - "description": [ - "El operador mayor o igual (>=) compara los valores de dos números. Si el número de la izquierda es mayor o igual a el número de la derecha, este retorna true(verdadero). De otra manera, este retorna false(falso).", - "Como el operador de igualdad, el operador mayor o igual convertirá tipos de datos mientras está comparando.", - "Ejemplos", - "
6 >= 6 // true
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // false
", - "

Instrucciones

", - "Agrega el operador mayor o igual a las líneas indicadas de manera que las sentencias de retorno tengan sentido." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d6", - "title": "Comparison with the Less Than Operator", - "description": [ - "The less than operator (<) compares the values of two numbers. If the number to the left is less than the number to the right, it returns true. Otherwise, it returns false. Like the equality operator, less than operator converts data types while comparing.", - "Examples", - "
2 < 5 // true
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // false
", - "
", - "Add the less than operator to the indicated lines so that the return statements make sense." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testLessThan(val) {", - " if (val) { // Change this line", - " return \"Under 25\";", - " }", - " ", - " if (val) { // Change this line", - " return \"Under 55\";", - " }", - "", - " return \"55 or Over\";", - "}", - "", - "// Change this value to test", - "testLessThan(10);" - ], - "solutions": [ - "function testLessThan(val) {\n if (val < 25) { // Change this line\n return \"Under 25\";\n }\n \n if (val < 55) { // Change this line\n return \"Under 55\";\n }\n\n return \"55 or Over\";\n}" - ], - "tests": [ - "assert(testLessThan(0) === \"Under 25\", 'message: testLessThan(0) should return \"Under 25\"');", - "assert(testLessThan(24) === \"Under 25\", 'message: testLessThan(24) should return \"Under 25\"');", - "assert(testLessThan(25) === \"Under 55\", 'message: testLessThan(25) should return \"Under 55\"');", - "assert(testLessThan(54) === \"Under 55\", 'message: testLessThan(54) should return \"Under 55\"');", - "assert(testLessThan(55) === \"55 or Over\", 'message: testLessThan(55) should return \"55 or Over\"');", - "assert(testLessThan(99) === \"55 or Over\", 'message: testLessThan(99) should return \"55 or Over\"');", - "assert(code.match(/val\\s*<\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the < operator at least twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador menor que", - "description": [ - "El operador menor que (<) compara los valores de dos números. Si el número a la izquierda es menor que el número de la derecha, este retorna true(verdadero). De otra manera, este retorna false(falso). Como el operador de igualdad, el operador menor que convierte tipos de datos mientra compara.", - "Ejemplos", - "
2 < 5 // true
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // false
", - "

Instrucciones

", - "Agregar el operador menor que a las líneas indicadas de modo que las sentencias de retorno tengan sentido." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d7", - "title": "Comparison with the Less Than Or Equal To Operator", - "description": [ - "The less than or equal to operator (<=) compares the values of two numbers. If the number to the left is less than or equal to the number to the right, it returns true. If the number on the left is greater than the number on the right, it returns false. Like the equality operator, less than or equal to converts data types.", - "Examples", - "
4 <= 5 // true
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // false
", - "
", - "Add the less than or equal to operator to the indicated lines so that the return statements make sense." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testLessOrEqual(val) {", - " if (val) { // Change this line", - " return \"Smaller Than or Equal to 12\";", - " }", - " ", - " if (val) { // Change this line", - " return \"Smaller Than or Equal to 24\";", - " }", - "", - " return \"More Than 24\";", - "}", - "", - "// Change this value to test", - "testLessOrEqual(10);", - "" - ], - "solutions": [ - "function testLessOrEqual(val) {\n if (val <= 12) { // Change this line\n return \"Smaller Than or Equal to 12\";\n }\n \n if (val <= 24) { // Change this line\n return \"Smaller Than or Equal to 24\";\n }\n\n return \"More Than 24\";\n}" - ], - "tests": [ - "assert(testLessOrEqual(0) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(0) should return \"Smaller Than or Equal to 12\"');", - "assert(testLessOrEqual(11) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(11) should return \"Smaller Than or Equal to 12\"');", - "assert(testLessOrEqual(12) === \"Smaller Than or Equal to 12\", 'message: testLessOrEqual(12) should return \"Smaller Than or Equal to 12\"');", - "assert(testLessOrEqual(23) === \"Smaller Than or Equal to 24\", 'message: testLessOrEqual(23) should return \"Smaller Than or Equal to 24\"');", - "assert(testLessOrEqual(24) === \"Smaller Than or Equal to 24\", 'message: testLessOrEqual(24) should return \"Smaller Than or Equal to 24\"');", - "assert(testLessOrEqual(25) === \"More Than 24\", 'message: testLessOrEqual(25) should return \"More Than 24\"');", - "assert(testLessOrEqual(55) === \"More Than 24\", 'message: testLessOrEqual(55) should return \"More Than 24\"');", - "assert(code.match(/val\\s*<=\\s*('|\")*\\d+('|\")*/g).length > 1, 'message: You should use the <= operator at least twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador menor o igual", - "description": [ - "El operador menor o igual (<=) compara los valores de dos números. Si el número a la izquierda es menor o igual que el número de la derecha, este retorna true(verdadero). Si el número a la izquierda es mayor que el número de la derecha, este retorna false(falso). Al igual que el operador de igualdad, menor o igual convierte tipos de datos.", - "Ejemplos", - "
4 <= 5 // true
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // false
", - "

Instrucciones

", - "Agrega el operador menor o igual a las líneas indicadas de modo que las sentencias de retorno tengan sentido." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d8", - "title": "Comparisons with the Logical And Operator", - "description": [ - "Sometimes you will need to test more than one thing at a time. The logical and operator (&&) returns true if and only if the operands to the left and right of it are true.", - "The same effect could be achieved by nesting an if statement inside another if:", - "
if (num > 5) {
if (num < 10) {
return \"Yes\";
}
}
return \"No\";
", - "will only return \"Yes\" if num is greater than 5 and less than 10. The same logic can be written as:", - "
if (num > 5 && num < 10) {
return \"Yes\";
}
return \"No\";
", - "
", - "Combine the two if statements into one statement which will return \"Yes\" if val is less than or equal to 50 and greater than or equal to 25. Otherwise, will return \"No\"." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testLogicalAnd(val) {", - " // Only change code below this line", - "", - " if (val) {", - " if (val) {", - " return \"Yes\";", - " }", - " }", - "", - " // Only change code above this line", - " return \"No\";", - "}", - "", - "// Change this value to test", - "testLogicalAnd(10);" - ], - "solutions": [ - "function testLogicalAnd(val) {\n if (val >= 25 && val <= 50) {\n return \"Yes\";\n }\n return \"No\";\n}" - ], - "tests": [ - "assert(code.match(/&&/g).length === 1, 'message: You should use the && operator once');", - "assert(code.match(/if/g).length === 1, 'message: You should only have one if statement');", - "assert(testLogicalAnd(0) === \"No\", 'message: testLogicalAnd(0) should return \"No\"');", - "assert(testLogicalAnd(24) === \"No\", 'message: testLogicalAnd(24) should return \"No\"');", - "assert(testLogicalAnd(25) === \"Yes\", 'message: testLogicalAnd(25) should return \"Yes\"');", - "assert(testLogicalAnd(30) === \"Yes\", 'message: testLogicalAnd(30) should return \"Yes\"');", - "assert(testLogicalAnd(50) === \"Yes\", 'message: testLogicalAnd(50) should return \"Yes\"');", - "assert(testLogicalAnd(51) === \"No\", 'message: testLogicalAnd(51) should return \"No\"');", - "assert(testLogicalAnd(75) === \"No\", 'message: testLogicalAnd(75) should return \"No\"');", - "assert(testLogicalAnd(80) === \"No\", 'message: testLogicalAnd(80) should return \"No\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador lógico y", - "description": [ - "A veces necesitarás probar más de una cosa a la vez. El operador lógico y (&&) retorna true(verdadero) si y solo si los operandos a la izquierda y derecha de este son verdaderos.", - "El mismo efecto podría lograrse anidando una sentencia if dentro de otro if:", - "
if (num > 5) {
if (num < 10) {
return \"Yes\";
}
}
return \"No\";
", - "solo retornará \"Yes\" si num está entre 6 y 9 (6 y 9 incluidos). La misma lógica puede ser escrita como:", - "
if (num > 5 && num < 10) {
return \"Yes\";
}
return \"No\";
", - "

Instrucciones

", - "Combina las dos sentencias if dentro de una sentencia la cual retornará \"Yes\" si val es menor o igual a 50 y mayor o igual a 25. De otra manera, retornará \"No\"." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244d9", - "title": "Comparisons with the Logical Or Operator", - "description": [ - "The logical or operator (||) returns true if either of the operands is true. Otherwise, it returns false.", - "The logical or operator is composed of two pipe symbols (|). This can typically be found between your Backspace and Enter keys.", - "The pattern below should look familiar from prior waypoints:", - "
if (num > 10) {
return \"No\";
}
if (num < 5) {
return \"No\";
}
return \"Yes\";
", - "will return \"Yes\" only if num is between 5 and 10 (5 and 10 included). The same logic can be written as:", - "
if (num > 10 || num < 5) {
return \"No\";
}
return \"Yes\";
", - "
", - "Combine the two if statements into one statement which returns \"Outside\" if val is not between 10 and 20, inclusive. Otherwise, return \"Inside\"." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testLogicalOr(val) {", - " // Only change code below this line", - "", - " if (val) {", - " return \"Outside\";", - " }", - "", - " if (val) {", - " return \"Outside\";", - " }", - "", - " // Only change code above this line", - " return \"Inside\";", - "}", - "", - "// Change this value to test", - "testLogicalOr(15);" - ], - "solutions": [ - "function testLogicalOr(val) {\n if (val < 10 || val > 20) {\n return \"Outside\";\n }\n return \"Inside\";\n}" - ], - "tests": [ - "assert(code.match(/\\|\\|/g).length === 1, 'message: You should use the || operator once');", - "assert(code.match(/if/g).length === 1, 'message: You should only have one if statement');", - "assert(testLogicalOr(0) === \"Outside\", 'message: testLogicalOr(0) should return \"Outside\"');", - "assert(testLogicalOr(9) === \"Outside\", 'message: testLogicalOr(9) should return \"Outside\"');", - "assert(testLogicalOr(10) === \"Inside\", 'message: testLogicalOr(10) should return \"Inside\"');", - "assert(testLogicalOr(15) === \"Inside\", 'message: testLogicalOr(15) should return \"Inside\"');", - "assert(testLogicalOr(19) === \"Inside\", 'message: testLogicalOr(19) should return \"Inside\"');", - "assert(testLogicalOr(20) === \"Inside\", 'message: testLogicalOr(20) should return \"Inside\"');", - "assert(testLogicalOr(21) === \"Outside\", 'message: testLogicalOr(21) should return \"Outside\"');", - "assert(testLogicalOr(25) === \"Outside\", 'message: testLogicalOr(25) should return \"Outside\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "La comparación con el operador lógico o", - "description": [ - "El operador lógico o (||) retorna true(verdadero) si cualquiera de los operandos es true(verdadero). De otra manera, este retorna false(falso).", - "El patrón de abajo debería ser familiar de los puntos de referencia anteriores:", - "
if (num > 10) {
return \"No\";
}
if (num < 5) {
return \"No\";
}
return \"Yes\";
", - "retornará \"Yes\" solo si num está entre 5 y 10 (5 y 10 incluidos). La misma lógica puede ser escrita como:", - "
if (num > 10 || num < 5) {
return \"No\";
}
return \"Yes\";
", - "

Instrucciones

", - "Combina las dos sentencias if dentro de una sentencia la cual retorne \"Outside\" si val no está entre 10 y 20, inclusive. De otra manera, retorna \"Inside\"." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244da", - "title": "Introducing Else Statements", - "description": [ - "When a condition for an if statement is true, the block of code following it is executed. What about when that condition is false? Normally nothing would happen. With an else statement, an alternate block of code can be executed.", - "
if (num > 10) {
return \"Bigger than 10\";
} else {
return \"10 or Less\";
}
", - "
", - "Combine the if statements into a single if/else statement." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testElse(val) {", - " var result = \"\";", - " // Only change code below this line", - " ", - " if (val > 5) {", - " result = \"Bigger than 5\";", - " }", - " ", - " if (val <= 5) {", - " result = \"5 or Smaller\";", - " }", - " ", - " // Only change code above this line", - " return result;", - "}", - "", - "// Change this value to test", - "testElse(4);", - "" - ], - "solutions": [ - "function testElse(val) {\n var result = \"\";\n if(val > 5) {\n result = \"Bigger than 5\";\n } else {\n result = \"5 or Smaller\";\n }\n return result;\n}" - ], - "tests": [ - "assert(code.match(/if/g).length === 1, 'message: You should only have one if statement in the editor');", - "assert(/else/g.test(code), 'message: You should use an else statement');", - "assert(testElse(4) === \"5 or Smaller\", 'message: testElse(4) should return \"5 or Smaller\"');", - "assert(testElse(5) === \"5 or Smaller\", 'message: testElse(5) should return \"5 or Smaller\"');", - "assert(testElse(6) === \"Bigger than 5\", 'message: testElse(6) should return \"Bigger than 5\"');", - "assert(testElse(10) === \"Bigger than 5\", 'message: testElse(10) should return \"Bigger than 5\"');", - "assert(/var result = \"\";/.test(code) && /return result;/.test(code), 'message: Do not change the code above or below the lines.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Introducción de las sentencias else", - "description": [ - "Cuando una condición de una sentencia if es verdadera, el siguiente bloque de código es ejecutado. ¿Y cuando esa condición es falsa? Normalmente nada pasaría. Con una sentencia else(además), un bloque alternativo de código puede ser ejecutado.", - "
if (num > 10) {
return \"Más grande que 10\";
} else {
return \"10 o Menos\";
}
", - "

Instrucciones

", - "Combina las sentencias if dentro de una sola sentencia if/else." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244db", - "title": "Introducing Else If Statements", - "description": [ - "If you have multiple conditions that need to be addressed, you can chain if statements together with else if statements.", - "
if (num > 15) {
return \"Bigger than 15\";
} else if (num < 5) {
return \"Smaller than 5\";
} else {
return \"Between 5 and 15\";
}
", - "
", - "Convert the logic to use else if statements." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testElseIf(val) {", - " if (val > 10) {", - " return \"Greater than 10\";", - " }", - " ", - " if (val < 5) {", - " return \"Smaller than 5\";", - " }", - " ", - " return \"Between 5 and 10\";", - "}", - "", - "// Change this value to test", - "testElseIf(7);", - "" - ], - "solutions": [ - "function testElseIf(val) {\n if(val > 10) {\n return \"Greater than 10\";\n } else if(val < 5) {\n return \"Smaller than 5\";\n } else {\n return \"Between 5 and 10\";\n }\n}" - ], - "tests": [ - "assert(code.match(/else/g).length > 1, 'message: You should have at least two else statements');", - "assert(code.match(/if/g).length > 1, 'message: You should have at least two if statements');", - "assert(testElseIf(0) === \"Smaller than 5\", 'message: testElseIf(0) should return \"Smaller than 5\"');", - "assert(testElseIf(5) === \"Between 5 and 10\", 'message: testElseIf(5) should return \"Between 5 and 10\"');", - "assert(testElseIf(7) === \"Between 5 and 10\", 'message: testElseIf(7) should return \"Between 5 and 10\"');", - "assert(testElseIf(10) === \"Between 5 and 10\", 'message: testElseIf(10) should return \"Between 5 and 10\"');", - "assert(testElseIf(12) === \"Greater than 10\", 'message: testElseIf(12) should return \"Greater than 10\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Introducción de las sentencias else if", - "description": [ - "Si tienes múltiples condiciones que deben abordarse, puedes encadenar sentencias if juntas con sentencias else if.", - "
if (num > 15) {
return \"Más grande que 15\";
} else if (num < 5) {
return \"Más pequeño que 5\";
} else {
return \"Entre 5 y 15\";
}
", - "

Instrucciones

", - "Convierte la lógica para usar sentencias else if." - ] - } - } - }, - { - "id": "5690307fddb111c6084545d7", - "title": "Logical Order in If Else Statements", - "description": [ - "Order is important in if, else if statements.", - "The function is executed from top to bottom so you will want to be careful of what statement comes first.", - "Take these two functions as an example.", - "Here's the first:", - "
function foo(x) {
if (x < 1) {
return \"Less than one\";
} else if (x < 2) {
return \"Less than two\";
} else {
return \"Greater than or equal to two\";
}
}
", - "And the second just switches the order of the statements:", - "
function bar(x) {
if (x < 2) {
return \"Less than two\";
} else if (x < 1) {
return \"Less than one\";
} else {
return \"Greater than or equal to two\";
}
}
", - "While these two functions look nearly identical if we pass a number to both we get different outputs.", - "
foo(0) // \"Less than one\"
bar(0) // \"Less than two\"
", - "
", - "Change the order of logic in the function so that it will return the correct statements in all cases." - ], - "challengeSeed": [ - "function orderMyLogic(val) {", - " if (val < 10) {", - " return \"Less than 10\";", - " } else if (val < 5) {", - " return \"Less than 5\";", - " } else {", - " return \"Greater than or equal to 10\";", - " }", - "}", - "", - "// Change this value to test", - "orderMyLogic(7);" - ], - "solutions": [ - "function orderMyLogic(val) {\n if(val < 5) {\n return \"Less than 5\"; \n } else if (val < 10) {\n return \"Less than 10\";\n } else {\n return \"Greater than or equal to 10\";\n }\n}" - ], - "tests": [ - "assert(orderMyLogic(4) === \"Less than 5\", 'message: orderMyLogic(4) should return \"Less than 5\"');", - "assert(orderMyLogic(6) === \"Less than 10\", 'message: orderMyLogic(6) should return \"Less than 10\"');", - "assert(orderMyLogic(11) === \"Greater than or equal to 10\", 'message: orderMyLogic(11) should return \"Greater than or equal to 10\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Orden lógico en sentencias else if", - "description": [ - "El orden es importante en las sentencia if y else if.", - "El ciclo es ejecutado de arriba hacia abajo por lo que tendrás que ser cuidadoso de cual sentencia va primero.", - "Toma estas dos funciones como ejemplo.", - "Aquí está la primera:", - "
function foo(x) {
if (x < 1) {
return \"Menor que uno\";
} else if (x < 2) {
return \"Menor que dos\";
} else {
return \"Mayor o igual a dos\";
}
}
", - "Y el segundo solo cambia el orden de las sentencias:", - "
function bar(x) {
if (x < 2) {
return \"Menor que dos\";
} else if (x < 1) {
return \"Menor que uno\";
} else {
return \"Mayor o igual a dos\";
}
}
", - "Mientras esas dos funciones parecen casi idénticas, si nosotros pasamos un número a ambas obtendremos diferentes salidas.", - "
foo(0) // \"Menor que uno\"
bar(0) // \"Menor que dos\"
", - "

Instrucciones

", - "Cambia el orden de la lógica en la función de manera que esta retorne las sentencias correctas en todos los casos." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244dc", - "title": "Chaining If Else Statements", - "description": [ - "if/else statements can be chained together for complex logic. Here is pseudocode of multiple chained if / else if statements:", - "
if (condition1) {
statement1
} else if (condition2) {
statement2
} else if (condition3) {
statement3
. . .
} else {
statementN
}
", - "
", - "Write chained if/else if statements to fulfill the following conditions:", - "num < 5 - return \"Tiny\"
num < 10 - return \"Small\"
num < 15 - return \"Medium\"
num < 20 - return \"Large\"
num >= 20 - return \"Huge\"" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function testSize(num) {", - " // Only change code below this line", - " ", - " ", - " return \"Change Me\";", - " // Only change code above this line", - "}", - "", - "// Change this value to test", - "testSize(7);" - ], - "solutions": [ - "function testSize(num) {\n if (num < 5) {\n return \"Tiny\";\n } else if (num < 10) {\n return \"Small\";\n } else if (num < 15) {\n return \"Medium\";\n } else if (num < 20) {\n return \"Large\";\n } else {\n return \"Huge\";\n }\n}" - ], - "tests": [ - "assert(code.match(/else/g).length > 3, 'message: You should have at least four else statements');", - "assert(code.match(/if/g).length > 3, 'message: You should have at least four if statements');", - "assert(code.match(/return/g).length >= 1, 'message: You should have at least one return statement');", - "assert(testSize(0) === \"Tiny\", 'message: testSize(0) should return \"Tiny\"');", - "assert(testSize(4) === \"Tiny\", 'message: testSize(4) should return \"Tiny\"');", - "assert(testSize(5) === \"Small\", 'message: testSize(5) should return \"Small\"');", - "assert(testSize(8) === \"Small\", 'message: testSize(8) should return \"Small\"');", - "assert(testSize(10) === \"Medium\", 'message: testSize(10) should return \"Medium\"');", - "assert(testSize(14) === \"Medium\", 'message: testSize(14) should return \"Medium\"');", - "assert(testSize(15) === \"Large\", 'message: testSize(15) should return \"Large\"');", - "assert(testSize(17) === \"Large\", 'message: testSize(17) should return \"Large\"');", - "assert(testSize(20) === \"Huge\", 'message: testSize(20) should return \"Huge\"');", - "assert(testSize(25) === \"Huge\", 'message: testSize(25) should return \"Huge\"');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Encadenamiento de sentencias else if", - "description": [ - "Las sentencias if/else(si/de lo contrario) pueden ser encadenadas juntas por una lógica compleja. Aquí está el pseudocódigo de múltiples sentencias if / else if encadenadas:", - "
if (condicion1) {
sentencias1
} else if (condicion2) {
sentencias2
} else if (condicion3) {
sentencias3
. . .
} else {
sentenciasN
}
", - "

Instrucciones

", - "Escribe sentencias if/else if encadenadas para cumplir las siguientes condiciones:", - "num < 5 - retorna \"Tiny\"
num < 10 - retorna \"Small\"
num < 15 - retorna \"Medium\"
num < 20 - retorna \"Large\"
num >= 20 - retorna \"Huge\"" - ] - } - } - }, - { - "id": "5664820f61c48e80c9fa476c", - "title": "Golf Code", - "description": [ - "In the game of golf each hole has a par meaning the average number of strokes a golfer is expected to make in order to sink the ball in a hole to complete the play. Depending on how far above or below par your strokes are, there is a different nickname.", - "Your function will be passed par and strokes arguments. Return the correct string according to this table which lists the strokes in order of priority; top (highest) to bottom (lowest):", - "
StrokesReturn
1\"Hole-in-one!\"
<= par - 2\"Eagle\"
par - 1\"Birdie\"
par\"Par\"
par + 1\"Bogey\"
par + 2\"Double Bogey\"
>= par + 3\"Go Home!\"
", - "par and strokes will always be numeric and positive. We have added an array of all the names for your convenience." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var names = [\"Hole-in-one!\", \"Eagle\", \"Birdie\", \"Par\", \"Bogey\", \"Double Bogey\", \"Go Home!\"];", - "function golfScore(par, strokes) {", - " // Only change code below this line", - " ", - " ", - " return \"Change Me\";", - " // Only change code above this line", - "}", - "", - "// Change these values to test", - "golfScore(5, 4);" - ], - "solutions": [ - "function golfScore(par, strokes) {\n if (strokes === 1) {\n return \"Hole-in-one!\";\n }\n \n if (strokes <= par - 2) {\n return \"Eagle\";\n }\n \n if (strokes === par - 1) {\n return \"Birdie\";\n }\n \n if (strokes === par) {\n return \"Par\";\n }\n \n if (strokes === par + 1) {\n return \"Bogey\";\n }\n \n if(strokes === par + 2) {\n return \"Double Bogey\";\n }\n \n return \"Go Home!\";\n}" - ], - "tests": [ - "assert(golfScore(4, 1) === \"Hole-in-one!\", 'message: golfScore(4, 1) should return \"Hole-in-one!\"');", - "assert(golfScore(4, 2) === \"Eagle\", 'message: golfScore(4, 2) should return \"Eagle\"');", - "assert(golfScore(5, 2) === \"Eagle\", 'message: golfScore(5, 2) should return \"Eagle\"');", - "assert(golfScore(4, 3) === \"Birdie\", 'message: golfScore(4, 3) should return \"Birdie\"');", - "assert(golfScore(4, 4) === \"Par\", 'message: golfScore(4, 4) should return \"Par\"');", - "assert(golfScore(1, 1) === \"Hole-in-one!\", 'message: golfScore(1, 1) should return \"Hole-in-one!\"');", - "assert(golfScore(5, 5) === \"Par\", 'message: golfScore(5, 5) should return \"Par\"');", - "assert(golfScore(4, 5) === \"Bogey\", 'message: golfScore(4, 5) should return \"Bogey\"');", - "assert(golfScore(4, 6) === \"Double Bogey\", 'message: golfScore(4, 6) should return \"Double Bogey\"');", - "assert(golfScore(4, 7) === \"Go Home!\", 'message: golfScore(4, 7) should return \"Go Home!\"');", - "assert(golfScore(5, 9) === \"Go Home!\", 'message: golfScore(5, 9) should return \"Go Home!\"');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Código de golf", - "description": [ - "En el juego de golf cada hoyo tiene un par promedio para el número de golpes necesarios para meter la pelota. Dependiendo de que tan lejos por encima o por debajo del par estén tus golpes, habrá un sobrenombre diferente.", - "Tu función pasará un par y el número de golpes, y retornará una cadena de acuerdo a esta tabla (basada en el orden de prioridad - arriba (lo más alto) hacia abajo (lo más bajo)):", - "
GolpesRetorna
1\"Hole-in-one!\"
<= par - 2\"Eagle\"
par - 1\"Birdie\"
par\"Par\"
par + 1\"Bogey\"
par + 2\"Double Bogey\"
>= par + 3\"Go Home!\"
", - "Tanto par como golpes siempre serán numéricos y positivos." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244dd", - "title": "Selecting from Many Options with Switch Statements", - "description": [ - "If you have many options to choose from, use a switch statement. A switch statement tests a value and can have many case statements which define various possible values. Statements are executed from the first matched case value until a break is encountered.", - "Here is a pseudocode example:", - "
switch(num) {
case value1:
statement1;
break;
case value2:
statement2;
break;
...
case valueN:
statementN;
break;
}
", - "case values are tested with strict equality (===). The break tells JavaScript to stop executing statements. If the break is omitted, the next statement will be executed.", - "
", - "Write a switch statement which tests val and sets answer for the following conditions:
1 - \"alpha\"
2 - \"beta\"
3 - \"gamma\"
4 - \"delta\"" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function caseInSwitch(val) {", - " var answer = \"\";", - " // Only change code below this line", - " ", - " ", - " ", - " // Only change code above this line ", - " return answer; ", - "}", - "", - "// Change this value to test", - "caseInSwitch(1);", - "" - ], - "solutions": [ - "function caseInSwitch(val) {\n var answer = \"\";\n\n switch(val) {\n case 1:\n answer = \"alpha\";\n break;\n case 2:\n answer = \"beta\";\n break;\n case 3:\n answer = \"gamma\";\n break;\n case 4:\n answer = \"delta\";\n }\n return answer; \n}" - ], - "tests": [ - "assert(caseInSwitch(1) === \"alpha\", 'message: caseInSwitch(1) should have a value of \"alpha\"');", - "assert(caseInSwitch(2) === \"beta\", 'message: caseInSwitch(2) should have a value of \"beta\"');", - "assert(caseInSwitch(3) === \"gamma\", 'message: caseInSwitch(3) should have a value of \"gamma\"');", - "assert(caseInSwitch(4) === \"delta\", 'message: caseInSwitch(4) should have a value of \"delta\"');", - "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if or else statements');", - "assert(code.match(/break/g).length > 2, 'message: You should have at least 3 break statements');" - ], - "type": "waypoint", - "MDNlinks": [ - "Switch Statement" - ], - "challengeType": 1, - "translations": { - "es": { - "title": "Seleccionar desde diferentes opciones con la sentencia switch", - "description": [ - "Si tienes varias opciones para elegir, usa una sentencia switch. Una sentencia switch prueba un valor y puede tener varias sentencias case las cuales definen varios posibles valores. Las sentencias son ejecutadas desde el primer valor case igualado hasta que se encuentr un break.", - "Aquí hay un pseudocódigo de ejemplo:", - "
switch(num) {
case valor1:
sentencia1;
break;
case valor2:
sentencia2;
break;
...
case valorN:
sentenciaN;
break;
}
", - "Los valores case son probados con estricta igualdad (===). El break le dice a JavaScript que pare la ejecución del bloque de sentencias en el que está. Si se omite break, se ejecutará la siguiente sentencia.", - "

Instrucciones

", - "Escribe una sentencia switch que pruebe val y establezca answer para las siguientes condiciones:
1 - \"alpha\"
2 - \"beta\"
3 - \"gamma\"
4 - \"delta\"" - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244de", - "title": "Adding a Default Option in Switch Statements", - "description": [ - "In a switch statement you may not be able to specify all possible values as case statements. Instead, you can add the default statement which will be executed if no matching case statements are found. Think of it like the final else statement in an if/else chain.", - "A default statement should be the last case.", - "
switch (num) {
case value1:
statement1;
break;
case value2:
statement2;
break;
...
default:
defaultStatement;
break;
}
", - "
", - "Write a switch statement to set answer for the following conditions:
\"a\" - \"apple\"
\"b\" - \"bird\"
\"c\" - \"cat\"
default - \"stuff\"" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function switchOfStuff(val) {", - " var answer = \"\";", - " // Only change code below this line", - " ", - " ", - " ", - " // Only change code above this line ", - " return answer; ", - "}", - "", - "// Change this value to test", - "switchOfStuff(1);", - "" - ], - "solutions": [ - "function switchOfStuff(val) {\n var answer = \"\";\n\n switch(val) {\n case \"a\":\n answer = \"apple\";\n break;\n case \"b\":\n answer = \"bird\";\n break;\n case \"c\":\n answer = \"cat\";\n break;\n default:\n answer = \"stuff\";\n }\n return answer; \n}" - ], - "tests": [ - "assert(switchOfStuff(\"a\") === \"apple\", 'message: switchOfStuff(\"a\") should have a value of \"apple\"');", - "assert(switchOfStuff(\"b\") === \"bird\", 'message: switchOfStuff(\"b\") should have a value of \"bird\"');", - "assert(switchOfStuff(\"c\") === \"cat\", 'message: switchOfStuff(\"c\") should have a value of \"cat\"');", - "assert(switchOfStuff(\"d\") === \"stuff\", 'message: switchOfStuff(\"d\") should have a value of \"stuff\"');", - "assert(switchOfStuff(4) === \"stuff\", 'message: switchOfStuff(4) should have a value of \"stuff\"');", - "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if or else statements');", - "assert(switchOfStuff(\"string-to-trigger-default-case\") === \"stuff\", 'message: You should use a default statement');", - "assert(code.match(/break/g).length > 2, 'message: You should have at least 3 break statements');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Agregar una opción por omisión (default) en una sentencia switch", - "description": [ - "En una sentencia switch puede que no seas capaz de especificar todos los posibles valores en las sentencias case. En su lugar, puedes agregar la sentencia default la cual será ejecutada si no es encontrada ninguna coincidencia con alguna sentencia case. Piensa en esto como la última sentencia else en una cadena if/else.", - "Una sentencia default debería ser el último caso.", - "
switch(num) {
case valor1:
sentencia1;
break;
case valor2:
sentencia2;
break;
...
default:
sentenciaDefault;
}
", - "

Instrucciones

", - "Escribe una sentencia switch para establecer answer para las siguientes condiciones:
\"a\" - \"apple\"
\"b\" - \"bird\"
\"c\" - \"cat\"
default - \"stuff\"" - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/adding-a-default-option-in-switch-statements" - }, - { - "id": "56533eb9ac21ba0edf2244df", - "title": "Multiple Identical Options in Switch Statements", - "description": [ - "If the break statement is omitted from a switch statement's case, the following case statement(s) are executed until a break is encountered. If you have multiple inputs with the same output, you can represent them in a switch statement like this:", - "
switch(val) {
case 1:
case 2:
case 3:
result = \"1, 2, or 3\";
break;
case 4:
result = \"4 alone\";
}
", - "Cases for 1, 2, and 3 will all produce the same result.", - "
", - "Write a switch statement to set answer for the following ranges:
1-3 - \"Low\"
4-6 - \"Mid\"
7-9 - \"High\"", - "Note
You will need to have a case statement for each number in the range." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function sequentialSizes(val) {", - " var answer = \"\";", - " // Only change code below this line", - " ", - " ", - " ", - " // Only change code above this line ", - " return answer; ", - "}", - "", - "// Change this value to test", - "sequentialSizes(1);", - "" - ], - "solutions": [ - "function sequentialSizes(val) {\n var answer = \"\";\n \n switch(val) {\n case 1:\n case 2:\n case 3:\n answer = \"Low\";\n break;\n case 4:\n case 5:\n case 6:\n answer = \"Mid\";\n break;\n case 7:\n case 8:\n case 9:\n answer = \"High\";\n }\n \n return answer; \n}" - ], - "tests": [ - "assert(sequentialSizes(1) === \"Low\", 'message: sequentialSizes(1) should return \"Low\"');", - "assert(sequentialSizes(2) === \"Low\", 'message: sequentialSizes(2) should return \"Low\"');", - "assert(sequentialSizes(3) === \"Low\", 'message: sequentialSizes(3) should return \"Low\"');", - "assert(sequentialSizes(4) === \"Mid\", 'message: sequentialSizes(4) should return \"Mid\"');", - "assert(sequentialSizes(5) === \"Mid\", 'message: sequentialSizes(5) should return \"Mid\"');", - "assert(sequentialSizes(6) === \"Mid\", 'message: sequentialSizes(6) should return \"Mid\"');", - "assert(sequentialSizes(7) === \"High\", 'message: sequentialSizes(7) should return \"High\"');", - "assert(sequentialSizes(8) === \"High\", 'message: sequentialSizes(8) should return \"High\"');", - "assert(sequentialSizes(9) === \"High\", 'message: sequentialSizes(9) should return \"High\"');", - "assert(!/else/g.test(code) || !/if/g.test(code), 'message: You should not use any if or else statements');", - "assert(code.match(/case/g).length === 9, 'message: You should have nine case statements');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Múltiples opciones idénticas en una sentencias switch", - "description": [ - "Si la sentencia break es omitida de una sentencia case de un switch, las siguientes sentencias case son ejecutadas hasta que sea encontrado un break. Si tienes multiples entradas con la misma salida, puede representarlas en una sentencia switch así:", - "
switch(val) {
case 1:
case 2:
case 3:
result = \"1, 2, or 3\";
break;
case 4:
result = \"4 alone\";
}
", - "Los casos 1, 2, y 3 producirán el mismo resultado.", - "

Instrucciones

", - "Escribe una sentencia switch para establecer answer para los siguientes rangos:
1-3 - \"Low\"
4-6 - \"Mid\"
7-9 - \"High\"", - "Nota
Necesitarás tener una sentencia case por cada número en el rango." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244e0", - "title": "Replacing If Else Chains with Switch", - "description": [ - "If you have many options to choose from, a switch statement can be easier to write than many chained if/else if statements. The following:", - "
if (val === 1) {
answer = \"a\";
} else if (val === 2) {
answer = \"b\";
} else {
answer = \"c\";
}
", - "can be replaced with:", - "
switch(val) {
case 1:
answer = \"a\";
break;
case 2:
answer = \"b\";
break;
default:
answer = \"c\";
}
", - "
", - "Change the chained if/else if statements into a switch statement." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function chainToSwitch(val) {", - " var answer = \"\";", - " // Only change code below this line", - " ", - " if (val === \"bob\") {", - " answer = \"Marley\";", - " } else if (val === 42) {", - " answer = \"The Answer\";", - " } else if (val === 1) {", - " answer = \"There is no #1\";", - " } else if (val === 99) {", - " answer = \"Missed me by this much!\";", - " } else if (val === 7) {", - " answer = \"Ate Nine\";", - " }", - " ", - " // Only change code above this line ", - " return answer; ", - "}", - "", - "// Change this value to test", - "chainToSwitch(7);", - "" - ], - "solutions": [ - "function chainToSwitch(val) {\n var answer = \"\";\n\n switch(val) {\n case \"bob\":\n answer = \"Marley\";\n break;\n case 42:\n answer = \"The Answer\";\n break;\n case 1:\n answer = \"There is no #1\";\n break;\n case 99:\n answer = \"Missed me by this much!\";\n break;\n case 7:\n answer = \"Ate Nine\";\n }\n return answer; \n}" - ], - "tests": [ - "assert(!/else/g.test(code), 'message: You should not use any else statements anywhere in the editor');", - "assert(!/if/g.test(code), 'message: You should not use any if statements anywhere in the editor');", - "assert(code.match(/break/g).length >= 4, 'message: You should have at least four break statements');", - "assert(chainToSwitch(\"bob\") === \"Marley\", 'message: chainToSwitch(\"bob\") should be \"Marley\"');", - "assert(chainToSwitch(42) === \"The Answer\", 'message: chainToSwitch(42) should be \"The Answer\"');", - "assert(chainToSwitch(1) === \"There is no #1\", 'message: chainToSwitch(1) should be \"There is no #1\"');", - "assert(chainToSwitch(99) === \"Missed me by this much!\", 'message: chainToSwitch(99) should be \"Missed me by this much!\"');", - "assert(chainToSwitch(7) === \"Ate Nine\", 'message: chainToSwitch(7) should be \"Ate Nine\"');", - "assert(chainToSwitch(\"John\") === \"\", 'message: chainToSwitch(\"John\") should be \"\" (empty string)');", - "assert(chainToSwitch(156) === \"\", 'message: chainToSwitch(156) should be \"\" (empty string)');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Reemplazar cadenas if else con switch", - "description": [ - "Si tienes varias opciones para elegir, una sentencia switch puede ser más fácil de escribir que varias sentencias if/if else anidadas. Lo siguiente:", - "
if (val === 1) {
respuesta = \"a\";
} else if (val === 2) {
respuesta = \"b\";
} else {
respuesta = \"c\";
}
", - "puede ser reemplazado con:", - "
switch(val) {
case 1:
respuesta = \"a\";
break;
case 2:
respuesta = \"b\";
break;
default:
respuesta = \"c\";
}
", - "

Instrucciones

", - "Cambia las sentencias if/if else anidadas dentro de una sentencia switch." - ] - } - } - }, - { - "id": "5679ceb97cbaa8c51670a16b", - "title": "Returning Boolean Values from Functions", - "description": [ - "You may recall from Comparison with the Equality Operator that all comparison operators return a boolean true or false value.", - "Sometimes people use an if/else statement to do a comparison, like this:", - "
function isEqual(a,b) {
if (a === b) {
return true;
} else {
return false;
}
}
", - "But there's a better way to do this. Since === returns true or false, we can return the result of the comparison:", - "
function isEqual(a,b) {
return a === b;
}
", - "
", - "Fix the function isLess to remove the if/else statements." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function isLess(a, b) {", - " // Fix this code", - " if (a < b) {", - " return true;", - " } else {", - " return false;", - " }", - "}", - "", - "// Change these values to test", - "isLess(10, 15);" - ], - "tail": [ - "" - ], - "solutions": [ - "function isLess(a, b) {\n return a < b;\n}" - ], - "tests": [ - "assert(isLess(10,15) === true, 'message: isLess(10,15) should return true');", - "assert(isLess(15, 10) === false, 'message: isLess(15,10) should return false');", - "assert(!/if|else/g.test(code), 'message: You should not use any if or else statements');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Retornar valores booleanos desde funciones", - "description": [ - "Tal vez recuerdes de La comparación con el operador de igualdad que todos los operadores de comparación retornan un valor booleano true (verdadero) o false (falso).", - "Un anti-patrón común es usar una sentencia if/else para hacer una comparación y entonces retornar true o false:", - "
function sonIguales(a,b) {
if (a === b) {
return true;
} else {
return false;
}
}
", - "Ya que === returna true (verdadero) o false (falso), podemos simplemente retornar el resultado de la comparación:", - "
function sonIguales(a,b) {
return a === b;
}
", - "

Instrucciones

", - "Arregla la función isLess para remover las sentencias if/else." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244c4", - "title": "Return Early Pattern for Functions", - "description": [ - "When a return statement is reached, the execution of the current function stops and control returns to the calling location.", - "Example", - "
function myFun() {
console.log(\"Hello\");
return \"World\";
console.log(\"byebye\")
}
myFun();
", - "The above outputs \"Hello\" to the console, returns \"World\", but \"byebye\" is never output, because the function exits at the return statement.", - "
", - "Modify the function abTest so that if a or b are less than 0 the function will immediately exit with a value of undefined.", - "Hint
Remember that undefined is a keyword, not a string." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function abTest(a, b) {", - " // Only change code below this line", - " ", - " ", - " ", - " // Only change code above this line", - "", - " return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));", - "}", - "", - "// Change values below to test your code", - "abTest(2,2);" - ], - "tail": [ - "" - ], - "solutions": [ - "function abTest(a, b) {\n if(a < 0 || b < 0) {\n return undefined;\n } \n return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));\n}" - ], - "tests": [ - "assert(typeof abTest(2,2) === 'number' , 'message: abTest(2,2) should return a number');", - "assert(abTest(2,2) === 8 , 'message: abTest(2,2) should return 8');", - "assert(abTest(-2,2) === undefined , 'message: abTest(-2,2) should return undefined');", - "assert(abTest(2,-2) === undefined , 'message: abTest(2,-2) should return undefined');", - "assert(abTest(2,8) === 18 , 'message: abTest(2,8) should return 18');", - "assert(abTest(3,3) === 12 , 'message: abTest(3,3) should return 12');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Retornar un patrón temprano para funciones", - "description": [ - "Cuando se alcanza una sentencia return, la ejecución de la presente función se detiene y el control la retorna a la ubicación de la llamada.", - "Ejemplo", - "
function miFuncion() {
console.log(\"Hola\");
return \"Mundo\";
console.log(\"chaochao\")
}
miFuncion();
", - "Esta presenta en consola \"Hola\", retorna \"Mundo\", pero \"chaochao\" nunca se presenta, porque la función sale con la sentencia return.", - "

Instrucciones

", - "Modifica la función abTest de manera que si a o b son menores que 0 la función saldrá inmediatamente con un valor undefined.", - "Pista
Recuerda que undefined es una palabra clave, no una cadena." - ] - } - } - }, - { - "id": "565bbe00e9cc8ac0725390f4", - "title": "Counting Cards", - "description": [ - "In the casino game Blackjack, a player can gain an advantage over the house by keeping track of the relative number of high and low cards remaining in the deck. This is called Card Counting.", - "Having more high cards remaining in the deck favors the player. Each card is assigned a value according to the table below. When the count is positive, the player should bet high. When the count is zero or negative, the player should bet low.", - "
Count ChangeCards
+12, 3, 4, 5, 6
07, 8, 9
-110, 'J', 'Q', 'K', 'A'
", - "You will write a card counting function. It will receive a card parameter, which can be a number or a string, and increment or decrement the global count variable according to the card's value (see table). The function will then return a string with the current count and the string Bet if the count is positive, or Hold if the count is zero or negative. The current count and the player's decision (Bet or Hold) should be separated by a single space.", - "Example Output
-3 Hold
5 Bet", - "Hint
Do NOT reset count to 0 when value is 7, 8, or 9.
Do NOT return an array.
Do NOT include quotes (single or double) in the output." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var count = 0;", - "", - "function cc(card) {", - " // Only change code below this line", - " ", - " ", - " return \"Change Me\";", - " // Only change code above this line", - "}", - "", - "// Add/remove calls to test your function.", - "// Note: Only the last will display", - "cc(2); cc(3); cc(7); cc('K'); cc('A');" - ], - "solutions": [ - "var count = 0;\nfunction cc(card) {\n switch(card) {\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n count++;\n break;\n case 10:\n case 'J':\n case 'Q':\n case 'K':\n case 'A':\n count--;\n }\n if(count > 0) {\n return count + \" Bet\";\n } else {\n return count + \" Hold\";\n }\n}" - ], - "tests": [ - "assert((function(){ count = 0; cc(2);cc(3);cc(4);cc(5);var out = cc(6); if(out === \"5 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, 3, 4, 5, 6 should return 5 Bet');", - "assert((function(){ count = 0; cc(7);cc(8);var out = cc(9); if(out === \"0 Hold\") {return true;} return false; })(), 'message: Cards Sequence 7, 8, 9 should return 0 Hold');", - "assert((function(){ count = 0; cc(10);cc('J');cc('Q');cc('K');var out = cc('A'); if(out === \"-5 Hold\") {return true;} return false; })(), 'message: Cards Sequence 10, J, Q, K, A should return -5 Hold');", - "assert((function(){ count = 0; cc(3);cc(7);cc('Q');cc(8);var out = cc('A'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 7, Q, 8, A should return -1 Hold');", - "assert((function(){ count = 0; cc(2);cc('J');cc(9);cc(2);var out = cc(7); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, J, 9, 2, 7 should return 1 Bet');", - "assert((function(){ count = 0; cc(2);cc(2);var out = cc(10); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, 2, 10 should return 1 Bet');", - "assert((function(){ count = 0; cc(3);cc(2);cc('A');cc(10);var out = cc('K'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 2, A, 10, K should return -1 Hold');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Contar cartas", - "description": [ - "En el juego de casino Blackjack, un jugador puede conseguir ventaja sobre la casa manteniendo un registro del número relativo de cartas altas y bajas restantes en la baraja. Esto es llamado Conteo de Cartas.", - "Tener más cartas altas restantes en la baraja favorece al jugador. A cada carta se le asigna un valor de acuerdo a la tabla de abajo. Cuando el conteo es positivo, el jugador debe apostar alto. Cuando el conteo es cero o negativo, el jugador debe apostar bajo.", - "
ValorCartas
+12, 3, 4, 5, 6
07, 8, 9
-110, 'J', 'Q', 'K','A'
", - "Vas a escribir una función de conteo de cartas. Esta recibirá un parametro card (carta) e incrementa o decrementa la variable count (conteo) global de acuerdo al valor de la carta (ver tabla). La función retornará entonces una cadena con el presente conteo y la cadena Bet si el conteo es positivo o Hold si el conteo es cero o negativo. El presente conteo y la desición del jugador (Bet o Hold) deben quedar separada por un único espacio.", - "Ejemplo de Salida
-3 Hold
5 Bet
" - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392d0", - "title": "Build JavaScript Objects", - "description": [ - "You may have heard the term object before.", - "Objects are similar to arrays, except that instead of using indexes to access and modify their data, you access the data in objects through what are called properties.", - "Objects are useful for storing data in a structured way, and can represent real world objects, like a cat.", - "Here's a sample cat object:", - "
var cat = {
\"name\": \"Whiskers\",
\"legs\": 4,
\"tails\": 1,
\"enemies\": [\"Water\", \"Dogs\"]
};
", - "In this example, all the properties are stored as strings, such as - \"name\", \"legs\", and \"tails\". However, you can also use numbers as properties. You can even omit the quotes for single-word string properties, as follows:", - "
var anotherObject = {
make: \"Ford\",
5: \"five\",
\"model\": \"focus\"
};
", - "However, if your object has any non-string properties, JavaScript will automatically typecast them as strings.", - "
", - "Make an object that represents a dog called myDog which contains the properties \"name\" (a string), \"legs\", \"tails\" and \"friends\".", - "You can set these object properties to whatever values you want, as long \"name\" is a string, \"legs\" and \"tails\" are numbers, and \"friends\" is an array." - ], - "challengeSeed": [ - "// Example", - "var ourDog = {", - " \"name\": \"Camper\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"everything!\"]", - "};", - "", - "// Only change code below this line.", - "", - "var myDog = {", - " ", - " ", - " ", - " ", - "};" - ], - "tail": [ - "(function(z){return z;})(myDog);" - ], - "solutions": [ - "var myDog = {\n \"name\": \"Camper\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"everything!\"] \n};" - ], - "tests": [ - "assert((function(z){if(z.hasOwnProperty(\"name\") && z.name !== undefined && typeof z.name === \"string\"){return true;}else{return false;}})(myDog), 'message: myDog should contain the property name and it should be a string.');", - "assert((function(z){if(z.hasOwnProperty(\"legs\") && z.legs !== undefined && typeof z.legs === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog should contain the property legs and it should be a number.');", - "assert((function(z){if(z.hasOwnProperty(\"tails\") && z.tails !== undefined && typeof z.tails === \"number\"){return true;}else{return false;}})(myDog), 'message: myDog should contain the property tails and it should be a number.');", - "assert((function(z){if(z.hasOwnProperty(\"friends\") && z.friends !== undefined && Array.isArray(z.friends)){return true;}else{return false;}})(myDog), 'message: myDog should contain the property friends and it should be an array.');", - "assert((function(z){return Object.keys(z).length === 4;})(myDog), 'message: myDog should only contain all the given properties.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Construye objetos en JavaScript", - "description": [ - "Es posible que haya oído el término objeto antes.", - "Los objetos son similares a los vectores, excepto que en lugar de utilizar los índices para acceder y modificar sus datos, pueden accederse mediante lo que se llama propiedades.", - "Esto es un objeto de ejemplo:", - "var cat = {", - "  \"name\": \"Whiskers\",", - "  \"legs\": 4,", - "  \"tails\": 1,", - "  \"enemies\": [\"Water\", \"Dogs\"]", - "};", - "Los objetos son útiles para almacenar datos de manera estructurada, y pueden representar objetos del mundo real, como un gato.", - "Vamos a tratar de hacer un objeto que representa un perro, lo llamaremos mydog y contendrá las propiedades \"name\" (una cadena con el nombre), \"legs\" (piernas), \"tails\" (colas) y \"friends\" (amigos). ", - "Podrás establecer estas propiedades del objeto en los valores que desees, siempre y cuando \"name\" sea una cadena, \"legs\" y \"tails\" sean números, y \"friends\" sea un vector." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244c7", - "title": "Accessing Object Properties with Dot Notation", - "description": [ - "There are two ways to access the properties of an object: dot notation (.) and bracket notation ([]), similar to an array.", - "Dot notation is what you use when you know the name of the property you're trying to access ahead of time.", - "Here is a sample of using dot notation (.) to read an object's property:", - "
var myObj = {
prop1: \"val1\",
prop2: \"val2\"
};
var prop1val = myObj.prop1; // val1
var prop2val = myObj.prop2; // val2
", - "
", - "Read in the property values of testObj using dot notation. Set the variable hatValue equal to the object's property hat and set the variable shirtValue equal to the object's property shirt." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var testObj = {", - " \"hat\": \"ballcap\",", - " \"shirt\": \"jersey\",", - " \"shoes\": \"cleats\"", - "};", - "", - "// Only change code below this line", - "", - "var hatValue = testObj; // Change this line", - "var shirtValue = testObj; // Change this line" - ], - "tail": [ - "(function(a,b) { return \"hatValue = '\" + a + \"', shirtValue = '\" + b + \"'\"; })(hatValue,shirtValue);" - ], - "solutions": [ - "var testObj = {\n \"hat\": \"ballcap\",\n \"shirt\": \"jersey\",\n \"shoes\": \"cleats\"\n};\n\nvar hatValue = testObj.hat; \nvar shirtValue = testObj.shirt;" - ], - "tests": [ - "assert(typeof hatValue === 'string' , 'message: hatValue should be a string');", - "assert(hatValue === 'ballcap' , 'message: The value of hatValue should be \"ballcap\"');", - "assert(typeof shirtValue === 'string' , 'message: shirtValue should be a string');", - "assert(shirtValue === 'jersey' , 'message: The value of shirtValue should be \"jersey\"');", - "assert(code.match(/testObj\\.\\w+/g).length > 1, 'message: You should use dot notation twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a propiedades de objetos con el operador punto", - "description": [ - "Hay dos maneras de acceder a las propiedades de un objeto: con el operador punto (.) y con la notación corchete ([]), similar al caso de un vector.", - "El operador punto es el que usas cuando de antemano sabes el nombre de la propiedad que estás intentando acceder.", - "Aquí está un ejemplo del uso del operador punto (.) para leer una propiedad de un objeto:", - "
var miObj = {
prop1: \"val1\",
prop2: \"val2\"
};
var prop1val = miObj.prop1; // val1
var prop2val = miObj.prop2; // val2
", - "

Instrucciones

", - "Lee los valores de propiedades de testObj usando notación punto. Asigna la variable hatValue igual a la propiedad objeto hat y asigna la variable shirtValue igual a la propiedad objeto shirt." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244c8", - "title": "Accessing Object Properties with Bracket Notation", - "description": [ - "The second way to access the properties of an object is bracket notation ([]). If the property of the object you are trying to access has a space in its name, you will need to use bracket notation.", - "However, you can still use bracket notation on object properties without spaces.", - "Here is a sample of using bracket notation to read an object's property:", - "
var myObj = {
\"Space Name\": \"Kirk\",
\"More Space\": \"Spock\",
\"NoSpace\": \"USS Enterprise\"
};
myObj[\"Space Name\"]; // Kirk
myObj['More Space']; // Spock
myObj[\"NoSpace\"]; // USS Enterprise
", - "Note that property names with spaces in them must be in quotes (single or double).", - "
", - "Read the values of the properties \"an entree\" and \"the drink\" of testObj using bracket notation and assign them to entreeValue and drinkValue respectively." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var testObj = {", - " \"an entree\": \"hamburger\",", - " \"my side\": \"veggies\",", - " \"the drink\": \"water\"", - "};", - "", - "// Only change code below this line", - "", - "var entreeValue = testObj; // Change this line", - "var drinkValue = testObj; // Change this line" - ], - "tail": [ - "(function(a,b) { return \"entreeValue = '\" + a + \"', drinkValue = '\" + b + \"'\"; })(entreeValue,drinkValue);" - ], - "solutions": [ - "var testObj = {\n \"an entree\": \"hamburger\",\n \"my side\": \"veggies\",\n \"the drink\": \"water\"\n};\nvar entreeValue = testObj[\"an entree\"];\nvar drinkValue = testObj['the drink'];" - ], - "tests": [ - "assert(typeof entreeValue === 'string' , 'message: entreeValue should be a string');", - "assert(entreeValue === 'hamburger' , 'message: The value of entreeValue should be \"hamburger\"');", - "assert(typeof drinkValue === 'string' , 'message: drinkValue should be a string');", - "assert(drinkValue === 'water' , 'message: The value of drinkValue should be \"water\"');", - "assert(code.match(/testObj\\s*?\\[('|\")[^'\"]+\\1\\]/g).length > 1, 'message: You should use bracket notation twice');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a las propiedades de objetos con la notación corchete", - "description": [ - "La segunda manera de acceder a las propiedades de un objeto es con la notación corchete ([]). Si el nombre de la propiedad del objeto que estás intentando acceder tiene un espacio, necesitarás usar la notación corchete.", - "Aquí está un ejemplo del uso de la notación corchete para leer una propiedad de un objeto:", - "
var miObj = {
\"Nombre con espacio\": \"Kirk\",
\"Mas espacio\": \"Spock\"
};
miObj[\"Nombre con espacio\"]; // Kirk
miObj['Mas espacio']; // Spock
", - "Nota que los nombres de propiedades con espacios tienen que estar entre comillas (apóstrofes o comillas).", - "

Instrucciones

", - "Lee los valores de las propiedades \"an entree\" y \"the drink\" de testObj usando la notación corchete." - ] - } - }, - "guideUrl": "https://guide.freecodecamp.org/certificates/accessing-objects-properties-with-bracket-notation" - }, - { - "id": "56533eb9ac21ba0edf2244c9", - "title": "Accessing Object Properties with Variables", - "description": [ - "Another use of bracket notation on objects is to access a property which is stored as the value of a variable. This can be very useful for iterating through an object's properties or when accessing a lookup table.", - "Here is an example of using a variable to access a property:", - "
var dogs = {
Fido: \"Mutt\",\n Hunter: \"Doberman\",\n Snoopie: \"Beagle\"
};
var myDog = \"Hunter\";
var myBreed = dogs[myDog];
console.log(myBreed); // \"Doberman\"
", - "Another way you can use this concept is when the property's name is collected dynamically during the program execution, as follows:", - "
var someObj = {
propName: \"John\"
};
function propPrefix(str) {
var s = \"prop\";
return s + str;
}
var someProp = propPrefix(\"Name\"); // someProp now holds the value 'propName'
console.log(someObj[someProp]); // \"John\"
", - "Note that we do not use quotes around the variable name when using it to access the property because we are using the value of the variable, not the name.", - "
", - "Use the playerNumber variable to look up player 16 in testObj using bracket notation. Then assign that name to the player variable." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var testObj = {", - " 12: \"Namath\",", - " 16: \"Montana\",", - " 19: \"Unitas\"", - "};", - "", - "// Only change code below this line;", - "", - "var playerNumber; // Change this Line", - "var player = testObj; // Change this Line" - ], - "tail": [ - "if(typeof player !== \"undefined\"){(function(v){return v;})(player);}" - ], - "solutions": [ - "var testObj = {\n 12: \"Namath\",\n 16: \"Montana\",\n 19: \"Unitas\"\n};\nvar playerNumber = 16;\nvar player = testObj[playerNumber];" - ], - "tests": [ - "assert(typeof playerNumber === 'number', 'message: playerNumber should be a number');", - "assert(typeof player === 'string', 'message: The variable player should be a string');", - "assert(player === 'Montana', 'message: The value of player should be \"Montana\"');", - "assert(/testObj\\s*?\\[.*?\\]/.test(code),'message: You should use bracket notation to access testObj');", - "assert(!code.match(/player\\s*=\\s*\"|\\'\\s*Montana\\s*\"|\\'\\s*;/gi),'message: You should not assign the value Montana to the variable player directly.');", - "assert(/testObj\\s*?\\[\\s*playerNumber\\s*\\]/.test(code),'message: You should be using the variable playerNumber in your bracket notation');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a propiedades de objetos con variables", - "description": [ - "Otro uso de la notación corchete sobre objetos es usar una variable para acceder a una propiedad. Esto puede ser muy útil en iteraciones sobre la lista de propiedades de un objetos o para hacer operaciones de búsqueda.", - "Aquí está un ejemplo del uso de una variable para acceder a una propiedad:", - "
var algunaProp = \"propNombre\";
var miObj = {
propNombre: \"Algún valor\"
}
miObj[algunaProp]; // \"Algún valor\"
", - "Aquí hay uno más:", - "
var miPerro = \"Cazador\";
var perros = {
Fido: \"Mutt\",\n Cazador: \"Doberman\",\n Snoopie: \"Beagle\"
}
var raza = perros[miPerro]; // \"Cazador\"
console.log(raza)// \"Doberman\"
", - "Nota que no usamos comillas alrededor del nombre de la variable (miPerro) cuando la usamos para acceder a la propiedad (perros[miPerro] porque estamos usando el valor de la variable y no su nombre", - "

Instrucciones

", - "Usa la variable playerNumber para buscar y asignar a player el jugador 16 de testObj, usa la notación corchete." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/accessing-objects-properties-with-variables" - }, - { - "id": "56bbb991ad1ed5201cd392d1", - "title": "Updating Object Properties", - "description": [ - "After you've created a JavaScript object, you can update its properties at any time just like you would update any other variable. You can use either dot or bracket notation to update.", - "For example, let's look at ourDog:", - "
var ourDog = {
\"name\": \"Camper\",
\"legs\": 4,
\"tails\": 1,
\"friends\": [\"everything!\"]
};
", - "Since he's a particularly happy dog, let's change his name to \"Happy Camper\". Here's how we update his object's name property:", - "ourDog.name = \"Happy Camper\"; or", - "ourDog[\"name\"] = \"Happy Camper\";", - "Now when we evaluate ourDog.name, instead of getting \"Camper\", we'll get his new name, \"Happy Camper\".", - "
", - "Update the myDog object's name property. Let's change her name from \"Coder\" to \"Happy Coder\". You can use either dot or bracket notation." - ], - "challengeSeed": [ - "// Example", - "var ourDog = {", - " \"name\": \"Camper\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"everything!\"]", - "};", - "", - "ourDog.name = \"Happy Camper\";", - "", - "// Setup", - "var myDog = {", - " \"name\": \"Coder\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"freeCodeCamp Campers\"]", - "};", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "(function(z){return z;})(myDog);" - ], - "solutions": [ - "var myDog = {\n \"name\": \"Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"]\n};\nmyDog.name = \"Happy Coder\";" - ], - "tests": [ - "assert(/happy coder/gi.test(myDog.name), 'message: Update myDog's \"name\" property to equal \"Happy Coder\".');", - "assert(/\"name\": \"Coder\"/.test(code), 'message: Do not edit the myDog definition');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Actualiza las propiedades de un objeto en JavaScript", - "description": [ - "Después de que hayas creado un objeto de JavaScript, puedes actualizar sus propiedades en cualquier momento, tal y como harías con cualquier otra variable.", - "Por ejemplo, echemos un vistazo a ourDog:", - "var ourDog = {", - "  \"name\": \"Camper\",", - "  \"legs\": 4,", - "  \"tails\": 1,", - "  \"friends\": [\"everything!\"]", - "};", - "Dado que es un perro particularmente feliz, vamos a cambiar su nombre a \"Happy Camper\". Así es como actualizamos la propiedad nombre del objeto: ", - "ourDog.name = \"Happy Camper\";", - "Ahora, cuando ejecutemos return ourDog.name, en lugar de obtener \"Camper\", vamos a recibir su nuevo nombre, \"Happy Camper\".", - "

Instrucciones

", - "Vamos a actualizar la propiedad del objeto mydog. Cambiemos su nombre de \"Coder\" a \"Happy Coder\"." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392d2", - "title": "Add New Properties to a JavaScript Object", - "description": [ - "You can add new properties to existing JavaScript objects the same way you would modify them.", - "Here's how we would add a \"bark\" property to ourDog:", - "ourDog.bark = \"bow-wow\"; ", - "or", - "ourDog[\"bark\"] = \"bow-wow\";", - "Now when we evaluate ourDog.bark, we'll get his bark, \"bow-wow\".", - "
", - "Add a \"bark\" property to myDog and set it to a dog sound, such as \"woof\". You may use either dot or bracket notation." - ], - "challengeSeed": [ - "// Example", - "var ourDog = {", - " \"name\": \"Camper\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"everything!\"]", - "};", - "", - "ourDog.bark = \"bow-wow\";", - "", - "// Setup", - "var myDog = {", - " \"name\": \"Happy Coder\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"freeCodeCamp Campers\"]", - "};", - "", - "// Only change code below this line.", - "" - ], - "tail": [ - "(function(z){return z;})(myDog);" - ], - "solutions": [ - "var myDog = {\n \"name\": \"Happy Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"]\n};\nmyDog.bark = \"Woof Woof\";" - ], - "tests": [ - "assert(myDog.bark !== undefined, 'message: Add the property \"bark\" to myDog.');", - "assert(!/bark[^\\n]:/.test(code), 'message: Do not add \"bark\" to the setup section');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Añade nuevas propiedades a un objeto JavaScript", - "description": [ - "Puedes añadir nuevas propiedades a objetos existente de la misma forma que usarías para modificarlos.", - "Así es como añadimos una propiedad \"bark\" (ladra) a nuestro objeto ourDog:", - "ourDog.bark = \"bow-wow\";", - "Ahora, cuando ejecutemos return ourDog.bark, vamos a recbir su ladrido, \" bow-wow \".", - "

Instrucciones

", - "Vamos a añadir una propiedad ladra a myDog y a ponerle un sonido de perro, tal como \"woof\"." - ] - } - } - }, - { - "id": "56bbb991ad1ed5201cd392d3", - "title": "Delete Properties from a JavaScript Object", - "description": [ - "We can also delete properties from objects like this:", - "delete ourDog.bark;", - "
", - "Delete the \"tails\" property from myDog. You may use either dot or bracket notation." - ], - "challengeSeed": [ - "// Example", - "var ourDog = {", - " \"name\": \"Camper\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"everything!\"],", - " \"bark\": \"bow-wow\"", - "};", - "", - "delete ourDog.bark;", - "", - "// Setup", - "var myDog = {", - " \"name\": \"Happy Coder\",", - " \"legs\": 4,", - " \"tails\": 1,", - " \"friends\": [\"freeCodeCamp Campers\"],", - " \"bark\": \"woof\"", - "};", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "(function(z){return z;})(myDog);" - ], - "solutions": [ - "var ourDog = {\n \"name\": \"Camper\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"everything!\"],\n \"bark\": \"bow-wow\"\n};\nvar myDog = {\n \"name\": \"Happy Coder\",\n \"legs\": 4,\n \"tails\": 1,\n \"friends\": [\"freeCodeCamp Campers\"],\n \"bark\": \"woof\"\n};\ndelete myDog.tails;" - ], - "tests": [ - "assert(typeof myDog === \"object\" && myDog.tails === undefined, 'message: Delete the property \"tails\" from myDog.');", - "assert(code.match(/\"tails\": 1/g).length > 1, 'message: Do not modify the myDog setup');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Elimina propiedades de un objeto JavaScript", - "description": [ - "También podemos eliminar propiedades de los objetos de esta manera:", - "delete ourDog.bark;", - "

Instrucciones

", - "Borremos la propiedad \"tails\" de myDog." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244ca", - "title": "Using Objects for Lookups", - "description": [ - "Objects can be thought of as a key/value storage, like a dictionary. If you have tabular data, you can use an object to \"lookup\" values rather than a switch statement or an if/else chain. This is most useful when you know that your input data is limited to a certain range.", - "Here is an example of a simple reverse alphabet lookup:", - "
var alpha = {
1:\"Z\",
2:\"Y\",
3:\"X\",
4:\"W\",
...
24:\"C\",
25:\"B\",
26:\"A\"
};
alpha[2]; // \"Y\"
alpha[24]; // \"C\"

var value = 2;
alpha[value]; // \"Y\"
", - "
", - "Convert the switch statement into an object called lookup. Use it to look up val and assign the associated string to the result variable." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "function phoneticLookup(val) {", - " var result = \"\";", - "", - " // Only change code below this line", - " switch(val) {", - " case \"alpha\": ", - " result = \"Adams\";", - " break;", - " case \"bravo\": ", - " result = \"Boston\";", - " break;", - " case \"charlie\": ", - " result = \"Chicago\";", - " break;", - " case \"delta\": ", - " result = \"Denver\";", - " break;", - " case \"echo\": ", - " result = \"Easy\";", - " break;", - " case \"foxtrot\": ", - " result = \"Frank\";", - " }", - "", - " // Only change code above this line", - " return result;", - "}", - "", - "// Change this value to test", - "phoneticLookup(\"charlie\");" - ], - "solutions": [ - "function phoneticLookup(val) {\n var result = \"\";\n\n var lookup = {\n alpha: \"Adams\",\n bravo: \"Boston\",\n charlie: \"Chicago\",\n delta: \"Denver\",\n echo: \"Easy\",\n foxtrot: \"Frank\"\n };\n\n result = lookup[val];\n\n return result;\n}" - ], - "tests": [ - "assert(phoneticLookup(\"alpha\") === 'Adams', 'message: phoneticLookup(\"alpha\") should equal \"Adams\"');", - "assert(phoneticLookup(\"bravo\") === 'Boston', 'message: phoneticLookup(\"bravo\") should equal \"Boston\"');", - "assert(phoneticLookup(\"charlie\") === 'Chicago', 'message: phoneticLookup(\"charlie\") should equal \"Chicago\"');", - "assert(phoneticLookup(\"delta\") === 'Denver', 'message: phoneticLookup(\"delta\") should equal \"Denver\"');", - "assert(phoneticLookup(\"echo\") === 'Easy', 'message: phoneticLookup(\"echo\") should equal \"Easy\"');", - "assert(phoneticLookup(\"foxtrot\") === 'Frank', 'message: phoneticLookup(\"foxtrot\") should equal \"Frank\"');", - "assert(typeof phoneticLookup(\"\") === 'undefined', 'message: phoneticLookup(\"\") should equal undefined');", - "assert(code.match(/return\\sresult;/), 'message: You should not modify the return statement');", - "assert(!/case|switch|if/g.test(code), 'message: You should not use case, switch, or if statements'); " - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Usar objetos para búsquedas", - "description": [ - "Los objetos pueden ser considerados como un almacenamiento llave/valor, como un diccionario. Si tienes datos tabulados, puedes almacenarlos en un objeto para después \"buscar\" valores, en lugar de emplear una sentencia switch o una secuencia de if/else. Esto es más útil cuando sabes que tus datos de entrada son limitados a un cierto rango.", - "Aquí está un ejemplo de una simple búsqueda inversa de alfabeto:", - "
var alfa = {
1:\"Z\",
2:\"Y\",
3:\"X\",
4:\"W\",
...
24:\"C\",
25:\"B\",
26:\"A\"
};
alfa[2]; // \"Y\"
alfa[24]; // \"C\"

var valor = 2;
alfa[valor]; // \"Y\"
", - "

Instrucciones

", - "Convierte la sentencia switch en una tabla de búsqueda llamada lookup. Usala para buscar val y asigna la cadena asociada a la variable result." - ] - } - } - }, - { - "id": "567af2437cbaa8c51670a16c", - "title": "Testing Objects for Properties", - "description": [ - "Sometimes it is useful to check if the property of a given object exists or not. We can use the .hasOwnProperty(propname) method of objects to determine if that object has the given property name. .hasOwnProperty() returns true or false if the property is found or not.", - "Example", - "
var myObj = {
top: \"hat\",
bottom: \"pants\"
};
myObj.hasOwnProperty(\"top\"); // true
myObj.hasOwnProperty(\"middle\"); // false
", - "
", - "Modify the function checkObj to test myObj for checkProp. If the property is found, return that property's value. If not, return \"Not Found\"." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var myObj = {", - " gift: \"pony\",", - " pet: \"kitten\",", - " bed: \"sleigh\"", - "};", - "", - "function checkObj(checkProp) {", - " // Your Code Here", - " ", - " return \"Change Me!\";", - "}", - "", - "// Test your code by modifying these values", - "checkObj(\"gift\");" - ], - "tail": [ - "" - ], - "solutions": [ - "var myObj = {\n gift: \"pony\",\n pet: \"kitten\",\n bed: \"sleigh\"\n};\nfunction checkObj(checkProp) {\n if(myObj.hasOwnProperty(checkProp)) {\n return myObj[checkProp];\n } else {\n return \"Not Found\";\n }\n}" - ], - "tests": [ - "assert(checkObj(\"gift\") === \"pony\", 'message: checkObj(\"gift\") should return \"pony\".');", - "assert(checkObj(\"pet\") === \"kitten\", 'message: checkObj(\"pet\") should return \"kitten\".');", - "assert(checkObj(\"house\") === \"Not Found\", 'message: checkObj(\"house\") should return \"Not Found\".');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Probar si un objeto tiene cierta propiedad", - "description": [ - "A veces es útil revisar si cierta propiedad existe o no en un objeto dado. Podemos usar el método de objetos .hasOwnProperty(nomprop) para determinar si un objeto tiene la propiedad nomprop. .hasOwnProperty() retorna true o false si la propiedad es encontrada o no.", - "Ejemplo", - "
var miObj = {
arriba: \"sombrero\",
abajo: \"pantalones\"
};
miObj.hasOwnProperty(\"arriba\"); // true
miObj.hasOwnProperty(\"medio\"); // false
", - "

Instrucciones

", - "Modifica la función checkObj que prueba si myObj tiene la propiedad checkProp. Si la propiedad es encontrada, retorna el valor de esa propiedad. Si no, retorna \"Not Found\"." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244cb", - "title": "Manipulating Complex Objects", - "description": [ - "Sometimes you may want to store data in a flexible Data Structure. A JavaScript object is one way to handle flexible data. They allow for arbitrary combinations of strings, numbers, booleans, arrays, functions, and objects.", - "Here's an example of a complex data structure:", - "
var ourMusic = [
{
\"artist\": \"Daft Punk\",
\"title\": \"Homework\",
\"release_year\": 1997,
\"formats\": [
\"CD\",
\"Cassette\",
\"LP\"
],
\"gold\": true
}
];
", - "This is an array which contains one object inside. The object has various pieces of metadata about an album. It also has a nested \"formats\" array. If you want to add more album records, you can do this by adding records to the top level array.", - "Objects hold data in a property, which has a key-value format. In the example above, \"artist\": \"Daft Punk\" is a property that has a key of \"artist\" and a value of \"Daft Punk\".", - "JavaScript Object Notation or JSON is a related data interchange format used to store data.", - "
{
\"artist\": \"Daft Punk\",
\"title\": \"Homework\",
\"release_year\": 1997,
\"formats\": [
\"CD\",
\"Cassette\",
\"LP\"
],
\"gold\": true
}
", - "Note
You will need to place a comma after every object in the array, unless it is the last object in the array.", - "
", - "Add a new album to the myMusic array. Add artist and title strings, release_year number, and a formats array of strings." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "var myMusic = [", - " {", - " \"artist\": \"Billy Joel\",", - " \"title\": \"Piano Man\",", - " \"release_year\": 1973,", - " \"formats\": [ ", - " \"CD\",", - " \"8T\",", - " \"LP\"", - " ],", - " \"gold\": true", - " }", - " // Add record here", - "];", - "" - ], - "tail": [ - "(function(x){ if (Array.isArray(x)) { return JSON.stringify(x); } return \"myMusic is not an array\"})(myMusic);" - ], - "solutions": [ - "var myMusic = [\n {\n \"artist\": \"Billy Joel\",\n \"title\": \"Piano Man\",\n \"release_year\": 1973,\n \"formats\": [ \n \"CS\", \n \"8T\", \n \"LP\" ],\n \"gold\": true\n }, \n {\n \"artist\": \"ABBA\",\n \"title\": \"Ring Ring\",\n \"release_year\": 1973,\n \"formats\": [ \n \"CS\", \n \"8T\", \n \"LP\",\n \"CD\",\n ]\n }\n];" - ], - "tests": [ - "assert(Array.isArray(myMusic), 'message: myMusic should be an array');", - "assert(myMusic.length > 1, 'message: myMusic should have at least two elements');", - "assert(typeof myMusic[1] === 'object', 'message: myMusic[1] should be an object');", - "assert(Object.keys(myMusic[1]).length > 3, 'message: myMusic[1] should have at least 4 properties');", - "assert(myMusic[1].hasOwnProperty('artist') && typeof myMusic[1].artist === 'string', 'message: myMusic[1] should contain an artist property which is a string');", - "assert(myMusic[1].hasOwnProperty('title') && typeof myMusic[1].title === 'string', 'message: myMusic[1] should contain a title property which is a string');", - "assert(myMusic[1].hasOwnProperty('release_year') && typeof myMusic[1].release_year === 'number', 'message: myMusic[1] should contain a release_year property which is a number');", - "assert(myMusic[1].hasOwnProperty('formats') && Array.isArray(myMusic[1].formats), 'message: myMusic[1] should contain a formats property which is an array');", - "assert(myMusic[1].formats.every(function(item) { return (typeof item === \"string\")}) && myMusic[1].formats.length > 1, 'message: formats should be an array of strings with at least two elements');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Manipula objetos complicados", - "description": [ - "Los objetos JavaScript son flexibles porque permiten Estructuras de Datos con combinaciones arbitrarias de cadenas, números, booleanos, vectores, funciones, y objetos.", - "Aquí está un ejemplo de un objeto complicado:", - "
var nuestraMusica = [
{
\"artista\": \"Daft Punk\",
\"titulo\": \"Homework\",
\"año_publicacion\": 1997,
\"formatos\": [
\"CD\",
\"Cassette\",
\"LP\" ],
\"oro\": true
}
];
", - "Este es un vector de objetos con diversos metadatos acerca de un álbum musical. Además tiene anidado un vector formatos. En el vector de nivel superior, pueden añadirse otros registros del álbum.", - "Nota
En vectores que tengan más de un objeto, necesitarás separar un objeto de otro mediante comas.", - "

Instrucciones

", - "Agrega un nuevo álbum al objeto myMusic. Agrega las cadenas artist y title, el número release_year y un vector de cadenas formats." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244cc", - "title": "Accessing Nested Objects", - "description": [ - "The sub-properties of objects can be accessed by chaining together the dot or bracket notation.", - "Here is a nested object:", - "
var ourStorage = {
\"desk\": {
\"drawer\": \"stapler\"
},
\"cabinet\": {
\"top drawer\": {
\"folder1\": \"a file\",
\"folder2\": \"secrets\"
},
\"bottom drawer\": \"soda\"
}
};
ourStorage.cabinet[\"top drawer\"].folder2; // \"secrets\"
ourStorage.desk.drawer; // \"stapler\"
", - "
", - "Access the myStorage object and assign the contents of the glove box property to the gloveBoxContents variable. Use bracket notation for properties with a space in their name." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var myStorage = {", - " \"car\": {", - " \"inside\": {", - " \"glove box\": \"maps\",", - " \"passenger seat\": \"crumbs\"", - " },", - " \"outside\": {", - " \"trunk\": \"jack\"", - " }", - " }", - "};", - "", - "var gloveBoxContents = undefined; // Change this line", - "" - ], - "tail": [ - "(function(x) { ", - " if(typeof x != 'undefined') { ", - " return \"gloveBoxContents = \" + x;", - " }", - " return \"gloveBoxContents is undefined\";", - "})(gloveBoxContents);" - ], - "solutions": [ - "var myStorage = { \n \"car\":{ \n \"inside\":{ \n \"glove box\":\"maps\",\n \"passenger seat\":\"crumbs\"\n },\n \"outside\":{ \n \"trunk\":\"jack\"\n }\n }\n};\nvar gloveBoxContents = myStorage.car.inside[\"glove box\"];" - ], - "tests": [ - "assert(gloveBoxContents === \"maps\", 'message: gloveBoxContents should equal \"maps\"');", - "assert(/=\\s*myStorage\\.car\\.inside\\[\\s*(\"|')glove box\\1\\s*\\]/g.test(code), 'message: Use dot and bracket notation to access myStorage');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a objetos anidados", - "description": [ - "Las sub-propiedades de los objetos pueden ser accesadas mediante encadenamiento de la notación punto o corchete.", - "Aquí está un objeto anidado:", - "
var nuestroAlmacen = {
\"escritorio\": {
\"cajon\": \"grapadora\"
},
\"armario\": {
\"cajón superior\": {
\"legajador1\": \"un archivo\",
\"legajador2\": \"secretos\"
},
\"cajón inferior\": \"gaseosa\"
}
}
nuestroAlmacen.armario[\"cajón superior\"].legajador2; // \"secretos\"
nuestroAlmacen.escritorio.cajon; // \"grapadora\"
", - "

Instrucciones

", - "Accede al objeto myStorage para recuperar el contenido de glove box. Usa notación corchete para las propiedades con un espacio en su nombre." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/accessing-nested-objects-in-json" - }, - { - "id": "56533eb9ac21ba0edf2244cd", - "title": "Accessing Nested Arrays", - "description": [ - "As we have seen in earlier examples, objects can contain both nested objects and nested arrays. Similar to accessing nested objects, Array bracket notation can be chained to access nested arrays.", - "Here is an example of how to access a nested array:", - "
var ourPets = [
{
animalType: \"cat\",
names: [
\"Meowzer\",
\"Fluffy\",
\"Kit-Cat\"
]
},
{
animalType: \"dog\",
names: [
\"Spot\",
\"Bowser\",
\"Frankie\"
]
}
];
ourPets[0].names[1]; // \"Fluffy\"
ourPets[1].names[0]; // \"Spot\"
", - "
", - "Retrieve the second tree from the variable myPlants using object dot and array bracket notation." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var myPlants = [", - " { ", - " type: \"flowers\",", - " list: [", - " \"rose\",", - " \"tulip\",", - " \"dandelion\"", - " ]", - " },", - " {", - " type: \"trees\",", - " list: [", - " \"fir\",", - " \"pine\",", - " \"birch\"", - " ]", - " } ", - "];", - "", - "// Only change code below this line", - "", - "var secondTree = \"\"; // Change this line", - "" - ], - "tail": [ - "(function(x) { ", - " if(typeof x != 'undefined') { ", - " return \"secondTree = \" + x;", - " }", - " return \"secondTree is undefined\";", - "})(secondTree);" - ], - "solutions": [ - "var myPlants = [\n { \n type: \"flowers\",\n list: [\n \"rose\",\n \"tulip\",\n \"dandelion\"\n ]\n },\n {\n type: \"trees\",\n list: [\n \"fir\",\n \"pine\",\n \"birch\"\n ]\n } \n];\n\n// Only change code below this line\n\nvar secondTree = myPlants[1].list[1];" - ], - "tests": [ - "assert(secondTree === \"pine\", 'message: secondTree should equal \"pine\"');", - "assert(/=\\s*myPlants\\[1\\].list\\[1\\]/.test(code), 'message: Use dot and bracket notation to access myPlants');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Acceder a vectores anidados", - "description": [ - "Como hemos visto en ejemplos anteriores, los objetos pueden contener objetos anidados y vectores anidados. De forma similar a acceder a objetos anidados, la notación corchete en vectores puede ser encadenada para acceder a vectores anidados.", - "Aquí está un ejemplo de como acceder a un vector anidado:", - "
var nuestrasMascotas = {
\"gatos\": [
\"Maullador\",
\"Blandito\",
\"Kit-Cat\"
],
\"perros\": [
\"Mancha\",
\"Bowser\",
\"Frankie\"
]
};
nuestrasMascotas.cats[1]; // \"Blandito\"
nuestrasMascotas.dogs[0]; // \"Mancha\"
", - "

Instrucciones

", - "Recupera el segundo arbol de la variable myPlants usando notación punto para objetos y notación corchete para vectores." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/access-array-data-with-indexes" - }, - { - "id": "56533eb9ac21ba0edf2244cf", - "title": "Record Collection", - "description": [ - "You are given a JSON object representing a part of your musical album collection. Each album has several properties and a unique id number as its key. Not all albums have complete information.", - "Write a function which takes an album's id (like 2548), a property prop (like \"artist\" or \"tracks\"), and a value (like \"Addicted to Love\") to modify the data in this collection.", - "If prop isn't \"tracks\" and value isn't empty (\"\"), update or set the value for that record album's property.", - "Your function must always return the entire collection object.", - "There are several rules for handling incomplete data:", - "If prop is \"tracks\" but the album doesn't have a \"tracks\" property, create an empty array before adding the new value to the album's corresponding property.", - "If prop is \"tracks\" and value isn't empty (\"\"), push the value onto the end of the album's existing tracks array.", - "If value is empty (\"\"), delete the given prop property from the album.", - "Hints
Use bracket notation when accessing object properties with variables.", - "Push is an array method you can read about on Mozilla Developer Network.", - "You may refer back to Manipulating Complex Objects Introducing JavaScript Object Notation (JSON) for a refresher." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Setup", - "var collection = {", - " \"2548\": {", - " \"album\": \"Slippery When Wet\",", - " \"artist\": \"Bon Jovi\",", - " \"tracks\": [ ", - " \"Let It Rock\", ", - " \"You Give Love a Bad Name\" ", - " ]", - " },", - " \"2468\": {", - " \"album\": \"1999\",", - " \"artist\": \"Prince\",", - " \"tracks\": [ ", - " \"1999\", ", - " \"Little Red Corvette\" ", - " ]", - " },", - " \"1245\": {", - " \"artist\": \"Robert Palmer\",", - " \"tracks\": [ ]", - " },", - " \"5439\": {", - " \"album\": \"ABBA Gold\"", - " }", - "};", - "// Keep a copy of the collection for tests", - "var collectionCopy = JSON.parse(JSON.stringify(collection));", - "", - "// Only change code below this line", - "function updateRecords(id, prop, value) {", - " ", - " ", - " return collection;", - "}", - "", - "// Alter values below to test your code", - "updateRecords(5439, \"artist\", \"ABBA\");", - "" - ], - "tail": [ - ";(function(x) { return \"collection = \\n\" + JSON.stringify(x, '\\n', 2); })(collection);" - ], - "solutions": [ - "var collection = {\n 2548: {\n album: \"Slippery When Wet\",\n artist: \"Bon Jovi\",\n tracks: [ \n \"Let It Rock\", \n \"You Give Love a Bad Name\" \n ]\n },\n 2468: {\n album: \"1999\",\n artist: \"Prince\",\n tracks: [ \n \"1999\", \n \"Little Red Corvette\" \n ]\n },\n 1245: {\n artist: \"Robert Palmer\",\n tracks: [ ]\n },\n 5439: {\n album: \"ABBA Gold\"\n }\n};\n// Keep a copy of the collection for tests\nvar collectionCopy = JSON.parse(JSON.stringify(collection));\n\n// Only change code below this line\nfunction updateRecords(id, prop, value) {\n if(value === \"\") delete collection[id][prop];\n else if(prop === \"tracks\") {\n collection[id][prop] = collection[id][prop] || [];\n collection[id][prop].push(value);\n } else {\n collection[id][prop] = value;\n }\n \n return collection;\n}" - ], - "tests": [ - "collection = collectionCopy; assert(updateRecords(5439, \"artist\", \"ABBA\")[5439][\"artist\"] === \"ABBA\", 'message: After updateRecords(5439, \"artist\", \"ABBA\"), artist should be \"ABBA\"');", - "assert(updateRecords(5439, \"tracks\", \"Take a Chance on Me\")[5439][\"tracks\"].pop() === \"Take a Chance on Me\", 'message: After updateRecords(5439, \"tracks\", \"Take a Chance on Me\"), tracks should have \"Take a Chance on Me\" as the last element.');", - "updateRecords(2548, \"artist\", \"\"); assert(!collection[2548].hasOwnProperty(\"artist\"), 'message: After updateRecords(2548, \"artist\", \"\"), artist should not be set');", - "assert(updateRecords(1245, \"tracks\", \"Addicted to Love\")[1245][\"tracks\"].pop() === \"Addicted to Love\", 'message: After updateRecords(1245, \"tracks\", \"Addicted to Love\"), tracks should have \"Addicted to Love\" as the last element.');", - "assert(updateRecords(2468, \"tracks\", \"Free\")[2468][\"tracks\"][0] === \"1999\", 'message: After updateRecords(2468, \"tracks\", \"Free\"), tracks should have \"1999\" as the first element.');", - "updateRecords(2548, \"tracks\", \"\"); assert(!collection[2548].hasOwnProperty(\"tracks\"), 'message: After updateRecords(2548, \"tracks\", \"\"), tracks should not be set');", - "assert(updateRecords(1245, \"album\", \"Riptide\")[1245][\"album\"] === \"Riptide\", 'message: After updateRecords(1245, \"album\", \"Riptide\"), album should be \"Riptide\"');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Colección de registros", - "description": [ - "Se te da un objeto que representa (una pequeña parte de) tu colección de grabaciones. Cada álbum es identificado por un número id único y tiene varias propiedades. No todos los álbumes tienen la información completa.", - "Escribe una función que reciba un id, una propiedad (prop) y un valor (value).", - "Para el id dado, en la colección collection:", - "Si el valor value no está en blanco (value !== \"\") y prop no es \"tracks\" entonces actualiza o establece el valor de la propiedad prop.", - "Si la propiedad prop es \"tracks\" y value no está en blanco, empuja (push) el valor value al final del vector tracks.", - "Si el valor value está en blanco, elimina esa prop.", - "Siempre retorna el objeto collection entero.", - "Nota
No olvides usar notación corchete cuando accedes a propiedades de objetos con variables." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb1bdef", - "title": "Iterate with JavaScript While Loops", - "description": [ - "You can run the same code multiple times by using a loop.", - "The first type of loop we will learn is called a \"while\" loop because it runs \"while\" a specified condition is true and stops once that condition is no longer true.", - "
var ourArray = [];
var i = 0;
while(i < 5) {
ourArray.push(i);
i++;
}
", - "Let's try getting a while loop to work by pushing values to an array.", - "
", - "Push the numbers 0 through 4 to myArray using a while loop." - ], - "challengeSeed": [ - "// Setup", - "var myArray = [];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var myArray = [];\nvar i = 0;\nwhile(i < 5) {\n myArray.push(i);\n i++;\n}" - ], - "tests": [ - "assert(code.match(/while/g), 'message: You should be using a while loop for this.');", - "assert.deepEqual(myArray, [0,1,2,3,4], 'message: myArray should equal [0,1,2,3,4].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Iterar con JavaScript con ciclos while", - "description": [ - "Puede ejecutar el mismo código varias veces mediante el uso de un ciclo.", - "Otro tipo de ciclo de JavaScript se llama un ciclo \"while\", ya que se ejecuta, \"mientras que\" algo sea cierto y se detiene una vez que ya no sea así.", - "var ourArray = [];", - "var i = 0;", - "while(i < 5) {", - "  ourArray.push(i);", - "  i++;", - "}", - "Intentemos que un ciclo while empuje valores en un vector.", - "

Instrucciones

", - "Empuja los números de 0 a 4 para myArray utilizando un ciclo while." - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb5bdef", - "title": "Iterate with JavaScript For Loops", - "description": [ - "You can run the same code multiple times by using a loop.", - "The most common type of JavaScript loop is called a \"for loop\" because it runs \"for\" a specific number of times.", - "For loops are declared with three optional expressions separated by semicolons:", - "for ([initialization]; [condition]; [final-expression])", - "The initialization statement is executed one time only before the loop starts. It is typically used to define and setup your loop variable.", - "The condition statement is evaluated at the beginning of every loop iteration and will continue as long as it evaluates to true. When condition is false at the start of the iteration, the loop will stop executing. This means if condition starts as false, your loop will never execute.", - "The final-expression is executed at the end of each loop iteration, prior to the next condition check and is usually used to increment or decrement your loop counter.", - "In the following example we initialize with i = 0 and iterate while our condition i < 5 is true. We'll increment i by 1 in each loop iteration with i++ as our final-expression.", - "
var ourArray = [];
for (var i = 0; i < 5; i++) {
ourArray.push(i);
}
", - "ourArray will now contain [0,1,2,3,4].", - "
", - "Use a for loop to work to push the values 1 through 5 onto myArray." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [];", - "", - "for (var i = 0; i < 5; i++) {", - " ourArray.push(i);", - "}", - "", - "// Setup", - "var myArray = [];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "if (typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var ourArray = [];\nfor (var i = 0; i < 5; i++) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 1; i < 6; i++) {\n myArray.push(i);\n}" - ], - "tests": [ - "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", - "assert.deepEqual(myArray, [1,2,3,4,5], 'message: myArray should equal [1,2,3,4,5].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Iterar en JavaScript con ciclos for", - "description": [ - "Puede ejecutar el mismo código varias veces mediante el uso de un ciclo.", - "El tipo más común de bucle de JavaScript se llama \"ciclo for\"porque se ejecuta \"por\" (for) un número específico de veces.", - "Los ciclos for se declaran con tres expresiones opcionales separadas por punto y coma:", - "for ([inicialización]; [condición]; [expresión-final])", - "La inicialización se ejecuta sólo una vez antes de que empiece el ciclo. Normalmente se utiliza para definir e inicializar su variable de ciclo. ", - "La expresión condición se evalúa al principio de cada iteración del ciclo y continuará en el ciclo siempre y cuando sea verdadera (true). Cuando la condición sea falsa (false) al comienzo de la iteración, se detendrá la ejecución del ciclo. Esto significa que si la condición inicia en el valor falso false, el ciclo no se ejecutará. ", - "La expresión final se ejecuta al final de cada repetición del ciclo, antes del siguiente chequeo de la condición y se utiliza generalmente para aumentar o disminuir el contador del ciclo.", - "En el siguiente ejemplo inicializamos con i = 0 e iteramos mientras nuestra condición i <5 sea verdadera. Vamos a incrementar i en 1 en cada iteración del ciclo con i++ como nuestra expresión final. ", - "var ourArray = [];", - "for (var i = 0; i < 5; i++) {", - "  ourArray.push(i);", - "}", - "ourArray ahora contendrá [0,1,2,3,4].", - "

Instrucciones

", - "Vamos a utilizar un ciclo for para empujar los valores del 1 al 5 en myArray." - ] - } - } - }, - { - "id": "56104e9e514f539506016a5c", - "title": "Iterate Odd Numbers With a For Loop", - "description": [ - "For loops don't have to iterate one at a time. By changing our final-expression, we can count by even numbers.", - "We'll start at i = 0 and loop while i < 10. We'll increment i by 2 each loop with i += 2.", - "
var ourArray = [];
for (var i = 0; i < 10; i += 2) {
ourArray.push(i);
}
", - "ourArray will now contain [0,2,4,6,8].", - "Let's change our initialization so we can count by odd numbers.", - "
", - "Push the odd numbers from 1 through 9 to myArray using a for loop." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [];", - "", - "for (var i = 0; i < 10; i += 2) {", - " ourArray.push(i);", - "}", - "", - "// Setup", - "var myArray = [];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var ourArray = [];\nfor (var i = 0; i < 10; i += 2) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 1; i < 10; i += 2) {\n myArray.push(i);\n}" - ], - "tests": [ - "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", - "assert.deepEqual(myArray, [1,3,5,7,9], 'message: myArray should equal [1,3,5,7,9].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Itera por los números pares con un ciclo for", - "description": [ - "Los ciclos for no siempre iteran incrementado de a uno. Cambiando nuestra expresión final, podemos contar los números pares.", - "Vamos a empezar con i = 0 e iterar mientras i <10. Vamos a incrementar i de a 2 en cada iteración i + = 2. ", - "var ourArray = [];", - "for (var i = 0; i < 10; i += 2) {", - "  ourArray.push(i);", - "}", - "ourArray ahora contendrá [0,2,4,6,8].", - "Vamos a cambiar nuestra inicialización y expresión final para que podamos contar los números impares.", - "

Instrucciones

", - "Empuja los números impares del 1 al 9 en myArray utilizando un ciclo for." - ] - } - } - }, - { - "id": "56105e7b514f539506016a5e", - "title": "Count Backwards With a For Loop", - "description": [ - "A for loop can also count backwards, so long as we can define the right conditions.", - "In order to count backwards by twos, we'll need to change our initialization, condition, and final-expression.", - "We'll start at i = 10 and loop while i > 0. We'll decrement i by 2 each loop with i -= 2.", - "
var ourArray = [];
for (var i=10; i > 0; i-=2) {
ourArray.push(i);
}
", - "ourArray will now contain [10,8,6,4,2].", - "Let's change our initialization and final-expression so we can count backward by twos by odd numbers.", - "
", - "Push the odd numbers from 9 through 1 to myArray using a for loop." - ], - "challengeSeed": [ - "// Example", - "var ourArray = [];", - "", - "for (var i = 10; i > 0; i -= 2) {", - " ourArray.push(i);", - "}", - "", - "// Setup", - "var myArray = [];", - "", - "// Only change code below this line.", - "", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var ourArray = [];\nfor (var i = 10; i > 0; i -= 2) {\n ourArray.push(i);\n}\nvar myArray = [];\nfor (var i = 9; i > 0; i -= 2) {\n myArray.push(i);\n}" - ], - "tests": [ - "assert(code.match(/for\\s*\\(/g).length > 1, 'message: You should be using a for loop for this.');", - "assert(code.match(/myArray.push/), 'message: You should be using the array method push.');", - "assert.deepEqual(myArray, [9,7,5,3,1], 'message: myArray should equal [9,7,5,3,1].');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Cuenta hacia atrás con un ciclo for", - "description": [ - "Un ciclo también puede contar hacia atrás, siempre y cuando definamos las condiciones adecuadas.", - "Para contar hacia atrás de dos en dos, tendremos que cambiar nuestra inicialización, la condición y la última-expresión.", - "Vamos a empezar con i = 10 e iteraremos mientras i > 0. Vamos a decrementar i de a 2 por cada iteración con i -= 2. ", - "var ourArray = [];", - "for (var i = 10; i > 0; i -= 2) {", - "  ourArray.push(i);", - "}", - "ourArray ahora contendrá [10,8,6,4,2].", - "Vamos a cambiar nuestra inicialización y la expresión final para que podamos contar hacia atrás de dos en dos pero números impares.", - "

Instrucciones

", - "Empuja los números impares del 9 a 1 en myArray utilizando un ciclo for." - ] - } - } - }, - { - "id": "5675e877dbd60be8ad28edc6", - "title": "Iterate Through an Array with a For Loop", - "description": [ - "A common task in JavaScript is to iterate through the contents of an array. One way to do that is with a for loop. This code will output each element of the array arr to the console:", - "
var arr = [10,9,8,7,6];
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
", - "Remember that Arrays have zero-based numbering, which means the last index of the array is length - 1. Our condition for this loop is i < arr.length, which stops when i is at length - 1.", - "
", - "Declare and initialize a variable total to 0. Use a for loop to add the value of each element of the myArr array to total." - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "// Example", - "var ourArr = [ 9, 10, 11, 12];", - "var ourTotal = 0;", - "", - "for (var i = 0; i < ourArr.length; i++) {", - " ourTotal += ourArr[i];", - "}", - "", - "// Setup", - "var myArr = [ 2, 3, 4, 5, 6];", - "", - "// Only change code below this line", - "", - "" - ], - "tail": [ - "(function(){if(typeof total !== 'undefined') { return \"total = \" + total; } else { return \"total is undefined\";}})()" - ], - "solutions": [ - "var ourArr = [ 9, 10, 11, 12];\nvar ourTotal = 0;\n\nfor (var i = 0; i < ourArr.length; i++) {\n ourTotal += ourArr[i];\n}\n\nvar myArr = [ 2, 3, 4, 5, 6];\nvar total = 0;\n\nfor (var i = 0; i < myArr.length; i++) {\n total += myArr[i];\n}" - ], - "tests": [ - "assert(code.match(/var.*?total\\s*=\\s*0.*?;/), 'message: total should be declared and initialized to 0');", - "assert(total === 20, 'message: total should equal 20');", - "assert(code.match(/for\\s*\\(/g).length > 1 && code.match(/myArr\\s*\\[/), 'message: You should use a for loop to iterate through myArr');", - "assert(!code.match(/total[\\s\\+\\-]*=\\s*(\\d(?!\\s*[;,])|[1-9])/g), 'message: Do not set total to 20 directly');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Iterar a través de un vector con un ciclo for", - "description": [ - "Una tarea común en JavaScript es iterar a traves del contenido de un vector. Una manera de hacerlo es con un ciclo for. Este código imprimirá cada elemento del vector arr en la consola:", - "
var arr = [10,9,8,7,6];
for (var i=0; i < arr.length; i++) {
console.log(arr[i]);
}
", - "Recuerda que los vectores tienen numeración que comienza en cero, la cual significa que el último índice del vector es su longitud - 1. Nuestra condición para este ciclo es i < arr.length, que lo detendrá cuando i sea la longitud - 1.", - "

Instrucciones

", - "Declara e inicializa una variable total en 0. Usa un ciclo for para añadir el valor de cada elemento del vector myArr a total." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244e1", - "title": "Nesting For Loops", - "description": [ - "If you have a multi-dimensional array, you can use the same logic as the prior waypoint to loop through both the array and any sub-arrays. Here is an example:", - "
var arr = [
[1,2], [3,4], [5,6]
];
for (var i=0; i < arr.length; i++) {
for (var j=0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}
", - "This outputs each sub-element in arr one at a time. Note that for the inner loop, we are checking the .length of arr[i], since arr[i] is itself an array.", - "
", - "Modify function multiplyAll so that it multiplies the product variable by each number in the sub-arrays of arr" - ], - "releasedOn": "January 1, 2016", - "challengeSeed": [ - "function multiplyAll(arr) {", - " var product = 1;", - " // Only change code below this line", - " ", - " // Only change code above this line", - " return product;", - "}", - "", - "// Modify values below to test your code", - "multiplyAll([[1,2],[3,4],[5,6,7]]);", - "" - ], - "tail": [ - "" - ], - "solutions": [ - "function multiplyAll(arr) {\n var product = 1;\n for (var i = 0; i < arr.length; i++) {\n for (var j = 0; j < arr[i].length; j++) {\n product *= arr[i][j];\n }\n }\n return product;\n}\n\nmultiplyAll([[1,2],[3,4],[5,6,7]]);" - ], - "tests": [ - "assert(multiplyAll([[1],[2],[3]]) === 6, 'message: multiplyAll([[1],[2],[3]]) should return 6');", - "assert(multiplyAll([[1,2],[3,4],[5,6,7]]) === 5040, 'message: multiplyAll([[1,2],[3,4],[5,6,7]]) should return 5040');", - "assert(multiplyAll([[5,1],[0.2, 4, 0.5],[3, 9]]) === 54, 'message: multiplyAll([[5,1],[0.2, 4, 0.5],[3, 9]]) should return 54');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Anidar ciclos for", - "description": [ - "Si tienes una matriz multi-dimensional, puedes usar la misma lógica del punto anterior para iterar a través de un vector y cualquier sub-vector. Aquí está un ejemplo:", - "
var arr = [
[1,2], [3,4], [5,6]
];
for (var i=0; i < arr.length; i++) {
for (var j=0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}
", - "Esto imprime cada sub-elemento en arr uno a la vez. Nota que en el ciclo interior, estamos comprobando la longitud .length de arr[i], ya que arr[i] es por si mismo un vector.", - "

Instrucciones

", - "Modifica la función multiplyAll de manera que esta multiplique la variable product por cada número en los sub-vectores de arr" - ] - } - } - }, - { - "id": "5a2efd662fb457916e1fe604", - "title": "Iterate with JavaScript Do...While Loops", - "description": [ - "You can run the same code multiple times by using a loop.", - "The next type of loop you will learn is called a \"do...while\" loop because it first will \"do\" one pass of the code inside the loop no matter what, and then it runs \"while\" a specified condition is true and stops once that condition is no longer true. Let's look at an example.", - "
var ourArray = [];
var i = 0;
do {
ourArray.push(i);
i++;
} while (i < 5);
", - "This behaves just as you would expect with any other type of loop, and the resulting array will look like [0, 1, 2, 3, 4]. However, what makes the do...while different from other loops is how it behaves when the condition fails on the first check. Let's see this in action.", - "Here is a regular while loop that will run the code in the loop as long as i < 5.", - "
var ourArray = [];
var i = 5;
while (i < 5) {
ourArray.push(i);
i++;
}
", - "Notice that we initialize the value of i to be 5. When we execute the next line, we notice that i is not less than 5. So we do not execute the code inside the loop. The result is that ourArray will end up with nothing added to it, so it will still look like this [] when all the code in the example above finishes running.", - "Now, take a look at a do...while loop.", - "
var ourArray = [];
var i = 5;
do {
ourArray.push(i);
i++;
} while (i < 5);
", - "In this case, we initialize the value of i as 5, just like we did with the while loop. When we get to the next line, there is no check for the value of i, so we go to the code inside the curly braces and execute it. We will add one element to the array and increment i before we get to the condition check. Then, when we get to checking if i < 5 see that i is now 6, which fails the conditional check. So we exit the loop and are done. At the end of the above example, the value of ourArray is [5].", - "Essentially, a do...while loop ensures that the code inside the loop will run at least once.", - "Let's try getting a do...while loop to work by pushing values to an array.", - "
", - "Change the while loop in the code to a do...while loop so that the loop will push the number 10 to myArray, and i will be equal to 11 when your code finishes running." - ], - "challengeSeed": [ - "// Setup", - "var myArray = [];", - "var i = 10;", - "", - "// Only change code below this line.", - "", - "while (i < 5) {", - " myArray.push(i);", - " i++;", - "}", - "" - ], - "tail": [ - "if(typeof myArray !== \"undefined\"){(function(){return myArray;})();}" - ], - "solutions": [ - "var myArray = [];\nvar i = 10;\ndo {\n myArray.push(i);\n i++;\n} while (i < 5)" - ], - "tests": [ - "assert(code.match(/do/g), 'message: You should be using a do...while loop for this.');", - "assert.deepEqual(myArray, [10], 'message: myArray should equal [10].');", - "assert.deepEqual(i, 11, 'message: i should equal 11');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - } - }, - { - "id": "5688e62ea601b2482ff8422b", - "title": "Profile Lookup", - "description": [ - "We have an array of objects representing different people in our contacts lists.", - "A lookUpProfile function that takes name and a property (prop) as arguments has been pre-written for you.", - "The function should check if name is an actual contact's firstName and the given property (prop) is a property of that contact.", - "If both are true, then return the \"value\" of that property.", - "If name does not correspond to any contacts then return \"No such contact\"", - "If prop does not correspond to any valid properties of a contact found to match name then return \"No such property\"" - ], - "releasedOn": "January 8, 2016", - "challengeSeed": [ - "//Setup", - "var contacts = [", - " {", - " \"firstName\": \"Akira\",", - " \"lastName\": \"Laine\",", - " \"number\": \"0543236543\",", - " \"likes\": [\"Pizza\", \"Coding\", \"Brownie Points\"]", - " },", - " {", - " \"firstName\": \"Harry\",", - " \"lastName\": \"Potter\",", - " \"number\": \"0994372684\",", - " \"likes\": [\"Hogwarts\", \"Magic\", \"Hagrid\"]", - " },", - " {", - " \"firstName\": \"Sherlock\",", - " \"lastName\": \"Holmes\",", - " \"number\": \"0487345643\",", - " \"likes\": [\"Intriguing Cases\", \"Violin\"]", - " },", - " {", - " \"firstName\": \"Kristian\",", - " \"lastName\": \"Vos\",", - " \"number\": \"unknown\",", - " \"likes\": [\"JavaScript\", \"Gaming\", \"Foxes\"]", - " }", - "];", - "", - "", - "function lookUpProfile(name, prop){", - "// Only change code below this line", - "", - "// Only change code above this line", - "}", - "", - "// Change these values to test your function", - "lookUpProfile(\"Akira\", \"likes\");" - ], - "solutions": [ - "var contacts = [\n {\n \"firstName\": \"Akira\",\n \"lastName\": \"Laine\",\n \"number\": \"0543236543\",\n \"likes\": [\"Pizza\", \"Coding\", \"Brownie Points\"]\n },\n {\n \"firstName\": \"Harry\",\n \"lastName\": \"Potter\",\n \"number\": \"0994372684\",\n \"likes\": [\"Hogwarts\", \"Magic\", \"Hagrid\"]\n },\n {\n \"firstName\": \"Sherlock\",\n \"lastName\": \"Holmes\",\n \"number\": \"0487345643\",\n \"likes\": [\"Intriguing Cases\", \"Violin\"]\n },\n {\n \"firstName\": \"Kristian\",\n \"lastName\": \"Vos\",\n \"number\": \"unknown\",\n \"likes\": [\"JavaScript\", \"Gaming\", \"Foxes\"]\n },\n];\n\n\n//Write your function in between these comments\nfunction lookUpProfile(name, prop){\n for(var i in contacts){\n if(contacts[i].firstName === name) {\n return contacts[i][prop] || \"No such property\";\n }\n }\n return \"No such contact\";\n}\n//Write your function in between these comments\n\nlookUpProfile(\"Akira\", \"likes\");" - ], - "tests": [ - "assert(lookUpProfile('Kristian','lastName') === \"Vos\", 'message: \"Kristian\", \"lastName\" should return \"Vos\"');", - "assert.deepEqual(lookUpProfile(\"Sherlock\", \"likes\"), [\"Intriguing Cases\", \"Violin\"], 'message: \"Sherlock\", \"likes\" should return [\"Intriguing Cases\", \"Violin\"]');", - "assert(typeof lookUpProfile(\"Harry\", \"likes\") === \"object\", 'message: \"Harry\",\"likes\" should return an array');", - "assert(lookUpProfile(\"Bob\", \"number\") === \"No such contact\", 'message: \"Bob\", \"number\" should return \"No such contact\"');", - "assert(lookUpProfile(\"Bob\", \"potato\") === \"No such contact\", 'message: \"Bob\", \"potato\" should return \"No such contact\"');", - "assert(lookUpProfile(\"Akira\", \"address\") === \"No such property\", 'message: \"Akira\", \"address\" should return \"No such property\"');" - ], - "type": "checkpoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Búsqueda de perfiles", - "description": [ - "Tenemos un vector de objetos que representan diferentes personas en nuestra lista de contactos.", - "Una función lookUp que recibe el nombre (firstName) y una propiedad (prop) como argumentos ya ha sido escrita previamente para ti.", - "La función debe comprobar si firstName es un nombre (firstName) de algún contacto y si la propiedad dada (prop) es una propiedad de ese contacto.", - "Si ambos son verdaderos, entonces retorna el valor (value) de esa propiedad.", - "Si firstName no corresponde a ningun contacto entonces retorna \"No such contact\"", - "Si prop no corresponde a ninguna propiedad válida entonces retorna \"No such property\"", - "" - ] - } - } - }, - { - "id": "cf1111c1c11feddfaeb9bdef", - "title": "Generate Random Fractions with JavaScript", - "description": [ - "Random numbers are useful for creating random behavior.", - "JavaScript has a Math.random() function that generates a random decimal number between 0 (inclusive) and not quite up to 1 (exclusive). Thus Math.random() can return a 0 but never quite return a 1", - "Note
Like Storing Values with the Equal Operator, all function calls will be resolved before the return executes, so we can return the value of the Math.random() function.", - "
", - "Change randomFraction to return a random number instead of returning 0." - ], - "challengeSeed": [ - "function randomFraction() {", - "", - " // Only change code below this line.", - "", - " return 0;", - "", - " // Only change code above this line.", - "}" - ], - "tail": [ - "(function(){return randomFraction();})();" - ], - "solutions": [ - "function randomFraction() {\n return Math.random();\n}" - ], - "tests": [ - "assert(typeof randomFraction() === \"number\", 'message: randomFraction should return a random number.');", - "assert((randomFraction()+''). match(/\\./g), 'message: The number returned by randomFraction should be a decimal.');", - "assert(code.match(/Math\\.random/g).length >= 0, 'message: You should be using Math.random to generate the random decimal number.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Generar fracciones al azar con JavaScript", - "description": [ - "Los números aleatorios son útiles para crear un comportamiento aleatorio.", - "JavaScript tiene una función Math.random() que genera un número decimal aleatorio.", - "

Instrucciones

", - "Cambia randomFraction para que devuelva un número al azar en lugar de devolver 0.", - "Ten en cuenta que puedes retornar lo retornado por una función, igual que harías para devolver una variable o valor." - ] - } - } - }, - { - "id": "cf1111c1c12feddfaeb1bdef", - "title": "Generate Random Whole Numbers with JavaScript", - "description": [ - "It's great that we can generate random decimal numbers, but it's even more useful if we use it to generate random whole numbers.", - "
  1. Use Math.random() to generate a random decimal.
  2. Multiply that random decimal by 20.
  3. Use another function, Math.floor() to round the number down to its nearest whole number.
", - "Remember that Math.random() can never quite return a 1 and, because we're rounding down, it's impossible to actually get 20. This technique will give us a whole number between 0 and 19.", - "Putting everything together, this is what our code looks like:", - "Math.floor(Math.random() * 20);", - "We are calling Math.random(), multiplying the result by 20, then passing the value to Math.floor() function to round the value down to the nearest whole number.", - "
", - "Use this technique to generate and return a random whole number between 0 and 9." - ], - "challengeSeed": [ - "var randomNumberBetween0and19 = Math.floor(Math.random() * 20);", - "", - "function randomWholeNum() {", - "", - " // Only change code below this line.", - "", - " return Math.random();", - "}" - ], - "tail": [ - "(function(){return randomWholeNum();})();" - ], - "solutions": [ - "var randomNumberBetween0and19 = Math.floor(Math.random() * 20);\nfunction randomWholeNum() {\n return Math.floor(Math.random() * 10);\n}" - ], - "tests": [ - "assert(typeof randomWholeNum() === \"number\" && (function(){var r = randomWholeNum();return Math.floor(r) === r;})(), 'message: The result of randomWholeNum should be a whole number.');", - "assert(code.match(/Math.random/g).length > 1, 'message: You should be using Math.random to generate a random number.');", - "assert(code.match(/\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?\\*\\s*?10[\\D]\\s*?/g) || code.match(/\\s*?10\\s*?\\*\\s*?Math.random\\s*?\\(\\s*?\\)\\s*?/g), 'message: You should have multiplied the result of Math.random by 10 to make it a number that is between zero and nine.');", - "assert(code.match(/Math.floor/g).length > 1, 'message: You should use Math.floor to remove the decimal part of the number.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Genera números aleatorios enteros con JavaScript", - "description": [ - "Es muy bueno que podamos generar números decimales al azar, pero es aún más útil si lo utilizamos para generar números enteros aleatorios.", - "En primer lugar, vamos a usar Math.random() para generar un decimal aleatorio.", - "Entonces vamos a multiplicar este decimal azar por 20.", - "Por último, vamos a usar otra función, Math.floor() para redondear el número hasta su número entero más próximo.", - "Esta técnica nos da un número entero entre 0 y 19.", - "Tenga en cuenta que debido a que estamos redondeando, es imposible obtener 20.", - "Poniendo todo junto, así es como se ve nuestro código:", - "Math.floor(Math.random() * 20);", - "¿Ves como Math.floor toma (Math.random() * 20) como su argumento? Así es - puedes pasar el resultado de un función como argumento de otra función.", - "

Instrucciones

", - "Usa esta técnica para generar y devolver un número entero aleatorio entre 0 y 9." - ] - } - } - }, - { - "id": "cf1111c1c12feddfaeb2bdef", - "title": "Generate Random Whole Numbers within a Range", - "description": [ - "Instead of generating a random number between zero and a given number like we did before, we can generate a random number that falls within a range of two specific numbers.", - "To do this, we'll define a minimum number min and a maximum number max.", - "Here's the formula we'll use. Take a moment to read it and try to understand what this code is doing:", - "Math.floor(Math.random() * (max - min + 1)) + min", - "
", - "Create a function called randomRange that takes a range myMin and myMax and returns a random number that's greater than or equal to myMin, and is less than or equal to myMax, inclusive." - ], - "challengeSeed": [ - "// Example", - "function ourRandomRange(ourMin, ourMax) {", - "", - " return Math.floor(Math.random() * (ourMax - ourMin + 1)) + ourMin;", - "}", - "", - "ourRandomRange(1, 9);", - "", - "// Only change code below this line.", - "", - "function randomRange(myMin, myMax) {", - "", - " return 0; // Change this line", - "", - "}", - "", - "// Change these values to test your function", - "var myRandom = randomRange(5, 15);" - ], - "tail": [ - "var calcMin = 100;", - "var calcMax = -100;", - "for(var i = 0; i < 100; i++) {", - " var result = randomRange(5,15);", - " calcMin = Math.min(calcMin, result);", - " calcMax = Math.max(calcMax, result);", - "}", - "(function(){", - " if(typeof myRandom === 'number') {", - " return \"myRandom = \" + myRandom;", - " } else {", - " return \"myRandom undefined\";", - " }", - "})();" - ], - "solutions": [ - "function randomRange(myMin, myMax) {\n return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;\n}" - ], - "tests": [ - "assert(calcMin === 5, 'message: The lowest random number that can be generated by randomRange should be equal to your minimum number, myMin.');", - "assert(calcMax === 15, 'message: The highest random number that can be generated by randomRange should be equal to your maximum number, myMax.');", - "assert(randomRange(0,1) % 1 === 0 , 'message: The random number generated by randomRange should be an integer, not a decimal.');", - "assert((function(){if(code.match(/myMax/g).length > 1 && code.match(/myMin/g).length > 2 && code.match(/Math.floor/g) && code.match(/Math.random/g)){return true;}else{return false;}})(), 'message: randomRange should use both myMax and myMin, and return a random number in your range.');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": { - "es": { - "title": "Genera números aleatorios enteros dentro de un rango", - "description": [ - "En lugar de generar un número aleatorio entre cero y un número dado como lo hicimos antes, podemos generar un número aleatorio que caiga dentro de un rango de dos números específicos.", - "Para ello, vamos a definir un número mínimo min y un número máximo max.", - "He aquí la fórmula que utilizaremos. Tómate un momento para leer y tratar de entender lo que el código está haciendo: ", - "Math.floor(Math.random() * (max - min + 1)) + min", - "Definir dos variables: myMin y myMax, y asignales valores enteros.", - "

Instrucciones

", - "A continuación, crea una función llamada myFunction que devuelva un número aleatorio mayor o igual a myMin, y menor o igual a myMax. " - ] - } - } - }, - { - "id": "587d7b7e367417b2b2512b23", - "title": "Use the parseInt Function", - "description": [ - "The parseInt() function parses a string and returns an integer. Here's an example:", - "var a = parseInt(\"007\");", - "The above function converts the string \"007\" to an integer 7. If the first character in the string can't be converted into a number, then it returns NaN.", - "
", - "Use parseInt() in the convertToInteger function so it converts the input string str into an integer, and returns it." - ], - "challengeSeed": [ - "function convertToInteger(str) {", - " ", - "}", - "", - "convertToInteger(\"56\");" - ], - "tail": [], - "solutions": [], - "tests": [ - "assert(/parseInt/g.test(code), 'message: convertToInteger should use the parseInt() function');", - "assert(typeof(convertToInteger(\"56\")) === \"number\", 'message: convertToInteger(\"56\") should return a number');", - "assert(convertToInteger(\"56\") === 56, 'message: convertToInteger(\"56\") should return 56');", - "assert(convertToInteger(\"77\") === 77, 'message: convertToInteger(\"77\") should return 77');", - "assert.isNaN(convertToInteger(\"JamesBond\"), 'message: convertToInteger(\"JamesBond\") should return NaN');" - ], - "type": "waypoint", - "challengeType": 1, - "translations": {}, - "releasedOn": "February 17, 2017" - }, - { - "id": "587d7b7e367417b2b2512b22", - "title": "Use the parseInt Function with a Radix", - "description": [ - "The parseInt() function parses a string and returns an integer. It takes a second argument for the radix, which specifies the base of the number in the string. The radix can be an integer between 2 and 36.", - "The function call looks like:", - "parseInt(string, radix);", - "And here's an example:", - "var a = parseInt(\"11\", 2);", - "The radix variable says that \"11\" is in the binary system, or base 2. This example converts the string \"11\" to an integer 3.", - "
", - "Use parseInt() in the convertToInteger function so it converts a binary number to an integer and returns it." - ], - "challengeSeed": [ - "function convertToInteger(str) {", - " ", - "}", - "", - "convertToInteger(\"10011\");" - ], - "tail": [], - "solutions": [], - "tests": [ - "assert(/parseInt/g.test(code), 'message: convertToInteger should use the parseInt() function');", - "assert(typeof(convertToInteger(\"10011\")) === \"number\", 'message: convertToInteger(\"10011\") should return a number');", - "assert(convertToInteger(\"10011\") === 19, 'message: convertToInteger(\"10011\") should return 19');", - "assert(convertToInteger(\"111001\") === 57, 'message: convertToInteger(\"111001\") should return 57');", - "assert.isNaN(convertToInteger(\"JamesBond\"), 'message: convertToInteger(\"JamesBond\") should return NaN');" - ], - "type": "waypoint", - "challengeType": 1, - "releasedOn": "February 17, 2017", - "translations": {} - }, - { - "id": "587d7b7e367417b2b2512b24", - "title": "Use the Conditional (Ternary) Operator", - "description": [ - "The conditional operator, also called the ternary operator, can be used as a one line if-else expression.", - "The syntax is:", - "condition ? statement-if-true : statement-if-false;", - "The following function uses an if-else statement to check a condition:", - "
function findGreater(a, b) {
if(a > b) {
return \"a is greater\";
}
else {
return \"b is greater\";
}
}
", - "This can be re-written using the conditional operator:", - "
function findGreater(a, b) {
return a > b ? \"a is greater\" : \"b is greater\";
}
", - "
", - "Use the conditional operator in the checkEqual function to check if two numbers are equal or not. The function should return either true or false." - ], - "challengeSeed": [ - "function checkEqual(a, b) {", - " ", - "}", - "", - "checkEqual(1, 2);" - ], - "tail": [], - "solutions": [], - "tests": [ - "assert(/.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?/gi.test(code), 'message: checkEqual should use the conditional operator');", - "assert(checkEqual(1, 2) === false, 'message: checkEqual(1, 2) should return false');", - "assert(checkEqual(1, 1) === true, 'message: checkEqual(1, 1) should return true');", - "assert(checkEqual(1, -1) === false, 'message: checkEqual(1, -1) should return false');" - ], - "type": "waypoint", - "challengeType": 1, - "releasedOn": "February 17, 2017", - "translations": {} - }, - { - "id": "587d7b7e367417b2b2512b21", - "title": "Use Multiple Conditional (Ternary) Operators", - "description": [ - "In the previous challenge, you used a single conditional operator. You can also chain them together to check for multiple conditions.", - "The following function uses if, else if, and else statements to check multiple conditions:", - "
function findGreaterOrEqual(a, b) {
if(a === b) {
return \"a and b are equal\";
}
else if(a > b) {
return \"a is greater\";
}
else {
return \"b is greater\";
}
}
", - "The above function can be re-written using multiple conditional operators:", - "
function findGreaterOrEqual(a, b) {
return (a === b) ? \"a and b are equal\" : (a > b) ? \"a is greater\" : \"b is greater\";
}
", - "
", - "Use multiple conditional operators in the checkSign function to check if a number is positive, negative or zero." - ], - "challengeSeed": [ - "function checkSign(num) {", - " ", - "}", - "", - "checkSign(10);" - ], - "tail": [], - "solutions": [], - "tests": [ - "assert(/.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?\\s*?\\?\\s*?.+?\\s*?:\\s*?.+?/gi.test(code), 'message: checkSign should use multiple conditional operators');", - "assert(checkSign(10) === 'positive', 'message: checkSign(10) should return \"positive\". Note that capitalization matters');", - "assert(checkSign(-12) === 'negative', 'message: checkSign(-12) should return \"negative\". Note that capitalization matters');", - "assert(checkSign(0) === 'zero', 'message: checkSign(0) should return \"zero\". Note that capitalization matters');" - ], - "type": "waypoint", - "challengeType": 1, - "releasedOn": "February 17, 2017", - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json deleted file mode 100644 index d308cc9c86..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/debugging.json +++ /dev/null @@ -1,423 +0,0 @@ -{ - "name": "Debugging", - "order": 4, - "time": "1 hour", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7b83367417b2b2512b32", - "title": "Introduction to the Debugging Challenges", - "description": [ - "", - "", - "Debugging is a valuable and (unfortunately) necessary tool for programmers. It follows the testing phase of checking if your code works as intended, and discovering it does not. Debugging is the process of finding exactly what isn't working and fixing it.", - "", - "@@STEP@@", - "", - "", - "After spending time creating a brilliant block of code, it is tough realizing it may have errors. These issues generally come in three forms: 1) syntax errors that prevent a program from running, 2) runtime errors when code fails to execute or has unexpected behavior, and 3) semantic (or logical) errors when code doesn't do what it's meant to.

Modern code editors (and experience) can help identify syntax errors. Semantic and runtime errors are harder to find. They may cause your program to crash, make it run forever, or give incorrect output. Think of debugging as trying to understand why your code is behaving the way it is.

Example of a syntax error - often detected by the code editor:

funtion willNotWork( {
  console.log(\"Yuck\");
}
// \"function\" keyword is misspelled and there's a missing parenthesis


Here's an example of a runtime error - often detected while the program executes:

function loopy() {
  while(true) {
    console.log(\"Hello, world!\");
  }
}
// Calling loopy starts an infinite loop, which may crash your browser


Example of a semantic error - often detected after testing code output:

function calcAreaOfRect(w, h) {
  return w + h; // This should be w * h
}
let myRectArea = calcAreaOfRect(2, 3);
// Correct syntax and the program executes, but this gives the wrong answer
", - "", - "@@STEP@@", - "", - "", - "Debugging is frustrating, but it helps to develop (and follow) a step-by-step approach to review your code. This means checking the intermediate values and types of variables to see if they are what they should be. You can start with a simple process of elimination.

For example, if function A works and returns what it's supposed to, then function B may have the issue. Or start checking values in a block of code from the middle to try to cut the search space in half. A problem in one spot indicates a bug in the first half of the code. If not, it's likely in the second.

This section will cover a couple helpful tools to find bugs, and some of the common forms they take. Fortunately, debugging is a learnable skill that just requires a little patience and practice to master.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7b83367417b2b2512b33", - "title": "Use the JavaScript Console to Check the Value of a Variable", - "description": [ - "Both Chrome and Firefox have excellent JavaScript consoles, also known as DevTools, for debugging your JavaScript.", - "You can find Developer tools in your Chrome's menu or Web Console in FireFox's menu. If you're using a different browser, or a mobile phone, we strongly recommend switching to desktop Firefox or Chrome.", - "The console.log() method, which \"prints\" the output of what's within its parentheses to the console, will likely be the most helpful debugging tool. Placing it at strategic points in your code can show you the intermediate values of variables. It's good practice to have an idea of what the output should be before looking at what it is. Having check points to see the status of your calculations throughout your code will help narrow down where the problem is.", - "Here's an example to print 'Hello world!' to the console:", - "console.log('Hello world!');", - "
", - "Use the console.log() method to print the value of the variable a where noted in the code." - ], - "challengeSeed": [ - "let a = 5;", - "let b = 1;", - "a++;", - "// Add your code below this line", - "", - "", - "let sumAB = a + b;", - "console.log(sumAB);" - ], - "tests": [ - "assert(code.match(/console\\.log\\(a\\)/g), 'message: Your code should use console.log() to check the value of the variable a.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b83367417b2b2512b37", - "title": "Understanding the Differences between the freeCodeCamp and Browser Console", - "description": [ - "You may have noticed that some freeCodeCamp JavaScript challenges include their own console. This console behaves a little differently than the browser console you used in the last challenge.", - "The following challenge is meant to highlight some of the differences between the freeCodeCamp console and the browser console.", - "First, the browser console. When you load and run an ordinary JavaScript file in your browser the console.log() statements will print exactly what you tell them to print to the browser console the exact number of times you requested. In your in-browser text editor the process is slightly different and can be confusing at first.", - "Values passed to console.log() in the text editor block run each set of tests as well as one more time for any function calls that you have in you code.", - "This lends itself to some interesting behavior and might trip you up in the beginning, because a logged value that you expect to see only once may print out many more times depending on the number of tests and the values being passed to those tests.", - "If you would like to see only your single output and not have to worry about running through the test cycles, you can use console.clear().", - "
", - "Use console.log() to print the variables in the code where indicated.", - "" - ], - "challengeSeed": [ - "// Open your browser console", - "let outputTwo = \"This will print to the browser console 2 times\";", - "// Use console.log() to print the outputTwo variable", - "", - "", - "let outputOne = \"Try to get this to log only once to the browser console\";", - "// Use console.clear() in the next line to print the outputOne only once", - "", - "", - "// Use console.log() to print the outputOne variable", - "", - "" - ], - "tests": [ - "assert(code.match(/console\\.log\\(outputTwo\\)/g), 'message: Use console.log() to print the outputTwice variable. In your Browser Console this should print out the value of the variable two times.');", - "assert(code.match(/console\\.log\\(outputOne\\)/g), 'message: Use console.log() to print the outputOne variable.');", - "assert(code.match(/console\\.clear\\(\\)/g), 'message: Use console.clear() to modify your output so that outputOne variable only outputs once.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b84367417b2b2512b34", - "title": "Use typeof to Check the Type of a Variable", - "description": [ - "You can use typeof to check the data structure, or type, of a variable. This is useful in debugging when working with multiple data types. If you think you're adding two numbers, but one is actually a string, the results can be unexpected. Type errors can lurk in calculations or function calls. Especially take care when you're accessing and working with external data in the form of a JavaScript object (JSON).", - "Here are some examples using typeof:", - "
console.log(typeof \"\"); // outputs \"string\"
console.log(typeof 0); // outputs \"number\"
console.log(typeof []); // outputs \"object\"
console.log(typeof {}); // outputs \"object\"
", - "JavaScript recognizes six primitive (immutable) data types: Boolean, Null, Undefined, Number, String, and Symbol (new with ES6) and one type for mutable items: Object. Note that in JavaScript, arrays are technically a type of object.", - "
", - "Add two console.log() statements to check the typeof each of the two variables seven and three in the code." - ], - "challengeSeed": [ - "let seven = 7;", - "let three = \"3\";", - "console.log(seven + three);", - "// Add your code below this line", - "" - ], - "tests": [ - "assert(code.match(/console\\.log\\(typeof[\\( ].*\\)?\\)/g).length == 2, 'message: Your code should use typeof in two console.log() statements to check the type of the variables.');", - "assert(code.match(/typeof[\\( ]seven\\)?/g), 'message: Your code should use typeof to check the type of the variable seven.');", - "assert(code.match(/typeof[\\( ]three\\)?/g), 'message: Your code should use typeof to check the type of the variable three.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b84367417b2b2512b35", - "title": "Catch Misspelled Variable and Function Names", - "description": [ - "The console.log() and typeof methods are the two primary ways to check intermediate values and types of program output. Now it's time to get into the common forms that bugs take. One syntax-level issue that fast typers can commiserate with is the humble spelling error.", - "Transposed, missing, or mis-capitalized characters in a variable or function name will have the browser looking for an object that doesn't exist - and complain in the form of a reference error. JavaScript variable and function names are case-sensitive.", - "
", - "Fix the two spelling errors in the code so the netWorkingCapital calculation works." - ], - "challengeSeed": [ - "let receivables = 10;", - "let payables = 8;", - "let netWorkingCapital = recievables - payable;", - "console.log(`Net working capital is: ${netWorkingCapital}`);" - ], - "tests": [ - "assert(netWorkingCapital === 2, 'message: Check the spelling of the two variables used in the netWorkingCapital calculation, the console output should show that \"Net working capital is: 2\".');", - "assert(!code.match(/recievables/g), 'message: There should be no instances of mis-spelled variables in the code.');", - "assert(code.match(/receivables/g).length == 2, 'message: The receivables variable should be declared and used properly in the code.');", - "assert(!code.match(/payable;/g), 'message: There should be no instances of mis-spelled variables in the code.');", - "assert(code.match(/payables/g).length == 2, 'message: The payables variable should be declared and used properly in the code.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b84367417b2b2512b36", - "title": "Catch Unclosed Parentheses, Brackets, Braces and Quotes", - "description": [ - "Another syntax error to be aware of is that all opening parentheses, brackets, curly braces, and quotes have a closing pair. Forgetting a piece tends to happen when you're editing existing code and inserting items with one of the pair types. Also, take care when nesting code blocks into others, such as adding a callback function as an argument to a method.", - "One way to avoid this mistake is as soon as the opening character is typed, immediately include the closing match, then move the cursor back between them and continue coding. Fortunately, most modern code editors generate the second half of the pair automatically.", - "
", - "Fix the two pair errors in the code." - ], - "challengeSeed": [ - "let myArray = [1, 2, 3;", - "let arraySum = myArray.reduce((previous, current => previous + current);", - "console.log(`Sum of array values is: ${arraySum}`);" - ], - "tests": [ - "assert(code.match(/myArray\\s*?=\\s*?\\[\\s*?1\\s*?,\\s*?2\\s*?,\\s*?3\\s*?\\];/g), 'message: Your code should fix the missing piece of the array.');", - "assert(arraySum === 6, 'message: Your code should fix the missing piece of the .reduce() method. The console output should show that \"Sum of array values is: 6\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b84367417b2b2512b37", - "title": "Catch Mixed Usage of Single and Double Quotes", - "description": [ - "JavaScript allows the use of both single ('') and double (\"\") quotes to declare a string. Deciding which one to use generally comes down to personal preference, with some exceptions.", - "Having two choices is great when a string has contractions or another piece of text that's in quotes. Just be careful that you don't close the string too early, which causes a syntax error.", - "Here are some examples of mixing quotes:", - "
// These are correct:
const grouchoContraction = \"I've had a perfectly wonderful evening, but this wasn't it.\";
const quoteInString = \"Groucho Marx once said 'Quote me as saying I was mis-quoted.'\";
// This is incorrect:
const uhOhGroucho = 'I've had a perfectly wonderful evening, but this wasn't it.';
", - "Of course, it is okay to use only one style of quotes. You can escape the quotes inside the string by using the backslash (\\) escape character:", - "
// Correct use of same quotes:
const allSameQuotes = 'I\\'ve had a perfectly wonderful evening, but this wasn\\'t it.';
", - "
", - "Fix the string so it either uses different quotes for the href value, or escape the existing ones. Keep the double quote marks around the entire string." - ], - "challengeSeed": [ - "let innerHtml = \"

Click here to return home

\";", - "console.log(innerHtml);" - ], - "tests": [ - "assert(code.match(//g), 'message: Your code should fix the quotes around the href value \"#Home\" by either changing or escaping them.');", - "assert(code.match(/\"

.*?<\\/p>\";/g), 'message: Your code should keep the double quotes around the entire string.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b85367417b2b2512b38", - "title": "Catch Use of Assignment Operator Instead of Equality Operator", - "description": [ - "Branching programs, i.e. ones that do different things if certain conditions are met, rely on if, else if, and else statements in JavaScript. The condition sometimes takes the form of testing whether a result is equal to a value.", - "This logic is spoken (in English, at least) as \"if x equals y, then ...\" which can literally translate into code using the =, or assignment operator. This leads to unexpected control flow in your program.", - "As covered in previous challenges, the assignment operator (=) in JavaScript assigns a value to a variable name. And the == and === operators check for equality (the triple === tests for strict equality, meaning both value and type are the same).", - "The code below assigns x to be 2, which evaluates as true. Almost every value on its own in JavaScript evaluates to true, except what are known as the \"falsy\" values: false, 0, \"\" (an empty string), NaN, undefined, and null.", - "

let x = 1;
let y = 2;
if (x = y) {
  // this code block will run for any value of y (unless y were originally set as a falsy)
} else {
  // this code block is what should run (but won't) in this example
}
", - "
", - "Fix the condition so the program runs the right branch, and the appropriate value is assigned to result." - ], - "challengeSeed": [ - "let x = 7;", - "let y = 9;", - "let result = \"to come\";", - "", - "if(x = y) {", - " result = \"Equal!\";", - "} else {", - " result = \"Not equal!\";", - "}", - "", - "console.log(result);" - ], - "tests": [ - "assert(result == \"Not equal!\", 'message: Your code should fix the condition so it checks for equality, instead of using assignment.');", - "assert(code.match(/x\\s*?===?\\s*?y/g), 'message: The condition can use either == or === to test for equality.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b85367417b2b2512b39", - "title": "Catch Missing Open and Closing Parenthesis After a Function Call", - "description": [ - "When a function or method doesn't take any arguments, you may forget to include the (empty) opening and closing parentheses when calling it. Often times the result of a function call is saved in a variable for other use in your code. This error can be detected by logging variable values (or their types) to the console and seeing that one is set to a function reference, instead of the expected value the function returns.", - "The variables in the following example are different:", - "
function myFunction() {
  return \"You rock!\";
}
let varOne = myFunction; // set to equal a function
let varTwo = myFunction(); // set to equal the string \"You rock!\"
", - "
", - "Fix the code so the variable result is set to the value returned from calling the function getNine." - ], - "challengeSeed": [ - "function getNine() {", - " let x = 6;", - " let y = 3;", - " return x + y;", - "}", - "", - "let result = getNine;", - "console.log(result);" - ], - "tests": [ - "assert(result == 9, 'message: Your code should fix the variable result so it is set to the number that the function getNine returns.');", - "assert(code.match(/getNine\\(\\)/g).length == 2, 'message: Your code should call the getNine function.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b85367417b2b2512b3a", - "title": "Catch Arguments Passed in the Wrong Order When Calling a Function", - "description": [ - "Continuing the discussion on calling functions, the next bug to watch out for is when a function's arguments are supplied in the incorrect order. If the arguments are different types, such as a function expecting an array and an integer, this will likely throw a runtime error. If the arguments are the same type (all integers, for example), then the logic of the code won't make sense. Make sure to supply all required arguments, in the proper order to avoid these issues.", - "
", - "The function raiseToPower raises a base to an exponent. Unfortunately, it's not called properly - fix the code so the value of power is the expected 8." - ], - "challengeSeed": [ - "function raiseToPower(b, e) {", - " return Math.pow(b, e);", - "}", - "", - "let base = 2;", - "let exp = 3;", - "let power = raiseToPower(exp, base);", - "console.log(power);" - ], - "tests": [ - "assert(power == 8, 'message: Your code should fix the variable power so it equals 2 raised to the 3rd power, not 3 raised to the 2nd power.');", - "assert(code.match(/raiseToPower\\(\\s*?base\\s*?,\\s*?exp\\s*?\\);/g), 'message: Your code should use the correct order of the arguments for the raiseToPower function call.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b86367417b2b2512b3b", - "title": "Catch Off By One Errors When Using Indexing", - "description": [ - "Off by one errors (sometimes called OBOE) crop up when you're trying to target a specific index of a string or array (to slice or access a segment), or when looping over the indices of them. JavaScript indexing starts at zero, not one, which means the last index is always one less than the length of the item. If you try to access an index equal to the length, the program may throw an \"index out of range\" reference error or print undefined.", - "When you use string or array methods that take index ranges as arguments, it helps to read the documentation and understand if they are inclusive (the item at the given index is part of what's returned) or not. Here are some examples of off by one errors:", - "
let alphabet = \"abcdefghijklmnopqrstuvwxyz\";
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
  // loops one too many times at the end
  console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
  // loops one too few times and misses the first character at index 0
  console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
  // Goldilocks approves - this is just right
  console.log(alphabet[k]);
}
", - "
", - "Fix the two indexing errors in the following function so all the numbers 1 through 5 are printed to the console." - ], - "challengeSeed": [ - "function countToFive() {", - " let firstFive = \"12345\";", - " let len = firstFive.length;", - " // Fix the line below", - " for (let i = 1; i <= len; i++) {", - " // Do not alter code below this line", - " console.log(firstFive[i]);", - " }", - "}", - "", - "countToFive();" - ], - "tests": [ - "assert(code.match(/i\\s*?=\\s*?0\\s*?;/g).length == 1, 'message: Your code should set the initial condition of the loop so it starts at the first index.');", - "assert(!code.match(/i\\s?=\\s*?1\\s*?;/g), 'message: Your code should fix the initial condition of the loop so that the index starts at 0.');", - "assert(code.match(/i\\s*?<\\s*?len\\s*?;/g).length == 1, 'message: Your code should set the terminal condition of the loop so it stops at the last index.');", - "assert(!code.match(/i\\s*?<=\\s*?len;/g), 'message: Your code should fix the terminal condition of the loop so that it stops at 1 before the length.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b86367417b2b2512b3c", - "title": "Use Caution When Reinitializing Variables Inside a Loop", - "description": [ - "Sometimes it's necessary to save information, increment counters, or re-set variables within a loop. A potential issue is when variables either should be reinitialized, and aren't, or vice versa. This is particularly dangerous if you accidentally reset the variable being used for the terminal condition, causing an infinite loop.", - "Printing variable values with each cycle of your loop by using console.log() can uncover buggy behavior related to resetting, or failing to reset a variable.", - "
", - "The following function is supposed to create a two-dimensional array with m rows and n columns of zeroes. Unfortunately, it's not producing the expected output because the row variable isn't being reinitialized (set back to an empty array) in the outer loop. Fix the code so it returns a correct 3x2 array of zeroes, which looks like [[0, 0], [0, 0], [0, 0]]." - ], - "challengeSeed": [ - "function zeroArray(m, n) {", - " // Creates a 2-D array with m rows and n columns of zeroes", - " let newArray = [];", - " let row = [];", - " for (let i = 0; i < m; i++) {", - " // Adds the m-th row into newArray", - " ", - " for (let j = 0; j < n; j++) {", - " // Pushes n zeroes into the current row to create the columns", - " row.push(0);", - " }", - " // Pushes the current row, which now has n zeroes in it, to the array", - " newArray.push(row);", - " }", - " return newArray;", - "}", - "", - "let matrix = zeroArray(3, 2);", - "console.log(matrix);" - ], - "tests": [ - "assert(JSON.stringify(matrix) == \"[[0,0],[0,0],[0,0]]\", 'message: Your code should set the matrix variable to an array holding 3 rows of 2 columns of zeroes each.');", - "assert(matrix.length == 3, 'message: The matrix variable should have 3 rows.');", - "assert(matrix[0].length == 2 && matrix[1].length === 2 && matrix[2].length === 2, 'message: The matrix variable should have 2 columns in each row.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b86367417b2b2512b3d", - "title": "Prevent Infinite Loops with a Valid Terminal Condition", - "description": [ - "The final topic is the dreaded infinite loop. Loops are great tools when you need your program to run a code block a certain number of times or until a condition is met, but they need a terminal condition that ends the looping. Infinite loops are likely to freeze or crash the browser, and cause general program execution mayhem, which no one wants.", - "There was an example of an infinite loop in the introduction to this section - it had no terminal condition to break out of the while loop inside loopy(). Do NOT call this function!", - "
function loopy() {
  while(true) {
    console.log(\"Hello, world!\");
  }
}
", - "It's the programmer's job to ensure that the terminal condition, which tells the program when to break out of the loop code, is eventually reached. One error is incrementing or decrementing a counter variable in the wrong direction from the terminal condition. Another one is accidentally resetting a counter or index variable within the loop code, instead of incrementing or decrementing it.", - "
", - "The myFunc() function contains an infinite loop because the terminal condition i != 4 will never evaluate to false (and break the looping) - i will increment by 2 each pass, and jump right over 4 since i is odd to start. Fix the comparison operator in the terminal condition so the loop only runs for i less than or equal to 4." - ], - "challengeSeed": [ - "function myFunc() {", - " for (let i = 1; i != 4; i += 2) {", - " console.log(\"Still going!\");", - " }", - "}" - ], - "tests": [ - "assert(code.match(/i\\s*?<=\\s*?4;/g).length == 1, 'message: Your code should change the comparison operator in the terminal condition (the middle part) of the for loop.');", - "assert(!code.match(/i\\s*?!=\\s*?4;/g), 'message: Your code should fix the comparison operator in the terminal condition of the loop.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json deleted file mode 100644 index 7a72cc1302..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/es6.json +++ /dev/null @@ -1,971 +0,0 @@ -{ - "name": "ES6", - "order": 2, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7b86367417b2b2512b3e", - "title": "Introduction to the ES6 Challenges", - "description": [ - "", - "", - "ECMAScript is a standardized version of JavaScript with the goal of unifying the language's specifications and features. As all major browsers and JavaScript-runtimes follow this specification, the term ECMAScript is interchangeable with the term JavaScript.

Most of the challenges on freeCodeCamp use the ECMAScript 5 (ES5) specification of the language, finalized in 2009. But JavaScript is an evolving programming language. As features are added and revisions are made, new versions of the language are released for use by developers.

The most recent standardized version is called ECMAScript 6 (ES6), released in 2015. This new version of the language adds some powerful features that will be covered in this section of challenges, including:

  • Arrow functions
  • Classes
  • Modules
  • Promises
  • Generators
  • let and const


Note
Not all browsers support ES6 features. If you use ES6 in your own projects, you may need to use a program (transpiler) to convert your ES6 code into ES5 until browsers support ES6.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7b87367417b2b2512b3f", - "title": "Explore Differences Between the var and let Keywords", - "description": [ - "One of the biggest problems with declaring variables with the var keyword is that you can overwrite variable declarations without an error.", - "
var camper = 'James';
var camper = 'David';
console.log(camper);
// logs 'David'
", - "As you can see in the code above, the camper variable is originally declared as James and then overridden to be David.", - "In a small application, you might not run into this type of problem, but when your code becomes larger, you might accidently overwrite a variable that you did not intend to overwrite.", - "Because this behavior does not throw an error, searching and fixing bugs becomes more difficult.
", - "A new keyword called let was introduced in ES6 to solve this potential issue with the var keyword.", - "If you were to replace var with let in the variable declarations of the code above, the result would be an error.", - "
let camper = 'James';
let camper = 'David'; // throws an error
", - "This error can be seen in the console of your browser.", - "So unlike var, when using let, a variable with the same name can only be declared once.", - "Note the \"use strict\". This enables Strict Mode, which catches common coding mistakes and \"unsafe\" actions. For instance:", - "
\"use strict\";
x = 3.14; // throws an error because x is not declared
", - "
", - "Update the code so it only uses the let keyword." - ], - "challengeSeed": [ - "var catName;", - "var quote;", - "function catTalk() {", - " \"use strict\";", - "", - " catName = \"Oliver\";", - " quote = catName + \" says Meow!\";", - "", - "}", - "catTalk();" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var does not exist in code.');", - "assert(catName === \"Oliver\", 'message: catName should be Oliver.');", - "assert(quote === \"Oliver says Meow!\", 'message: quote should be \"Oliver says Meow!\"');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b87367417b2b2512b40", - "title": "Compare Scopes of the var and let Keywords", - "description": [ - "When you declare a variable with the var keyword, it is declared globally, or locally if declared inside a function.", - "The let keyword behaves similarly, but with some extra features. When you declare a variable with the let keyword inside a block, statement, or expression, its scope is limited to that block, statement, or expression.", - "For example:", - "
var numArray = [];
for (var i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3
", - "With the var keyword, i is declared globally. So when i++ is executed, it updates the global variable. This code is similiar to the following:", - "
var numArray = [];
var i;
for (i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
// returns [0, 1, 2]
console.log(i);
// returns 3
", - "This behavior will cause problems if you were to create a function and store it for later use inside a for loop that uses the i variable. This is because the stored function will always refer to the value of the updated global i variable.", - "
var printNumTwo;
for (var i = 0; i < 3; i++) {
if(i === 2){
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 3
", - "As you can see, printNumTwo() prints 3 and not 2. This is because the value assigned to i was updated and the printNumTwo() returns the global i and not the value i had when the function was created in the for loop. The let keyword does not follow this behavior:", - "
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
// returns 2
console.log(i);
// returns \"i is not defined\"
", - "i is not defined because it was not declared in the global scope. It is only declared within the for loop statement. printNumTwo() returned the correct value because three different i variables with unique values (0, 1, and 2) were created by the let keyword within the loop statement.", - "
", - "Fix the code so that i declared in the if statement is a separate variable than i declared in the first line of the function. Be certain not to use the var keyword anywhere in your code.", - "This exercise is designed to illustrate the difference between how var and let keywords assign scope to the declared variable. When programming a function similar to the one used in this exercise, it is often better to use different variable names to avoid confusion." - ], - "challengeSeed": [ - "", - "function checkScope() {", - "\"use strict\";", - " var i = \"function scope\";", - " if (true) {", - " i = \"block scope\";", - " console.log(\"Block scope i is: \", i);", - " }", - " console.log(\"Function scope i is: \", i);", - " return i;", - "}" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var does not exist in code.');", - "getUserInput => assert(getUserInput('index').match(/(i\\s*=\\s*).*\\s*.*\\s*.*\\1('|\")block\\s*scope\\2/g), 'message: The variable i declared in the if statement should equal \"block scope\".');", - "assert(checkScope() === \"function scope\", 'message: checkScope() should return \"function scope\"');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b87367417b2b2512b41", - "title": "Declare a Read-Only Variable with the const Keyword", - "description": [ - "let is not the only new way to declare variables. In ES6, you can also declare variables using the const keyword.", - "const has all the awesome features that let has, with the added bonus that variables declared using const are read-only. They are a constant value, which means that once a variable is assigned with const, it cannot be reassigned.", - "
\"use strict\"
const FAV_PET = \"Cats\";
FAV_PET = \"Dogs\"; // returns error
", - "As you can see, trying to reassign a variable declared with const will throw an error. You should always name variables you don't want to reassign using the const keyword. This helps when you accidentally attempt to reassign a variable that is meant to stay constant. A common practice is to name your constants in all upper-cases and with an underscore to separate words (e.g. EXAMPLE_VARIABLE).", - "
", - "Change the code so that all variables are declared using let or const. Use let when you want the variable to change, and const when you want the variable to remain constant. Also, rename variables declared with const to conform to common practices, meaning constants should be in all caps" - ], - "challengeSeed": [ - "function printManyTimes(str) {", - " \"use strict\";", - "", - " // change code below this line", - "", - " var sentence = str + \" is cool!\";", - " for(var i = 0; i < str.length; i+=2) {", - " console.log(str);", - " }", - "", - " // change code above this line", - "", - "}", - "printManyTimes(\"freeCodeCamp\");" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g),'message: var does not exist in code.');", - "getUserInput => assert(getUserInput('index').match(/(const SENTENCE)/g), 'message: SENTENCE should be a constant variable (by using const).');", - "getUserInput => assert(getUserInput('index').match(/(let i)/g), 'message: i should be a variable only defined within the for loop scope (by usinglet).');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b87367417b2b2512b42", - "title": "Mutate an Array Declared with const", - "description": [ - "The const declaration has many use cases in modern JavaScript.", - "Some developers prefer to assign all their variables using const by default, unless they know they will need to reassign the value. Only in that case, they use let.", - "However, it is important to understand that objects (including arrays and functions) assigned to a variable using const are still mutable. Using the const declaration only prevents reassignment of the variable identifier.", - "
\"use strict\";
const s = [5, 6, 7];
s = [1, 2, 3]; // throws error, trying to assign a const
s[2] = 45; // works just as it would with an array declared with var or let
console.log(s); // returns [5, 6, 45]
", - "As you can see, you can mutate the object [5, 6, 7] itself and the variable s will still point to the altered array [5, 6, 45]. Like all arrays, the array elements in s are mutable, but because const was used, you cannot use the variable identifier s to point to a different array using the assignment operator.", - "
", - "An array is declared as const s = [5, 7, 2]. Change the array to [2, 5, 7] using various element assignment." - ], - "challengeSeed": [ - "const s = [5, 7, 2];", - "function editInPlace() {", - " \"use strict\";", - " // change code below this line", - "", - " // s = [2, 5, 7]; <- this is invalid", - "", - " // change code above this line", - "}", - "editInPlace();" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/const/g), 'message: Do not replace const keyword.');", - "getUserInput => assert(getUserInput('index').match(/const\\s+s/g), 'message: s should be a constant variable (by using const).');", - "getUserInput => assert(getUserInput('index').match(/const\\s+s\\s*=\\s*\\[\\s*5\\s*,\\s*7\\s*,\\s*2\\s*\\]\\s*;?/g), 'message: Do not change the original array declaration.');", - "assert.deepEqual(s, [2, 5, 7], 'message: s should be equal to [2, 5, 7].');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "598f48a36c8c40764b4e52b3", - "title": "Prevent Object Mutation", - "description": [ - "As seen in previous challenge, const declaration alone doesn't really protect your data from mutation. To ensure your data doesn't change, JavaScript provides a function Object.freeze to prevent data mutation.", - "Once the object is freezed, you can no longer add/update/delete properties from it. Any attempt at changing the object will be rejected without any error.", - "
\nlet obj = {\n name:\"FreeCodeCamp\"\n review:\"Awesome\"\n};\nObject.freeze(obj);\nobj.review = \"bad\"; //will be ignored. Mutation not allowed\nobj.newProp = \"Test\"; // will be ignored. Mutation not allowed\nconsole.log(obj); \n// { name: \"FreeCodeCamp\", review:\"Awesome\"}\n
", - "
", - "In this challenge you are going to use Object.freeze to prevent mathematical constants from changing. You need to freeze MATH_CONSTANTS object so that noone is able alter the value of PI or add any more properties to it." - ], - "challengeSeed": [ - "function freezeObj() {", - " \"use strict\";", - " const MATH_CONSTANTS = {", - " PI: 3.14", - " };", - " // change code below this line", - "", - "", - " // change code above this line", - " try {", - " MATH_CONSTANTS.PI = 99;", - " } catch( ex ) {", - " console.log(ex);", - " }", - " return MATH_CONSTANTS.PI;", - "}", - "const PI = freezeObj();" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/const/g), 'message: Do not replace const keyword.');", - "getUserInput => assert(getUserInput('index').match(/const\\s+MATH_CONSTANTS/g), 'message: MATH_CONSTANTS should be a constant variable (by using const).');", - "getUserInput => assert(getUserInput('index').match(/const\\s+MATH_CONSTANTS\\s+=\\s+{\\s+PI:\\s+3.14\\s+};/g), 'message: Do not change original MATH_CONSTANTS.');", - "assert(PI === 3.14, 'message: PI equals 3.14.');" - ], - "type": "waypoint", - "releasedOn": "Aug 12, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b87367417b2b2512b43", - "title": "Use Arrow Functions to Write Concise Anonymous Functions", - "description": [ - "In JavaScript, we often don't need to name our functions, especially when passing a function as an argument to another function. Instead, we create inline functions. We don't need to name these functions because we do not reuse them anywhere else.", - "To achieve this, we often use the following syntax:", - "
const myFunc = function() {
const myVar = \"value\";
return myVar;
}
", - "ES6 provides us with the syntactic sugar to not have to write anonymous functions this way. Instead, you can use arrow function syntax:", - "
const myFunc = () => {
const myVar = \"value\";
return myVar;
}
", - "When there is no function body, and only a return value, arrow function syntax allows you to omit the keyword return as well as the brackets surrounding the code. This helps simplify smaller functions into one-line statements:", - "
const myFunc= () => \"value\"
", - "This code will still return value by default.", - "
", - "Rewrite the function assigned to the variable magic which returns a new Date() to use arrow function syntax. Also make sure nothing is defined using the keyword var." - ], - "challengeSeed": [ - "var magic = function() {", - " \"use strict\";", - " return new Date();", - "};" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var keyword.');", - "getUserInput => assert(getUserInput('index').match(/const\\s+magic/g), 'message: magic should be a constant variable (by using const).');", - "assert(typeof magic === 'function', 'message: magic is a function.');", - "assert(magic().getDate() == new Date().getDate(), 'message: magic() returns correct date.');", - "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function keyword was not used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b88367417b2b2512b44", - "title": "Write Arrow Functions with Parameters", - "description": [ - "Just like a normal function, you can pass arguments into arrow functions.", - "
// doubles input value and returns it
const doubler = (item) => item * 2;
", - "You can pass more than one argument into arrow functions as well.", - "
", - "Rewrite the myConcat function which appends contents of arr2 to arr1 so that the function uses arrow function syntax." - ], - "challengeSeed": [ - "var myConcat = function(arr1, arr2) {", - " \"use strict\";", - " return arr1.concat(arr2);", - "};", - "// test your code", - "console.log(myConcat([1, 2], [3, 4, 5]));" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var keyword.');", - "getUserInput => assert(getUserInput('index').match(/const\\s+myConcat/g), 'message: myConcat should be a constant variable (by using const).');", - "assert(typeof myConcat === 'function', 'message: myConcat should be a function');", - "assert(() => { const a = myConcat([1], [2]); return a[0] == 1 && a[1] == 2; }, 'message: myConcat() returns the correct array');", - "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function keyword was not used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b88367417b2b2512b45", - "title": "Write Higher Order Arrow Functions", - "description": [ - "It's time we see how powerful arrow functions are when processing data.", - "Arrow functions work really well with higher order functions, such as map(), filter(), and reduce(), that take other functions as arguments for processing collections of data.", - "Read the following code:", - "
FBPosts.filter(function(post) {
return post.thumbnail !== null && post.shares > 100 && post.likes > 500;
})
", - "We have written this with filter() to at least make it somewhat readable. Now compare it to the following code which uses arrow function syntax instead:", - "
FBPosts.filter((post) => post.thumbnail !== null && post.shares > 100 && post.likes > 500)
", - "This code is more succinct and accomplishes the same task with fewer lines of code.", - "
", - "Use arrow function syntax to compute the square of only the positive integers (fractions are not integers) in the array realNumberArray and store the new array in the variable squaredIntegers." - ], - "challengeSeed": [ - "const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34];", - "const squareList = (arr) => {", - " \"use strict\";", - " // change code below this line", - " const squaredIntegers = arr;", - " // change code above this line", - " return squaredIntegers;", - "};", - "// test your code", - "const squaredIntegers = squareList(realNumberArray);", - "console.log(squaredIntegers);" - ], - "tests": [ - "getUserInput => assert(!getUserInput('index').match(/var/g), 'message: User did replace var keyword.');", - "getUserInput => assert(getUserInput('index').match(/const\\s+squaredIntegers/g), 'message: squaredIntegers should be a constant variable (by using const).');", - "assert(Array.isArray(squaredIntegers), 'message: squaredIntegers should be an array');", - "assert(squaredIntegers[0] === 16 && squaredIntegers[1] === 1764 && squaredIntegers[2] === 36, 'message: squaredIntegers should be [16, 1764, 36]');", - "getUserInput => assert(!getUserInput('index').match(/function/g), 'message: function keyword was not used.');", - "getUserInput => assert(!getUserInput('index').match(/(for)|(while)/g), 'message: loop should not be used');", - "getUserInput => assert(getUserInput('index').match(/map|filter|reduce/g), 'message: map, filter, or reduce should be used');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b88367417b2b2512b46", - "title": "Set Default Parameters for Your Functions", - "description": [ - "In order to help us create more flexible functions, ES6 introduces default parameters for functions.", - "Check out this code:", - "
function greeting(name = \"Anonymous\") {
return \"Hello \" + name;
}
console.log(greeting(\"John\")); // Hello John
console.log(greeting()); // Hello Anonymous
", - "The default parameter kicks in when the argument is not specified (it is undefined). As you can see in the example above, the parameter name will receive its default value \"Anonymous\" when you do not provide a value for the parameter. You can add default values for as many parameters as you want.", - "
", - "Modify the function increment by adding default parameters so that it will add 1 to number if value is not specified." - ], - "challengeSeed": [ - "const increment = (function() {", - " \"use strict\";", - " return function increment(number, value) {", - " return number + value;", - " };", - "})();", - "console.log(increment(5, 2)); // returns 7", - "console.log(increment(5)); // returns NaN" - ], - "tests": [ - "assert(increment(5, 2) === 7, 'message: The result of increment(5, 2) should be 7.');", - "assert(increment(5) === 6, 'message: The result of increment(5) should be 6.');", - "getUserInput => assert(getUserInput('index').match(/value\\s*=\\s*1/g), 'message: default parameter 1 was used for value.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b88367417b2b2512b47", - "title": "Use the Rest Operator with Function Parameters", - "description": [ - "In order to help us create more flexible functions, ES6 introduces the rest operator for function parameters. With the rest operator, you can create functions that take a variable number of arguments. These arguments are stored in an array that can be accessed later from inside the function.", - "Check out this code:", - "
function howMany(...args) {
return \"You have passed \" + args.length + \" arguments.\";
}
console.log(howMany(0, 1, 2)); // You have passed 3 arguments
console.log(howMany(\"string\", null, [1, 2, 3], { })); // You have passed 4 arguments.
", - "The rest operator eliminates the need to check the args array and allows us to apply map(), filter() and reduce() on the parameters array.", - "
", - "Modify the function sum so that is uses the rest operator and it works in the same way with any number of parameters." - ], - "challengeSeed": [ - "const sum = (function() {", - " \"use strict\";", - " return function sum(x, y, z) {", - " const args = [ x, y, z ];", - " return args.reduce((a, b) => a + b, 0);", - " };", - "})();", - "console.log(sum(1, 2, 3)); // 6" - ], - "tests": [ - "assert(sum(0,1,2) === 3, 'message: The result of sum(0,1,2) should be 3');", - "assert(sum(1,2,3,4) === 10, 'message: The result of sum(1,2,3,4) should be 10');", - "assert(sum(5) === 5, 'message: The result of sum(5) should be 5');", - "assert(sum() === 0, 'message: The result of sum() should be 0');", - "getUserInput => assert(getUserInput('index').match(/function\\s+sum\\s*\\(\\s*...args\\s*\\)\\s*{/g), 'message: The sum function uses the ... spread operator on the args parameter.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b89367417b2b2512b48", - "title": "Use the Spread Operator to Evaluate Arrays In-Place", - "description": [ - "ES6 introduces the spread operator, which allows us to expand arrays and other expressions in places where multiple parameters or elements are expected.", - "The ES5 code below uses apply() to compute the maximum value in an array:", - "
var arr = [6, 89, 3, 45];
var maximus = Math.max.apply(null, arr); // returns 89
", - "We had to use Math.max.apply(null, arr) because Math.max(arr) returns NaN. Math.max() expects comma-separated arguments, but not an array.", - "The spread operator makes this syntax much better to read and maintain.", - "
const arr = [6, 89, 3, 45];
const maximus = Math.max(...arr); // returns 89
", - "...arr returns an unpacked array. In other words, it spreads the array.", - "However, the spread operator only works in-place, like in an argument to a function or in an array literal. The following code will not work:", - "
const spreaded = ...arr; // will throw a syntax error
", - "
", - "Copy all contents of arr1 into another array arr2 using the spread operator." - ], - "challengeSeed": [ - "const arr1 = ['JAN', 'FEB', 'MAR', 'APR', 'MAY'];", - "let arr2;", - "(function() {", - " \"use strict\";", - " arr2 = []; // change this line", - "})();", - "console.log(arr2);" - ], - "tests": [ - "assert(arr2.every((v, i) => v === arr1[i]), 'message: arr2 is correct copy of arr1.');", - "getUserInput => assert(getUserInput('index').match(/\\[\\s*...arr1\\s*\\]/g),'message: ... spread operator was used to duplicate arr1.');", - "assert((arr1, arr2) => {arr1.push('JUN'); return arr2.length < arr1.length},'message: arr2 remains unchanged when arr1 is changed.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b89367417b2b2512b49", - "title": "Use Destructuring Assignment to Assign Variables from Objects", - "description": [ - "We saw earlier how spread operator can effectively spread, or unpack, the contents of the array.", - "We can do something similar with objects as well. Destructuring assignment is special syntax for neatly assigning values taken directly from an object to variables.", - "Consider the following ES5 code:", - "
var voxel = {x: 3.6, y: 7.4, z: 6.54 };
var x = voxel.x; // x = 3.6
var y = voxel.y; // y = 7.4
var z = voxel.z; // z = 6.54
", - "Here's the same assignment statement with ES6 destructuring syntax:", - "
const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54
", - "If instead you want to store the values of voxel.x into a, voxel.y into b, and voxel.z into c, you have that freedom as well.", - "
const { x : a, y : b, z : c } = voxel // a = 3.6, b = 7.4, c = 6.54
", - "You may read it as \"get the field x and copy the value into a,\" and so on.", - "
", - "Use destructuring to obtain the length of the input string str, and assign the length to len in line." - ], - "challengeSeed": [ - "function getLength(str) {", - " \"use strict\";", - "", - " // change code below this line", - " const length = 0; // change this", - " // change code above this line", - "", - " return len; // you must assign length to len in line", - "", - "}", - "", - "console.log(getLength('FreeCodeCamp'));" - ], - "tests": [ - "assert(typeof getLength('') === 'number', 'message: the function getLength() returns a number.');", - "assert(getLength(\"FreeCodeCamp\") === 12, 'message: getLength(\"FreeCodeCamp\") should be 12');", - "getUserInput => assert(getUserInput('index').match(/\\{\\s*length\\s*:\\s*len\\s*}\\s*=\\s*str/g),'message: destructuring with reassignment was used');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b89367417b2b2512b4a", - "title": "Use Destructuring Assignment to Assign Variables from Nested Objects", - "description": [ - "We can similarly destructure nested objects into variables.", - "Consider the following code:", - "
const a = {
start: { x: 5, y: 6},
end: { x: 6, y: -9 }
};
const { start : { x: startX, y: startY }} = a;
console.log(startX, startY); // 5, 6
", - "In the example above, the variable start is assigned the value of a.start, which is also an object.", - "
", - "Use destructuring assignment to obtain max of forecast.tomorrow and assign it to maxOfTomorrow." - ], - "challengeSeed": [ - "const LOCAL_FORECAST = {", - " today: { min: 72, max: 83 },", - " tomorrow: { min: 73.3, max: 84.6 }", - "};", - "", - "function getMaxOfTmrw(forecast) {", - " \"use strict\";", - " // change code below this line", - " const maxOfTomorrow = undefined; // change this line", - " // change code above this line", - " return maxOfTomorrow;", - "}", - "", - "console.log(getMaxOfTmrw(LOCAL_FORECAST)); // should be 84.6" - ], - "tests": [ - "assert(getMaxOfTmrw(LOCAL_FORECAST) === 84.6, 'message: maxOfTomorrow equals 84.6');", - "getUserInput => assert(getUserInput('index').match(/\\{\\s*tomorrow\\s*:\\s*\\{\\s*max\\s*:\\s*maxOfTomorrow\\s*\\}\\s*\\}\\s*=\\s*forecast/g),'message: nested destructuring was used');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b89367417b2b2512b4b", - "title": "Use Destructuring Assignment to Assign Variables from Arrays", - "description": [ - "ES6 makes destructuring arrays as easy as destructuring objects.", - "One key difference between the spread operator and array destructuring is that the spread operator unpacks all contents of an array into a comma-separated list. Consequently, you cannot pick or choose which elements you want to assign to variables.", - "Destructuring an array lets us do exactly that:", - "
const [a, b] = [1, 2, 3, 4, 5, 6];
console.log(a, b); // 1, 2
", - "The variable a is assigned the first value of the array, and b is assigned the second value of the array.", - "We can also access the value at any index in an array with destructuring by using commas to reach the desired index:", - "
const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
console.log(a, b, c); // 1, 2, 5
", - "
", - "Use destructuring assignment to swap the values of a and b so that a receives the value stored in b, and b receives the value stored in a." - ], - "challengeSeed": [ - "let a = 8, b = 6;", - "(() => {", - " \"use strict\";", - " // change code below this line", - " ", - " // change code above this line", - "})();", - "console.log(a); // should be 6", - "console.log(b); // should be 8" - ], - "tests": [ - "assert(a === 6, 'message: Value of a should be 6, after swapping.');", - "assert(b === 8, 'message: Value of b should be 8, after swapping.');", - "// assert(/\\[\\s*(\\w)\\s*,\\s*(\\w)\\s*\\]\\s*=\\s*\\[\\s*\\2\\s*,\\s*\\1\\s*\\]/g.test(code), 'message: Use array destructuring to swap a and b.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8a367417b2b2512b4c", - "title": "Use Destructuring Assignment with the Rest Operator to Reassign Array Elements", - "description": [ - "In some situations involving array destructuring, we might want to collect the rest of the elements into a separate array.", - "The result is similar to Array.prototype.slice(), as shown below:", - "
const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
console.log(a, b); // 1, 2
console.log(arr); // [3, 4, 5, 7]
", - "Variables a and b take the first and second values from the array. After that, because of rest operator's presence, arr gets rest of the values in the form of an array.", - "The rest element only works correctly as the last variable in the list. As in, you cannot use the rest operator to catch a subarray that leaves out last element of the original array.", - "
", - "Use destructuring assignment with the rest operator to perform an effective Array.prototype.slice() so that arr is a sub-array of the original array source with the first two elements ommitted." - ], - "challengeSeed": [ - "const source = [1,2,3,4,5,6,7,8,9,10];", - "function removeFirstTwo(list) {", - " \"use strict\";", - " // change code below this line", - " arr = list; // change this", - " // change code below this line", - " return arr;", - "}", - "const arr = removeFirstTwo(source);", - "console.log(arr); // should be [3,4,5,6,7,8,9,10]", - "console.log(source); // should be [1,2,3,4,5,6,7,8,9,10];" - ], - "tests": [ - "assert(arr.every((v, i) => v === i + 3),'message: arr should be [3,4,5,6,7,8,9,10]');", - "getUserInput => assert(getUserInput('index').match(/\\[\\s*\\w\\s*,\\s*\\w\\s*,\\s*...arr\\s*\\]/g),'message: destructuring was used.');", - "getUserInput => assert(!getUserInput('index').match(/Array.slice/g), 'message: Array.slice() was not used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8a367417b2b2512b4d", - "title": "Use Destructuring Assignment to Pass an Object as a Function's Parameters", - "description": [ - "In some cases, you can destructure the object in a function argument itself.", - "Consider the code below:", - "
const profileUpdate = (profileData) => {
const { name, age, nationality, location } = profileData;
// do something with these variables
}
", - "This effectively destructures the object sent into the function. This can also be done in-place:", - "
const profileUpdate = ({ name, age, nationality, location }) => {
/* do something with these fields */
}
", - "This removes some extra lines and makes our code look neat.", - "This has the added benefit of not having to manipulate an entire object in a function; only the fields that are needed are copied inside the function.", - "
", - "Use destructuring assignment within the argument to the function half to send only max and min inside the function." - ], - "challengeSeed": [ - "const stats = {", - " max: 56.78,", - " standard_deviation: 4.34,", - " median: 34.54,", - " mode: 23.87,", - " min: -0.75,", - " average: 35.85", - "};", - "const half = (function() {", - " \"use strict\"; // do not change this line", - "", - " // change code below this line", - " return function half(stats) {", - " // use function argument destructuring", - " return (stats.max + stats.min) / 2.0;", - " };", - " // change code above this line", - "", - "})();", - "console.log(stats); // should be object", - "console.log(half(stats)); // should be 28.015" - ], - "tests": [ - "assert(typeof stats === 'object', 'message: stats should be an object.');", - "assert(half(stats) === 28.015, 'message: half(stats) should be 28.015');", - "getUserInput => assert(getUserInput('index').match(/\\(\\s*\\{\\s*\\w+\\s*,\\s*\\w+\\s*\\}\\s*\\)/g), 'message: Destructuring was used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8a367417b2b2512b4e", - "title": "Create Strings using Template Literals", - "description": [ - "A new feature of ES6 is the template literal. This is a special type of string that allows you to use string interpolation features to create strings.", - "Consider the code below:", - "
const person = {
name: \"Zodiac Hasbro\",
age: 56
};

// string interpolation
const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;

console.log(greeting); // prints
// Hello, my name is Zodiac Hasbro!
// I am 56 years old.
", - "A lot of things happened there.", - "Firstly, the ${variable} syntax used above is a place holder. Basically, you won't have to use concatenation with the + operator anymore. To add variables to strings, you just drop the variable in a template string and wrap it with ${ and }.", - "Secondly, the example uses backticks (`), not quotes (' or \"), to wrap the string. Notice that the string is multi-line.", - "This new way of creating strings gives you more flexibility to create robust strings.", - "
", - "Use template literal syntax with backticks to display each entry of the result object's failure array. Each entry should be wrapped inside an li element with the class attribute text-warning, and listed within the resultDisplayArray." - ], - "challengeSeed": [ - "const result = {", - " success: [\"max-length\", \"no-amd\", \"prefer-arrow-functions\"],", - " failure: [\"no-var\", \"var-on-top\", \"linebreak\"],", - " skipped: [\"id-blacklist\", \"no-dup-keys\"]", - "};", - "function makeList(arr) {", - " \"use strict\";", - "", - " // change code below this line", - " const resultDisplayArray = null;", - " // change code above this line", - "", - " return resultDisplayArray;", - "}", - "/**", - " * makeList(result.failure) should return:", - " * [
  • no-var
  • ,", - " *
  • var-on-top
  • , ", - " *
  • linebreak
  • ]", - " **/", - "const resultDisplayArray = makeList(result.failure);" - ], - "tests": [ - "assert(typeof makeList(result.failure) === 'object' && resultDisplayArray.length === 3, 'message: resultDisplayArray is a list containing result failure messages.');", - "assert(makeList(result.failure).every((v, i) => v === `
  • ${result.failure[i]}
  • `), 'message: resultDisplayArray is the desired output.');", - "getUserInput => assert(getUserInput('index').match(/\\`
  • \\$\\{\\w+\\}<\\/li>\\`/g), 'message: Template strings were used');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8a367417b2b2512b4f", - "title": "Write Concise Object Literal Declarations Using Simple Fields", - "description": [ - "ES6 adds some nice support for easily definining object literals.", - "Consider the following code:", - "
    const getMousePosition = (x, y) => ({
    x: x,
    y: y
    });
    ", - "getMousePosition is a simple function that returns an object containing two fields.", - "ES6 provides the syntactic sugar to eliminate the redundancy of having to write x: x. You can simply write x once, and it will be converted tox: x (or something equivalent) under the hood.", - "Here is the same function from above rewritten to use this new syntax:", - "
    const getMousePosition = (x, y) => ({ x, y });
    ", - "
    ", - "Use simple fields with object literals to create and return a Person object." - ], - "challengeSeed": [ - "const createPerson = (name, age, gender) => {", - " \"use strict\";", - " // change code below this line", - " return {", - " name: name,", - " age: age,", - " gender: gender", - " };", - " // change code above this line", - "};", - "console.log(createPerson(\"Zodiac Hasbro\", 56, \"male\")); // returns a proper object" - ], - "tests": [ - "assert(() => {const res={name:\"Zodiac Hasbro\",age:56,gender:\"male\"}; const person=createPerson(\"Zodiac Hasbro\", 56, \"male\"); return Object.keys(person).every(k => person[k] === res[k]);}, 'message: the output is {name: \"Zodiac Hasbro\", age: 56, gender: \"male\"}.');", - "getUserInput => assert(!getUserInput('index').match(/:/g), 'message: No : were used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8b367417b2b2512b50", - "title": "Write Concise Declarative Functions with ES6", - "description": [ - "When defining functions within objects in ES5, we have to use the keyword function as follows:", - "
    const person = {
    name: \"Taylor\",
    sayHello: function() {
    return `Hello! My name is ${this.name}.`;
    }
    };
    ", - "With ES6, You can remove the function keyword and colon altogether when defining functions in objects. Here's an example of this syntax:", - "
    const person = {
    name: \"Taylor\",
    sayHello() {
    return `Hello! My name is ${this.name}.`;
    }
    };
    ", - "
    ", - "Refactor the function setGear inside the object bicycle to use the shorthand syntax described above." - ], - "challengeSeed": [ - "// change code below this line", - "const bicycle = {", - " gear: 2,", - " setGear: function(newGear) {", - " \"use strict\";", - " this.gear = newGear;", - " }", - "};", - "// change code above this line", - "bicycle.setGear(3);", - "console.log(bicycle.gear);" - ], - "tests": [ - "assert(() => { bicycle.setGear(48); return bicycle.gear === 48 }, 'message: setGear is a function and changes the gear variable.');", - "getUserInput => assert(!getUserInput('index').match(/:\\s*function\\s*\\(\\)/g), 'message: Declarative function was used.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8b367417b2b2512b53", - "title": "Use class Syntax to Define a Constructor Function", - "description": [ - "ES6 provides a new syntax to help create objects, using the keyword class.", - "This is to be noted, that the class syntax is just a syntax, and not a full-fledged class based implementation of object oriented paradigm, unlike in languages like Java, or Python, or Ruby etc.", - "In ES5, we usually define a constructor function, and use the new keyword to instantiate an object.", - "
    var SpaceShuttle = function(targetPlanet){
    this.targetPlanet = targetPlanet;
    }
    var zeus = new spaceShuttle('Jupiter');
    ", - "The class syntax simply replaces the constructor function creation:", - "
    class SpaceShuttle {
    constructor(targetPlanet){
    this.targetPlanet = targetPlanet;
    }
    }
    const zeus = new spaceShuttle('Jupiter');
    ", - "Notice that the class keyword declares a new function, and a constructor was added, which would be invoked when new is called - to create a new object.", - "
    ", - "Use class keyword and write a proper constructor to create the Vegetable class.", - "The Vegetable lets you create a vegetable object, with a property name, to be passed to constructor." - ], - "challengeSeed": [ - "function makeClass() {", - " \"use strict\";", - " /* Alter code below this line */", - "", - " /* Alter code above this line */", - " return Vegetable;", - "}", - "const Vegetable = makeClass();", - "const carrot = new Vegetable('carrot');", - "console.log(carrot.name); // => should be 'carrot'" - ], - "tests": [ - "assert(typeof Vegetable === 'function' && typeof Vegetable.constructor === 'function', 'message: Vegetable should be a class with a defined constructor method.');", - "getUserInput => assert(getUserInput('index').match(/class/g),'message: class keyword was used.');", - "assert(() => {const a = new Vegetable(\"apple\"); return typeof a === 'object';},'message: Vegetable can be instantiated.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8c367417b2b2512b54", - "title": "Use getters and setters to Control Access to an Object", - "description": [ - "You can obtain values from an object, and set a value of a property within an object.", - "These are classically called getters and setters.", - "Getter functions are meant to simply return (get) the value of an object's private variable to the user without the user directly accessing the private variable.", - "Setter functions are meant to modify (set) the value of an object's private variable based on the value passed into the setter function. This change could involve calculations, or even overwriting the previous value completely.", - "
    class Book {
    constructor(author) {
    this._author = author;
    }
    // getter
    get writer(){
    return this._author;
    }
    // setter
    set writer(updatedAuthor){
    this._author = updatedAuthor;
    }
    }
    const lol = new Book('anonymous');
    console.log(lol.writer);
    lol.writer = 'wut';
    console.log(lol.writer);
    ", - "Notice the syntax we are using to invoke the getter and setter - as if they are not even functions.", - "Getters and setters are important, because they hide internal implementation details.", - "
    ", - "Use class keyword to create a Thermostat class. The constructor accepts Farenheit temperature.", - "Now create getter and setter in the class, to obtain the temperature in Celsius scale.", - "Remember that C = 5/9 * (F - 32) and F = C * 9.0 / 5 + 32, where F is the value of temperature in Fahrenheit scale, and C is the value of the same temperature in Celsius scale", - "Note", - "When you implement this, you would be tracking the temperature inside the class in one scale - either Fahrenheit or Celsius.", - "This is the power of getter or setter - you are creating an API for another user, who would get the correct result, no matter which one you track.", - "In other words, you are abstracting implementation details from the consumer." - ], - "challengeSeed": [ - "function makeClass() {", - " \"use strict\";", - " /* Alter code below this line */", - "", - " /* Alter code above this line */", - " return Thermostat;", - "}", - "const Thermostat = makeClass();", - "const thermos = new Thermostat(76); // setting in Farenheit scale", - "let temp = thermos.temperature; // 24.44 in C", - "thermos.temperature = 26;", - "temp = thermos.temperature; // 26 in C" - ], - "tests": [ - "assert(typeof Thermostat === 'function' && typeof Thermostat.constructor === 'function','message: Thermostat should be a class with a defined constructor method.');", - "getUserInput => assert(getUserInput('index').match(/class/g),'message: class keyword was used.');", - "assert(() => {const t = new Thermostat(32); return typeof t === 'object' && t.temperature === 0;}, 'message: Thermostat can be instantiated.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8c367417b2b2512b55", - "title": "Understand the Differences Between import and require", - "description": [ - "In the past, the function require() would be used to import the functions and code in external files and modules. While handy, this presents a problem: some files and modules are rather large, and you may only need certain code from those external resources.", - "ES6 gives us a very handy tool known as import. With it, we can choose which parts of a module or file to load into a given file, saving time and memory.", - "Consider the following example. Imagine that math_array_functions has about 20 functions, but I only need one, countItems, in my current file. The old require() approach would force me to bring in all 20 functions. With this new import syntax, I can bring in just the desired function, like so:", - "
    import { countItems } from \"math_array_functions\"
    ", - "A description of the above code:", - "
    import { function } from \"file_path_goes_here\"
    // We can also import variables the same way!
    ", - "There are a few ways to write an import statement, but the above is a very common use-case.", - "Note
    The whitespace surrounding the function inside the curly braces is a best practice - it makes it easier to read the import statement.", - "Note
    The lessons in this section handle non-browser features. import, and the statements we introduce in the rest of these lessons, won't work on a browser directly. However, we can use various tools to create code out of this to make it work in browser.", - "Note
    In most cases, the file path requires a ./ before it; otherwise, node will look in the node_modules directory first trying to load it as a dependencie.", - "
    ", - "Add the appropriate import statement that will allow the current file to use the capitalizeString function. The file where this function lives is called \"string_functions\", and it is in the same directory as the current file." - ], - "head": [ - "window.require = function (str) {", - "if (str === 'string_functions') {", - "return {", - "capitalizeString: str => str.toUpperCase()", - "}}};" - ], - "challengeSeed": [ - "\"use strict\";", - "capitalizeString(\"hello!\");" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/import\\s+\\{\\s?capitalizeString\\s?\\}\\s+from\\s+\"string_functions\"/g), 'message: valid import statement');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8c367417b2b2512b56", - "title": "Use export to Reuse a Code Block", - "description": [ - "In the previous challenge, you learned about import and how it can be leveraged to import small amounts of code from large files. In order for this to work, though, we must utilize one of the statements that goes with import, known as export. When we want some code - a function, or a variable - to be usable in another file, we must export it in order to import it into another file. Like import, export is a non-browser feature.", - "The following is what we refer to as a named export. With this, we can import any code we export into another file with the import syntax you learned in the last lesson. Here's an example:", - "
    const capitalizeString = (string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
    }
    export { capitalizeString } //How to export functions.
    export const foo = \"bar\"; //How to export variables.
    ", - "Alternatively, if you would like to compact all your export statements into one line, you can take this approach:", - "
    const capitalizeString = (string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
    }
    const foo = \"bar\";
    export { capitalizeString, foo }
    ", - "Either approach is perfectly acceptable.", - "
    ", - "Below are two variables that I want to make available for other files to use. Utilizing the first way I demonstrated export, export the two variables." - ], - "head": [ - "window.exports = function(){};" - ], - "challengeSeed": [ - "\"use strict\";", - "const foo = \"bar\";", - "const boo = \"far\";" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/export\\s+const\\s+foo\\s+=+\\s\"bar\"/g), 'message: foo is exported.');", - "getUserInput => assert(getUserInput('index').match(/export\\s+const\\s+boo\\s+=+\\s\"far\"/g), 'message: bar is exported.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8c367417b2b2512b57", - "title": "Use * to Import Everything from a File", - "description": [ - "Suppose you have a file that you wish to import all of its contents into the current file. This can be done with the import * syntax.", - "Here's an example where the contents of a file named \"math_functions\" are imported into a file in the same directory:", - "
    import * as myMathModule from \"math_functions\"
    myMathModule.add(2,3);
    myMathModule.subtract(5,3);
    ", - "And breaking down that code:", - "
    import * as object_with_name_of_your_choice from \"file_path_goes_here\"
    object_with_name_of_your_choice.imported_function
    ", - "You may use any name following the import * as portion of the statement. In order to utilize this method, it requires an object that receives the imported values. From here, you will use the dot notation to call your imported values.", - "
    ", - "The code below requires the contents of a file, \"capitalize_strings\", found in the same directory as it, imported. Add the appropriate import * statement to the top of the file, using the object provided." - ], - "head": [ - "window.require = function(str) {", - "if (str === 'capitalize_strings') {", - "return {", - "capitalize: str => str.toUpperCase(),", - "lowercase: str => str.toLowerCase()", - "}}};" - ], - "challengeSeed": [ - "\"use strict\";", - "myStringModule.capitalize(\"foo\");", - "myStringModule.lowercase(\"Foo\");" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/import\\s+\\*\\s+as\\s+myStringModule\\s+from\\s+\"capitalize_strings\"/g), 'message: Properly uses import * as syntax.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8c367417b2b2512b58", - "title": "Create an Export Fallback with export default", - "description": [ - "In the export lesson, you learned about the syntax referred to as a named export. This allowed you to make multiple functions and variables available for use in other files.", - "There is another export syntax you need to know, known as export default. Usually you will use this syntax if only one value is being exported from a file. It is also used to create a fallback value for a file or module.", - "Here is a quick example of export default:", - "
    export default function add(x,y) {
    return x + y;
    }
    ", - "Note: Since export default is used to declare a fallback value for a module or file, you can only have one value be a default export in each module or file. Additionally, you cannot use export default with var, let, or const", - "
    ", - "The following function should be the fallback value for the module. Please add the necessary code to do so." - ], - "head": [ - "window.exports = function(){};" - ], - "challengeSeed": [ - "\"use strict\";", - "function subtract(x,y) {return x - y;}" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/export\\s+default\\s+function\\s+subtract\\(x,y\\)\\s+{return\\s+x\\s-\\s+y;}/g), 'message: Proper used of export fallback.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8d367417b2b2512b59", - "title": "Import a Default Export", - "description": [ - "In the last challenge, you learned about export default and its uses. It is important to note that, to import a default export, you need to use a different import syntax.", - "In the following example, we have a function, add, that is the default export of a file, \"math_functions\". Here is how to import it:", - "
    import add from \"math_functions\";
    add(5,4); //Will return 9
    ", - "The syntax differs in one key place - the imported value, add, is not surrounded by curly braces, {}. Unlike exported values, the primary method of importing a default export is to simply write the value's name after import.", - "
    ", - "In the following code, please import the default export, subtract, from the file \"math_functions\", found in the same directory as this file." - ], - "head": [ - "window.require = function(str) {", - "if (str === 'math_functions') {", - "return function(a, b) {", - "return a - b;", - "}}};" - ], - "challengeSeed": [ - "\"use strict\";", - "subtract(7,4);" - ], - "tests": [ - "getUserInput => assert(getUserInput('index').match(/import\\s+subtract\\s+from\\s+\"math_functions\"/g), 'message: Properly imports export default method.');" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - } - ] -} \ No newline at end of file diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json deleted file mode 100644 index 11f5ad3b91..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/functional-programming.json +++ /dev/null @@ -1,1276 +0,0 @@ -{ - "name": "Functional Programming", - "order": 8, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7b8d367417b2b2512b5a", - "title": "Introduction to the Functional Programming Challenges", - "description": [ - "", - "", - "Functional programming is an approach to software development based around the evaluation of functions. Like mathematics, functions in programming map input to output to produce a result. You can combine basic functions in many ways to build more and more complex programs.

    Functional programming follows a few core principles:

    • Functions are independent from the state of the program or global variables. They only depend on the arguments passed into them to make a calculation

    • Functions try to limit any changes to the state of the program and avoid changes to the global objects holding data

    • Functions have minimal side effects in the program


    The functional programming software development approach breaks a program into small, testable parts. This section covers basic functional programming principles in JavaScript.", - "", - "@@STEP@@" - ], - "releasedOn": "", - "challengeSeed": [], - "tests": [], - "type": "Waypoint", - "challengeType": 7, - "isRequired": false - }, - { - "id": "587d7b8d367417b2b2512b5b", - "title": "Learn About Functional Programming", - "description": [ - "Functional programming is a style of programming where solutions are simple, isolated functions, without any side effects outside of the function scope.", - "INPUT -> PROCESS -> OUTPUT", - "Functional programming is about:", - "1) Isolated functions - there is no dependence on the state of the program, which includes global variables that are subject to change", - "2) Pure functions - the same input always gives the same output", - "3) Functions with limited side effects - any changes, or mutations, to the state of the program outside the function are carefully controlled", - "
    ", - "The members of freeCodeCamp happen to love tea.", - "In the code editor, the prepareTea and getTea functions are already defined for you. Call the getTea function to get 40 cups of tea for the team, and store them in the tea4TeamFCC variable." - ], - "challengeSeed": [ - "/**", - " * A long process to prepare tea.", - " * @return {string} A cup of tea.", - " **/", - "const prepareTea = () => 'greenTea';", - "", - "/**", - " * Get given number of cups of tea.", - " * @param {number} numOfCups Number of required cups of tea.", - " * @return {Array} Given amount of tea cups.", - " **/", - "const getTea = (numOfCups) => {", - " const teaCups = [];", - " ", - " for(let cups = 1; cups <= numOfCups; cups += 1) {", - " const teaCup = prepareTea();", - " teaCups.push(teaCup);", - " }", - "", - " return teaCups;", - "};", - "", - "// Add your code below this line", - "", - "const tea4TeamFCC = null; // :(", - "", - "// Add your code above this line", - "", - "console.log(tea4TeamFCC);" - ], - "tests": [ - "assert(tea4TeamFCC.length === 40, 'message: The tea4TeamFCC variable should hold 40 cups of tea for the team.');", - "assert(tea4TeamFCC[0] === 'greenTea', 'message: The tea4TeamFCC variable should hold cups of green tea.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8e367417b2b2512b5c", - "title": "Understand Functional Programming Terminology", - "description": [ - "The FCC Team had a mood swing and now wants two types of tea: green tea and black tea. General Fact: Client mood swings are pretty common.", - "With that information, we'll need to revisit the getTea function from last challenge to handle various tea requests. We can modify getTea to accept a function as a parameter to be able to change the type of tea it prepares. This makes getTea more flexible, and gives the programmer more control when client requests change.", - "But first, let's cover some functional terminology:", - "Callbacks are the functions that are slipped or passed into another function to decide the invocation of that function. You may have seen them passed to other methods, for example in filter, the callback function tells JavaScript the criteria for how to filter an array.", - "Functions that can be assigned to a variable, passed into another function, or returned from another function just like any other normal value, are called first class functions. In JavaScript, all functions are first class functions.", - "The functions that take a function as an argument, or return a function as a return value are called higher order functions.", - "When the functions are passed in to another function or returned from another function, then those functions which gets passed in or returned can be called a lambda.", - "
    ", - "Prepare 27 cups of green tea and 13 cups of black tea and store them in tea4GreenTeamFCC and tea4BlackTeamFCC variables, respectively. Note that the getTea function has been modified so it now takes a function as the first argument.", - "Note: The data (the number of cups of tea) is supplied as the last argument. We'll discuss this more in later lessons." - ], - "challengeSeed": [ - "/**", - " * A long process to prepare green tea.", - " * @return {string} A cup of green tea.", - " **/", - "const prepareGreenTea = () => 'greenTea';", - "", - "/**", - " * A long process to prepare black tea.", - " * @return {string} A cup of black tea.", - " **/", - "const prepareBlackTea = () => 'blackTea';", - "", - "/**", - " * Get given number of cups of tea.", - " * @param {function():string} prepareTea The type of tea preparing function.", - " * @param {number} numOfCups Number of required cups of tea.", - " * @return {Array} Given amount of tea cups.", - " **/", - "const getTea = (prepareTea, numOfCups) => {", - " const teaCups = [];", - "", - " for(let cups = 1; cups <= numOfCups; cups += 1) {", - " const teaCup = prepareTea();", - " teaCups.push(teaCup);", - " }", - "", - " return teaCups;", - "};", - "", - "// Add your code below this line", - "", - "const tea4GreenTeamFCC = null; // :(", - "const tea4BlackTeamFCC = null; // :(", - "", - "// Add your code above this line", - "", - "console.log(", - " tea4GreenTeamFCC,", - " tea4BlackTeamFCC", - ");" - ], - "tests": [ - "assert(tea4GreenTeamFCC.length === 27, 'message: The tea4GreenTeamFCC variable should hold 27 cups of green tea for the team.');", - "assert(tea4GreenTeamFCC[0] === 'greenTea', 'message: The tea4GreenTeamFCC variable should hold cups of green tea.');", - "assert(tea4BlackTeamFCC.length === 13, 'message: The tea4BlackTeamFCC variable should hold 13 cups of black tea.');", - "assert(tea4BlackTeamFCC[0] === 'blackTea', 'message: The tea4BlackTeamFCC variable should hold cups of black tea.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8e367417b2b2512b5d", - "title": "Understand the Hazards of Using Imperative Code", - "description": [ - "Functional programming is a good habit. It keeps your code easy to manage, and saves you from sneaky bugs. But before we get there, let's look at an imperative approach to programming to highlight where you may have issues.", - "In English (and many other languages), the imperative tense is used to give commands. Similarly, an imperative style in programming is one that gives the computer a set of statements to perform a task.", - "Often the statements change the state of the program, like updating global variables. A classic example is writing a for loop that gives exact directions to iterate over the indices of an array.", - "In contrast, functional programming is a form of declarative programming. You tell the computer what you want done by calling a method or function.", - "JavaScript offers many predefined methods that handle common tasks so you don't need to write out how the computer should perform them. For example, instead of using the for loop mentioned above, you could call the map method which handles the details of iterating over an array. This helps to avoid semantic errors, like the \"Off By One Errors\" that were covered in the Debugging section.", - "Consider the scenario: you are browsing the web in your browser, and want to track the tabs you have opened. Let's try to model this using some simple object-oriented code.", - "A Window object is made up of tabs, and you usually have more than one Window open. The titles of each open site in each Window object is held in an array. After working in the browser (opening new tabs, merging windows, and closing tabs), you want to print the tabs that are still open. Closed tabs are removed from the array and new tabs (for simplicity) get added to the end of it.", - "The code editor shows an implementation of this functionality with functions for tabOpen(), tabClose(), and join(). The array tabs is part of the Window object that stores the name of the open pages.", - "

    Instructions

    ", - "Run the code in the editor. It's using a method that has side effects in the program, causing incorrect output. The final list of open tabs should be ['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab'] but the output will be slightly different.", - "Work through the code and see if you can figure out the problem, then advance to the next challenge to learn more." - ], - "challengeSeed": [ - "// tabs is an array of titles of each site open within the window", - "var Window = function(tabs) {", - " this.tabs = tabs; // we keep a record of the array inside the object", - "};", - "", - "// When you join two windows into one window", - "Window.prototype.join = function (otherWindow) {", - " this.tabs = this.tabs.concat(otherWindow.tabs);", - " return this;", - "};", - "", - "// When you open a new tab at the end", - "Window.prototype.tabOpen = function (tab) {", - " this.tabs.push('new tab'); // let's open a new tab for now", - " return this;", - "};", - "", - "// When you close a tab", - "Window.prototype.tabClose = function (index) {", - " var tabsBeforeIndex = this.tabs.splice(0, index); // get the tabs before the tab", - " var tabsAfterIndex = this.tabs.splice(index); // get the tabs after the tab", - "", - " this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // join them together ", - " return this;", - " };", - "", - "// Let's create three browser windows", - "var workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // Your mailbox, drive, and other work sites", - "var socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // Social sites", - "var videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // Entertainment sites", - "", - "// Now perform the tab opening, closing, and other operations", - "var finalTabs = socialWindow", - " .tabOpen() // Open a new tab for cat memes", - " .join(videoWindow.tabClose(2)) // Close third tab in video window, and join", - " .join(workWindow.tabClose(1).tabOpen());", - "", - "alert(finalTabs.tabs);" - ], - "tests": [ - "assert(true, 'message: Move ahead to understand the error.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8e367417b2b2512b5e", - "title": "Avoid Mutations and Side Effects Using Functional Programming", - "description": [ - "If you haven't already figured it out, the issue in the previous challenge was with the splice call in the tabClose() function. Unfortunately, splice changes the original array it is called on, so the second call to it used a modified array, and gave unexpected results.", - "This is a small example of a much larger pattern - you call a function on a variable, array, or an object, and the function changes the variable or something in the object.", - "One of the core principle of functional programming is to not change things. Changes lead to bugs. It's easier to prevent bugs knowing that your functions don't change anything, including the function arguments or any global variable.", - "The previous example didn't have any complicated operations but the splice method changed the original array, and resulted in a bug.", - "Recall that in functional programming, changing or altering things is called mutation, and the outcome is called a side effect. A function, ideally, should be a pure function, meaning that it does not cause any side effects.", - "Let's try to master this discipline and not alter any variable or object in our code.", - "
    ", - "Fill in the code for the function incrementer so it returns the value of the global variable fixedValue increased by one." - ], - "challengeSeed": [ - "// the global variable", - "var fixedValue = 4;", - "", - "function incrementer () {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "", - "var newValue = incrementer(); // Should equal 5", - "console.log(fixedValue); // Should print 4" - ], - "tests": [ - "assert(fixedValue === 4, 'message: Your function incrementer should not change the value of fixedValue.');", - "assert(newValue === 5, 'message: Your incrementer function should return a value that is one larger than the fixedValue value.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8e367417b2b2512b5f", - "title": "Pass Arguments to Avoid External Dependence in a Function", - "description": [ - "The last challenge was a step closer to functional programming principles, but there is still something missing.", - "We didn't alter the global variable value, but the function incrementer would not work without the global variable fixedValue being there.", - "Another principle of functional programming is to always declare your dependencies explicitly. This means if a function depends on a variable or object being present, then pass that variable or object directly into the function as an argument.", - "There are several good consequences from this principle. The function is easier to test, you know exactly what input it takes, and it won't depend on anything else in your program.", - "This can give you more confidence when you alter, remove, or add new code. You would know what you can or cannot change and you can see where the potential traps are.", - "Finally, the function would always produce the same output for the same set of inputs, no matter what part of the code executes it.", - "
    ", - "Let's update the incrementer function to clearly declare its dependencies.", - "Write the incrementer function so it takes an argument, and then increases the value by one." - ], - "challengeSeed": [ - "// the global variable", - "var fixedValue = 4;", - "", - "// Add your code below this line", - "function incrementer () {", - " ", - " ", - " // Add your code above this line", - "}", - "", - "var newValue = incrementer(fixedValue); // Should equal 5", - "console.log(fixedValue); // Should print 4" - ], - "tests": [ - "assert(fixedValue === 4, 'message: Your function incrementer should not change the value of fixedValue.');", - "assert(code.match(/function\\s+?incrementer\\s*?\\(.+?\\)/g), 'message: Your incrementer function should take a parameter.');", - "assert(newValue === 5, 'message: Your incrementer function should return a value that is one larger than the fixedValue value.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8f367417b2b2512b60", - "title": "Refactor Global Variables Out of Functions", - "description": [ - "So far, we have seen two distinct principles for functional programming:", - "1) Don't alter a variable or object - create new variables and objects and return them if need be from a function.", - "2) Declare function arguments - any computation inside a function depends only on the arguments, and not on any global object or variable.", - "Adding one to a number is not very exciting, but we can apply these principles when working with arrays or more complex objects.", - "
    ", - "Refactor (rewrite) the code so the global array bookList is not changed inside either function. The add function should add the given bookName to the end of an array. The remove function should remove the given bookName from an array. Both functions should return an array, and any new parameters should be added before the bookName one." - ], - "challengeSeed": [ - "// the global variable", - "var bookList = [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"];", - "", - "/* This function should add a book to the list and return the list */", - "// New parameters should come before the bookName one", - "", - "// Add your code below this line", - "function add (bookName) {", - " ", - " return bookList.push(bookName);", - " ", - " // Add your code above this line", - "}", - "", - "/* This function should remove a book from the list and return the list */", - "// New parameters should come before the bookName one", - "", - "// Add your code below this line", - "function remove (bookName) {", - " if (bookList.indexOf(bookName) >= 0) {", - " ", - " return bookList.splice(0, 1, bookName);", - " ", - " // Add your code above this line", - " }", - "}", - "", - "var newBookList = add(bookList, 'A Brief History of Time');", - "var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');", - "var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');", - "", - "console.log(bookList);" - ], - "tests": [ - "assert(JSON.stringify(bookList) === JSON.stringify([\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"]), 'message: bookList should not change and still equal [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"].');", - "assert(JSON.stringify(newBookList) === JSON.stringify(['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']), 'message: newBookList should equal [\"The Hound of the Baskervilles\", \"On The Electrodynamics of Moving Bodies\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\", \"A Brief History of Time\"].');", - "assert(JSON.stringify(newerBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']), 'message: newerBookList should equal [\"The Hound of the Baskervilles\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\"].');", - "assert(JSON.stringify(newestBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']), 'message: newestBookList should equal [\"The Hound of the Baskervilles\", \"Philosophiæ Naturalis Principia Mathematica\", \"Disquisitiones Arithmeticae\", \"A Brief History of Time\"].');" - ], - "solutions": [], - "hints": [ - "Look at how the functions are called to see the correct order of the parameters.", - "Consider using the concat method instead of push.", - "The slice method returns a new array without modifying the original." - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8f367417b2b2512b61", - "title": "Use the map Method to Extract Data from an Array", - "description": [ - "So far we have learned to use pure functions to avoid side effects in a program. Also, we have seen the value in having a function only depend on its input arguments.", - "This is only the beginning. As its name suggests, functional programming is centered around a theory of functions.", - "It would make sense to be able to pass them as arguments to other functions, and return a function from another function. Functions are considered First Class Objects in JavaScript, which means they can be used like any other object. They can be saved in variables, stored in an object, or passed as function arguments.", - "Let's start with some simple array functions, which are methods on the array object prototype. In this exercise we are looking at Array.prototype.map(), or more simply map.", - "Remember that the map method is a way to iterate over each item in an array. It creates a new array (without changing the original one) after applying a callback function to every element.", - "
    ", - "The watchList array holds objects with information on several movies. Use map to pull the title and rating from watchList and save the new array in the rating variable. The code in the editor currently uses a for loop to do this, replace the loop functionality with your map expression." - ], - "challengeSeed": [ - "// the global variable", - "var watchList = [", - " { ", - " \"Title\": \"Inception\",", - " \"Year\": \"2010\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"16 Jul 2010\",", - " \"Runtime\": \"148 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Christopher Nolan\",", - " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",", - " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",", - " \"Language\": \"English, Japanese, French\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.8\",", - " \"imdbVotes\": \"1,446,708\",", - " \"imdbID\": \"tt1375666\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Interstellar\",", - " \"Year\": \"2014\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"07 Nov 2014\",", - " \"Runtime\": \"169 min\",", - " \"Genre\": \"Adventure, Drama, Sci-Fi\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",", - " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",", - " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",", - " \"Language\": \"English\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.6\",", - " \"imdbVotes\": \"910,366\",", - " \"imdbID\": \"tt0816692\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"The Dark Knight\",", - " \"Year\": \"2008\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Jul 2008\",", - " \"Runtime\": \"152 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",", - " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",", - " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",", - " \"Language\": \"English, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"82\",", - " \"imdbRating\": \"9.0\",", - " \"imdbVotes\": \"1,652,832\",", - " \"imdbID\": \"tt0468569\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Batman Begins\",", - " \"Year\": \"2005\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"15 Jun 2005\",", - " \"Runtime\": \"140 min\",", - " \"Genre\": \"Action, Adventure\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",", - " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",", - " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",", - " \"Language\": \"English, Urdu, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",", - " \"Metascore\": \"70\",", - " \"imdbRating\": \"8.3\",", - " \"imdbVotes\": \"972,584\",", - " \"imdbID\": \"tt0372784\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"Avatar\",", - " \"Year\": \"2009\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Dec 2009\",", - " \"Runtime\": \"162 min\",", - " \"Genre\": \"Action, Adventure, Fantasy\",", - " \"Director\": \"James Cameron\",", - " \"Writer\": \"James Cameron\",", - " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",", - " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",", - " \"Language\": \"English, Spanish\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",", - " \"Metascore\": \"83\",", - " \"imdbRating\": \"7.9\",", - " \"imdbVotes\": \"876,575\",", - " \"imdbID\": \"tt0499549\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " }", - "];", - "", - "// Add your code below this line", - "", - "var rating = [];", - "for(var i=0; i < watchList.length; i++){", - " rating.push({title: watchList[i][\"Title\"], rating: watchList[i][\"imdbRating\"]});", - "}", - "", - "// Add your code above this line", - "", - "console.log(rating); " - ], - "tests": [ - "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList variable should not change.');", - "assert(!code.match(/for\\s*?\\(.+?\\)/g), 'message: Your code should not use a for loop.');", - "assert(code.match(/\\.map/g), 'message: Your code should use the map method.');", - "assert(JSON.stringify(rating) === JSON.stringify([{\"title\":\"Inception\",\"rating\":\"8.8\"},{\"title\":\"Interstellar\",\"rating\":\"8.6\"},{\"title\":\"The Dark Knight\",\"rating\":\"9.0\"},{\"title\":\"Batman Begins\",\"rating\":\"8.3\"},{\"title\":\"Avatar\",\"rating\":\"7.9\"}]), 'message: rating should equal [{\"title\":\"Inception\",\"rating\":\"8.8\"},{\"title\":\"Interstellar\",\"rating\":\"8.6\"},{\"title\":\"The Dark Knight\",\"rating\":\"9.0\"},{\"title\":\"Batman Begins\",\"rating\":\"8.3\"},{\"title\":\"Avatar\",\"rating\":\"7.9\"}].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8f367417b2b2512b62", - "title": "Implement map on a Prototype", - "description": [ - "As you have seen from applying Array.prototype.map(), or simply map() earlier, the map method returns an array of the same length as the one it was called on. It also doesn't alter the original array, as long as its callback function doesn't.", - "In other words, map is a pure function, and its output depends solely on its inputs. Plus, it takes another function as its argument.", - "It would teach us a lot about map to try to implement a version of it that behaves exactly like the Array.prototype.map() with a for loop or Array.prototype.forEach().", - "Note: A pure function is allowed to alter local variables defined within its scope, although, it's preferable to avoid that as well.", - "
    ", - "Write your own Array.prototype.myMap(), which should behave exactly like Array.prototype.map(). You may use a for loop or the forEach method." - ], - "challengeSeed": [ - "// the global Array", - "var s = [23, 65, 98, 5];", - "", - "Array.prototype.myMap = function(callback){", - " var newArray = [];", - " // Add your code below this line", - " ", - " // Add your code above this line", - " return newArray;", - "", - "};", - "", - "var new_s = s.myMap(function(item){", - " return item * 2;", - "});" - ], - "tests": [ - "assert(JSON.stringify(new_s) === JSON.stringify([46, 130, 196, 10]), 'message: new_s should equal [46, 130, 196, 10].');", - "assert(!code.match(/\\.map/g), 'message: Your code should not use the map method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8f367417b2b2512b63", - "title": "Use the filter Method to Extract Data from an Array", - "description": [ - "Another useful array function is Array.prototype.filter(), or simply filter(). The filter method returns a new array which is at most as long as the original array, but usually has fewer items.", - "Filter doesn't alter the original array, just like map. It takes a callback function that applies the logic inside the callback on each element of the array. If an element returns true based on the criteria in the callback function, then it is included in the new array.", - "
    ", - "The variable watchList holds an array of objects with information on several movies. Use a combination of filter and map to return a new array of objects with only title and rating keys, but where imdbRating is greater than or equal to 8.0. Note that the rating values are saved as strings in the object and you may want to convert them into numbers to perform mathematical operations on them." - ], - "challengeSeed": [ - "// the global variable", - "var watchList = [", - " { ", - " \"Title\": \"Inception\",", - " \"Year\": \"2010\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"16 Jul 2010\",", - " \"Runtime\": \"148 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Christopher Nolan\",", - " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",", - " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",", - " \"Language\": \"English, Japanese, French\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.8\",", - " \"imdbVotes\": \"1,446,708\",", - " \"imdbID\": \"tt1375666\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Interstellar\",", - " \"Year\": \"2014\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"07 Nov 2014\",", - " \"Runtime\": \"169 min\",", - " \"Genre\": \"Adventure, Drama, Sci-Fi\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",", - " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",", - " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",", - " \"Language\": \"English\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.6\",", - " \"imdbVotes\": \"910,366\",", - " \"imdbID\": \"tt0816692\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"The Dark Knight\",", - " \"Year\": \"2008\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Jul 2008\",", - " \"Runtime\": \"152 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",", - " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",", - " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",", - " \"Language\": \"English, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"82\",", - " \"imdbRating\": \"9.0\",", - " \"imdbVotes\": \"1,652,832\",", - " \"imdbID\": \"tt0468569\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Batman Begins\",", - " \"Year\": \"2005\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"15 Jun 2005\",", - " \"Runtime\": \"140 min\",", - " \"Genre\": \"Action, Adventure\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",", - " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",", - " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",", - " \"Language\": \"English, Urdu, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",", - " \"Metascore\": \"70\",", - " \"imdbRating\": \"8.3\",", - " \"imdbVotes\": \"972,584\",", - " \"imdbID\": \"tt0372784\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"Avatar\",", - " \"Year\": \"2009\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Dec 2009\",", - " \"Runtime\": \"162 min\",", - " \"Genre\": \"Action, Adventure, Fantasy\",", - " \"Director\": \"James Cameron\",", - " \"Writer\": \"James Cameron\",", - " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",", - " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",", - " \"Language\": \"English, Spanish\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",", - " \"Metascore\": \"83\",", - " \"imdbRating\": \"7.9\",", - " \"imdbVotes\": \"876,575\",", - " \"imdbID\": \"tt0499549\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " }", - "];", - "", - "// Add your code below this line", - "", - "var filteredList;", - "", - "// Add your code above this line", - "", - "console.log(filteredList); " - ], - "tests": [ - "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList variable should not change.');", - "assert(code.match(/\\.filter/g), 'message: Your code should use the filter method.');", - "assert(!code.match(/for\\s*?\\(.+?\\)/g), 'message: Your code should not use a for loop.');", - "assert.deepEqual(filteredList, [{\"title\": \"Inception\",\"rating\": \"8.8\"},{\"title\": \"Interstellar\",\"rating\": \"8.6\"},{\"title\": \"The Dark Knight\",\"rating\": \"9.0\"},{\"title\": \"Batman Begins\",\"rating\": \"8.3\"}], 'message: filteredList should equal [{\"title\": \"Inception\",\"rating\": \"8.8\"},{\"title\": \"Interstellar\",\"rating\": \"8.6\"},{\"title\": \"The Dark Knight\",\"rating\": \"9.0\"},{\"title\": \"Batman Begins\",\"rating\": \"8.3\"}].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b8f367417b2b2512b64", - "title": "Implement the filter Method on a Prototype", - "description": [ - "It would teach us a lot about the filter method if we try to implement a version of it that behaves exactly like Array.prototype.filter(). It can use either a for loop or Array.prototype.forEach().", - "Note: A pure function is allowed to alter local variables defined within its scope, although, it's preferable to avoid that as well.", - "
    ", - "Write your own Array.prototype.myFilter(), which should behave exactly like Array.prototype.filter(). You may use a for loop or the Array.prototype.forEach() method." - ], - "challengeSeed": [ - "// the global Array", - "var s = [23, 65, 98, 5];", - "", - "Array.prototype.myFilter = function(callback){", - " var newArray = [];", - " // Add your code below this line", - " ", - " // Add your code above this line", - " return newArray;", - "", - "};", - "", - "var new_s = s.myFilter(function(item){", - " return item % 2 === 1;", - "});" - ], - "tests": [ - "assert(JSON.stringify(new_s) === JSON.stringify([23, 65, 5]), 'message: new_s should equal [23, 65, 5].');", - "assert(!code.match(/\\.filter/g), 'message: Your code should not use the filter method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7b90367417b2b2512b65", - "title": "Return Part of an Array Using the slice Method", - "description": [ - "The slice method returns a copy of certain elements of an array. It can take two arguments, the first gives the index of where to begin the slice, the second is the index for where to end the slice (and it's non-inclusive). If the arguments are not provided, the default is to start at the beginning of the array through the end, which is an easy way to make a copy of the entire array. The slice method does not mutate the original array, but returns a new one.", - "Here's an example:", - "
    var arr = [\"Cat\", \"Dog\", \"Tiger\", \"Zebra\"];
    var newArray = arr.slice(1, 3);
    // Sets newArray to [\"Dog\", \"Tiger\"]
    ", - "
    ", - "Use the slice method in the sliceArray function to return part of the anim array given the provided beginSlice and endSlice indices. The function should return an array." - ], - "challengeSeed": [ - "function sliceArray(anim, beginSlice, endSlice) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "var inputAnim = [\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"];", - "sliceArray(inputAnim, 1, 3);" - ], - "tests": [ - "assert(code.match(/\\.slice/g), 'message: Your code should use the slice method.');", - "assert(JSON.stringify(inputAnim) === JSON.stringify([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"]), 'message: The inputAnim variable should not change.');", - "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 3)) === JSON.stringify([\"Dog\", \"Tiger\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 3) should return [\"Dog\", \"Tiger\"].');", - "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 0, 1)) === JSON.stringify([\"Cat\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 0, 1) should return [\"Cat\"].');", - "assert(JSON.stringify(sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 4)) === JSON.stringify([\"Dog\", \"Tiger\", \"Zebra\"]), 'message: sliceArray([\"Cat\", \"Dog\", \"Tiger\", \"Zebra\", \"Ant\"], 1, 4) should return [\"Dog\", \"Tiger\", \"Zebra\"].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "9d7123c8c441eeafaeb5bdef", - "title": "Remove Elements from an Array Using slice Instead of splice", - "description": [ - "A common pattern while working with arrays is when you want to remove items and keep the rest of the array. JavaScript offers the splice method for this, which takes arguments for the index of where to start removing items, then the number of items to remove. If the second argument is not provided, the default is to remove items through the end. However, the splice method mutates the original array it is called on. Here's an example:", - "
    var cities = [\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"];
    cities.splice(3, 1); // Returns \"London\" and deletes it from the cities array
    // cities is now [\"Chicago\", \"Delhi\", \"Islamabad\", \"Berlin\"]
    ", - "As we saw in the last challenge, the slice method does not mutate the original array, but returns a new one which can be saved into a variable. Recall that the slice method takes two arguments for the indices to begin and end the slice (the end is non-inclusive), and returns those items in a new array. Using the slice method instead of splice helps to avoid any array-mutating side effects.", - "
    ", - "Rewrite the function nonMutatingSplice by using slice instead of splice. It should limit the provided cities array to a length of 3, and return a new array with only the first three items.", - "Do not mutate the original array provided to the function." - ], - "challengeSeed": [ - "function nonMutatingSplice(cities) {", - " // Add your code below this line", - " return cities.splice(3);", - " ", - " // Add your code above this line", - "}", - "var inputCities = [\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"];", - "nonMutatingSplice(inputCities);" - ], - "tests": [ - "assert(code.match(/\\.slice/g), 'message: Your code should use the slice method.');", - "assert(!code.match(/\\.splice/g), 'message: Your code should not use the splice method.');", - "assert(JSON.stringify(inputCities) === JSON.stringify([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"]), 'message: The inputCities array should not change.');", - "assert(JSON.stringify(nonMutatingSplice([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"])) === JSON.stringify([\"Chicago\", \"Delhi\", \"Islamabad\"]), 'message: nonMutatingSplice([\"Chicago\", \"Delhi\", \"Islamabad\", \"London\", \"Berlin\"]) should return [\"Chicago\", \"Delhi\", \"Islamabad\"].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7da9367417b2b2512b66", - "title": "Combine Two Arrays Using the concat Method", - "description": [ - "Concatenation means to join items end to end. JavaScript offers the concat method for both strings and arrays that work in the same way. For arrays, the method is called on one, then another array is provided as the argument to concat, which is added to the end of the first array. It returns a new array and does not mutate either of the original arrays. Here's an example:", - "
    [1, 2, 3].concat([4, 5, 6]);
    // Returns a new array [1, 2, 3, 4, 5, 6]
    ", - "
    ", - "Use the concat method in the nonMutatingConcat function to concatenate attach to the end of original. The function should return the concatenated array." - ], - "challengeSeed": [ - "function nonMutatingConcat(original, attach) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "var first = [1, 2, 3];", - "var second = [4, 5];", - "nonMutatingConcat(first, second);" - ], - "tests": [ - "assert(code.match(/\\.concat/g), 'message: Your code should use the concat method.');", - "assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]), 'message: The first array should not change.');", - "assert(JSON.stringify(second) === JSON.stringify([4, 5]), 'message: The second array should not change.');", - "assert(JSON.stringify(nonMutatingConcat([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]), 'message: nonMutatingConcat([1, 2, 3], [4, 5]) should return [1, 2, 3, 4, 5].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7da9367417b2b2512b67", - "title": "Add Elements to the End of an Array Using concat Instead of push", - "description": [ - "Functional programming is all about creating and using non-mutating functions.", - "The last challenge introduced the concat method as a way to combine arrays into a new one without mutating the original arrays. Compare concat to the push method. Push adds an item to the end of the same array it is called on, which mutates that array. Here's an example:", - "
    var arr = [1, 2, 3];
    arr.push([4, 5, 6]);
    // arr is changed to [1, 2, 3, [4, 5, 6]]
    // Not the functional programming way
    ", - "Concat offers a way to add new items to the end of an array without any mutating side effects.", - "
    ", - "Change the nonMutatingPush function so it uses concat to add newItem to the end of original instead of push. The function should return an array." - ], - "challengeSeed": [ - "function nonMutatingPush(original, newItem) {", - " // Add your code below this line", - " return original.push(newItem);", - " ", - " // Add your code above this line", - "}", - "var first = [1, 2, 3];", - "var second = [4, 5];", - "nonMutatingPush(first, second);" - ], - "tests": [ - "assert(code.match(/\\.concat/g), 'message: Your code should use the concat method.');", - "assert(!code.match(/\\.push/g), 'message: Your code should not use the push method.');", - "assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]), 'message: The first array should not change.');", - "assert(JSON.stringify(second) === JSON.stringify([4, 5]), 'message: The second array should not change.');", - "assert(JSON.stringify(nonMutatingPush([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]), 'message: nonMutatingPush([1, 2, 3], [4, 5]) should return [1, 2, 3, 4, 5].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7da9367417b2b2512b68", - "title": "Use the reduce Method to Analyze Data", - "description": [ - "Array.prototype.reduce(), or simply reduce(), is the most general of all array operations in JavaScript. You can solve almost any array processing problem using the reduce method.", - "This is not the case with the filter and map methods since they do not allow interaction between two different elements of the array. For example, if you want to compare elements of the array, or add them together, filter or map could not process that.", - "The reduce method allows for more general forms of array processing, and it's possible to show that both filter and map can be derived as a special application of reduce.", - "However, before we get there, let's practice using reduce first.", - "
    ", - "The variable watchList holds an array of objects with information on several movies. Use reduce to find the average IMDB rating of the movies directed by Christopher Nolan. Recall from prior challenges how to filter data and map over it to pull what you need. You may need to create other variables, but save the final average into the variable averageRating. Note that the rating values are saved as strings in the object and need to be converted into numbers before they are used in any mathematical operations." - ], - "challengeSeed": [ - "// the global variable", - "var watchList = [", - " { ", - " \"Title\": \"Inception\",", - " \"Year\": \"2010\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"16 Jul 2010\",", - " \"Runtime\": \"148 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Christopher Nolan\",", - " \"Actors\": \"Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy\",", - " \"Plot\": \"A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.\",", - " \"Language\": \"English, Japanese, French\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 4 Oscars. Another 143 wins & 198 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.8\",", - " \"imdbVotes\": \"1,446,708\",", - " \"imdbID\": \"tt1375666\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Interstellar\",", - " \"Year\": \"2014\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"07 Nov 2014\",", - " \"Runtime\": \"169 min\",", - " \"Genre\": \"Adventure, Drama, Sci-Fi\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan, Christopher Nolan\",", - " \"Actors\": \"Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow\",", - " \"Plot\": \"A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.\",", - " \"Language\": \"English\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 1 Oscar. Another 39 wins & 132 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg\",", - " \"Metascore\": \"74\",", - " \"imdbRating\": \"8.6\",", - " \"imdbVotes\": \"910,366\",", - " \"imdbID\": \"tt0816692\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"The Dark Knight\",", - " \"Year\": \"2008\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Jul 2008\",", - " \"Runtime\": \"152 min\",", - " \"Genre\": \"Action, Adventure, Crime\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)\",", - " \"Actors\": \"Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine\",", - " \"Plot\": \"When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.\",", - " \"Language\": \"English, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 2 Oscars. Another 146 wins & 142 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg\",", - " \"Metascore\": \"82\",", - " \"imdbRating\": \"9.0\",", - " \"imdbVotes\": \"1,652,832\",", - " \"imdbID\": \"tt0468569\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " { ", - " \"Title\": \"Batman Begins\",", - " \"Year\": \"2005\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"15 Jun 2005\",", - " \"Runtime\": \"140 min\",", - " \"Genre\": \"Action, Adventure\",", - " \"Director\": \"Christopher Nolan\",", - " \"Writer\": \"Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)\",", - " \"Actors\": \"Christian Bale, Michael Caine, Liam Neeson, Katie Holmes\",", - " \"Plot\": \"After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.\",", - " \"Language\": \"English, Urdu, Mandarin\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Nominated for 1 Oscar. Another 15 wins & 66 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg\",", - " \"Metascore\": \"70\",", - " \"imdbRating\": \"8.3\",", - " \"imdbVotes\": \"972,584\",", - " \"imdbID\": \"tt0372784\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " },", - " {", - " \"Title\": \"Avatar\",", - " \"Year\": \"2009\",", - " \"Rated\": \"PG-13\",", - " \"Released\": \"18 Dec 2009\",", - " \"Runtime\": \"162 min\",", - " \"Genre\": \"Action, Adventure, Fantasy\",", - " \"Director\": \"James Cameron\",", - " \"Writer\": \"James Cameron\",", - " \"Actors\": \"Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang\",", - " \"Plot\": \"A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.\",", - " \"Language\": \"English, Spanish\",", - " \"Country\": \"USA, UK\",", - " \"Awards\": \"Won 3 Oscars. Another 80 wins & 121 nominations.\",", - " \"Poster\": \"http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg\",", - " \"Metascore\": \"83\",", - " \"imdbRating\": \"7.9\",", - " \"imdbVotes\": \"876,575\",", - " \"imdbID\": \"tt0499549\",", - " \"Type\": \"movie\",", - " \"Response\": \"True\"", - " }", - "];", - "", - "// Add your code below this line", - "", - "var averageRating;", - "", - "// Add your code above this line", - "", - "console.log(averageRating); " - ], - "tests": [ - "assert(watchList[0].Title === \"Inception\" && watchList[4].Director == \"James Cameron\", 'message: The watchList variable should not change.');", - "assert(code.match(/\\.reduce/g), 'message: Your code should use the reduce method.');", - "assert(averageRating == 8.675, 'message: The averageRating should equal 8.675.');", - "assert(!code.match(/for\\s*?\\(.*\\)/g), 'message: Your code should not use a for loop.');" - ], - "solutions": [], - "hints": [ - "Try using .filter() to filter the watchList by Director.", - "Try using .map() to return an array of ratings.", - "You can use Number() to convert a string into a number." - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7da9367417b2b2512b69", - "title": "Sort an Array Alphabetically using the sort Method", - "description": [ - "The sort method sorts the elements of an array according to the callback function.", - "For example:", - "
    function ascendingOrder(arr) {
      return arr.sort(function(a, b) {
        return a - b;
      });
    }
    ascendingOrder([1, 5, 2, 3, 4]);
    // Returns [1, 2, 3, 4, 5]

    function reverseAlpha(arr) {
      return arr.sort(function(a, b) {
        return a < b;
      });
    }
    reverseAlpha(['l', 'h', 'z', 'b', 's']);
    // Returns ['z', 's', 'l', 'h', 'b']
    ", - "Note: It's encouraged to provide a callback function to specify how to sort the array items. JavaScript's default sorting method is by string Unicode point value, which may return unexpected results.", - "
    ", - "Use the sort method in the alphabeticalOrder function to sort the elements of arr in alphabetical order." - ], - "challengeSeed": [ - "function alphabeticalOrder(arr) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"]);" - ], - "tests": [ - "assert(code.match(/\\.sort/g), 'message: Your code should use the sort method.');", - "assert(JSON.stringify(alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"])) === JSON.stringify([\"a\", \"a\", \"c\", \"d\", \"g\", \"z\"]), 'message: alphabeticalOrder([\"a\", \"d\", \"c\", \"a\", \"z\", \"g\"]) should return [\"a\", \"a\", \"c\", \"d\", \"g\", \"z\"].');", - "assert(JSON.stringify(alphabeticalOrder([\"x\", \"h\", \"a\", \"m\", \"n\", \"m\"])) === JSON.stringify([\"a\", \"h\", \"m\", \"m\", \"n\", \"x\"]), 'message: alphabeticalOrder([\"x\", \"h\", \"a\", \"m\", \"n\", \"m\"]) should return [\"a\", \"h\", \"m\", \"m\", \"n\", \"x\"].');", - "assert(JSON.stringify(alphabeticalOrder([\"a\", \"a\", \"a\", \"a\", \"x\", \"t\"])) === JSON.stringify([\"a\", \"a\", \"a\", \"a\", \"t\", \"x\"]), 'message: alphabeticalOrder([\"a\", \"a\", \"a\", \"a\", \"x\", \"t\"]) should return [\"a\", \"a\", \"a\", \"a\", \"t\", \"x\"].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7da9367417b2b2512b6a", - "title": "Return a Sorted Array Without Changing the Original Array", - "description": [ - "A side effect of the sort method is that it changes the order of the elements in the original array. In other words, it mutates the array in place. One way to avoid this is to first concatenate an empty array to the one being sorted (remember that concat returns a new array), then run the sort method.", - "
    ", - "Use the sort method in the nonMutatingSort function to sort the elements of an array in ascending order. The function should return a new array, and not mutate the globalArray variable." - ], - "challengeSeed": [ - "var globalArray = [5, 6, 3, 2, 9];", - "function nonMutatingSort(arr) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "nonMutatingSort(globalArray);" - ], - "tests": [ - "assert(code.match(/\\.sort/g), 'message: Your code should use the sort method.');", - "assert(code.match(/\\.concat/g), 'message: Your code should use the concat method.');", - "assert(JSON.stringify(globalArray) === JSON.stringify([5, 6, 3, 2, 9]), 'message: The globalArray variable should not change.');", - "assert(JSON.stringify(nonMutatingSort(globalArray)) === JSON.stringify([2, 3, 5, 6, 9]), 'message: nonMutatingSort(globalArray) should return [2, 3, 5, 6, 9].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daa367417b2b2512b6b", - "title": "Split a String into an Array Using the split Method", - "description": [ - "The split method splits a string into an array of strings. It takes an argument for the delimiter, which can be a character to use to break up the string or a regular expression. For example, if the delimiter is a space, you get an array of words, and if the delimiter is an empty string, you get an array of each character in the string.", - "Here are two examples that split one string by spaces, then another by digits using a regular expression:", - "
    var str = \"Hello World\";
    var bySpace = str.split(\" \");
    // Sets bySpace to [\"Hello\", \"World\"]

    var otherString = \"How9are7you2today\";
    var byDigits = str.split(/\\d/);
    // Sets byDigits to [\"How\", \"are\", \"you\", \"today\"]
    ", - "Since strings are immutable, the split method makes it easier to work with them.", - "
    ", - "Use the split method inside the splitify function to split str into an array of words. The function should return the array. Note that the words are not always separated by spaces, and the array should not contain punctuation." - ], - "challengeSeed": [ - "function splitify(str) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "splitify(\"Hello World,I-am code\");" - ], - "tests": [ - "assert(code.match(/\\.split/g), 'message: Your code should use the split method.');", - "assert(JSON.stringify(splitify(\"Hello World,I-am code\")) === JSON.stringify([\"Hello\", \"World\", \"I\", \"am\", \"code\"]), 'message: splitify(\"Hello World,I-am code\") should return [\"Hello\", \"World\", \"I\", \"am\", \"code\"].');", - "assert(JSON.stringify(splitify(\"Earth-is-our home\")) === JSON.stringify([\"Earth\", \"is\", \"our\", \"home\"]), 'message: splitify(\"Earth-is-our home\") should return [\"Earth\", \"is\", \"our\", \"home\"].');", - "assert(JSON.stringify(splitify(\"This.is.a-sentence\")) === JSON.stringify([\"This\", \"is\", \"a\", \"sentence\"]), 'message: splitify(\"This.is.a-sentence\") should return [\"This\", \"is\", \"a\", \"sentence\"].');" - ], - "solutions": [], - "hints": [ - "The regex pre-defined character class for non-alphanumerics is \\W." - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daa367417b2b2512b6c", - "title": "Combine an Array into a String Using the join Method", - "description": [ - "The join method is used to join the elements of an array together to create a string. It takes an argument for the delimiter that is used to separate the array elements in the string.", - "Here's an example:", - "
    var arr = [\"Hello\", \"World\"];
    var str = arr.join(\" \");
    // Sets str to \"Hello World\"
    ", - "
    ", - "Use the join method (among others) inside the sentensify function to make a sentence from the words in the string str. The function should return a string. For example, \"I-like-Star-Wars\" would be converted to \"I like Star Wars\". For this challenge, do not use the replace method." - ], - "challengeSeed": [ - "function sentensify(str) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "sentensify(\"May-the-force-be-with-you\");" - ], - "tests": [ - "assert(code.match(/\\.join/g), 'message: Your code should use the join method.');", - "assert(!code.match(/\\.replace/g), 'message: Your code should not use the replace method.');", - "assert(typeof sentensify(\"May-the-force-be-with-you\") === \"string\", 'message: sentensify(\"May-the-force-be-with-you\") should return a string.');", - "assert(sentensify(\"May-the-force-be-with-you\") === \"May the force be with you\", 'message: sentensify(\"May-the-force-be-with-you\") should return \"May the force be with you\".');", - "assert(sentensify(\"The.force.is.strong.with.this.one\") === \"The force is strong with this one\", 'message: sentensify(\"The.force.is.strong.with.this.one\") should return \"The force is strong with this one\".');", - "assert(sentensify(\"There,has,been,an,awakening\") === \"There has been an awakening\", 'message: sentensify(\"There,has,been,an,awakening\") should return \"There has been an awakening\".');" - ], - "solutions": [], - "hints": [ - "First try to split the given string before applying the join method." - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dab367417b2b2512b6d", - "title": "Apply Functional Programming to Convert Strings to URL Slugs", - "description": [ - "The last several challenges covered a number of useful array and string methods that follow functional programming principles. We've also learned about reduce, which is a powerful method used to reduce problems to simpler forms. From computing averages to sorting, any array operation can be achieved by applying it. Recall that map and filter are special cases of reduce.", - "Let's combine what we've learned to solve a practical problem.", - "Many content management sites (CMS) have the titles of a post added to part of the URL for simple bookmarking purposes. For example, if you write a Medium post titled \"Stop Using Reduce\", it's likely the URL would have some form of the title string in it (\".../stop-using-reduce\"). You may have already noticed this on the freeCodeCamp site.", - "
    ", - "Fill in the urlSlug function so it converts a string title and returns the hyphenated version for the URL. You can use any of the methods covered in this section, and don't use replace. Here are the requirements:", - "The input is a string with spaces and title-cased words", - "The output is a string with the spaces between words replaced by a hyphen (-)", - "The output should be all lower-cased letters", - "The output should not have any spaces" - ], - "challengeSeed": [ - "// the global variable", - "var globalTitle = \"Winter Is Coming\";", - "", - "// Add your code below this line", - "function urlSlug(title) {", - " ", - " ", - "}", - "// Add your code above this line", - "", - "var winterComing = urlSlug(globalTitle); // Should be \"winter-is-coming\"" - ], - "tests": [ - "assert(globalTitle === \"Winter Is Coming\", 'message: The globalTitle variable should not change.');", - "assert(!code.match(/\\.replace/g), 'message: Your code should not use the replace method for this challenge.');", - "assert(urlSlug(\"Winter Is Coming\") === \"winter-is-coming\", 'message: urlSlug(\"Winter Is Coming\") should return \"winter-is-coming\".');", - "assert(urlSlug(\" Winter Is Coming\") === \"winter-is-coming\", 'message: urlSlug(\" Winter Is  Coming\") should return \"winter-is-coming\".');", - "assert(urlSlug(\"A Mind Needs Books Like A Sword Needs A Whetstone\") === \"a-mind-needs-books-like-a-sword-needs-a-whetstone\", 'message: urlSlug(\"A Mind Needs Books Like A Sword Needs A Whetstone\") should return \"a-mind-needs-books-like-a-sword-needs-a-whetstone\".');", - "assert(urlSlug(\"Hold The Door\") === \"hold-the-door\", 'message: urlSlug(\"Hold The Door\") should return \"hold-the-door\".');" - ], - "solutions": [], - "hints": [ - "When several spaces in a row are split by space, it puts an empty string in the array.", - "You can use the .toLowerCase() method to make the title all lower case." - ], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dab367417b2b2512b6e", - "title": "Use the every Method to Check that Every Element in an Array Meets a Criteria", - "description": [ - "The every method works with arrays to check if every element passes a particular test. It returns a Boolean value - true if all values meet the criteria, false if not.", - "For example, the following code would check if every element in the numbers array is less than 10:", - "
    var numbers = [1, 5, 8, 0, 10, 11];
    numbers.every(function(currentValue) {
      return currentValue < 10;
    });
    // Returns false
    ", - "
    ", - "Use the every method inside the checkPositive function to check if every element in arr is positive. The function should return a Boolean value." - ], - "challengeSeed": [ - "function checkPositive(arr) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "checkPositive([1, 2, 3, -4, 5]);" - ], - "tests": [ - "assert(code.match(/\\.every/g), 'message: Your code should use the every method.');", - "assert(!checkPositive([1, 2, 3, -4, 5]), 'message: checkPositive([1, 2, 3, -4, 5]) should return false.');", - "assert(checkPositive([1, 2, 3, 4, 5]), 'message: checkPositive([1, 2, 3, 4, 5]) should return true.');", - "assert(!checkPositive([1, -2, 3, -4, 5]), 'message: checkPositive([1, -2, 3, -4, 5]) should return false.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dab367417b2b2512b6f", - "title": "Use the some Method to Check that Any Elements in an Array Meet a Criteria", - "description": [ - "The some method works with arrays to check if any element passes a particular test. It returns a Boolean value - true if any of the values meet the criteria, false if not.", - "For example, the following code would check if any element in the numbers array is less than 10:", - "
    var numbers = [10, 50, 8, 220, 110, 11];
    numbers.some(function(currentValue) {
      return currentValue < 10;
    });
    // Returns true
    ", - "
    ", - "Use the some method inside the checkPositive function to check if any element in arr is positive. The function should return a Boolean value." - ], - "challengeSeed": [ - "function checkPositive(arr) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "checkPositive([1, 2, 3, -4, 5]);" - ], - "tests": [ - "assert(code.match(/\\.some/g), 'message: Your code should use the some method.');", - "assert(checkPositive([1, 2, 3, -4, 5]), 'message: checkPositive([1, 2, 3, -4, 5]) should return true.');", - "assert(checkPositive([1, 2, 3, 4, 5]), 'message: checkPositive([1, 2, 3, 4, 5]) should return true.');", - "assert(!checkPositive([-1, -2, -3, -4, -5]), 'message: checkPositive([-1, -2, -3, -4, -5]) should return false.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dab367417b2b2512b70", - "title": "Introduction to Currying and Partial Application", - "description": [ - "The arity of a function is the number of arguments it requires. Currying a function means to convert a function of N arity into N functions of arity 1.", - "In other words, it restructures a function so it takes one argument, then returns another function that takes the next argument, and so on.", - "Here's an example:", - "
    //Un-curried function
    function unCurried(x, y, z) {
      return x + y + z;
    }

    //Curried function
    function curried(x) {
      return function(y) {
        return x + y;
      }
    }
    curried(1)(2) // Returns 3
    ", - "This is useful in your program if you can't supply all the arguments to a function at one time. You can save each function call into a variable, which will hold the returned function reference that takes the next argument when it's available. Here's an example using the curried function in the example above:", - "
    // Call a curried function in parts:
    var funcForY = curried(1);
    var funcForZ = funcForY(2);
    console.log(funcForZ(3)); // Prints 6
    ", - "Similarly, partial application can be described as applying a few arguments to a function at a time and returning another function that is applied to more arguments.", - "Here's an example:", - "
    //Impartial function
    function impartial(x, y, z) {
      return x + y + z;
    }
    var partialFn = impartial.bind(this, 1, 2);
    partialFn(10); // Returns 13
    ", - "
    ", - "Fill in the body of the add function so it uses currying to add parameters x, y, and z." - ], - "challengeSeed": [ - "function add(x) {", - " // Add your code below this line", - " ", - " ", - " // Add your code above this line", - "}", - "add(10)(20)(30);" - ], - "tests": [ - "assert(add(10)(20)(30) === 60, 'message: add(10)(20)(30) should return 60.');", - "assert(add(1)(2)(3) === 6, 'message: add(1)(2)(3) should return 6.');", - "assert(add(11)(22)(33) === 66, 'message: add(11)(22)(33) should return 66.');", - "assert(code.match(/[xyz]\\s*?\\+\\s*?[xyz]\\s*?\\+\\s*?[xyz]/g), 'message: Your code should include a final statement that returns x + y + z.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "challengeType": 1, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json deleted file mode 100644 index 275f69bdcd..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json +++ /dev/null @@ -1,1212 +0,0 @@ -{ - "name": "Intermediate Algorithm Scripting", - "order": 9, - "time": "50 hours", - "helpRoom": "HelpJavaScript", - "challenges": [ - { - "id": "a3566b1109230028080c9345", - "title": "Sum All Numbers in a Range", - "description": [ - "We'll pass you an array of two numbers. Return the sum of those two numbers plus the sum of all the numbers between them.", - "The lowest number will not always come first.", - "Remember to use
    Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function sumAll(arr) {", - " return 1;", - "}", - "", - "sumAll([1, 4]);" - ], - "hints": [ - "Use Math.max() to find the maximum value of two numbers.", - "Use Math.min() to find the minimum value of two numbers.", - "Remember to that you must add all the numbers in between so this would require a way to get those numbers." - ], - "solutions": [ - "function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}" - ], - "tests": [ - "assert(typeof sumAll([1, 4]) === 'number', 'message: sumAll([1, 4]) should return a number.');", - "assert.deepEqual(sumAll([1, 4]), 10, 'message: sumAll([1, 4]) should return 10.');", - "assert.deepEqual(sumAll([4, 1]), 10, 'message: sumAll([4, 1]) should return 10.');", - "assert.deepEqual(sumAll([5, 10]), 45, 'message: sumAll([5, 10]) should return 45.');", - "assert.deepEqual(sumAll([10, 5]), 45, 'message: sumAll([10, 5]) should return 45.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Math.max()", - "Math.min()", - "Array.prototype.reduce()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Suma todos los números en un rango", - "description": [ - "Te pasaremos un vector que contiene dos números. Crea una función que devuelva la suma de esos dos números y todos los números entre ellos.", - "El número menor no siempre será el primer elemento en el vector.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Additionner tous les nombres d'une série", - "description": [ - "Nous te passons un tableau de deux nombres. Crée une fonction qui renvoie la somme de ces 2 nombres ainsi que tous les nombres entre ceux-ci.", - "Le plus petit nombre ne viendra pas forcément en premier.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a5de63ebea8dbee56860f4f2", - "title": "Diff Two Arrays", - "description": [ - "Compare two arrays and return a new array with any items only found in one of the two given arrays, but not both. In other words, return the symmetric difference of the two arrays.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.", - "Note
    You can return the array with its elements in any order." - ], - "challengeSeed": [ - "function diffArray(arr1, arr2) {", - " var newArr = [];", - " // Same, same; but different.", - " return newArr;", - "}", - "", - "diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);" - ], - "solutions": [ - "function diffArray(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}" - ], - "tests": [ - "assert(typeof diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'message: diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) should return an array.');", - "assert.sameMembers(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"pink wool\"].');", - "assert(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 1, 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return an array with one item.');", - "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [\"diorite\", \"pink wool\"].');", - "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 2, 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return an array with two items.');", - "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return [].');", - "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 0, 'message: [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"] should return an empty array.');", - "assert.sameMembers(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5] should return [4].');", - "assert(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]).length === 1, 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5] should return an array with one item.');", - "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4] should return [\"piglet\", 4].');", - "assert(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]).length === 2, 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4] should return an array with two items.');", - "assert.sameMembers(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"] should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"].');", - "assert(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]).length === 3, 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"] should return an array with three items.');", - "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"] should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"].');", - "assert(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]).length === 6, 'message: [1, \"calf\", 3, \"piglet\"], [7, \"filly\"] should return an array with six items.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Comparison Operators", - "Array.prototype.slice()", - "Array.prototype.filter()", - "Array.prototype.indexOf()", - "Array.prototype.concat()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Obtén la diferencia entre dos vectores", - "description": [ - "Crea una función que compare dos vectores y que devuelva un nuevo vector que contenga los elementos que sólo se encuentre en uno de los vectores dados, pero no en ambos En otras palabras, devuelve la diferencia simétrica entre los dos vectores.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Comparer 2 arrays", - "description": [ - "Compare les 2 tableaux donnés et renvoie un nouvel tableau avec les éléments trouvé dans un seul des deux tableaux, pas dans les deux. En d'autres termes, renvoie la différence symétrique des deux tableaux.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a39963a4c10bc8b4d4f06d7e", - "title": "Seek and Destroy", - "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.", - "Note
    You have to use the arguments object.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "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], 'message: destroyer([1, 2, 3, 1, 2, 3], 2, 3) should return [1, 1].');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'message: destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3) should return [1, 5, 1].');", - "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'message: destroyer([3, 5, 1, 2, 2], 2, 3, 5) should return [1].');", - "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'message: destroyer([2, 3, 2, 3], 2, 3) should return [].');", - "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'message: destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53) should return [\"hamburger\"].');", - "assert.deepEqual(destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\"), [12,92,65], 'message: destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\") should return [12,92,65].');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function destroyer(arr) {\n var hash = Object.create(null);\n [].slice.call(arguments, 1).forEach(function(e) {\n hash[e] = true;\n });\n // Remove all the values\n return arr.filter(function(e) { return !(e in hash);});\n}\n\ndestroyer([1, 2, 3, 1, 2, 3], 2, 3);\n" - ], - "MDNlinks": [ - "Arguments object", - "Array.prototype.filter()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Buscar y Destruir", - "description": [ - "Se te proveerá un arreglo inicial (el primer argumento en la función destroyer), seguido por uno o más argumentos. Elimina todos los elementos del arreglo inicial que tengan el mismo valor que el resto de argumentos.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Buscar e Destruir", - "description": [ - "Será fornecido a você uma matriz inicial (o primeiro argumento da função destroyer), seguido por um ou mais argumentos. Remova todos os elementos da matriz inicial que possuem o mesmo valor desses argumentos.", - "Nota
    Você precisa usar o objeto arguments.", - "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a8e512fbe388ac2f9198f0fa", - "title": "Wherefore art thou", - "description": [ - "Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching name and value pairs (second argument). Each name and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.", - "For example, if the first argument is [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], and the second argument is { last: \"Capulet\" }, then you must return the third object from the array (the first argument), because it contains the name and its value, that was passed on as the second argument.", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function whatIsInAName(collection, source) {", - " // What's in a name?", - " var arr = [];", - " // Only change code below this line", - " ", - " ", - " // Only change code above this line", - " return arr;", - "}", - "", - "whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });" - ], - "solutions": [ - "function whatIsInAName(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}" - ], - "tests": [ - "assert.deepEqual(whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }) should return [{ first: \"Tybalt\", last: \"Capulet\" }].');", - "assert.deepEqual(whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 }), [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], 'message: whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 }) should return [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }].');", - "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 }) should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }].');", - "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 }), [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 }) should return [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }].');", - "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, {\"bat\":2}], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }], 'message: whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 }) should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }].');", - "assert.deepEqual(whatIsInAName([{ \"a\": 1, \"b\": 2, \"c\": 3 }], { \"a\": 1, \"b\": 9999, \"c\": 3 }), [], 'message: whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3}) should return []');" - ], - "type": "bonfire", - "MDNlinks": [ - "Global Object", - "Object.prototype.hasOwnProperty()", - "Object.keys()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "¿Dónde estás que no te veo?", - "description": [ - "Crea una función que busque en un vector de objetos (primer argumento) y devuelva un vector con todos los objetos que compartan el valor indicado para una propiedad dada (segundo argumento). Cada pareja de propiedad y valor debe estar presente en el objeto de la colección para ser incluido en el vector devuelto por la función", - "Por ejemplo, si el primer argumento es [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], y el segundo argumento es { last: \"Capulet\" }, entonces tu función debe devolver el tercer objeto del vector en el primer argumento, ya que contiene la propiedad y el valor indicados en el segundo argumento.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "O Roméo! Roméo!", - "description": [ - "Écris une fonction qui parcourt un array d'objets (premier argument) et renvoie un array de tous les objects ayant les paires de nom/valeur correspondantes à l'objet donné (second argument). Chaque paire de nom et de valeur de l'objet source doit être présente dans les objects renvoyés.", - "Par exemple, si le premier argument est [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], et le second argument est { last: \"Capulet\" }, tu dois renvoyer le troisième objet de l'array (premier argument), parce qu'il contient le nom et sa valeur, donnés en deuxième argument.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a103376db3ba46b2d50db289", - "title": "Spinal Tap Case", - "description": [ - "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function spinalCase(str) {", - " // \"It's such a fine line between stupid, and clever.\"", - " // --David St. Hubbins", - " return str;", - "}", - "", - "spinalCase('This Is Spinal Tap');" - ], - "solutions": [ - "function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}" - ], - "tests": [ - "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'message: spinalCase(\"This Is Spinal Tap\") should return \"this-is-spinal-tap\".');", - "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'message: spinalCase(\"thisIsSpinalTap\") should return \"this-is-spinal-tap\".');", - "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'message: spinalCase(\"The_Andy_Griffith_Show\") should return \"the-andy-griffith-show\".');", - "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'message: spinalCase(\"Teletubbies say Eh-oh\") should return \"teletubbies-say-eh-oh\".');", - "assert.strictEqual(spinalCase(\"AllThe-small Things\"), \"all-the-small-things\", 'message: spinalCase(\"AllThe-small Things\") should return \"all-the-small-things\".');" - ], - "type": "bonfire", - "MDNlinks": [ - "RegExp", - "String.prototype.replace()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "separado-por-guiones", - "description": [ - "Convierte la cadena de texto que se te pasa al formato spinal case. Spinal case es cuando escribes todas las palabras en-minúsculas-unidas-por-guiones.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Trait d'union", - "description": [ - "Convertis la chaîne de caractères en spinal case. Spinal case correspond au bas-de-casse-séparé-par-des-tirets.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "aa7697ea2477d1316795783b", - "title": "Pig Latin", - "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.", - "Input strings are guaranteed to be English words in all lowercase.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function translatePigLatin(str) {", - " return str;", - "}", - "", - "translatePigLatin(\"consonant\");" - ], - "solutions": [ - "function translatePigLatin(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}" - ], - "tests": [ - "assert.deepEqual(translatePigLatin(\"california\"), \"aliforniacay\", 'message: translatePigLatin(\"california\") should return \"aliforniacay\".');", - "assert.deepEqual(translatePigLatin(\"paragraphs\"), \"aragraphspay\", 'message: translatePigLatin(\"paragraphs\") should return \"aragraphspay\".');", - "assert.deepEqual(translatePigLatin(\"glove\"), \"oveglay\", 'message: translatePigLatin(\"glove\") should return \"oveglay\".');", - "assert.deepEqual(translatePigLatin(\"algorithm\"), \"algorithmway\", 'message: translatePigLatin(\"algorithm\") should return \"algorithmway\".');", - "assert.deepEqual(translatePigLatin(\"eight\"), \"eightway\", 'message: translatePigLatin(\"eight\") should return \"eightway\".');", - "assert.deepEqual(translatePigLatin(\"schwartz\"), \"artzschway\", 'message: Should handle words where the first vowel comes in the end of the word.');", - "assert.deepEqual(translatePigLatin(\"rhythm\"), \"rhythmay\", 'message: Should handle words without vowels.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Array.prototype.indexOf()", - "Array.prototype.push()", - "Array.prototype.join()", - "String.prototype.substring()", - "String.prototype.split()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Latín de los cerdos", - "description": [ - "Traduce la cadena de texto que se te provee al Latín de los cerdos (Pig Latin)", - "Pig Latin toma la primera consonante (o grupo de consonantes) de una palabra en inglés, la mueve al final de la palabra y agrega un \"ay\".", - "Si la palabra comienza con una vocal, simplemente añade \"way\" al final.", - "Cadenas de entrada están garantizadas de ser palabras en Inglés en minúscula.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Pig latin", - "description": [ - "Traduis la phrase donnée en pig latin (verlan anglais)", - "Le Pig Latin prend la ou les première(s) consonne(s) d'un mot en anglais et les mets à la fin du mot accompagné par le suffixe \"ay\".", - "Si un mot commence par une voyelle ajoute \"way\" à la fin du mot.", - "Les chaînes de caractères entrées sont garanties d'être des mots anglais, en lettres minuscules.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a0b5010f579e69b815e7c5d6", - "title": "Search and Replace", - "description": [ - "Perform a search and replace on the sentence using the arguments provided and return the new sentence.", - "First argument is the sentence to 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 first character in 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 Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function myReplace(str, before, after) {", - " return str;", - "}", - "", - "myReplace(\"A quick brown fox jumped over the lazy dog\", \"jumped\", \"leaped\");" - ], - "solutions": [ - "function myReplace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}" - ], - "tests": [ - "assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: myReplace(\"Let us go to the store\", \"store\", \"mall\") should return \"Let us go to the mall\".');", - "assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\") should return \"He is Sitting on the couch\".');", - "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\") should return \"This has a spelling error\".');", - "assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: myReplace(\"His name is Tom\", \"Tom\", \"john\") should return \"His name is John\".');", - "assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\"), \"Let us get back to more Algorithms\", 'message: myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\") should return \"Let us get back to more Algorithms\".');" - ], - "type": "bonfire", - "MDNlinks": [ - "Array.prototype.splice()", - "String.prototype.replace()", - "Array.prototype.join()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Buscar y reemplazar", - "description": [ - "Crea una función que busque un fragmento en una frase dada y lo reemplace por otro fragmento, devolviendo la nueva frase.", - "El primer argumento es la frase en la que se ejecutará la búsqueda y el reemplazo", - "El segundo argumento es la palabra que se va a reemplazar", - "El tercer argumento es lo que reemplazará a la palabra indicada en el segundo argumento", - "NOTA: Debes respetar mayúsculas y minúsculas de la palabra original cuando ejecutes el reemplazo. Por ejemplo, si quisieras reemplazar la palabra \"Libro\" con la palabra \"perro\", deberías insertar en vez la palabra \"Perro\"", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Cherche et remplace", - "description": [ - "Crée une fonction qui cherche et remplace une partie de la phrase en utilisant les arguments et renvoie la nouvelle phrase.", - "Le premier argument est la phrase à modifier.", - "Le deuxième argument est le mot à remplacer (avant).", - "Le troisième argument est le mot qui doit remplacer le deuxième argument (après).", - "NB: Tu dois respecter les majuscules ou miniscules du mot originel que tu remplaces. Par exemple, si tu veux remplacer le mot \"Livre\" par \"chien\", tu devras le remplacer par \"Chien\"", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "afd15382cdfb22c9efe8b7de", - "title": "DNA Pairing", - "description": [ - "The DNA strand is missing the pairing element. Take each character, get its pair, 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.", - "For example, for the input GCG, return [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]", - "The character and its pair are paired up in an array, and all the arrays are grouped into one encapsulating array.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function pairElement(str) {", - " return str;", - "}", - "", - "pairElement(\"GCG\");" - ], - "solutions": [ - "var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pairElement(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}" - ], - "tests": [ - "assert.deepEqual(pairElement(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'message: pairElement(\"ATCGA\") should return [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]].');", - "assert.deepEqual(pairElement(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: pairElement(\"TTGAG\") should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]].');", - "assert.deepEqual(pairElement(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: pairElement(\"CTCTA\") should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]].');" - ], - "type": "bonfire", - "MDNlinks": [ - "Array.prototype.push()", - "String.prototype.split()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Emparejando bases de ADN", - "description": [ - "A la cadena de ADN que se te pasa le hace falta una hebra. Toma cada una de las letras, obtén su pareja correspondiente y devuelve los resultados en un segundo vector", - "Parejas de bases son pares de AT y CG. Encuentra el elemento que hace falta para cada una de las letras que se te presentan.", - "Devuelve la letra que se te provee como el primer elemento en cada vector", - "Por ejemplo, si te pasáramos la cadena GCG, tu función debería devolver el vector: [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]", - "Cada letra que se te provee y su pareja deben estar contenidos en un vector, y cada uno de estos vectores debe estar contenidos en un vector.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Coupler les bases d'ADN", - "description": [ - "Une base d'ADN a perdu sa paire. Assemble chaque paire de caractères et renvoie les résultats dans un second tableau.", - "Les paires de bases sont des paires d'AT et CG. Associe l'élement manquant au caractère donné.", - "Renvoie le caractère donné comme premier élément de chaque tableau.", - "Par exemple, pour GCG, il faut renvoyer [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]", - "Chaque caractère et sa paire sont couplées dans un tableau, et tous les tableaux sont groupés dans un tableau.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "af7588ade1100bde429baf20", - "title": "Missing letters", - "description": [ - "Find the missing letter in the passed letter range and return it.", - "If all letters are present in the range, return undefined.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function fearNotLetter(str) {", - " return str;", - "}", - "", - "fearNotLetter(\"abce\");" - ], - "solutions": [ - "function fearNotLetter (str) {\n for (var i = str.charCodeAt(0); i <= str.charCodeAt(str.length - 1); i++) {\n var letter = String.fromCharCode(i);\n if (str.indexOf(letter) === -1) {\n return letter;\n }\n }\n \n return undefined;\n}" - ], - "tests": [ - "assert.deepEqual(fearNotLetter('abce'), 'd', 'message: fearNotLetter(\"abce\") should return \"d\".');", - "assert.deepEqual(fearNotLetter('abcdefghjklmno'), 'i', 'message: fearNotLetter(\"abcdefghjklmno\") should return \"i\".');", - "assert.deepEqual(fearNotLetter('stvwx'), 'u', 'message: fearNotLetter(\"stvwx\") should return \"u\".');", - "assert.deepEqual(fearNotLetter('bcdf'), 'e', 'message: fearNotLetter(\"bcdf\") should return \"e\".');", - "assert.isUndefined(fearNotLetter('abcdefghijklmnopqrstuvwxyz'), 'message: fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\") should return undefined.');" - ], - "type": "bonfire", - "MDNlinks": [ - "String.prototype.charCodeAt()", - "String.fromCharCode()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Letras perdidas", - "description": [ - "Crea una función que devuelva la letra que falta en el rango de letras que se le pasa", - "Si todas las letras en el rango están presentes, la función debe devolver undefined.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Lettres perdues", - "description": [ - "Crée une fonction qui renvoie la lettre manquante dans la série.", - "Si aucune lettre n'est manquante, renvoie undefined.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a105e963526e7de52b219be9", - "title": "Sorted Union", - "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.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function uniteUnique(arr) {", - " return arr;", - "}", - "", - "uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);" - ], - "solutions": [ - "function uniteUnique(arr) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}" - ], - "tests": [ - "assert.deepEqual(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) should return [1, 3, 2, 5, 4].');", - "assert.deepEqual(uniteUnique([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: uniteUnique([1, 3, 2], [1, [5]], [2, [4]]) should return [1, 3, 2, [5], [4]].');", - "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: uniteUnique([1, 2, 3], [5, 2, 1]) should return [1, 2, 3, 5].');", - "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'message: uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) should return [1, 2, 3, 5, 4, 6, 7, 8].');" - ], - "type": "bonfire", - "MDNlinks": [ - "Arguments object", - "Array.prototype.reduce()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Intersección ordenada", - "description": [ - "Escribe una función que tome dos o más vectores y que devuelva un nuevo vector con los valores únicos en el orden de aparición de los vectores que se te pasaron", - "En otra palabras, todos los valores presentes en todos los vectores deben aparecer en el vector final en su orden original, pero sin duplicados.", - "Los valores únicos deben aparecer en el orden original, pero el vector final no necesariamente debe mostrar los elementos en orden numérico.", - "Puedes usar de referencia las pruebas de verificación si necesitas ejemplos.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Union arrangée", - "description": [ - "Crée une fonction qui accepte deux tableaux ou plus et renvoie un nouvel array de valeurs uniques dans l'ordre des tableaux donnés.", - "En d'autres termes, toutes les valeurs des tableaux doivent être incluses dans l'ordre originel, sans doublon dans le tableau final.", - "Les valeurs uniques doivent être classées dans l'ordre originel, mais le tableau final ne doit pas être classé par ordre croissant.", - "Réfère toi aux test pour plus d'examples.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a6b0bb188d873cb2c8729495", - "title": "Convert HTML Entities", - "description": [ - "Convert the characters &, <, >, \" (double quote), and ' (apostrophe), in a string to their corresponding HTML entities.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function convertHTML(str) {", - " // :)", - " return str;", - "}", - "", - "convertHTML(\"Dolce & Gabbana\");" - ], - "solutions": [ - "var MAP = { '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''};\n\nfunction convertHTML(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}" - ], - "tests": [ - "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'message: convertHTML(\"Dolce & Gabbana\") should return Dolce &​amp; Gabbana.');", - "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'message: convertHTML(\"Hamburgers < Pizza < Tacos\") should return Hamburgers &​lt; Pizza &​lt; Tacos.');", - "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'message: convertHTML(\"Sixty > twelve\") should return Sixty &​gt; twelve.');", - "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'message: convertHTML('Stuff in \"quotation marks\"') should return Stuff in &​quot;quotation marks&​quot;.');", - "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'message: convertHTML(\"Schindler's List\") should return Schindler&​apos;s List.');", - "assert.match(convertHTML('<>'), /<>/, 'message: convertHTML(\"<>\") should return &​lt;&​gt;.');", - "assert.strictEqual(convertHTML('abc'), 'abc', 'message: convertHTML(\"abc\") should return abc.');" - ], - "type": "bonfire", - "MDNlinks": [ - "RegExp", - "HTML Entities", - "String.prototype.replace()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Convierte entidades HTML", - "description": [ - "Convierte los caracteres &, <, >, \"' (comilla), y ' (apóstrofe), contenidos en la cadena de texto que se te pasa, en sus entidades HTML correspondientes", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Convertir les entités HTML", - "description": [ - "Convertis les caractères &, <, >, \"' (guillemet), y ' (apostrophe), contenus dans la chaîne de caractères en entités HTML.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a5229172f011153519423690", - "title": "Sum All Odd Fibonacci Numbers", - "description": [ - "Given a positive integer num, return the sum of all odd Fibonacci numbers that are less than or equal to num.", - "The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.", - "For example, sumFibs(10) should return 10 because all odd Fibonacci numbers less than or equal to 10 are 1, 1, 3, and 5.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function sumFibs(num) {", - " return num;", - "}", - "", - "sumFibs(4);" - ], - "solutions": [ - "function sumFibs(num) {\n var a = 1; \n var b = 1;\n var s = 0;\n while (a <= num) {\n if (a % 2 !== 0) { \n s += a; \n }\n a = [b, b=b+a][0];\n }\n return s;\n}" - ], - "tests": [ - "assert(typeof sumFibs(1) === \"number\", 'message: sumFibs(1) should return a number.');", - "assert(sumFibs(1000) === 1785, 'message: sumFibs(1000) should return 1785.');", - "assert(sumFibs(4000000) === 4613732, 'message: sumFibs(4000000) should return 4613732.');", - "assert(sumFibs(4) === 5, 'message: sumFibs(4) should return 5.');", - "assert(sumFibs(75024) === 60696, 'message: sumFibs(75024) should return 60696.');", - "assert(sumFibs(75025) === 135721, 'message: sumFibs(75025) should return 135721.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Remainder" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Suma todos los números de Fibonacci que son impares", - "description": [ - "Crea una función que devuelva la suma de todos los números impares en la secuencia de Fibonacci hasta el número que se le pasa como argumento, incluyéndolo en caso de ser un número de la secuencia.", - "Los primeros números de la secuencia son 1, 1, 2, 3, 5 y 8, y cada número siguiente es la suma de los dos números anteriores.", - "Por ejemplo, si se te pasa el número 4, la función deberá devolver 5, ya que los números impares menores que 4 son 1, 1 y 3.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Additionner tous les nombre de Fibonacci impairs", - "description": [ - "Crée une fonction qui additionne tous les nombre de Fibonacci jusqu'au nombre donné (inclus si c'est un nombre de Fibonacci).", - "Les premiers chiffres de la séquence sont 1, 1, 2, 3, 5 y 8, et chaque nombre correspond à la somme des deux nombres précédents.", - "Par example, pour le chiffre 4, la fonction doit retourner 5, puisque les chiffres précédent 4 sont 1, 1 et 3.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a3bfc1673c0526e06d3ac698", - "title": "Sum All Primes", - "description": [ - "Sum all the prime numbers up to and including the provided number.", - "A prime number is defined as a number greater than one and having only two divisors, one and itself. For example, 2 is a prime number because it's only divisible by one and two.", - "The provided number may not be a prime.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function sumPrimes(num) {", - " return num;", - "}", - "", - "sumPrimes(10);" - ], - "solutions": [ - "function eratosthenesArray(n) {\n var primes = [];\n if (n > 2) {\n var half = n>>1;\n var sieve = Array(half);\n for (var i = 1, limit = Math.sqrt(n)>>1; i <= limit; i++) {\n if (!sieve[i]) {\n for (var step = 2*i+1, j = (step*step)>>1; j < half; j+=step) {\n sieve[j] = true;\n }\n }\n }\n primes.push(2);\n for (var p = 1; p < half; p++) {\n if (!sieve[p]) primes.push(2*p+1);\n }\n }\n return primes;\n}\n\nfunction sumPrimes(num) {\n return eratosthenesArray(num+1).reduce(function(a,b) {return a+b;}, 0);\n}\n\nsumPrimes(10);" - ], - "tests": [ - "assert.deepEqual(typeof sumPrimes(10), 'number', 'message: sumPrimes(10) should return a number.');", - "assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10) should return 17.');", - "assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977) should return 73156.');" - ], - "type": "bonfire", - "MDNlinks": [ - "For Loops", - "Array.prototype.push()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Suma todos los números primos", - "description": [ - "Suma todos los números primos hasta, e incluyendo, el número que se te pasa", - "Números primos son todos aquellos que sólo son divisibles entre 1 y entre sí mismos. Por ejemplo, el número 2 es primo porque solo es divisible por 1 y por 2. Por el contrario, el número 1 no es primo, ya que sólo puede dividirse por sí mismo", - "El número que se le provee a la función no puede ser primo", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Additionner tous les nombres primaires", - "description": [ - "Additionne tous les nombres primaires jusqu'au nombre donné (inclus).", - "Un nombre primaire est un nombre divisible que par 1 ou par lui-même (plus grand que 1). Par exemple, 2 est un nombre primaire puisqu'il n'est divisible que par 1 et 2. 1 n'est pas primaire puiqu'il n'est divisible que par lui-même.", - "Le nombre donné en argument n'est pas forcément un nombre primaire.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "ae9defd7acaf69703ab432ea", - "title": "Smallest Common Multiple", - "description": [ - "Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by all sequential numbers in the range between these parameters.", - "The range will be an array of two numbers that will not necessarily be in numerical order.", - "For example, if given 1 and 3, find the smallest common multiple of both 1 and 3 that is also evenly divisible by all numbers between 1 and 3. The answer here would be 6.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function smallestCommons(arr) {", - " return arr;", - "}", - "", - "", - "smallestCommons([1,5]);" - ], - "solutions": [ - "function gcd(a, b) {\n while (b !== 0) {\n a = [b, b = a % b][0];\n }\n return a;\n}\n\nfunction lcm(a, b) {\n return (a * b) / gcd(a, b);\n}\n\nfunction smallestCommons(arr) {\n arr.sort(function(a,b) {return a-b;});\n var rng = [];\n for (var i = arr[0]; i <= arr[1]; i++) {\n rng.push(i);\n }\n return rng.reduce(lcm);\n}" - ], - "tests": [ - "assert.deepEqual(typeof smallestCommons([1, 5]), 'number', 'message: smallestCommons([1, 5]) should return a number.');", - "assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5]) should return 60.');", - "assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1]) should return 60.');", - "assert.deepEqual(smallestCommons([2, 10]), 2520, 'message: smallestCommons([2, 10]) should return 2520.');", - "assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13]) should return 360360.');", - "assert.deepEqual(smallestCommons([23, 18]), 6056820, 'message: smallestCommons([23, 18]) should return 6056820.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Smallest Common Multiple" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Mínimo común múltiplo", - "description": [ - "En el ejercicio se te provee un vector con dos números. Crea una función que encuentre el número más pequeño que sea divisible entre ambos números, así como entre todos los números enteros entre ellos.", - "Tu función debe aceptar como argumento un vector con dos números, los cuales no necesariamente estarán en orden.", - "Por ejemplo, si se te pasan los números 1 y 3, deberás encontrar el mínimo común múltiplo de 1 y 3 que es divisible por todos los números entre 1 y 3.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Plus petit commun multiple", - "description": [ - "Cherche le plus petit commun multiple qui soit divisible par les deux nombres donnés et par les nombres de la série entre ces deux nombres.", - "La série est un tableau de deux nombres qui ne seront pas nécessairement dans l'ordre croissant.", - "Par exemple, pour 1 et 3, il faut trouver le plus petit commun multiple de 1 et 3 mais aussi des nombres entre 1 et 3/", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a5deed1811a43193f9f1c841", - "title": "Drop it", - "description": [ - "Given the array arr, iterate through and remove each element starting from the first element (the 0 index) until the function func returns true when the iterated element is passed through it.", - "Then return the rest of the array once the condition is satisfied, otherwise, arr should be returned as an empty array.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function dropElements(arr, func) {", - " // Drop them elements.", - " return arr;", - "}", - "", - "dropElements([1, 2, 3], function(n) {return n < 3; });" - ], - "solutions": [ - "function dropElements(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}" - ], - "tests": [ - "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n >= 3;}), [3, 4], 'message: dropElements([1, 2, 3, 4], function(n) {return n >= 3;}) should return [3, 4].');", - "assert.deepEqual(dropElements([0, 1, 0, 1], function(n) {return n === 1;}), [1, 0, 1], 'message: dropElements([0, 1, 0, 1], function(n) {return n === 1;}) should return [1, 0, 1].');", - "assert.deepEqual(dropElements([1, 2, 3], function(n) {return n > 0;}), [1, 2, 3], 'message: dropElements([1, 2, 3], function(n) {return n > 0;}) should return [1, 2, 3].');", - "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: dropElements([1, 2, 3, 4], function(n) {return n > 5;}) should return [].');", - "assert.deepEqual(dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;}), [7, 4], 'message: dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;}) should return [7, 4].');", - "assert.deepEqual(dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;}), [3, 9, 2], 'message: dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;}) should return [3, 9, 2].');" - ], - "type": "bonfire", - "MDNlinks": [ - "Arguments object", - "Array.prototype.shift()", - "Array.prototype.slice()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "¡Fuera de aquí!", - "description": [ - "Toma los elementos contenidos en el vector que se te provee en el primer argumento de la función y elimínalos uno por uno, hasta que la función provista en el segundo argumento devuelva true.", - "Retorna el resto del vector, de lo contrario retorna un vector vacío.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Laisse tomber", - "description": [ - "Écarte les éléments du tableau (premier argument), en commençant par la gauche, jusqu'à ce la fonction (second argument) renvoie true.", - "Renvoie le reste du tableau, ou dans le cas contraire un tableau vide", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "ab306dbdcc907c7ddfc30830", - "title": "Steamroller", - "description": [ - "Flatten a nested array. You must account for varying levels of nesting.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function steamrollArray(arr) {", - " // I'm a steamroller, baby", - " return arr;", - "}", - "", - "steamrollArray([1, [2], [3, [[4]]]]);" - ], - "solutions": [ - "function steamrollArray(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamrollArray(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}" - ], - "tests": [ - "assert.deepEqual(steamrollArray([[[\"a\"]], [[\"b\"]]]), [\"a\", \"b\"], 'message: steamrollArray([[[\"a\"]], [[\"b\"]]]) should return [\"a\", \"b\"].');", - "assert.deepEqual(steamrollArray([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: steamrollArray([1, [2], [3, [[4]]]]) should return [1, 2, 3, 4].');", - "assert.deepEqual(steamrollArray([1, [], [3, [[4]]]]), [1, 3, 4], 'message: steamrollArray([1, [], [3, [[4]]]]) should return [1, 3, 4].');", - "assert.deepEqual(steamrollArray([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: steamrollArray([1, {}, [3, [[4]]]]) should return [1, {}, 3, 4].');" - ], - "type": "bonfire", - "MDNlinks": [ - "Array.isArray()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Aplanadora", - "description": [ - "Aplana el vector anidado que se te provee. Tu función debe poder aplanar vectores de cualquier forma.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Rouleau compresseur", - "description": [ - "Aplatis le tableau donné. Ta fonction doit pour gérer différentes formes de tableaux.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a8d97bd4c764e91f9d2bda01", - "title": "Binary Agents", - "description": [ - "Return an English translated sentence of the passed binary string.", - "The binary string will be space separated.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "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\");" - ], - "solutions": [ - "function binaryAgent(str) {\n return str.split(' ').map(function(s) { return parseInt(s, 2); }).map(function(b) { return String.fromCharCode(b);}).join('');\n}" - ], - "tests": [ - "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'message: binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\") should return \"Aren't bonfires fun!?\"');", - "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\") should return \"I love FreeCodeCamp!\"');" - ], - "type": "bonfire", - "MDNlinks": [ - "String.prototype.charCodeAt()", - "String.fromCharCode()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Mensaje secreto", - "description": [ - "Haz que la función devuelva el mensaje en inglés escondido en el código binario de la cadena de texto que se le pasa.", - "La cadena de texto binaria estará separada por espacios.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Agent binaire", - "description": [ - "Traduis la chaîne binaire donnée en anglais.", - "La chaîne binaire comporte des espaces.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a10d2431ad0c6a099a4b8b52", - "title": "Everything Be True", - "description": [ - "Check if the predicate (second argument) is truthy on all elements of a collection (first argument).", - "In other words, you are given an array collection of objects. The predicate pre will be an object property and you need to return true if its value is truthy. Otherwise, return false.", - "In JavaScript, truthy values are values that translate to true when evaluated in a Boolean context.", - "Remember, you can access object properties through either dot notation or [] notation.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function truthCheck(collection, pre) {", - " // Is everyone being true?", - " return pre;", - "}", - "", - "truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\");" - ], - "solutions": [ - "function truthCheck(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}" - ], - "tests": [ - "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\") should return true.');", - "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\") should return false.');", - "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\") should return false.');", - "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\") should return false');", - "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\") should return true');", - "assert.strictEqual(truthCheck([{\"single\": \"yes\"}], \"single\"), true, 'message: truthCheck([{\"single\": \"yes\"}], \"single\") should return true');", - "assert.strictEqual(truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\") should return false');", - "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\") should return false');", - "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\") should return false');" - ], - "isRequired": true, - "type": "bonfire", - "MDNlinks": [ - "Truthy", - "Falsy" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Que todo sea verdadero", - "description": [ - "Verifica si la función en el segundo argumento devuelve true para todos los elementos de la colección en el primer argumento.", - "Recuerda que puedes accesar a las propiedades de un objeto, ya sea a través de la notación por punto o de la notación por corchete usando [].", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Tout doit être vrai", - "description": [ - "Vérifie que la fonction donnée (second argument) est vraie sur tous les éléments de la collection (premier argument).", - "Tu peux utiliser un point ou des [] pour accéder aux propritétés de l'objet.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "a97fd23d9b809dac9921074f", - "title": "Arguments Optional", - "description": [ - "Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum.", - "For example, addTogether(2, 3) should return 5, and addTogether(2) should return a function.", - "Calling this returned function with a single argument will then return the sum:", - "var sumTwoAnd = addTogether(2);", - "sumTwoAnd(3) returns 5.", - "If either argument isn't a valid number, return undefined.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function addTogether() {", - " return false;", - "}", - "", - "addTogether(2,3);" - ], - "solutions": [ - "function addTogether() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}" - ], - "tests": [ - "assert.deepEqual(addTogether(2, 3), 5, 'message: addTogether(2, 3) should return 5.');", - "assert.deepEqual(addTogether(2)(3), 5, 'message: addTogether(2)(3) should return 5.');", - "assert.isUndefined(addTogether(\"http://bit.ly/IqT6zt\"), 'message: addTogether(\"http://bit.ly/IqT6zt\") should return undefined.');", - "assert.isUndefined(addTogether(2, \"3\"), 'message: addTogether(2, \"3\") should return undefined.');", - "assert.isUndefined(addTogether(2)([3]), 'message: addTogether(2)([3]) should return undefined.');" - ], - "type": "bonfire", - "MDNlinks": [ - "Closures", - "Arguments object" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Argumentos opcionales", - "description": [ - "Crea una función que sume dos argumentos. Si sólo se le pasa un argumento a la función, haz que devuelva otra función que acepte un argumento y que devuelva la suma correspondiente.", - "Por ejemplo, add(2, 3) debe devolver 5, y add(2) debe devolver una función.", - "Al llamar esta función con un único argumento devolverá la suma:", - "var sumTwoAnd = add(2);", - "sumTwoAnd(3) devuelve 5.", - "Si alguno de los argumentos no es un número válido, haz que devuelva undefined.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Arguments optionnels", - "description": [ - "Crée une fonction qui additionne deux arguments. Si un seul argument est donné, renvoie une fonction qui attend un argument et renvoie la somme.", - "Par exemple, add(2, 3), doit renvoyer 5, et add(2) doit renvoyer une fonction.", - "Appeler cette fonction avec un seul argument renvoie la somme:", - "var sumTwoAnd = add(2);", - "sumTwoAnd(3) renvoie 5.", - "Si aucun argument n'est un nombre, renvoie undefined.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - }, - "guideUrl":"https://guide.freecodecamp.org/certificates/arguments-optional" - }, - { - "id": "a2f1d72d9b908d0bd72bb9f6", - "title": "Make a Person", - "description": [ - "Fill in the object constructor with the following methods below:", - "
    getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
    ", - "Run the tests to see the expected output for each method.", - "The methods that take an argument must accept only one argument and it has to be a string.", - "These methods must be the only available means of interacting with the object.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "var Person = function(firstAndLast) {", - " // Complete the method below and implement the others similarly", - " this.getFullName = function() {", - " return \"\";", - " };", - " return firstAndLast;", - "};", - "", - "var bob = new Person('Bob Ross');", - "bob.getFullName();" - ], - "solutions": [ - "var Person = function(firstAndLast) {\n\n var firstName, lastName;\n\n function updateName(str) { \n firstName = str.split(\" \")[0];\n lastName = str.split(\" \")[1]; \n }\n\n updateName(firstAndLast);\n\n this.getFirstName = function(){\n return firstName;\n };\n \n this.getLastName = function(){\n return lastName;\n };\n \n this.getFullName = function(){\n return firstName + \" \" + lastName;\n };\n \n this.setFirstName = function(str){\n firstName = str;\n };\n \n\n this.setLastName = function(str){\n lastName = str;\n };\n \n this.setFullName = function(str){\n updateName(str);\n };\n};\n\nvar bob = new Person('Bob Ross');\nbob.getFullName();" - ], - "tests": [ - "assert.deepEqual(Object.keys(bob).length, 6, 'message: Object.keys(bob).length should return 6.');", - "assert.deepEqual(bob instanceof Person, true, 'message: bob instanceof Person should return true.');", - "assert.deepEqual(bob.firstName, undefined, 'message: bob.firstName should return undefined.');", - "assert.deepEqual(bob.lastName, undefined, 'message: bob.lastName should return undefined.');", - "assert.deepEqual(bob.getFirstName(), 'Bob', 'message: bob.getFirstName() should return \"Bob\".');", - "assert.deepEqual(bob.getLastName(), 'Ross', 'message: bob.getLastName() should return \"Ross\".');", - "assert.deepEqual(bob.getFullName(), 'Bob Ross', 'message: bob.getFullName() should return \"Bob Ross\".');", - "assert.strictEqual((function () { bob.setFirstName(\"Haskell\"); return bob.getFullName(); })(), 'Haskell Ross', 'message: bob.getFullName() should return \"Haskell Ross\" after bob.setFirstName(\"Haskell\").');", - "assert.strictEqual((function () { var _bob=new Person('Haskell Ross'); _bob.setLastName(\"Curry\"); return _bob.getFullName(); })(), 'Haskell Curry', 'message: bob.getFullName() should return \"Haskell Curry\" after bob.setLastName(\"Curry\").');", - "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFullName(); })(), 'Haskell Curry', 'message: bob.getFullName() should return \"Haskell Curry\" after bob.setFullName(\"Haskell Curry\").');", - "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getFirstName(); })(), 'Haskell', 'message: bob.getFirstName() should return \"Haskell\" after bob.setFullName(\"Haskell Curry\").');", - "assert.strictEqual((function () { bob.setFullName(\"Haskell Curry\"); return bob.getLastName(); })(), 'Curry', 'message: bob.getLastName() should return \"Curry\" after bob.setFullName(\"Haskell Curry\").');" - ], - "type": "bonfire", - "MDNlinks": [ - "Closures", - "Details of the Object Model" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Crea una Persona", - "description": [ - "Completa el constructor de objetos con los métodos especificados a continuación:", - "
    getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
    ", - "Ejecuta las pruebas para ver el resultado esperado de cada método.", - "Las funciones que aceptan argumentos deben aceptar sólo uno, y este tiene que ser una cadena.", - "Estos métodos deben ser el único medio para interactuar con el objeto.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "it": { - "title": "Crea una Persona", - "description": [ - "Completa il costruttore dell'oggetto con i metodi specificati qui sotto:", - "
    getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
    ", - "Esegui i test per vedere il risultato atteso per ogni metodo.", - "I metodi che richiedono un argomento devono accettarne solo uno e questo deve essere una stringa.", - "Questi metodi devono essere l'unica maniera possibile di interagire con l'oggetto.", - "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te." - ] - }, - "pt-br": { - "title": "Faça uma Pessoa", - "description": [ - "Preencha o contrutor do objeto com seguintes métodos:", - "
    getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)
    ", - "Rode os testes para ver o resultado esperado de cada método.", - "Os métodos que recebem um argumento deve aceitar somente um argumento e deve ser uma string.", - "Esses métodos devem ser o único meio de interação com o objeto.", - "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código." - ] - } - } - }, - { - "id": "af4afb223120f7348cdfc9fd", - "title": "Map the Debris", - "description": [ - "Return a new array that transforms the elements' average altitude into their orbital periods (in seconds).", - "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 km3s-2.", - "Remember to use Read-Search-Ask 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 : \"sputnik\", avgAlt : 35873.5553}]);" - ], - "solutions": [ - "function orbitalPeriod(arr) {\n var GM = 398600.4418;\n var earthRadius = 6367.4447;\n var TAU = 2 * Math.PI; \n return arr.map(function(obj) {\n return {\n name: obj.name,\n orbitalPeriod: Math.round(TAU * Math.sqrt(Math.pow(obj.avgAlt+earthRadius, 3)/GM))\n };\n });\n}\n\norbitalPeriod([{name : \"sputkin\", avgAlt : 35873.5553}]);\n" - ], - "tests": [ - "assert.deepEqual(orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]), [{name: \"sputnik\", orbitalPeriod: 86400}], 'message: orbitalPeriod([{name : \"sputnik\", avgAlt : 35873.5553}]) should return [{name: \"sputnik\", orbitalPeriod: 86400}].');", - "assert.deepEqual(orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}]), [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}], 'message: orbitalPeriod([{name: \"iss\", avgAlt: 413.6}, {name: \"hubble\", avgAlt: 556.7}, {name: \"moon\", avgAlt: 378632.553}]) should return [{name : \"iss\", orbitalPeriod: 5557}, {name: \"hubble\", orbitalPeriod: 5734}, {name: \"moon\", orbitalPeriod: 2377399}].');" - ], - "type": "bonfire", - "MDNlinks": [ - "Math.pow()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Ubica los Escombros", - "description": [ - "Crea una función que devuelva un nuevo arreglo que transforme la altitud promedio del elemento en su período orbital.", - "El arreglo debe contener objetos en el formato {name: 'name', avgAlt: avgAlt}.", - "Puedes leer acerca de períodos orbitales en Wikipedia.", - "Los valores deben estar redondeados al número entero más próximo. El cuerpo orbitado es la Tierra", - "El radio de la Tierra es 6367.4447 kilómetros, y el valor GM del planeta es de 398600.4418 km3s-2.", - "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "it": { - "title": "Mappa i Detriti", - "description": [ - "Ritorna un nuovo array che trasformi l'altitudine media degli elementi nel loro periodo orbitale.", - "L'array conterrà oggetti in formato {name: 'name', avgAlt: avgAlt}.", - "Puoi leggere riguardo i periodi orbitali su Wikipedia.", - "I valori devono essere arrotondati al numero intero più vicino. Il corpo attorno a cui orbitano gli elementi è la Terra.", - "Il raggio della Terra è di 6367.4447 kilometri, e il valore GM della Terra è di 398600.4418 km3s-2.", - "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te." - ] - }, - "pt-br": { - "title": "Mapeie o Lixo espacial", - "description": [ - "Retorne uma nova matriz que transforma a altitude média do elemento em seu período orbital.", - "A matriz vai conter objetos no formato {name: 'name', avgAlt: avgAlt}.", - "Você pode ler sobre período orbital na Wikipedia.", - "Os valores devem ser arredondados para número inteiro mais próximo. O corpe sendo orbitado é a Terra.", - "O raio da terra é 6367.4447 quilômetros, e o valor GM da terra é 398600.4418 km3s-2.", - "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código." - ] - } - } - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json deleted file mode 100644 index efa1583697..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "name": "JavaScript Algorithms and Data Structures Projects", - "order": 10, - "time": "50 hours", - "helpRoom": "HelpJavaScript", - "challenges": [ - { - "id": "aaa48de84e1ecc7c742e1124", - "title": "Palindrome Checker", - "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.", - "Note
    You'll need to remove all non-alphanumeric characters (punctuation, spaces and symbols) and turn everything into the same case (lower or upper 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 also pass strings with special symbols, such as \"2A3*3a2\", \"2A3 3a2\", and \"2_A3*3#A2\".", - "Remember to use Read-Search-Ask if you get stuck. Write your own code." - ], - "challengeSeed": [ - "function palindrome(str) {", - " // Good luck!", - " return true;", - "}", - "", - "", - "", - "palindrome(\"eye\");" - ], - "tests": [ - "assert(typeof palindrome(\"eye\") === \"boolean\", 'message: palindrome(\"eye\") should return a boolean.');", - "assert(palindrome(\"eye\") === true, 'message: palindrome(\"eye\") should return true.');", - "assert(palindrome(\"_eye\") === true, 'message: palindrome(\"_eye\") should return true.');", - "assert(palindrome(\"race car\") === true, 'message: palindrome(\"race car\") should return true.');", - "assert(palindrome(\"not a palindrome\") === false, 'message: palindrome(\"not a palindrome\") should return false.');", - "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'message: palindrome(\"A man, a plan, a canal. Panama\") should return true.');", - "assert(palindrome(\"never odd or even\") === true, 'message: palindrome(\"never odd or even\") should return true.');", - "assert(palindrome(\"nope\") === false, 'message: palindrome(\"nope\") should return false.');", - "assert(palindrome(\"almostomla\") === false, 'message: palindrome(\"almostomla\") should return false.');", - "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'message: palindrome(\"My age is 0, 0 si ega ym.\") should return true.');", - "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'message: palindrome(\"1 eye for of 1 eye.\") should return false.');", - "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'message: palindrome(\"0_0 (: /-\\ :) 0-0\") should return true.');", - "assert(palindrome(\"five|\\_/|four\") === false, 'message: palindrome(\"five|\\_/|four\") should return false.');" - ], - "type": "bonfire", - "isRequired": true, - "solutions": [ - "function palindrome(str) {\n var string = str.toLowerCase().split(/[^A-Za-z0-9]/gi).join('');\n var aux = string.split('');\n if (aux.join('') === aux.reverse().join('')){\n return true;\n }\n\n return false;\n}" - ], - "MDNlinks": [ - "String.prototype.replace()", - "String.prototype.toLowerCase()" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Verifica si es palíndromo", - "description": [ - "Crea una función que devuelva true si una cadena de texto dada es un palíndromo, y que devuelva false en caso contrario", - "Un palíndromo es una palabra u oración que se escribe de la misma forma en ambos sentidos, sin tomar en cuenta signos de puntuación, espacios y sin distinguir entre mayúsculas y minúsculas.", - "Tendrás que quitar los caracteres no alfanuméricos (signos de puntuación, espacioes y símbolos) y transformar las letras a minúsculas para poder verificar si el texto es palíndromo.", - "Te proveeremos textos en varios formatos, como \"racecar\", \"RaceCar\", and \"race CAR\" entre otros.", - "También vamos a pasar cadenas con símbolos especiales, tales como \"2A3*3a2\", \"2A3 3a2\", y \"2_A3*3#A2\".", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Procure por Palíndromos", - "description": [ - "Retorne true se o texto fornecida é um palíndromo. Caso contrário, retorne false.", - "Um palíndromo é uma palavra ou sentença que é soletrada da mesma maneira tanto para a frente quanto para trás, ignorando pontuação, maiúsculas e minúsculas, e espaçamento.", - "Nota
    Você precisará remover todos caracteres não alfanuméricos (pontuação, espaços e símbolos) e transformar todas as letras em maiúsculas ou minúsculas para procurar por palíndromos.", - "Nós vamos passar textos de vários formatos, tais como \"racecar\", \"RaceCar\" e \"race CAR\" entre outras.", - "Nós também vamos passar textos com símbolos especiais, tais como \"2A3*3a2\", \"2A3 3a2\" e \"2_A3*3#A2\".", - "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "a7f4d8f2483413a6ce226cac", - "title": "Roman Numeral Converter", - "description": [ - "Convert the given number into a roman numeral.", - "All roman numerals answers should be provided in upper-case.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function convertToRoman(num) {", - " return num;", - "}", - "", - "convertToRoman(36);" - ], - "solutions": [ - "function convertToRoman(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}" - ], - "tests": [ - "assert.deepEqual(convertToRoman(2), \"II\", 'message: convertToRoman(2) should return \"II\".');", - "assert.deepEqual(convertToRoman(3), \"III\", 'message: convertToRoman(3) should return \"III\".');", - "assert.deepEqual(convertToRoman(4), \"IV\", 'message: convertToRoman(4) should return \"IV\".');", - "assert.deepEqual(convertToRoman(5), \"V\", 'message: convertToRoman(5) should return \"V\".');", - "assert.deepEqual(convertToRoman(9), \"IX\", 'message: convertToRoman(9) should return \"IX\".');", - "assert.deepEqual(convertToRoman(12), \"XII\", 'message: convertToRoman(12) should return \"XII\".');", - "assert.deepEqual(convertToRoman(16), \"XVI\", 'message: convertToRoman(16) should return \"XVI\".');", - "assert.deepEqual(convertToRoman(29), \"XXIX\", 'message: convertToRoman(29) should return \"XXIX\".');", - "assert.deepEqual(convertToRoman(44), \"XLIV\", 'message: convertToRoman(44) should return \"XLIV\".');", - "assert.deepEqual(convertToRoman(45), \"XLV\", 'message: convertToRoman(45) should return \"XLV\"');", - "assert.deepEqual(convertToRoman(68), \"LXVIII\", 'message: convertToRoman(68) should return \"LXVIII\"');", - "assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'message: convertToRoman(83) should return \"LXXXIII\"');", - "assert.deepEqual(convertToRoman(97), \"XCVII\", 'message: convertToRoman(97) should return \"XCVII\"');", - "assert.deepEqual(convertToRoman(99), \"XCIX\", 'message: convertToRoman(99) should return \"XCIX\"');", - "assert.deepEqual(convertToRoman(400), \"CD\", 'message: convertToRoman(400) should return \"CD\"');", - "assert.deepEqual(convertToRoman(500), \"D\", 'message: convertToRoman(500) should return \"D\"');", - "assert.deepEqual(convertToRoman(501), \"DI\", 'message: convertToRoman(501) should return \"DI\"');", - "assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'message: convertToRoman(649) should return \"DCXLIX\"');", - "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'message: convertToRoman(798) should return \"DCCXCVIII\"');", - "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'message: convertToRoman(891) should return \"DCCCXCI\"');", - "assert.deepEqual(convertToRoman(1000), \"M\", 'message: convertToRoman(1000) should return \"M\"');", - "assert.deepEqual(convertToRoman(1004), \"MIV\", 'message: convertToRoman(1004) should return \"MIV\"');", - "assert.deepEqual(convertToRoman(1006), \"MVI\", 'message: convertToRoman(1006) should return \"MVI\"');", - "assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'message: convertToRoman(1023) should return \"MXXIII\"');", - "assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'message: convertToRoman(2014) should return \"MMXIV\"');", - "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'message: convertToRoman(3999) should return \"MMMCMXCIX\"');" - ], - "type": "bonfire", - "MDNlinks": [ - "Roman Numerals", - "Array.prototype.splice()", - "Array.prototype.indexOf()", - "Array.prototype.join()" - ], - "isRequired": true, - "challengeType": 5, - "translations": { - "es": { - "title": "Convertior de números romanos", - "description": [ - "Convierte el número dado en numeral romano.", - "Todos los numerales romanos en las respuestas deben estar en mayúsculas.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "fr": { - "title": "Convertir en chiffres romains", - "description": [ - "Convertis le nombre donné en chiffres romains.", - "Tous les chiffres romains doivent être en lettres capitales.", - "N'oublie pas d'utiliser Lire-Chercher-Demander si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code." - ] - } - } - }, - { - "id": "56533eb9ac21ba0edf2244e2", - "title": "Caesars Cipher", - "description": [ - "One of the simplest and most widely known ciphers is a Caesar cipher, also known as a shift cipher. In a shift cipher the meanings of the letters are shifted by some set amount.", - "A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus 'A' ↔ 'N', 'B' ↔ 'O' and so on.", - "Write a function which takes a ROT13 encoded string as input and returns a decoded string.", - "All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function rot13(str) { // LBH QVQ VG!", - " ", - " return str;", - "}", - "", - "// Change the inputs below to test", - "rot13(\"SERR PBQR PNZC\");" - ], - "tail": [ - "" - ], - "solutions": [ - "var lookup = {\n 'A': 'N','B': 'O','C': 'P','D': 'Q',\n 'E': 'R','F': 'S','G': 'T','H': 'U',\n 'I': 'V','J': 'W','K': 'X','L': 'Y',\n 'M': 'Z','N': 'A','O': 'B','P': 'C',\n 'Q': 'D','R': 'E','S': 'F','T': 'G',\n 'U': 'H','V': 'I','W': 'J','X': 'K',\n 'Y': 'L','Z': 'M' \n};\n\nfunction rot13(encodedStr) {\n var codeArr = encodedStr.split(\"\"); // String to Array\n var decodedArr = []; // Your Result goes here\n // Only change code below this line\n \n decodedArr = codeArr.map(function(letter) {\n if(lookup.hasOwnProperty(letter)) {\n letter = lookup[letter];\n }\n return letter;\n });\n\n // Only change code above this line\n return decodedArr.join(\"\"); // Array to String\n}" - ], - "tests": [ - "assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", 'message: rot13(\"SERR PBQR PNZC\") should decode to FREE CODE CAMP');", - "assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", 'message: rot13(\"SERR CVMMN!\") should decode to FREE PIZZA!');", - "assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", 'message: rot13(\"SERR YBIR?\") should decode to FREE LOVE?');", - "assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", 'message: rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") should decode to THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.');" - ], - "type": "bonfire", - "MDNlinks": [ - "String.prototype.charCodeAt()", - "String.fromCharCode()" - ], - "challengeType": 5, - "isRequired": true, - "releasedOn": "January 1, 2016", - "translations": { - "es": { - "title": "Cifrado César", - "description": [ - "Uno de los cifrados más simples y ampliamente conocidos es el cifrado César, también llamado cifrado por desplazamiento. En un cifrado por desplazamiento los significados de las letras se desplazan por una cierta cantidad.", - "Un uso moderno común es el cifrado ROT13 , donde los valores de las letras se desplazan 13 espacios. De esta forma 'A' ↔ 'N', 'B' ↔ 'O' y así.", - "Crea una función que tome una cadena de texto cifrada en ROT13 como argumento y que devuelva la cadena de texto decodificada.", - "Todas las letras que se te pasen van a estar en mayúsculas. No transformes ningún caracter no-alfabético (por ejemplo: espacios, puntuación). Simplemente pásalos intactos.", - "Recuerda utilizar Leer-Buscar-Preguntar si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "pt-br": { - "title": "Cifra de César", - "description": [ - "Uma das mais simples e mais conhecidas cifras é a cifra de César, também conhecida como cifra de troca. Em uma cifra de troca os significados das letras são deslocados por um determinado valor.", - "Um uso moderno comum é a cifra ROT13, aonde os valores das letras são deslocados por 13 lugares. Logo 'A' ↔ 'N', 'B' ↔ 'O' e assim por diante.", - "Escreva uma função que recebe um texto criptografado com ROT13 como entrada e retorna o texto desencriptado.", - "Todas as letras serão maiúsculas. Não transforme nenhum caracter não alfanuméricos (como espaços, pontuação), mas passe-os adiante.", - "Lembre-se de usar Ler-Pesquisar-Perguntar se você ficar travado. Escreva seu próprio código." - ] - } - } - }, - { - "id": "aff0395860f5d3034dc0bfc9", - "title": "Telephone Number Validator", - "description": [ - "Return true if the passed string looks like a valid US phone number.", - "The user may fill out the form field any way they choose as long as it has the format of a valid US number. The following are examples of valid formats for US numbers (refer to the tests below for other variants):", - "
    555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 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 return false.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code." - ], - "challengeSeed": [ - "function telephoneCheck(str) {", - " // Good luck!", - " return true;", - "}", - "", - "telephoneCheck(\"555-555-5555\");" - ], - "solutions": [ - "var re = /^([+]?1[\\s]?)?((?:[(](?:[2-9]1[02-9]|[2-9][02-8][0-9])[)][\\s]?)|(?:(?:[2-9]1[02-9]|[2-9][02-8][0-9])[\\s.-]?)){1}([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2}[\\s.-]?){1}([0-9]{4}){1}$/;\n\nfunction telephoneCheck(str) {\n return re.test(str);\n}\n\ntelephoneCheck(\"555-555-5555\");" - ], - "tests": [ - "assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", 'message: telephoneCheck(\"555-555-5555\") should return a boolean.');", - "assert(telephoneCheck(\"1 555-555-5555\") === true, 'message: telephoneCheck(\"1 555-555-5555\") should return true.');", - "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'message: telephoneCheck(\"1 (555) 555-5555\") should return true.');", - "assert(telephoneCheck(\"5555555555\") === true, 'message: telephoneCheck(\"5555555555\") should return true.');", - "assert(telephoneCheck(\"555-555-5555\") === true, 'message: telephoneCheck(\"555-555-5555\") should return true.');", - "assert(telephoneCheck(\"(555)555-5555\") === true, 'message: telephoneCheck(\"(555)555-5555\") should return true.');", - "assert(telephoneCheck(\"1(555)555-5555\") === true, 'message: telephoneCheck(\"1(555)555-5555\") should return true.');", - "assert(telephoneCheck(\"555-5555\") === false, 'message: telephoneCheck(\"555-5555\") should return false.');", - "assert(telephoneCheck(\"5555555\") === false, 'message: telephoneCheck(\"5555555\") should return false.');", - "assert(telephoneCheck(\"1 555)555-5555\") === false, 'message: telephoneCheck(\"1 555)555-5555\") should return false.');", - "assert(telephoneCheck(\"1 555 555 5555\") === true, 'message: telephoneCheck(\"1 555 555 5555\") should return true.');", - "assert(telephoneCheck(\"1 456 789 4444\") === true, 'message: telephoneCheck(\"1 456 789 4444\") should return true.');", - "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'message: telephoneCheck(\"123**&!!asdf#\") should return false.');", - "assert(telephoneCheck(\"55555555\") === false, 'message: telephoneCheck(\"55555555\") should return false.');", - "assert(telephoneCheck(\"(6054756961)\") === false, 'message: telephoneCheck(\"(6054756961)\") should return false');", - "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'message: telephoneCheck(\"2 (757) 622-7382\") should return false.');", - "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'message: telephoneCheck(\"0 (757) 622-7382\") should return false.');", - "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'message: telephoneCheck(\"-1 (757) 622-7382\") should return false');", - "assert(telephoneCheck(\"2 757 622-7382\") === false, 'message: telephoneCheck(\"2 757 622-7382\") should return false.');", - "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'message: telephoneCheck(\"10 (757) 622-7382\") should return false.');", - "assert(telephoneCheck(\"27576227382\") === false, 'message: telephoneCheck(\"27576227382\") should return false.');", - "assert(telephoneCheck(\"(275)76227382\") === false, 'message: telephoneCheck(\"(275)76227382\") should return false.');", - "assert(telephoneCheck(\"2(757)6227382\") === false, 'message: telephoneCheck(\"2(757)6227382\") should return false.');", - "assert(telephoneCheck(\"2(757)622-7382\") === false, 'message: telephoneCheck(\"2(757)622-7382\") should return false.');", - "assert(telephoneCheck(\"555)-555-5555\") === false, 'message: telephoneCheck(\"555)-555-5555\") should return false.');", - "assert(telephoneCheck(\"(555-555-5555\") === false, 'message: telephoneCheck(\"(555-555-5555\") should return false.');", - "assert(telephoneCheck(\"(555)5(55?)-5555\") === false, 'message: telephoneCheck(\"(555)5(55?)-5555\") should return false.');" - ], - "type": "bonfire", - "MDNlinks": [ - "RegExp" - ], - "challengeType": 5, - "isRequired": true, - "translations": { - "es": { - "title": "Valida Números Telefónicos de los EEUU", - "description": [ - "Haz que la función devuelva true (verdadero) si el texto introducido parece un número válido en los EEUU.", - "El usuario debe llenar el campo del formulario de la forma que desee siempre y cuando tenga el formato de un número válido en los EEUU. Los números mostrados a continuación tienen formatos válidos en los EEUU:", - "
    555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
    ", - "Para esta prueba se te presentará una cadena de texto como por ejemplo: 800-692-7753 o 8oo-six427676;laskdjf. Tu trabajo consiste en validar o rechazar el número telefónico tomando como base cualquier combinación de los formatos anteriormente presentados. El código de área es requrido. Si el código de país es provisto, debes confirmar que este es 1. La función debe devolver true si la cadena de texto es un número telefónico válido en los EEUU; de lo contrario, debe devolver false.", - "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "it": { - "title": "Verifica i numeri telefonici degli Stati Uniti", - "description": [ - "Ritorna true se la stringa passata come argomento è un numero valido negli Stati Uniti.", - "L'utente può digitare qualunque stringa nel campo di inserimento, purchè sia un numero di telefono valido negli Stati Uniti. Qui sotto alcuni esempi di numeri di telefono validi negli Stati Uniti (fai riferimento ai test per le altre varianti):", - "
    555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
    ", - "In questo problema ti saranno presentate delle stringe come 800-692-7753 o 8oo-six427676;laskdjf. Il tuo obiettivo è di validare o rigettare il numero di telefono basato su una qualunque combinazione dei formati specificati sopra. Il prefisso di zona è obbligatorio. Se il prefisso nazionale è presente, devi confermare che corrisponda a 1. Ritorna true se la stringa è un numero di telefono valido negli Stati Uniti; altrimenti ritorna false.", - "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te." - ] - }, - "pt-br": { - "title": "Valida números telefônicos dos EUA", - "description": [ - "Retorna true se a string passada é um número telefônico válido nos EUA.", - "O usuário pode preencher o campo de qualquer maneira com tanto que seja um número válido nos EUA. Os seguintes exemplos são formatos válidos para números de telefone nos EUA (baseie-se nos testes abaixo para outras variações):", - "
    555-555-5555\n(555)555-5555\n(555) 555-5555\n555 555 5555\n5555555555\n1 555 555 5555
    ", - "Para esse desafio será dado a você uma string como 800-692-7753 ou 8oo-six427676;laskdjf. Seu trabalho é validar ou rejeitar o número de telefone dos EUA baseado nos exmplos de formatos fornecidos acima. O código de área é obrigatório. Se o código do país for fornecido, você deve confirmar que o código do país é 1. Retorne true se a string é um número válido nos EUA; caso contrário retorne false.", - "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código." - ] - } - } - }, - { - "id": "aa2e6f85cab2ab736c9a9b24", - "title": "Cash Register", - "description": [ - "Design a cash register drawer function checkCashRegister() that accepts purchase price as the first argument (price), payment as the second argument (cash), and cash-in-drawer (cid) as the third argument.", - "cid is a 2D array listing available currency.", - "The checkCashRegister() function should always return an object with a status key and a change key.", - "Return {status: \"INSUFFICIENT_FUNDS\", change: []} if cash-in-drawer is less than the change due, or if you cannot return the exact change.", - "Return {status: \"CLOSED\", change: [...]} with cash-in-drawer as the value for the key change if it is equal to the change due.", - "Otherwise, return {status: \"OPEN\", change: [...]}, with the change due in coins and bills, sorted in highest to lowest order, as the value of the change key.", - "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.", - "
    Currency UnitAmount
    Penny$0.01 (PENNY)
    Nickel$0.05 (NICKEL)
    Dime$0.1 (DIME)
    Quarter$0.25 (QUARTER)
    Dollar$1 (DOLLAR)
    Five Dollars$5 (FIVE)
    Ten Dollars$10 (TEN)
    Twenty Dollars$20 (TWENTY)
    One-hundred Dollars$100 (ONE HUNDRED)
    " - ], - "challengeSeed": [ - "function checkCashRegister(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.1],", - "// [\"QUARTER\", 4.25],", - "// [\"ONE\", 90],", - "// [\"FIVE\", 55],", - "// [\"TEN\", 20],", - "// [\"TWENTY\", 60],", - "// [\"ONE HUNDRED\", 100]]", - "", - "checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]);" - ], - "solutions": [ - "var denom = [\n\t{ name: 'ONE HUNDRED', val: 100},\n\t{ name: 'TWENTY', val: 20},\n\t{ name: 'TEN', val: 10},\n\t{ name: 'FIVE', val: 5},\n\t{ name: 'ONE', val: 1},\n\t{ name: 'QUARTER', val: 0.25},\n\t{ name: 'DIME', val: 0.1},\n\t{ name: 'NICKEL', val: 0.05},\n\t{ name: 'PENNY', val: 0.01}\n];\n\nfunction checkCashRegister(price, cash, cid) {\n var output = {status: null, change: []};\n var change = cash - price;\n var register = cid.reduce(function(acc, curr) {\n acc.total += curr[1];\n acc[curr[0]] = curr[1];\n return acc;\n }, {total: 0});\n if(register.total === change) {\n output.status = 'CLOSED';\n output.change = cid;\n return output;\n }\n if(register.total < change) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n var change_arr = denom.reduce(function(acc, curr) {\n var value = 0;\n while(register[curr.name] > 0 && change >= curr.val) {\n change -= curr.val;\n register[curr.name] -= curr.val;\n value += curr.val;\n change = Math.round(change * 100) / 100;\n }\n if(value > 0) {\n acc.push([ curr.name, value ]);\n }\n return acc;\n }, []);\n if(change_arr.length < 1 || change > 0) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n output.status = 'OPEN';\n output.change = change_arr;\n return output;\n}" - ], - "tests": [ - "assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]) should return an object.');", - "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]) should return {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}.');", - "assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, 'message: checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]) should return {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}.');", - "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return {status: \"INSUFFICIENT_FUNDS\", change: []}.');", - "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return {status: \"INSUFFICIENT_FUNDS\", change: []}.');", - "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, 'message: checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]) should return {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}.');" - ], - "type": "bonfire", - "isRequired": true, - "MDNlinks": [ - "Global Object", - "Floating Point Guide" - ], - "challengeType": 5, - "translations": { - "es": { - "title": "Cambio Exacto", - "description": [ - "Crea una función que simule una caja registradora que acepte el precio de compra como el primer argumento, la cantidad recibida como el segundo argumento, y la cantidad de dinero disponible en la registradora (cid) como tercer argumento", - "cid es un arreglo bidimensional que lista la cantidad de dinero disponible", - "La función debe devolver la cadena de texto \"Insufficient Funds\" si el cid es menor al cambio requerido. También debe devolver \"Closed\" si el cid es igual al cambio", - "De no ser el caso, devuelve el cambio en monedas y billetes, ordenados de mayor a menor denominación.", - "Recuerda utilizar Read-Search-Ask si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." - ] - }, - "it": { - "title": "Cambio Esatto", - "description": [ - "Scrivi una funzione che simuli un registro di cassa chiamata checkCashRegister() che accetti il prezzo degli articoli come primo argomento (price), la somma pagata (cash), e la somma disponibile nel registratore di cassa (cid) come terzo argomento.", - "cid è un array a due dimensioni che contiene la quantità di monete e banconote disponibili.", - "Ritorna la stringa \"Insufficient Funds\" se la quantità di denaro disponibile nel registratore di cassa non è abbastanza per restituire il resto. Ritorna la stringa \"Closed\" se il denaro disponibile è esattamente uguale al resto.", - "Altrimenti, ritorna il resto in monete e banconote, ordinate da quelle con valore maggiore a quelle con valore minore.", - "Ricorda di usare Leggi-Cerca-Chiedi se rimani bloccato. Prova a programmare in coppia. Scrivi il codice da te." - ] - }, - "pt-br": { - "title": "Troco Exato", - "description": [ - "Crie uma função que simula uma caixa registradora chamada checkCashRegister() e aceita o valor da compra como primeiro argumento (price), pagamento como segundo argumento (cash), e o dinheiro na caixa registradora (cid) como terceiro argumento.", - "cid é uma matriz bidimensional que lista o dinheiro disponível.", - "Retorne a string \"Insufficient Funds\" se o dinheiro na caixa registradora é menor do que o troco ou se não é possível retornar o troco exato. Retorne a string \"Closed\" se o dinheiro na caixa é igual ao troco.", - "Case cotrário, retorne o troco em moedas e notas, ordenado do maior para menor.", - "Lembre-se de usar Ler-Procurar-Perguntar se você ficar preso. Tente programar em par. Escreva seu próprio código.", - "
    Currency UnitAmount
    Penny$0.01 (PENNY)
    Nickel$0.05 (NICKEL)
    Dime$0.1 (DIME)
    Quarter$0.25 (QUARTER)
    Dollar$1 (DOLLAR)
    Five Dollars$5 (FIVE)
    Ten Dollars$10 (TEN)
    Twenty Dollars$20 (TWENTY)
    One-hundred Dollars$100 (ONE HUNDRED)
    " - ] - } - } - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json deleted file mode 100644 index 77e2e8c2aa..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/object-oriented-programming.json +++ /dev/null @@ -1,1062 +0,0 @@ -{ - "name": "Object Oriented Programming", - "order": 7, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7dac367417b2b2512b72", - "title": "Introduction to the Object Oriented Programming Challenges", - "description": [ - "", - "", - "At its core, software development solves a problem or achieves a result with computation. The software development process first defines a problem, then presents a solution. Object oriented programming is one of several major approaches to the software development process.

    As its name implies, object oriented programming organizes code into object definitions. These are sometimes called classes, and they group together data with related behavior. The data is an object's attributes, and the behavior (or functions) are methods.

    The object structure makes it flexible within a program. Objects can transfer information by calling and passing data to another object's methods. Also, new classes can receive, or inherit, all the features from a base or parent class. This helps to reduce repeated code.

    Your choice of programming approach depends on a few factors. These include the type of problem, as well as how you want to structure your data and algorithms. This section covers object oriented programming principles in JavaScript.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7dac367417b2b2512b73", - "title": "Create a Basic JavaScript Object", - "description": [ - "Think about things people see everyday, like cars, shops, and birds. These are all objects: tangible things people can observe and interact with.", - "What are some qualities of these objects? A car has wheels. Shops sell items. Birds have wings.", - "These qualities, or properties, define what makes up an object. Note that similar objects share the same properties, but may have different values for those properties. For example, all cars have wheels, but not all cars have the same number of wheels.", - "Objects in JavaScript are used to model real-world objects, giving them properties and behavior just like their real-world counterparts. Here's an example using these concepts to create a duck object:", - "
    let duck = {
      name: \"Aflac\",
      numLegs: 2
    };
    ", - "This duck object has two property/value pairs: a name of \"Aflac\" and a numLegs of 2.", - "
    ", - "Create a dog object with name and numLegs properties, and set them to a string and a number, respectively." - ], - "challengeSeed": [ - "let dog = {", - " ", - "};" - ], - "tests": [ - "assert(typeof(dog) === 'object', 'message: dog should be an object.');", - "assert(typeof(dog.name) === 'string', 'message: dog should have a name property set to a string.');", - "assert(typeof(dog.numLegs) === 'number', 'message: dog should have a numLegs property set to a number.');" - ], - "solutions": [ - "let dog = {\n name: '',\n numLegs: 4\n};" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dac367417b2b2512b74", - "title": "Use Dot Notation to Access the Properties of an Object", - "description": [ - "The last challenge created an object with various properties, now you'll see how to access the values of those properties. Here's an example:", - "
    let duck = {
      name: \"Aflac\",
      numLegs: 2
    };
    console.log(duck.name);
    // This prints \"Aflac\" to the console
    ", - "Dot notation is used on the object name, duck, followed by the name of the property, name, to access the value of \"Aflac\".", - "
    ", - "Print both properties of the dog object below to your console." - ], - "challengeSeed": [ - "let dog = {", - " name: \"Spot\",", - " numLegs: 4", - "};", - "// Add your code below this line", - "", - "" - ], - "tests": [ - "assert(/console.log\\(.*dog\\.name.*\\)/g.test(code), 'message: Your should use console.log to print the value for the name property of the dog object.');", - "assert(/console.log\\(.*dog\\.numLegs.*\\)/g.test(code), 'message: Your should use console.log to print the value for the numLegs property of the dog object.');" - ], - "solutions": [ - "let dog = {\n name: \"Spot\",\n numLegs: 4\n};\nconsole.log(dog.name);\nconsole.log(dog.numLegs);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dad367417b2b2512b75", - "title": "Create a Method on an Object", - "description": [ - "Objects can have a special type of property, called a method.", - "Methods are properties that are functions. This adds different behavior to an object. Here is the duck example with a method:", - "
    let duck = {
      name: \"Aflac\",
      numLegs: 2,
      sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
    };
    duck.sayName();
    // Returns \"The name of this duck is Aflac.\"
    ", - "The example adds the sayName method, which is a function that returns a sentence giving the name of the duck.", - "Notice that the method accessed the name property in the return statement using duck.name. The next challenge will cover another way to do this.", - "
    ", - "Using the dog object, give it a method called sayLegs. The method should return the sentence \"This dog has 4 legs.\"" - ], - "challengeSeed": [ - "let dog = {", - " name: \"Spot\",", - " numLegs: 4,", - " ", - "};", - "", - "dog.sayLegs();" - ], - "tests": [ - "assert(typeof(dog.sayLegs) === 'function', 'message: dog.sayLegs() should be a function.');", - "assert(dog.sayLegs() === 'This dog has 4 legs.', 'message: dog.sayLegs() should return the given string - note that punctuation and spacing matter.');" - ], - "solutions": [ - "let dog = {\n name: \"Spot\",\n numLegs: 4,\n sayLegs () {\n return 'This dog has ' + this.numLegs + ' legs.';\n }\n};\n\ndog.sayLegs();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dad367417b2b2512b76", - "title": "Make Code More Reusable with the this Keyword", - "description": [ - "The last challenge introduced a method to the duck object. It used duck.name dot notation to access the value for the name property within the return statement:", - "sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}", - "While this is a valid way to access the object's property, there is a pitfall here. If the variable name changes, any code referencing the original name would need to be updated as well. In a short object definition, it isn't a problem, but if an object has many references to its properties there is a greater chance for error.", - "A way to avoid these issues is with the this keyword:", - "
    let duck = {
      name: \"Aflac\",
      numLegs: 2,
      sayName: function() {return \"The name of this duck is \" + this.name + \".\";}
    };
    ", - "this is a deep topic, and the above example is only one way to use it. In the current context, this refers to the object that the method is associated with: duck.", - "If the object's name is changed to mallard, it is not necessary to find all the references to duck in the code. It makes the code reusable and easier to read.", - "
    ", - "Modify the dog.sayLegs method to remove any references to dog. Use the duck example for guidance." - ], - "challengeSeed": [ - "", - "let dog = {", - " name: \"Spot\",", - " numLegs: 4,", - " sayLegs: function() {return \"This dog has \" + dog.numLegs + \" legs.\";}", - "};", - "", - "dog.sayLegs();" - ], - "tests": [ - "assert(dog.sayLegs() === 'This dog has 4 legs.', 'message: dog.sayLegs() should return the given string.');", - "assert(code.match(/this\\.numLegs/g), 'message: Your code should use the this keyword to access the numLegs property of dog.');" - ], - "solutions": [ - "let dog = {\n name: \"Spot\",\n numLegs: 4,\n sayLegs () {\n return 'This dog has ' + this.numLegs + ' legs.';\n }\n};\n\ndog.sayLegs();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dad367417b2b2512b77", - "title": "Define a Constructor Function", - "description": [ - "Constructors are functions that create new objects. They define properties and behaviors that will belong to the new object. Think of them as a blueprint for the creation of new objects.", - "Here is an example of a constructor:", - "
    function Bird() {
      this.name = \"Albert\";
      this.color = \"blue\";
      this.numLegs = 2;
    }
    ", - "This constructor defines a Bird object with properties name, color, and numLegs set to Albert, blue, and 2, respectively.", - "Constructors follow a few conventions:", - "
    • Constructors are defined with a capitalized name to distinguish them from other functions that are not constructors.
    • Constructors use the keyword this to set properties of the object they will create. Inside the constructor, this refers to the new object it will create.
    • Constructors define properties and behaviors instead of returning a value as other functions might.
    ", - "
    ", - "Create a constructor, Dog, with properties name, color, and numLegs that are set to a string, a string, and a number, respectively." - ], - "challengeSeed": [ - "", - "", - "" - ], - "tests": [ - "assert(typeof (new Dog()).name === 'string', 'message: Dog should have a name property set to a string.');", - "assert(typeof (new Dog()).color === 'string', 'message: Dog should have a color property set to a string.');", - "assert(typeof (new Dog()).numLegs === 'number', 'message: Dog should have a numLegs property set to a number.');" - ], - "solutions": [ - "function Dog (name, color, numLegs) {\n this.name = 'name';\n this.color = 'color';\n this.numLegs = 4;\n}" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dad367417b2b2512b78", - "title": "Use a Constructor to Create Objects", - "description": [ - "Here's the Bird constructor from the previous challenge:", - "
    function Bird() {
      this.name = \"Albert\";
      this.color = \"blue\";
      this.numLegs = 2;
      // \"this\" inside the constructor always refers to the object being created
    }

    let blueBird = new Bird();
    ", - "Notice that the new operator is used when calling a constructor. This tells JavaScript to create a new instance of Bird called blueBird. Without the new operator, this inside the constructor would not point to the newly created object, giving unexpected results.", - "Now blueBird has all the properties defined inside the Bird constructor:", - "
    blueBird.name; // => Albert
    blueBird.color; // => blue
    blueBird.numLegs; // => 2
    ", - "Just like any other object, its properties can be accessed and modified:", - "
    blueBird.name = 'Elvira';
    blueBird.name; // => Elvira
    ", - "
    ", - "Use the Dog constructor from the last lesson to create a new instance of Dog, assigning it to a variable hound." - ], - "challengeSeed": [ - "function Dog() {", - " this.name = \"Rupert\";", - " this.color = \"brown\";", - " this.numLegs = 4;", - "}", - "// Add your code below this line", - "", - "" - ], - "tests": [ - "assert(hound instanceof Dog, 'message: hound should be created using the Dog constructor.');", - "assert(code.match(/new/g), 'message: Your code should use the new operator to create an instance of Dog.');" - ], - "solutions": [ - "function Dog() {\n this.name = \"Rupert\";\n this.color = \"brown\";\n this.numLegs = 4;\n}\nconst hound = new Dog();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dae367417b2b2512b79", - "title": "Extend Constructors to Receive Arguments", - "description": [ - "The Bird and Dog constructors from last challenge worked well. However, notice that all Birds that are created with the Bird constructor are automatically named Albert, are blue in color, and have two legs. What if you want birds with different values for name and color? It's possible to change the properties of each bird manually but that would be a lot of work:", - "
    let swan = new Bird();
    swan.name = \"Carlos\";
    swan.color = \"white\";
    ", - "Suppose you were writing a program to keep track of hundreds or even thousands of different birds in an aviary. It would take a lot of time to create all the birds, then change the properties to different values for every one.", - "To more easily create different Bird objects, you can design your Bird constructor to accept parameters:", - "
    function Bird(name, color) {
      this.name = name;
      this.color = color;
      this.numLegs = 2;
    }
    ", - "Then pass in the values as arguments to define each unique bird into the Bird constructor:", - "let cardinal = new Bird(\"Bruce\", \"red\");", - "This gives a new instance of Bird with name and color properties set to Bruce and red, respectively. The numLegs property is still set to 2.", - "The cardinal has these properties:", - "
    cardinal.name // => Bruce
    cardinal.color // => red
    cardinal.numLegs // => 2
    ", - "The constructor is more flexible. It's now possible to define the properties for each Bird at the time it is created, which is one way that JavaScript constructors are so useful. They group objects together based on shared characteristics and behavior and define a blueprint that automates their creation.", - "
    ", - "Create another Dog constructor. This time, set it up to take the parameters name and color, and have the property numLegs fixed at 4. Then create a new Dog saved in a variable terrier. Pass it two strings as arguments for the name and color properties." - ], - "challengeSeed": [ - "function Dog() {", - " ", - "}", - "", - "" - ], - "tests": [ - "assert((new Dog('Clifford')).name === 'Clifford', 'message: Dog should receive an argument for name.');", - "assert((new Dog('Clifford', 'yellow')).color === 'yellow', 'message: Dog should receive an argument for color.');", - "assert((new Dog('Clifford')).numLegs === 4, 'message: Dog should have property numLegs set to 4.');", - "assert(terrier instanceof Dog, 'message: terrier should be created using the Dog constructor.');" - ], - "solutions": [ - "function Dog (name, color) {\n this.numLegs = 4;\n this.name = name;\n this.color = color;\n}\n\nconst terrier = new Dog();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dae367417b2b2512b7a", - "title": "Verify an Object's Constructor with instanceof", - "description": [ - "Anytime a constructor function creates a new object, that object is said to be an instance of its constructor. JavaScript gives a convenient way to verify this with the instanceof operator. instanceof allows you to compare an object to a constructor, returning true or false based on whether or not that object was created with the constructor. Here's an example:", - "
    let Bird = function(name, color) {
      this.name = name;
      this.color = color;
      this.numLegs = 2;
    }

    let crow = new Bird(\"Alexis\", \"black\");

    crow instanceof Bird; // => true
    ", - "If an object is created without using a constructor, instanceof will verify that it is not an instance of that constructor:", - "
    let canary = {
      name: \"Mildred\",
      color: \"Yellow\",
      numLegs: 2
    };

    canary instanceof Bird; // => false
    ", - "
    ", - "Create a new instance of the House constructor, calling it myHouse and passing a number of bedrooms. Then, use instanceof to verify that it is an instance of House." - ], - "challengeSeed": [ - "/* jshint expr: true */", - "", - "function House(numBedrooms) {", - " this.numBedrooms = numBedrooms;", - "}", - "", - "// Add your code below this line", - "", - "", - "" - ], - "tests": [ - "assert(typeof myHouse.numBedrooms === 'number', 'message: myHouse should have a numBedrooms attribute set to a number.');", - "assert(/myHouse\\s*instanceof\\s*House/.test(code), 'message: Be sure to verify that myHouse is an instance of House using the instanceof operator.');" - ], - "solutions": [ - "function House(numBedrooms) {\n this.numBedrooms = numBedrooms;\n}\nconst myHouse = new House(4);\nconsole.log(myHouse instanceof House);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dae367417b2b2512b7b", - "title": "Understand Own Properties", - "description": [ - "In the following example, the Bird constructor defines two properties: name and numLegs:", - "
    function Bird(name) {
      this.name = name;
      this.numLegs = 2;
    }

    let duck = new Bird(\"Donald\");
    let canary = new Bird(\"Tweety\");
    ", - "name and numLegs are called own properties, because they are defined directly on the instance object. That means that duck and canary each has its own separate copy of these properties.", - "In fact every instance of Bird will have its own copy of these properties.", - "The following code adds all of the own properties of duck to the array ownProps:", - "
    let ownProps = [];

    for (let property in duck) {
      if(duck.hasOwnProperty(property)) {
        ownProps.push(property);
      }
    }

    console.log(ownProps); // prints [ \"name\", \"numLegs\" ]
    ", - "
    ", - "Add the own properties of canary to the array ownProps." - ], - "challengeSeed": [ - "function Bird(name) {", - " this.name = name;", - " this.numLegs = 2;", - "}", - "", - "let canary = new Bird(\"Tweety\");", - "let ownProps = [];", - "// Add your code below this line", - "", - "", - "" - ], - "tests": [ - "assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1, 'message: ownProps should include the values \"numLegs\" and \"name\".');", - "assert(!/\\Object.keys/.test(code), 'message: Solve this challenge without using the built in method Object.keys().');" - ], - "solutions": [ - "function Bird(name) {\n this.name = name;\n this.numLegs = 2;\n}\n\nlet canary = new Bird(\"Tweety\");\nfunction getOwnProps (obj) {\n const props = [];\n \n for (let prop in obj) {\n if (obj.hasOwnProperty(prop)) {\n props.push(prop);\n }\n }\n \n return props;\n}\n\nconst ownProps = getOwnProps(canary);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dae367417b2b2512b7c", - "title": "Use Prototype Properties to Reduce Duplicate Code", - "description": [ - "Since numLegs will probably have the same value for all instances of Bird, you essentially have a duplicated variable numLegs inside each Bird instance.", - "This may not be an issue when there are only two instances, but imagine if there are millions of instances. That would be a lot of duplicated variables.", - "A better way is to use Bird’s prototype. The prototype is an object that is shared among ALL instances of Bird. Here's how to add numLegs to the Bird prototype:", - "
    Bird.prototype.numLegs = 2;
    ", - "Now all instances of Bird have the numLegs property.", - "
    console.log(duck.numLegs); // prints 2
    console.log(canary.numLegs); // prints 2
    ", - "Since all instances automatically have the properties on the prototype, think of a prototype as a \"recipe\" for creating objects.", - "Note that the prototype for duck and canary is part of the Bird constructor as Bird.prototype. Nearly every object in JavaScript has a prototype property which is part of the constructor function that created it.", - "
    ", - "Add a numLegs property to the prototype of Dog" - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name;", - "}", - "", - "", - "", - "// Add your code above this line", - "let beagle = new Dog(\"Snoopy\");" - ], - "tests": [ - "assert(beagle.numLegs !== undefined, 'message: beagle should have a numLegs property.');", - "assert(typeof(beagle.numLegs) === 'number' , 'message: beagle.numLegs should be a number.');", - "assert(beagle.hasOwnProperty('numLegs') === false, 'message: numLegs should be a prototype property not an own property.');" - ], - "solutions": [ - "function Dog (name) {\n this.name = name;\n}\nDog.prototype.numLegs = 4;\nlet beagle = new Dog(\"Snoopy\");" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daf367417b2b2512b7d", - "title": "Iterate Over All Properties", - "description": [ - "You have now seen two kinds of properties: own properties and prototype properties. Own properties are defined directly on the object instance itself. And prototype properties are defined on the prototype.", - "
    function Bird(name) {
      this.name = name; //own property
    }

    Bird.prototype.numLegs = 2; // prototype property

    let duck = new Bird(\"Donald\");
    ", - "Here is how you add duck’s own properties to the array ownProps and prototype properties to the array prototypeProps:", - "
    let ownProps = [];
    let prototypeProps = [];

    for (let property in duck) {
      if(duck.hasOwnProperty(property)) {
        ownProps.push(property);
      } else {
        prototypeProps.push(property);
      }
    }

    console.log(ownProps); // prints [\"name\"]
    console.log(prototypeProps); // prints [\"numLegs\"]
    ", - "
    ", - "Add all of the own properties of beagle to the array ownProps. Add all of the prototype properties of Dog to the array prototypeProps." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name;", - "}", - "", - "Dog.prototype.numLegs = 4;", - "", - "let beagle = new Dog(\"Snoopy\");", - "", - "let ownProps = [];", - "let prototypeProps = [];", - "", - "// Add your code below this line ", - "", - "", - "" - ], - "tests": [ - "assert(ownProps.indexOf('name') !== -1, 'message: The ownProps array should include \"name\".');", - "assert(prototypeProps.indexOf('numLegs') !== -1, 'message: The prototypeProps array should include \"numLegs\".');", - "assert(!/\\Object.keys/.test(code), 'message: Solve this challenge without using the built in method Object.keys().');" - ], - "solutions": [ - "function Dog(name) {\n this.name = name;\n}\n\nDog.prototype.numLegs = 4;\n\nlet beagle = new Dog(\"Snoopy\");\n\nlet ownProps = [];\nlet prototypeProps = [];\nfor (let prop in beagle) {\n if (beagle.hasOwnProperty(prop)) {\n ownProps.push(prop);\n } else {\n prototypeProps.push(prop);\n }\n}" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daf367417b2b2512b7e", - "title": "Understand the Constructor Property", - "description": [ - "There is a special constructor property located on the object instances duck and beagle that were created in the previous challenges:", - "
    let duck = new Bird();
    let beagle = new Dog();

    console.log(duck.constructor === Bird); //prints true
    console.log(beagle.constructor === Dog); //prints true
    ", - "Note that the constructor property is a reference to the constructor function that created the instance.", - "The advantage of the constructor property is that it's possible to check for this property to find out what kind of object it is. Here's an example of how this could be used:", - "
    function joinBirdFraternity(candidate) {
      if (candidate.constructor === Bird) {
        return true;
      } else {
        return false;
      }
    }
    ", - "Note
    Since the constructor property can be overwritten (which will be covered in the next two challenges) it’s generally better to use the instanceof method to check the type of an object.", - "
    ", - "Write a joinDogFraternity function that takes a candidate parameter and, using the constructor property, return true if the candidate is a Dog, otherwise return false." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name;", - "}", - "", - "// Add your code below this line", - "function joinDogFraternity(candidate) {", - " ", - "}", - "" - ], - "tests": [ - "assert(typeof(joinDogFraternity) === 'function', 'message: joinDogFraternity should be defined as a function.');", - "assert(joinDogFraternity(new Dog(\"\")) === true, 'message: joinDogFraternity should return true ifcandidate is an instance of Dog.');", - "assert(/\\.constructor/.test(code) && !/instanceof/.test(code), 'message: joinDogFraternity should use the constructor property.');" - ], - "solutions": [ - "function Dog(name) {\n this.name = name;\n}\nfunction joinDogFraternity(candidate) {\n return candidate.constructor === Dog;\n}" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daf367417b2b2512b7f", - "title": "Change the Prototype to a New Object", - "description": [ - "Up until now you have been adding properties to the prototype individually:", - "
    Bird.prototype.numLegs = 2;
    ", - "This becomes tedious after more than a few properties.", - "
    Bird.prototype.eat = function() {
      console.log(\"nom nom nom\");
    }

    Bird.prototype.describe = function() {
      console.log(\"My name is \" + this.name);
    }
    ", - "A more efficient way is to set the prototype to a new object that already contains the properties. This way, the properties are added all at once:", - "
    Bird.prototype = {
      numLegs: 2,
      eat: function() {
        console.log(\"nom nom nom\");
      },
      describe: function() {
        console.log(\"My name is \" + this.name);
      }
    };
    ", - "
    ", - "Add the property numLegs and the two methods eat() and describe() to the prototype of Dog by setting the prototype to a new object." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name; ", - "}", - "", - "Dog.prototype = {", - " // Add your code below this line", - " ", - "};" - ], - "tests": [ - "assert((/Dog\\.prototype\\s*?=\\s*?{/).test(code), 'message: Dog.prototype should be set to a new object.');", - "assert(Dog.prototype.numLegs !== undefined, 'message: Dog.prototype should have the property numLegs.');", - "assert(typeof Dog.prototype.eat === 'function', 'message: Dog.prototype should have the method eat().'); ", - "assert(typeof Dog.prototype.describe === 'function', 'message: Dog.prototype should have the method describe().'); " - ], - "solutions": [ - "function Dog(name) {\n this.name = name; \n}\nDog.prototype = {\nnumLegs: 4,\n eat () {\n console.log('nom nom nom');\n },\n describe () {\n console.log('My name is ' + this.name);\n }\n};" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7daf367417b2b2512b80", - "title": "Remember to Set the Constructor Property when Changing the Prototype", - "description": [ - "There is one crucial side effect of manually setting the prototype to a new object. It erased the constructor property! The code in the previous challenge would print the following for duck:", - "
    console.log(duck.constructor)
    // prints ‘undefined’ - Oops!
    ", - "To fix this, whenever a prototype is manually set to a new object, remember to define the constructor property:", - "
    Bird.prototype = {
      constructor: Bird, // define the constructor property
      numLegs: 2,
      eat: function() {
        console.log(\"nom nom nom\");
      },
      describe: function() {
        console.log(\"My name is \" + this.name);
      }
    };
    ", - "
    ", - "Define the constructor property on the Dog prototype." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name; ", - "}", - "", - "// Modify the code below this line", - "Dog.prototype = {", - " ", - " numLegs: 2, ", - " eat: function() {", - " console.log(\"nom nom nom\"); ", - " }, ", - " describe: function() {", - " console.log(\"My name is \" + this.name); ", - " }", - "};" - ], - "tests": [ - "assert(Dog.prototype.constructor === Dog, 'message: Dog.prototype should set the constructor property.');" - ], - "solutions": [ - "function Dog(name) {\n this.name = name; \n}\nDog.prototype = {\n constructor: Dog,\n numLegs: 2, \n eat: function() {\n console.log(\"nom nom nom\"); \n }, \n describe: function() {\n console.log(\"My name is \" + this.name); \n }\n};" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db0367417b2b2512b81", - "title": "Understand Where an Object’s Prototype Comes From", - "description": [ - "Just like people inherit genes from their parents, an object inherits its prototype directly from the constructor function that created it. For example, here the Bird constructor creates the duck object:", - "
    function Bird(name) {
      this.name = name;
    }

    let duck = new Bird(\"Donald\");
    ", - "duck inherits its prototype from the Bird constructor function. You can show this relationship with the isPrototypeOf method:", - "
    Bird.prototype.isPrototypeOf(duck);
    // returns true
    ", - "
    ", - "Use isPrototypeOf to check the prototype of beagle." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name;", - "}", - "", - "let beagle = new Dog(\"Snoopy\");", - "", - "// Add your code below this line", - "", - "" - ], - "tests": [ - "assert(/Dog\\.prototype\\.isPrototypeOf\\(beagle\\)/.test(code), 'message: Show that Dog.prototype is the prototype of beagle');" - ], - "solutions": [ - "function Dog(name) {\n this.name = name;\n}\nlet beagle = new Dog(\"Snoopy\");\nDog.prototype.isPrototypeOf(beagle);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db0367417b2b2512b82", - "title": "Understand the Prototype Chain", - "description": [ - "All objects in JavaScript (with a few exceptions) have a prototype. Also, an object’s prototype itself is an object.", - "
    function Bird(name) {
      this.name = name;
    }

    typeof Bird.prototype; // => object
    ", - "Because a prototype is an object, a prototype can have its own prototype! In this case, the prototype of Bird.prototype is Object.prototype:", - "
    Object.prototype.isPrototypeOf(Bird.prototype);
    // returns true
    ", - "How is this useful? You may recall the hasOwnProperty method from a previous challenge:", - "
    let duck = new Bird(\"Donald\");
    duck.hasOwnProperty(\"name\"); // => true
    ", - "The hasOwnProperty method is defined in Object.prototype, which can be accessed by Bird.prototype, which can then be accessed by duck. This is an example of the prototype chain.", - "In this prototype chain, Bird is the supertype for duck, while duck is the subtype. Object is a supertype for both Bird and duck.", - "Object is a supertype for all objects in JavaScript. Therefore, any object can use the hasOwnProperty method.", - "
    ", - "Modify the code to show the correct prototype chain." - ], - "challengeSeed": [ - "function Dog(name) {", - " this.name = name;", - "}", - "", - "let beagle = new Dog(\"Snoopy\");", - "", - "Dog.prototype.isPrototypeOf(beagle); // => true", - "", - "// Fix the code below so that it evaluates to true", - "???.isPrototypeOf(Dog.prototype);", - "" - ], - "tests": [ - "assert(/Object\\.prototype\\.isPrototypeOf/.test(code), \"message: Your code should show that Object.prototype is the prototype of Dog.prototype\");" - ], - "solutions": [ - "function Dog(name) {\n this.name = name;\n}\nlet beagle = new Dog(\"Snoopy\");\nDog.prototype.isPrototypeOf(beagle);\nObject.prototype.isPrototypeOf(Dog.prototype);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db0367417b2b2512b83", - "title": "Use Inheritance So You Don't Repeat Yourself", - "description": [ - "There's a principle in programming called Don't Repeat Yourself (DRY). The reason repeated code is a problem is because any change requires fixing code in multiple places. This usually means more work for programmers and more room for errors.", - "Notice in the example below that the describe method is shared by Bird and Dog:", - "
    Bird.prototype = {
      constructor: Bird,
      describe: function() {
        console.log(\"My name is \" + this.name);
      }
    };

    Dog.prototype = {
      constructor: Dog,
      describe: function() {
        console.log(\"My name is \" + this.name);
      }
    };
    ", - "The describe method is repeated in two places. The code can be edited to follow the DRY principle by creating a supertype (or parent) called Animal:", - "
    function Animal() { };

    Animal.prototype = {
      constructor: Animal,
      describe: function() {
        console.log(\"My name is \" + this.name);
      }
    };
    ", - "Since Animal includes the describe method, you can remove it from Bird and Dog:", - "
    Bird.prototype = {
      constructor: Bird
    };

    Dog.prototype = {
      constructor: Dog
    };
    ", - "
    ", - "The eat method is repeated in both Cat and Bear. Edit the code in the spirit of DRY by moving the eat method to the Animal supertype." - ], - "challengeSeed": [ - "function Cat(name) {", - " this.name = name; ", - "}", - "", - "Cat.prototype = {", - " constructor: Cat, ", - " eat: function() {", - " console.log(\"nom nom nom\");", - " }", - "};", - "", - "function Bear(name) {", - " this.name = name; ", - "}", - "", - "Bear.prototype = {", - " constructor: Bear, ", - " eat: function() {", - " console.log(\"nom nom nom\");", - " }", - "};", - "", - "function Animal() { }", - "", - "Animal.prototype = {", - " constructor: Animal,", - " ", - "};" - ], - "tests": [ - "assert(Animal.prototype.hasOwnProperty('eat'), 'message: Animal.prototype should have the eat property.');", - "assert(!(Bear.prototype.hasOwnProperty('eat')), 'message: Bear.prototype should not have the eat property.');", - "assert(!(Cat.prototype.hasOwnProperty('eat')), 'message: Cat.prototype should not have the eat property.');" - ], - "solutions": [ - "function Cat(name) {\n this.name = name; \n}\n\nCat.prototype = {\n constructor: Cat\n};\n\nfunction Bear(name) {\n this.name = name; \n}\n\nBear.prototype = {\n constructor: Bear\n};\n\nfunction Animal() { }\n\nAnimal.prototype = {\n constructor: Animal,\n eat: function() {\n console.log(\"nom nom nom\");\n }\n};" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db0367417b2b2512b84", - "title": "Inherit Behaviors from a Supertype", - "description": [ - "In the previous challenge, you created a supertype called Animal that defined behaviors shared by all animals:", - "
    function Animal() { }
    Animal.prototype.eat = function() {
      console.log(\"nom nom nom\");
    };
    ", - "This and the next challenge will cover how to reuse Animal's methods inside Bird and Dog without defining them again. It uses a technique called inheritance.", - "This challenge covers the first step: make an instance of the supertype (or parent).", - "You already know one way to create an instance of Animal using the new operator:", - "
    let animal = new Animal();
    ", - "There are some disadvantages when using this syntax for inheritance, which are too complex for the scope of this challenge. Instead, here's an alternative approach without those disadvantages:", - "
    let animal = Object.create(Animal.prototype);
    ", - "Object.create(obj) creates a new object, and sets obj as the new object's prototype. Recall that the prototype is like the \"recipe\" for creating an object. By setting the prototype of animal to be Animal's prototype, you are effectively giving the animal instance the same \"recipe\" as any other instance of Animal.", - "
    animal.eat(); // prints \"nom nom nom\"
    animal instanceof Animal; // => true
    ", - "
    ", - "Use Object.create to make two instances of Animal named duck and beagle." - ], - "challengeSeed": [ - "function Animal() { }", - "", - "Animal.prototype = {", - " constructor: Animal, ", - " eat: function() {", - " console.log(\"nom nom nom\");", - " }", - "};", - "", - "// Add your code below this line", - "", - "let duck; // Change this line", - "let beagle; // Change this line", - "", - "duck.eat(); // Should print \"nom nom nom\"", - "beagle.eat(); // Should print \"nom nom nom\" " - ], - "tests": [ - "assert(typeof duck !== \"undefined\", 'message: The duck variable should be defined.');", - "assert(typeof beagle !== \"undefined\", 'message: The beagle variable should be defined.');", - "assert(duck instanceof Animal, 'message: duck should have a prototype of Animal.');", - "assert(beagle instanceof Animal, 'message: beagle should have a prototype of Animal.');" - ], - "solutions": [ - "function Animal() { }\n\nAnimal.prototype = {\n constructor: Animal, \n eat: function() {\n console.log(\"nom nom nom\");\n }\n};\nlet duck = Object.create(Animal.prototype);\nlet beagle = Object.create(Animal.prototype);\n\nduck.eat();\nbeagle.eat();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db1367417b2b2512b85", - "title": "Set the Child's Prototype to an Instance of the Parent", - "description": [ - "In the previous challenge you saw the first step for inheriting behavior from the supertype (or parent) Animal: making a new instance of Animal.", - "This challenge covers the next step: set the prototype of the subtype (or child)—in this case, Bird—to be an instance of Animal.", - "
    Bird.prototype = Object.create(Animal.prototype);
    ", - "Remember that the prototype is like the \"recipe\" for creating an object. In a way, the recipe for Bird now includes all the key \"ingredients\" from Animal.", - "
    let duck = new Bird(\"Donald\");
    duck.eat(); // prints \"nom nom nom\"
    ", - "duck inherits all of Animal's properties, including the eat method.", - "
    ", - "Modify the code so that instances of Dog inherit from Animal." - ], - "challengeSeed": [ - "function Animal() { }", - "", - "Animal.prototype = {", - " constructor: Animal,", - " eat: function() {", - " console.log(\"nom nom nom\");", - " }", - "};", - "", - "function Dog() { }", - "", - "// Add your code below this line", - "", - "", - "let beagle = new Dog();", - "beagle.eat(); // Should print \"nom nom nom\"" - ], - "tests": [ - "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype should be an instance of Animal.');" - ], - "solutions": [ - "function Animal() { }\n\nAnimal.prototype = {\n constructor: Animal,\n eat: function() {\n console.log(\"nom nom nom\");\n }\n};\n\nfunction Dog() { }\nDog.prototype = Object.create(Animal.prototype);\n\nlet beagle = new Dog();\nbeagle.eat();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db1367417b2b2512b86", - "title": "Reset an Inherited Constructor Property", - "description": [ - "When an object inherits its prototype from another object, it also inherits the supertype's constructor property.", - "Here's an example:", - "
    function Bird() { }
    Bird.prototype = Object.create(Animal.prototype);
    let duck = new Bird();
    duck.constructor // function Animal(){...}
    ", - "But duck and all instances of Bird should show that they were constructed by Bird and not Animal. To do so, you can manually set Bird's constructor property to the Bird object:", - "
    Bird.prototype.constructor = Bird;
    duck.constructor // function Bird(){...}
    ", - "
    ", - "Fix the code so duck.constructor and beagle.constructor return their respective constructors." - ], - "challengeSeed": [ - "function Animal() { }", - "function Bird() { }", - "function Dog() { }", - "", - "Bird.prototype = Object.create(Animal.prototype);", - "Dog.prototype = Object.create(Animal.prototype);", - "", - "// Add your code below this line", - "", - "", - "", - "let duck = new Bird();", - "let beagle = new Dog();" - ], - "tests": [ - "assert(Animal.prototype.isPrototypeOf(Bird.prototype), 'message: Bird.prototype should be an instance of Animal.');", - "assert(duck.constructor === Bird, 'message: duck.constructor should return Bird.');", - "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'message: Dog.prototype should be an instance of Animal.');", - "assert(beagle.constructor === Dog, 'message: beagle.constructor should return Dog.');" - ], - "solutions": [ - "function Animal() { }\nfunction Bird() { }\nfunction Dog() { }\nBird.prototype = Object.create(Animal.prototype);\nDog.prototype = Object.create(Animal.prototype);\nDog.prototype.constructor = Dog;\nBird.prototype.constructor = Bird;\nlet duck = new Bird();\nlet beagle = new Dog();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db1367417b2b2512b87", - "title": "Add Methods After Inheritance", - "description": [ - "A constructor function that inherits its prototype object from a supertype constructor function can still have its own methods in addition to inherited methods.", - "For example, Bird is a constructor that inherits its prototype from Animal:", - "
    function Animal() { }
    Animal.prototype.eat = function() {
      console.log(\"nom nom nom\");
    };
    function Bird() { }
    Bird.prototype = Object.create(Animal.prototype);
    Bird.prototype.constructor = Bird;
    ", - "In addition to what is inherited from Animal, you want to add behavior that is unique to Bird objects. Here, Bird will get a fly() function. Functions are added to Bird's prototype the same way as any constructor function:", - "
    Bird.prototype.fly = function() {
      console.log(\"I'm flying!\");
    };
    ", - "Now instances of Bird will have both eat() and fly() methods:", - "
    let duck = new Bird();
    duck.eat(); // prints \"nom nom nom\"
    duck.fly(); // prints \"I'm flying!\"
    ", - "
    ", - "Add all necessary code so the Dog object inherits from Animal and the Dog's prototype constructor is set to Dog. Then add a bark() method to the Dog object so that beagle can both eat() and bark(). The bark() method should print \"Woof!\" to the console." - ], - "challengeSeed": [ - "function Animal() { }", - "Animal.prototype.eat = function() { console.log(\"nom nom nom\"); };", - "", - "function Dog() { }", - "", - "// Add your code below this line", - "", - "", - "", - "", - "// Add your code above this line", - "", - "let beagle = new Dog();", - "", - "beagle.eat(); // Should print \"nom nom nom\"", - "beagle.bark(); // Should print \"Woof!\"" - ], - "tests": [ - "assert(typeof Animal.prototype.bark == \"undefined\", 'message: Animal should not respond to the bark() method.');", - "assert(typeof Dog.prototype.eat == \"function\", 'message: Dog should inherit the eat() method from Animal.');", - "assert(Dog.prototype.hasOwnProperty('bark'), 'message: Dog should have the bark() method as an own property.');", - "assert(beagle instanceof Animal, 'message: beagle should be an instanceof Animal.');", - "assert(beagle.constructor === Dog, 'message: The constructor for beagle should be set to Dog.');" - ], - "solutions": [ - "function Animal() { }\nAnimal.prototype.eat = function() { console.log(\"nom nom nom\"); };\n\nfunction Dog() { }\nDog.prototype = Object.create(Animal.prototype);\nDog.prototype.constructor = Dog;\nDog.prototype.bark = function () {\n console.log('Woof!');\n};\nlet beagle = new Dog();\n\nbeagle.eat();\nbeagle.bark();" - ], - "hints": [ - "Objects inherit methods from other objects by cloning their prototype. The Object.create method will come in handy, and don't forget to reset the constructor property afterward!" - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db1367417b2b2512b88", - "title": "Override Inherited Methods", - "description": [ - "In previous lessons, you learned that an object can inherit its behavior (methods) from another object by cloning its prototype object:", - "
    ChildObject.prototype = Object.create(ParentObject.prototype);
    ", - "Then the ChildObject received its own methods by chaining them onto its prototype:", - "
    ChildObject.prototype.methodName = function() {...};
    ", - "It's possible to override an inherited method. It's done the same way - by adding a method to ChildObject.prototype using the same method name as the one to override.", - "Here's an example of Bird overriding the eat() method inherited from Animal:", - "
    function Animal() { }
    Animal.prototype.eat = function() {
      return \"nom nom nom\";
    };
    function Bird() { }

    // Inherit all methods from Animal
    Bird.prototype = Object.create(Animal.prototype);

    // Bird.eat() overrides Animal.eat()
    Bird.prototype.eat = function() {
      return \"peck peck peck\";
    };
    ", - "If you have an instance let duck = new Bird(); and you call duck.eat(), this is how JavaScript looks for the method on duck’s prototype chain:", - "1. duck => Is eat() defined here? No.", - "2. Bird => Is eat() defined here? => Yes. Execute it and stop searching.", - "3. Animal => eat() is also defined, but JavaScript stopped searching before reaching this level.", - "4. Object => JavaScript stopped searching before reaching this level.", - "
    ", - "Override the fly() method for Penguin so that it returns \"Alas, this is a flightless bird.\"" - ], - "challengeSeed": [ - "function Bird() { }", - "", - "Bird.prototype.fly = function() { return \"I am flying!\"; };", - "", - "function Penguin() { }", - "Penguin.prototype = Object.create(Bird.prototype);", - "Penguin.prototype.constructor = Penguin;", - "", - "// Add your code below this line", - "", - "", - "", - "// Add your code above this line", - "", - "let penguin = new Penguin();", - "console.log(penguin.fly());" - ], - "tests": [ - "assert(penguin.fly() === \"Alas, this is a flightless bird.\", 'message: penguin.fly() should return the string \"Alas, this is a flightless bird.\"');", - "assert((new Bird()).fly() === \"I am flying!\", 'message: The bird.fly() method should return \"I am flying!\"');" - ], - "solutions": [ - "function Bird() { }\n\nBird.prototype.fly = function() { return \"I am flying!\"; };\n\nfunction Penguin() { }\nPenguin.prototype = Object.create(Bird.prototype);\nPenguin.prototype.constructor = Penguin;\nPenguin.prototype.fly = () => 'Alas, this is a flightless bird.';\nlet penguin = new Penguin();\nconsole.log(penguin.fly());" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db2367417b2b2512b89", - "title": "Use a Mixin to Add Common Behavior Between Unrelated Objects", - "description": [ - "As you have seen, behavior is shared through inheritance. However, there are cases when inheritance is not the best solution. Inheritance does not work well for unrelated objects like Bird and Airplane. They can both fly, but a Bird is not a type of Airplane and vice versa.", - "For unrelated objects, it's better to use mixins. A mixin allows other objects to use a collection of functions.", - "
    let flyMixin = function(obj) {
      obj.fly = function() {
        console.log(\"Flying, wooosh!\");
      }
    };
    ", - "The flyMixin takes any object and gives it the fly method.", - "
    let bird = {
      name: \"Donald\",
      numLegs: 2
    };

    let plane = {
      model: \"777\",
      numPassengers: 524
    };

    flyMixin(bird);
    flyMixin(plane);
    ", - "Here bird and plane are passed into flyMixin, which then assigns the fly function to each object. Now bird and plane can both fly:", - "
    bird.fly(); // prints \"Flying, wooosh!\"
    plane.fly(); // prints \"Flying, wooosh!\"
    ", - "Note how the mixin allows for the same fly method to be reused by unrelated objects bird and plane.", - "
    ", - "Create a mixin named glideMixin that defines a method named glide. Then use the glideMixin to give both bird and boat the ability to glide." - ], - "challengeSeed": [ - "let bird = {", - " name: \"Donald\",", - " numLegs: 2", - "};", - "", - "let boat = {", - " name: \"Warrior\",", - " type: \"race-boat\"", - "};", - "", - "// Add your code below this line", - "", - "", - "", - "", - "", - "" - ], - "tests": [ - "assert(typeof glideMixin === \"function\", 'message: Your code should declare a glideMixin variable that is a function.');", - "assert(typeof bird.glide === \"function\", 'message: Your code should use the glideMixin on the bird object to give it the glide method.');", - "assert(typeof boat.glide === \"function\", 'message: Your code should use the glideMixin on the boat object to give it the glide method.');" - ], - "solutions": [ - "let bird = {\n name: \"Donald\",\n numLegs: 2\n};\n\nlet boat = {\n name: \"Warrior\",\n type: \"race-boat\"\n};\nfunction glideMixin (obj) {\n obj.glide = () => 'Gliding!';\n}\n\nglideMixin(bird);\nglideMixin(boat);" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db2367417b2b2512b8a", - "title": "Use Closure to Protect Properties Within an Object from Being Modified Externally", - "description": [ - "In the previous challenge, bird had a public property name. It is considered public because it can be accessed and changed outside of bird's definition.", - "
    bird.name = \"Duffy\";
    ", - "Therefore, any part of your code can easily change the name of bird to any value. Think about things like passwords and bank accounts being easily changeable by any part of your codebase. That could cause a lot of issues.", - "The simplest way to make properties private is by creating a variable within the constructor function. This changes the scope of that variable to be within the constructor function versus available globally. This way, the property can only be accessed and changed by methods also within the constructor function.", - "
    function Bird() {
      let hatchedEgg = 10; // private property

      this.getHatchedEggCount = function() { // publicly available method that a bird object can use
        return hatchedEgg;
      };
    }
    let ducky = new Bird();
    ducky.getHatchedEggCount(); // returns 10
    ", - "Here getHachedEggCount is a privileged method, because it has access to the private variable hatchedEgg. This is possible because hatchedEgg is declared in the same context as getHachedEggCount. In JavaScript, a function always has access to the context in which it was created. This is called closure.", - "
    ", - "Change how weight is declared in the Bird function so it is a private variable. Then, create a method getWeight that returns the value of weight." - ], - "challengeSeed": [ - "function Bird() {", - " this.weight = 15;", - " ", - " ", - "}", - "" - ], - "tests": [ - "assert(!code.match(/this\\.weight/g), 'message: The weight property should be a private variable.');", - "assert((new Bird()).getWeight() === 15, 'message: Your code should create a method in Bird called getWeight that returns the weight.');" - ], - "solutions": [ - "function Bird() {\n let weight = 15;\n \n this.getWeight = () => weight;\n}" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db2367417b2b2512b8b", - "title": "Understand the Immediately Invoked Function Expression (IIFE)", - "description": [ - "A common pattern in JavaScript is to execute a function as soon as it is declared:", - "
    (function () {
      console.log(\"Chirp, chirp!\");
    })(); // this is an anonymous function expression that executes right away
    // Outputs \"Chirp, chirp!\" immediately
    ", - "Note that the function has no name and is not stored in a variable. The two parentheses () at the end of the function expression cause it to be immediately executed or invoked. This pattern is known as an immediately invoked function expression or IIFE.", - "
    ", - "Rewrite the function makeNest and remove its call so instead it's an anonymous immediately invoked function expression (IIFE)." - ], - "challengeSeed": [ - "function makeNest() {", - " console.log(\"A cozy nest is ready\");", - "}", - "", - "makeNest(); " - ], - "tests": [ - "assert(/\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?{/.test(code), 'message: The function should be anonymous.');", - "assert(/}\\s*?\\)\\s*?\\(\\s*?\\)/.test(code), 'message: Your function should have parentheses at the end of the expression to call it immediately.');" - ], - "solutions": [ - "(function () {\n console.log(\"A cozy nest is ready\");\n})();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db2367417b2b2512b8c", - "title": "Use an IIFE to Create a Module", - "description": [ - "An immediately invoked function expression (IIFE) is often used to group related functionality into a single object or module. For example, an earlier challenge defined two mixins:", - "
    function glideMixin(obj) {
      obj.glide = function() {
        console.log(\"Gliding on the water\");
      };
    }
    function flyMixin(obj) {
      obj.fly = function() {
        console.log(\"Flying, wooosh!\");
      };
    }
    ", - "We can group these mixins into a module as follows:", - "
    let motionModule = (function () {
      return {
        glideMixin: function (obj) {
          obj.glide = function() {
            console.log(\"Gliding on the water\");
          };
        },
        flyMixin: function(obj) {
          obj.fly = function() {
            console.log(\"Flying, wooosh!\");
          };
        }
      }
    }) (); // The two parentheses cause the function to be immediately invoked
    ", - "Note that you have an immediately invoked function expression (IIFE) that returns an object motionModule. This returned object contains all of the mixin behaviors as properties of the object.", - "The advantage of the module pattern is that all of the motion behaviors can be packaged into a single object that can then be used by other parts of your code. Here is an example using it:", - "
    motionModule.glideMixin(duck);
    duck.glide();
    ", - "
    ", - "Create a module named funModule to wrap the two mixins isCuteMixin and singMixin. funModule should return an object." - ], - "challengeSeed": [ - "let isCuteMixin = function(obj) {", - " obj.isCute = function() {", - " return true;", - " };", - "};", - "let singMixin = function(obj) {", - " obj.sing = function() {", - " console.log(\"Singing to an awesome tune\");", - " };", - "};" - ], - "tests": [ - "assert(typeof funModule === \"object\", 'message: funModule should be defined and return an object.');", - "assert(typeof funModule.isCuteMixin === \"function\", 'message: funModule.isCuteMixin should access a function.');", - "assert(typeof funModule.singMixin === \"function\", 'message: funModule.singMixin should access a function.');" - ], - "solutions": [ - "const funModule = (function () {\n return {\n isCuteMixin: obj => {\n obj.isCute = () => true;\n },\n singMixin: obj => {\n obj.sing = () => console.log(\"Singing to an awesome tune\");\n }\n };\n})();" - ], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json b/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json deleted file mode 100644 index 56e34f93bb..0000000000 --- a/packages/learn/seed/tmp/02-javascript-algorithms-and-data-structures/regular-expressions.json +++ /dev/null @@ -1,994 +0,0 @@ -{ - "name": "Regular Expressions", - "order": 3, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7db3367417b2b2512b8d", - "title": "Introduction to the Regular Expression Challenges", - "description": [ - "", - "", - "Regular expressions are special strings that represent a search pattern. Also known as \"regex\" or \"regexp\", they help programmers match, search, and replace text. Regular expressions can appear cryptic because a few characters have special meaning. The goal is to combine the symbols and text into a pattern that matches what you want, but only what you want. This section will cover the characters, a few shortcuts, and the common uses for writing regular expressions.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7db3367417b2b2512b8e", - "title": "Using the Test Method", - "description": [ - "Regular expressions are used in programming languages to match parts of strings. You create patterns to help you do that matching.", - "If you want to find the word \"the\" in the string \"The dog chased the cat\", you could use the following regular expression: /the/. Notice that quote marks are not required within the regular expression.", - "JavaScript has multiple ways to use regexes. One way to test a regex is using the .test() method. The .test() method takes the regex, applies it to a string (which is placed inside the parentheses), and returns true or false if your pattern finds something or not.", - "
    let testStr = \"freeCodeCamp\";
    let testRegex = /Code/;
    testRegex.test(testStr);
    // Returns true
    ", - "
    ", - "Apply the regex myRegex on the string myString using the .test() method." - ], - "challengeSeed": [ - "let myString = \"Hello, World!\";", - "let myRegex = /Hello/;", - "let result = myRegex; // Change this line" - ], - "tests": [ - "assert(code.match(/myRegex.test\\(\\s*myString\\s*\\)/), 'message: You should use .test() to test the regex.');", - "assert(result === true, 'message: Your result should return true.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db3367417b2b2512b8f", - "title": "Match Literal Strings", - "description": [ - "In the last challenge, you searched for the word \"Hello\" using the regular expression /Hello/. That regex searched for a literal match of the string \"Hello\". Here's another example searching for a literal match of the string \"Kevin\":", - "
    let testStr = \"Hello, my name is Kevin.\";
    let testRegex = /Kevin/;
    testRegex.test(testStr);
    // Returns true
    ", - "Any other forms of \"Kevin\" will not match. For example, the regex /Kevin/ will not match \"kevin\" or \"KEVIN\".", - "
    let wrongRegex = /kevin/;
    wrongRegex.test(testStr);
    // Returns false
    ", - "A future challenge will show how to match those other forms as well.", - "
    ", - "Complete the regex waldoRegex to find \"Waldo\" in the string waldoIsHiding with a literal match." - ], - "challengeSeed": [ - "let waldoIsHiding = \"Somewhere Waldo is hiding in this text.\";", - "let waldoRegex = /search/; // Change this line", - "let result = waldoRegex.test(waldoIsHiding);" - ], - "tests": [ - "assert(waldoRegex.test(waldoIsHiding), 'message: Your regex waldoRegex should find \"Waldo\"');", - "assert(!waldoRegex.test('Somewhere is hiding in this text.'), 'message: Your regex waldoRegex should not search for anything else.');", - "assert(!/\\/.*\\/i/.test(code), 'message: You should perform a literal string match with your regex.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db4367417b2b2512b90", - "title": "Match a Literal String with Different Possibilities", - "description": [ - "Using regexes like /coding/, you can look for the pattern \"coding\" in another string.", - "This is powerful to search single strings, but it's limited to only one pattern. You can search for multiple patterns using the alternation or OR operator: |.", - "This operator matches patterns either before or after it. For example, if you wanted to match \"yes\" or \"no\", the regex you want is /yes|no/.", - "You can also search for more than just two patterns. You can do this by adding more patterns with more OR operators separating them, like /yes|no|maybe/.", - "
    ", - "Complete the regex petRegex to match the pets \"dog\", \"cat\", \"bird\", or \"fish\"." - ], - "challengeSeed": [ - "let petString = \"James has a pet cat.\";", - "let petRegex = /change/; // Change this line", - "let result = petRegex.test(petString);" - ], - "tests": [ - "assert(petRegex.test('John has a pet dog.'), 'message: Your regex petRegex should return true for the string \"John has a pet dog.\"');", - "assert(!petRegex.test('Emma has a pet rock.'), 'message: Your regex petRegex should return false for the string \"Emma has a pet rock.\"');", - "assert(petRegex.test('Emma has a pet bird.'), 'message: Your regex petRegex should return true for the string \"Emma has a pet bird.\"');", - "assert(petRegex.test('Liz has a pet cat.'), 'message: Your regex petRegex should return true for the string \"Liz has a pet cat.\"');", - "assert(!petRegex.test('Kara has a pet dolphin.'), 'message: Your regex petRegex should return false for the string \"Kara has a pet dolphin.\"');", - "assert(petRegex.test('Alice has a pet fish.'), 'message: Your regex petRegex should return true for the string \"Alice has a pet fish.\"');", - "assert(!petRegex.test('Jimmy has a pet computer.'), 'message: Your regex petRegex should return false for the string \"Jimmy has a pet computer.\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db4367417b2b2512b91", - "title": "Ignore Case While Matching", - "description": [ - "Up until now, you've looked at regexes to do literal matches of strings. But sometimes, you might want to also match case differences.", - "Case (or sometimes letter case) is the difference between uppercase letters and lowercase letters. Examples of uppercase are \"A\", \"B\", and \"C\". Examples of lowercase are \"a\", \"b\", and \"c\".", - "You can match both cases using what is called a flag. There are other flags but here you'll focus on the flag that ignores case - the i flag. You can use it by appending it to the regex. An example of using this flag is /ignorecase/i. This regex can match the strings \"ignorecase\", \"igNoreCase\", and \"IgnoreCase\".", - "
    ", - "Write a regex fccRegex to match \"freeCodeCamp\", no matter its case. Your regex should not match any abbreviations or variations with spaces." - ], - "challengeSeed": [ - "let myString = \"freeCodeCamp\";", - "let fccRegex = /change/; // Change this line", - "let result = fccRegex.test(myString);" - ], - "tests": [ - "assert(fccRegex.test('freeCodeCamp'), 'message: Your regex should match freeCodeCamp');", - "assert(fccRegex.test('FreeCodeCamp'), 'message: Your regex should match FreeCodeCamp');", - "assert(fccRegex.test('FreecodeCamp'), 'message: Your regex should match FreecodeCamp');", - "assert(fccRegex.test('FreeCodecamp'), 'message: Your regex should match FreeCodecamp');", - "assert(!fccRegex.test('Free Code Camp'), 'message: Your regex should not match Free Code Camp');", - "assert(fccRegex.test('FreeCOdeCamp'), 'message: Your regex should match FreeCOdeCamp');", - "assert(!fccRegex.test('FCC'), 'message: Your regex should not match FCC');", - "assert(fccRegex.test('FrEeCoDeCamp'), 'message: Your regex should match FrEeCoDeCamp');", - "assert(fccRegex.test('FrEeCodECamp'), 'message: Your regex should match FrEeCodECamp');", - "assert(fccRegex.test('FReeCodeCAmp'), 'message: Your regex should match FReeCodeCAmp');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db4367417b2b2512b92", - "title": "Extract Matches", - "description": [ - "So far, you have only been checking if a pattern exists or not within a string. You can also extract the actual matches you found with the .match() method.", - "To use the .match() method, apply the method on a string and pass in the regex inside the parentheses. Here's an example:", - "
    \"Hello, World!\".match(/Hello/);
    // Returns [\"Hello\"]
    let ourStr = \"Regular expressions\";
    let ourRegex = /expressions/;
    ourStr.match(ourRegex);
    // Returns [\"expressions\"]
    ", - "
    ", - "Apply the .match() method to extract the word coding." - ], - "challengeSeed": [ - "let extractStr = \"Extract the word 'coding' from this string.\";", - "let codingRegex = /change/; // Change this line", - "let result = extractStr; // Change this line" - ], - "tests": [ - "assert(result.join() === \"coding\", 'message: The result should have the word coding');", - "assert(codingRegex.source === \"coding\", 'message: Your regex codingRegex should search for coding');", - "assert(code.match(/\\.match\\(.*\\)/), 'message: You should use the .match() method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db4367417b2b2512b93", - "title": "Find More Than the First Match", - "description": [ - "So far, you have only been able to extract or search a pattern once.", - "
    let testStr = \"Repeat, Repeat, Repeat\";
    let ourRegex = /Repeat/;
    testStr.match(ourRegex);
    // Returns [\"Repeat\"]
    ", - "To search or extract a pattern more than once, you can use the g flag.", - "
    let repeatRegex = /Repeat/g;
    testStr.match(repeatRegex);
    // Returns [\"Repeat\", \"Repeat\", \"Repeat\"]
    ", - "
    ", - "Using the regex starRegex, find and extract both \"Twinkle\" words from the string twinkleStar.", - "Note
    You can have multiple flags on your regex like /search/gi" - ], - "challengeSeed": [ - "let twinkleStar = \"Twinkle, twinkle, little star\";", - "let starRegex = /change/; // Change this line", - "let result = twinkleStar; // Change this line" - ], - "tests": [ - "assert(starRegex.flags.match(/g/).length == 1, 'message: Your regex starRegex should use the global flag g');", - "assert(starRegex.flags.match(/i/).length == 1, 'message: Your regex starRegex should use the case insensitive flag i');", - "assert(result.sort().join() == twinkleStar.match(/twinkle/gi).sort().join(), 'message: Your match should match both occurrences of the word \"Twinkle\"');", - "assert(result.length == 2, 'message: Your match result should have two elements in it.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db5367417b2b2512b94", - "title": "Match Anything with Wildcard Period", - "description": [ - "Sometimes you won't (or don't need to) know the exact characters in your patterns. Thinking of all words that match, say, a misspelling would take a long time. Luckily, you can save time using the wildcard character: .", - "The wildcard character . will match any one character. The wildcard is also called dot and period. You can use the wildcard character just like any other character in the regex. For example, if you wanted to match \"hug\", \"huh\", \"hut\", and \"hum\", you can use the regex /hu./ to match all four words.", - "
    let humStr = \"I'll hum a song\";
    let hugStr = \"Bear hug\";
    let huRegex = /hu./;
    humStr.match(huRegex); // Returns [\"hum\"]
    hugStr.match(huRegex); // Returns [\"hug\"]
    ", - "
    ", - "Complete the regex unRegex so that it matches the strings \"run\", \"sun\", \"fun\", \"pun\", \"nun\", and \"bun\". Your regex should use the wildcard character." - ], - "challengeSeed": [ - "let exampleStr = \"Let's have fun with regular expressions!\";", - "let unRegex = /change/; // Change this line", - "let result = unRegex.test(exampleStr);" - ], - "tests": [ - "assert(code.match(/\\.test\\(.*\\)/), 'message: You should use the .test() method.');", - "assert(/\\./.test(unRegex.source), 'message: You should use the wildcard character in your regex unRegex');", - "assert(unRegex.test(\"Let us go on a run.\"), 'message: Your regex unRegex should match \"run\" in \"Let us go on a run.\"');", - "assert(unRegex.test(\"The sun is out today.\"), 'message: Your regex unRegex should match \"sun\" in \"The sun is out today.\"');", - "assert(unRegex.test(\"Coding is a lot of fun.\"), 'message: Your regex unRegex should match \"fun\" in \"Coding is a lot of fun.\"');", - "assert(unRegex.test(\"Seven days without a pun makes one weak.\"), 'message: Your regex unRegex should match \"pun\" in \"Seven days without a pun makes one weak.\"');", - "assert(unRegex.test(\"One takes a vow to be a nun.\"), 'message: Your regex unRegex should match \"nun\" in \"One takes a vow to be a nun.\"');", - "assert(unRegex.test(\"She got fired from the hot dog stand for putting her hair in a bun.\"), 'message: Your regex unRegex should match \"bun\" in \"She got fired from the hot dog stand for putting her hair in a bun.\"');", - "assert(!unRegex.test(\"There is a bug in my code.\"), 'message: Your regex unRegex should not match \"There is a bug in my code.\"');", - "assert(!unRegex.test(\"Can me if you can.\"), 'message: Your regex unRegex should not match \"Catch me if you can.\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db5367417b2b2512b95", - "title": "Match Single Character with Multiple Possibilities", - "description": [ - "You learned how to match literal patterns (/literal/) and wildcard character (/./). Those are the extremes of regular expressions, where one finds exact matches and the other matches everything. There are options that are a balance between the two extremes.", - "You can search for a literal pattern with some flexibility with character classes. Character classes allow you to define a group of characters you wish to match by placing them inside square ([ and ]) brackets.", - "For example, you want to match \"bag\", \"big\", and \"bug\" but not \"bog\". You can create the regex /b[aiu]g/ to do this. The [aiu] is the character class that will only match the characters \"a\", \"i\", or \"u\".", - "
    let bigStr = \"big\";
    let bagStr = \"bag\";
    let bugStr = \"bug\";
    let bogStr = \"bog\";
    let bgRegex = /b[aiu]g/;
    bigStr.match(bgRegex); // Returns [\"big\"]
    bagStr.match(bgRegex); // Returns [\"bag\"]
    bugStr.match(bgRegex); // Returns [\"bug\"]
    bogStr.match(bgRegex); // Returns null
    ", - "
    ", - "Use a character class with vowels (a, e, i, o, u) in your regex vowelRegex to find all the vowels in the string quoteSample.", - "Note
    Be sure to match both upper- and lowercase vowels." - ], - "challengeSeed": [ - "let quoteSample = \"Beware of bugs in the above code; I have only proved it correct, not tried it.\";", - "let vowelRegex = /change/; // Change this line", - "let result = vowelRegex; // Change this line" - ], - "tests": [ - "assert(result.length == 25, 'message: You should find all 25 vowels.');", - "assert(/\\[.*\\]/.test(vowelRegex.source), 'message: Your regex vowelRegex should use a character class.');", - "assert(vowelRegex.flags.match(/g/).length == 1, 'message: Your regex vowelRegex should use the global flag.');", - "assert(vowelRegex.flags.match(/i/).length == 1, 'message: Your regex vowelRegex should use the case insensitive flag.');", - "assert(!/[b-df-hj-np-tv-z]/gi.test(result.join()), 'message: Your regex should not match any consonants.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db5367417b2b2512b96", - "title": "Match Letters of the Alphabet", - "description": [ - "You saw how you can use character sets to specify a group of characters to match, but that's a lot of typing when you need to match a large range of characters (for example, every letter in the alphabet). Fortunately, there is a built-in feature that makes this short and simple.", - "Inside a character set, you can define a range of characters to match using a hyphen character: -.", - "For example, to match lowercase letters a through e you would use [a-e].", - "
    let catStr = \"cat\";
    let batStr = \"bat\";
    let matStr = \"mat\";
    let bgRegex = /[a-e]at/;
    catStr.match(bgRegex); // Returns [\"cat\"]
    batStr.match(bgRegex); // Returns [\"bat\"]
    matStr.match(bgRegex); // Returns null
    ", - "
    ", - "Match all the letters in the string quoteSample.", - "Note
    Be sure to match both upper- and lowercase vowels." - ], - "challengeSeed": [ - "let quoteSample = \"The quick brown fox jumps over the lazy dog.\";", - "let alphabetRegex = /change/; // Change this line", - "let result = alphabetRegex; // Change this line" - ], - "tests": [ - "assert(result.length == 35, 'message: Your regex alphabetRegex should match 35 items.');", - "assert(alphabetRegex.flags.match(/g/).length == 1, 'message: Your regex alphabetRegex should use the global flag.');", - "assert(alphabetRegex.flags.match(/i/).length == 1, 'message: Your regex alphabetRegex should use the case insensitive flag.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db5367417b2b2512b97", - "title": "Match Numbers and Letters of the Alphabet", - "description": [ - "Using the hyphen (-) to match a range of characters is not limited to letters. It also works to match a range of numbers.", - "For example, /[0-5]/ matches any number between 0 and 5, including the 0 and 5.", - "Also, it is possible to combine a range of letters and numbers in a single character set.", - "
    let jennyStr = \"Jenny8675309\";
    let myRegex = /[a-z0-9]/ig;
    // matches all letters and numbers in jennyStr
    jennyStr.match(myRegex);
    ", - "
    ", - "Create a single regex that matches a range of letters between h and s, and a range of numbers between 2 and 6. Remember to include the appropriate flags in the regex." - ], - "challengeSeed": [ - "let quoteSample = \"Blueberry 3.141592653s are delicious.\";", - "let myRegex = /change/; // Change this line", - "let result = myRegex; // Change this line" - ], - "tests": [ - "assert(result.length == 17, 'message: Your regex myRegex should match 17 items.');", - "assert(myRegex.flags.match(/g/).length == 1, 'message: Your regex myRegex should use the global flag.');", - "assert(myRegex.flags.match(/i/).length == 1, 'message: Your regex myRegex should use the case insensitive flag.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db6367417b2b2512b98", - "title": "Match Single Characters Not Specified", - "description": [ - "So far, you have created a set of characters that you want to match, but you could also create a set of characters that you do not want to match. These types of character sets are called negated character sets.", - "To create a negated character set, you place a caret character (^) after the opening bracket and before the characters you do not want to match.", - "For example, /[^aeiou]/gi matches all characters that are not a vowel. Note that characters like ., !, [, @, / and white space are matched - the negated vowel character set only excludes the vowel characters.", - "
    ", - "Create a single regex that matches all characters that are not a number or a vowel. Remember to include the appropriate flags in the regex." - ], - "challengeSeed": [ - "let quoteSample = \"3 blind mice.\";", - "let myRegex = /change/; // Change this line", - "let result = myRegex; // Change this line" - ], - "tests": [ - "assert(result.length == 9, 'message: Your regex myRegex should match 9 items.');", - "assert(myRegex.flags.match(/g/).length == 1, 'message: Your regex myRegex should use the global flag.');", - "assert(myRegex.flags.match(/i/).length == 1, 'message: Your regex myRegex should use the case insensitive flag.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db6367417b2b2512b99", - "title": "Match Characters that Occur One or More Times", - "description": [ - "Sometimes, you need to match a character (or group of characters) that appears one or more times in a row. This means it occurs at least once, and may be repeated.", - "You can use the + character to check if that is the case. Remember, the character or pattern has to be present consecutively. That is, the character has to repeat one after the other.", - "For example, /a+/g would find one match in \"abc\" and return [\"a\"]. Because of the +, it would also find a single match in \"aabc\" and return [\"aa\"].", - "If it were instead checking the string \"abab\", it would find two matches and return [\"a\", \"a\"] because the a characters are not in a row - there is a b between them. Finally, since there is no \"a\" in the string \"bcd\", it wouldn't find a match.", - "
    ", - "You want to find matches when the letter s occurs one or more times in \"Mississippi\". Write a regex that uses the + sign." - ], - "challengeSeed": [ - "let difficultSpelling = \"Mississippi\";", - "let myRegex = /change/; // Change this line", - "let result = difficultSpelling.match(myRegex);" - ], - "tests": [ - "assert(/\\+/.test(myRegex.source), 'message: Your regex myRegex should use the + sign to match one or more s characters.');", - "assert(result.length == 2, 'message: Your regex myRegex should match 2 items.');", - "assert(result[0] == 'ss' && result[1] == 'ss', 'message: The result variable should be an array with two matches of \"ss\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db6367417b2b2512b9a", - "title": "Match Characters that Occur Zero or More Times", - "description": [ - "The last challenge used the plus + sign to look for characters that occur one or more times. There's also an option that matches characters that occur zero or more times.", - "The character to do this is the asterisk or star: *.", - "
    let soccerWord = \"gooooooooal!\";
    let gPhrase = \"gut feeling\";
    let oPhrase = \"over the moon\";
    let goRegex = /go*/;
    soccerWord.match(goRegex); // Returns [\"goooooooo\"]
    gPhrase.match(goRegex); // Returns [\"g\"]
    oPhrase.match(goRegex); // Returns null
    ", - "
    ", - "Create a regex chewieRegex that uses the * character to match all the upper and lower\"a\" characters in chewieQuote. Your regex does not need flags, and it should not match any of the other quotes." - ], - "challengeSeed": [ - "let chewieQuote = \"Aaaaaaaaaaaaaaaarrrgh!\";", - "let chewieRegex = /change/; // Change this line", - "let result = chewieQuote.match(chewieRegex);" - ], - "tests": [ - "assert(/\\*/.test(chewieRegex.source), 'message: Your regex chewieRegex should use the * character to match zero or more a characters.');", - "assert(result[0].length === 16, 'message: Your regex chewieRegex should match 16 characters.');", - "assert(result[0] === 'Aaaaaaaaaaaaaaaa', 'message: Your regex should match \"Aaaaaaaaaaaaaaaa\".');", - "assert(!\"He made a fair move. Screaming about it can\\'t help you.\".match(chewieRegex), 'message: Your regex should not match any characters in \"He made a fair move. Screaming about it can't help you.\"');", - "assert(!\"Let him have it. It\\'s not wise to upset a Wookiee.\".match(chewieRegex), 'message: Your regex should not match any characters in \"Let him have it. It's not wise to upset a Wookiee.\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db6367417b2b2512b9b", - "title": "Find Characters with Lazy Matching", - "description": [ - "In regular expressions, a greedy match finds the longest possible part of a string that fits the regex pattern and returns it as a match. The alternative is called a lazy match, which finds the smallest possible part of the string that satisfies the regex pattern.", - "You can apply the regex /t[a-z]*i/ to the string \"titanic\". This regex is basically a pattern that starts with t, ends with i, and has some letters in between.", - "Regular expressions are by default greedy, so the match would return [\"titani\"]. It finds the largest sub-string possible to fit the pattern.", - "However, you can use the ? character to change it to lazy matching. \"titanic\" matched against the adjusted regex of /t[a-z]*?i/ returns [\"ti\"].", - "
    ", - "Fix the regex /<.*>/ to return the HTML tag <h1> and not the text \"<h1>Winter is coming</h1>\". Remember the wildcard . in a regular expression matches any character." - ], - "challengeSeed": [ - "let text = \"

    Winter is coming

    \";", - "let myRegex = /<.*>/; // Change this line", - "let result = text.match(myRegex);" - ], - "tests": [ - "assert(result[0] == '

    ', 'message: The result variable should be an array with <h1> in it');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db7367417b2b2512b9c", - "title": "Find One or More Criminals in a Hunt", - "description": [ - "Time to pause and test your new regex writing skills. A group of criminals escaped from jail and ran away, but you don't know how many. However, you do know that they stay close together when they are around other people. You are responsible for finding all of the criminals at once.", - "Here's an example to review how to do this:", - "The regex /z+/ matches the letter z when it appears one or more times in a row. It would find matches in all of the following strings:", - "
    \"z\"
    \"zzzzzz\"
    \"ABCzzzz\"
    \"zzzzABC\"
    \"abczzzzzzzzzzzzzzzzzzzzzabc\"
    ", - "But it does not find matches in the following strings since there are no letter z characters:", - "
    \"\"
    \"ABC\"
    \"abcabc\"
    ", - "
    ", - "Write a greedy regex that finds one or more criminals within a group of other people. A criminal is represented by the capital letter C." - ], - "challengeSeed": [ - "// example crowd gathering", - "let crowd = 'P1P2P3P4P5P6CCCP7P8P9';", - "", - "let reCriminals = /./; // Change this line", - "", - "let matchedCriminals = crowd.match(reCriminals);", - "console.log(matchedCriminals);" - ], - "tests": [ - "assert('C'.match(reCriminals) && 'C'.match(reCriminals)[0] == 'C', 'message: Your regex should match one criminal (\"C\") in \"C\"');", - "assert('CC'.match(reCriminals) && 'CC'.match(reCriminals)[0] == 'CC', 'message: Your regex should match two criminals (\"CC\") in \"CC\"');", - "assert('P1P5P4CCCP2P6P3'.match(reCriminals) && 'P1P5P4CCCP2P6P3'.match(reCriminals)[0] == 'CCC', 'message: Your regex should match three criminals (\"CCC\") in \"P1P5P4CCCP2P6P3\"');", - "assert('P6P2P7P4P5CCCCCP3P1'.match(reCriminals) && 'P6P2P7P4P5CCCCCP3P1'.match(reCriminals)[0] == 'CCCCC', 'message: Your regex should match five criminals (\"CCCCC\") in \"P6P2P7P4P5CCCCCP3P1\"');", - "assert(!reCriminals.test(''), 'message: Your regex should not match any criminals in \"\"');", - "assert(!reCriminals.test('P1P2P3'), 'message: Your regex should not match any criminals in \"P1P2P3\"');", - "assert('P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3'.match(reCriminals) && 'P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3'.match(reCriminals)[0] == \"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\", 'message: Your regex should match fifty criminals (\"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\") in \"P2P1P5P4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCP3\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db7367417b2b2512b9d", - "title": "Match Beginning String Patterns", - "description": [ - "Prior challenges showed that regular expressions can be used to look for a number of matches. They are also used to search for patterns in specific positions in strings.", - "In an earlier challenge, you used the caret character (^) inside a character set to create a negated character set in the form [^thingsThatWillNotBeMatched]. Outside of a character set, the caret is used to search for patterns at the beginning of strings.", - "
    let firstString = \"Ricky is first and can be found.\";
    let firstRegex = /^Ricky/;
    firstRegex.test(firstString);
    // Returns true
    let notFirst = \"You can't find Ricky now.\";
    firstRegex.test(notFirst);
    // Returns false
    ", - "
    ", - "Use the caret character in a regex to find \"Cal\" only in the beginning of the string rickyAndCal." - ], - "challengeSeed": [ - "let rickyAndCal = \"Cal and Ricky both like racing.\";", - "let calRegex = /change/; // Change this line", - "let result = calRegex.test(rickyAndCal);" - ], - "tests": [ - "assert(calRegex.source == \"^Cal\", 'message: Your regex should search for \"Cal\" with a capital letter.');", - "assert(calRegex.flags == \"\", 'message: Your regex should not use any flags.');", - "assert(calRegex.test(\"Cal and Ricky both like racing.\"), 'message: Your regex should match \"Cal\" at the beginning of the string.');", - "assert(!calRegex.test(\"Ricky and Cal both like racing.\"), 'message: Your regex should not match \"Cal\" in the middle of a string.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db7367417b2b2512b9e", - "title": "Match Ending String Patterns", - "description": [ - "In the last challenge, you learned to use the caret character to search for patterns at the beginning of strings. There is also a way to search for patterns at the end of strings.", - "You can search the end of strings using the dollar sign character $ at the end of the regex.", - "
    let theEnding = \"This is a never ending story\";
    let storyRegex = /story$/;
    storyRegex.test(theEnding);
    // Returns true
    let noEnding = \"Sometimes a story will have to end\";
    storyRegex.test(noEnding);
    // Returns false
    ", - "
    ", - "Use the anchor character ($) to match the string \"caboose\" at the end of the string caboose." - ], - "challengeSeed": [ - "let caboose = \"The last car on a train is the caboose\";", - "let lastRegex = /change/; // Change this line", - "let result = lastRegex.test(caboose);" - ], - "tests": [ - "assert(lastRegex.source == \"caboose$\", 'message: You should search for \"caboose\" with the dollar sign $ anchor in your regex.');", - "assert(lastRegex.flags == \"\", 'message: Your regex should not use any flags.');", - "assert(lastRegex.test(\"The last car on a train is the caboose\"), 'message: You should match \"caboose\" at the end of the string \"The last car on a train is the caboose\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db7367417b2b2512b9f", - "title": "Match All Letters and Numbers", - "description": [ - "Using character classes, you were able to search for all letters of the alphabet with [a-z]. This kind of character class is common enough that there is a shortcut for it, although it includes a few extra characters as well.", - "The closest character class in JavaScript to match the alphabet is \\w. This shortcut is equal to [A-Za-z0-9_]. This character class matches upper and lowercase letters plus numbers. Note, this character class also includes the underscore character (_).", - "
    let longHand = /[A-Za-z0-9_]+/;
    let shortHand = /\\w+/;
    let numbers = \"42\";
    let varNames = \"important_var\";
    longHand.test(numbers); // Returns true
    shortHand.test(numbers); // Returns true
    longHand.test(varNames); // Returns true
    shortHand.test(varNames); // Returns true
    ", - "These shortcut character classes are also known as shorthand character classes.", - "
    ", - "Use the shorthand character class \\w to count the number of alphanumeric characters in various quotes and strings." - ], - "challengeSeed": [ - "let quoteSample = \"The five boxing wizards jump quickly.\";", - "let alphabetRegexV2 = /change/; // Change this line", - "let result = quoteSample.match(alphabetRegexV2).length;" - ], - "tests": [ - "assert(alphabetRegexV2.global, 'message: Your regex should use the global flag.');", - "assert(\"The five boxing wizards jump quickly.\".match(alphabetRegexV2).length === 31, 'message: Your regex should find 31 alphanumeric characters in \"The five boxing wizards jump quickly.\"');", - "assert(\"Pack my box with five dozen liquor jugs.\".match(alphabetRegexV2).length === 32, 'message: Your regex should find 32 alphanumeric characters in \"Pack my box with five dozen liquor jugs.\"');", - "assert(\"How vexingly quick daft zebras jump!\".match(alphabetRegexV2).length === 30, 'message: Your regex should find 30 alphanumeric characters in \"How vexingly quick daft zebras jump!\"');", - "assert(\"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\".match(alphabetRegexV2).length === 36, 'message: Your regex should find 36 alphanumeric characters in \"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db8367417b2b2512ba0", - "title": "Match Everything But Letters and Numbers", - "description": [ - "You've learned that you can use a shortcut to match alphanumerics [A-Za-z0-9_] using \\w. A natural pattern you might want to search for is the opposite of alphanumerics.", - "You can search for the opposite of the \\w with \\W. Note, the opposite pattern uses a capital letter. This shortcut is the same as [^A-Za-z0-9_].", - "
    let shortHand = /\\W/;
    let numbers = \"42%\";
    let sentence = \"Coding!\";
    numbers.match(shortHand); // Returns [\"%\"]
    sentence.match(shortHand); // Returns [\"!\"]
    ", - "
    ", - "Use the shorthand character class \\W to count the number of non-alphanumeric characters in various quotes and strings." - ], - "challengeSeed": [ - "let quoteSample = \"The five boxing wizards jump quickly.\";", - "let nonAlphabetRegex = /change/; // Change this line", - "let result = quoteSample.match(nonAlphabetRegex).length;" - ], - "tests": [ - "assert(nonAlphabetRegex.global, 'message: Your regex should use the global flag.');", - "assert(\"The five boxing wizards jump quickly.\".match(nonAlphabetRegex).length == 6, 'message: Your regex should find 6 non-alphanumeric characters in \"The five boxing wizards jump quickly.\".');", - "assert(\"Pack my box with five dozen liquor jugs.\".match(nonAlphabetRegex).length == 8, 'message: Your regex should find 8 non-alphanumeric characters in \"Pack my box with five dozen liquor jugs.\"');", - "assert(\"How vexingly quick daft zebras jump!\".match(nonAlphabetRegex).length == 6, 'message: Your regex should find 6 non-alphanumeric characters in \"How vexingly quick daft zebras jump!\"');", - "assert(\"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\".match(nonAlphabetRegex).length == 12, 'message: Your regex should find 12 non-alphanumeric characters in \"123 456 7890 ABC def GHI jkl MNO pqr STU vwx YZ.\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "5d712346c441eddfaeb5bdef", - "title": "Match All Numbers", - "description": [ - "You've learned shortcuts for common string patterns like alphanumerics. Another common pattern is looking for just digits or numbers.", - "The shortcut to look for digit characters is \\d, with a lowercase d. This is equal to the character class [0-9], which looks for a single character of any number between zero and nine.", - "
    ", - "Use the shorthand character class \\d to count how many digits are in movie titles. Written out numbers (\"six\" instead of 6) do not count." - ], - "challengeSeed": [ - "let numString = \"Your sandwich will be $5.00\";", - "let numRegex = /change/; // Change this line", - "let result = numString.match(numRegex).length;" - ], - "tests": [ - "assert(/\\\\d/.test(numRegex.source), 'message: Your regex should use the shortcut character to match digit characters');", - "assert(numRegex.global, 'message: Your regex should use the global flag.');", - "assert(\"9\".match(numRegex).length == 1, 'message: Your regex should find 1 digit in \"9\".');", - "assert(\"Catch 22\".match(numRegex).length == 2, 'message: Your regex should find 2 digits in \"Catch 22\".');", - "assert(\"101 Dalmatians\".match(numRegex).length == 3, 'message: Your regex should find 3 digits in \"101 Dalmatians\".');", - "assert(\"One, Two, Three\".match(numRegex) == null, 'message: Your regex should find no digits in \"One, Two, Three\".');", - "assert(\"21 Jump Street\".match(numRegex).length == 2, 'message: Your regex should find 2 digits in \"21 Jump Street\".');", - "assert(\"2001: A Space Odyssey\".match(numRegex).length == 4, 'message: Your regex should find 4 digits in \"2001: A Space Odyssey\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db8367417b2b2512ba1", - "title": "Match All Non-Numbers", - "description": [ - "The last challenge showed how to search for digits using the shortcut \\d with a lowercase d. You can also search for non-digits using a similar shortcut that uses an uppercase D instead.", - "The shortcut to look for non-digit characters is \\D. This is equal to the character class [^0-9], which looks for a single character that is not a number between zero and nine.", - "
    ", - "Use the shorthand character class for non-digits \\D to count how many non-digits are in movie titles." - ], - "challengeSeed": [ - "let numString = \"Your sandwich will be $5.00\";", - "let noNumRegex = /change/; // Change this line", - "let result = numString.match(noNumRegex).length;" - ], - "tests": [ - "assert(/\\\\D/.test(noNumRegex.source), 'message: Your regex should use the shortcut character to match non-digit characters');", - "assert(noNumRegex.global, 'message: Your regex should use the global flag.');", - "assert(\"9\".match(noNumRegex) == null, 'message: Your regex should find no non-digits in \"9\".');", - "assert(\"Catch 22\".match(noNumRegex).length == 6, 'message: Your regex should find 6 non-digits in \"Catch 22\".');", - "assert(\"101 Dalmatians\".match(noNumRegex).length == 11, 'message: Your regex should find 11 non-digits in \"101 Dalmatians\".');", - "assert(\"One, Two, Three\".match(noNumRegex).length == 15, 'message: Your regex should find 15 non-digits in \"One, Two, Three\".');", - "assert(\"21 Jump Street\".match(noNumRegex).length == 12, 'message: Your regex should find 12 non-digits in \"21 Jump Street\".');", - "assert(\"2001: A Space Odyssey\".match(noNumRegex).length == 17, 'message: Your regex should find 17 non-digits in \"2001: A Space Odyssey\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db8367417b2b2512ba2", - "title": "Restrict Possible Usernames", - "description": [ - "Usernames are used everywhere on the internet. They are what give users a unique identity on their favorite sites.", - "You need to check all the usernames in a database. Here are some simple rules that users have to follow when creating their username.", - "1) The only numbers in the username have to be at the end. There can be zero or more of them at the end.", - "2) Username letters can be lowercase and uppercase.", - "3) Usernames have to be at least two characters long. A two-letter username can only use alphabet letter characters.", - "
    ", - "Change the regex userCheck to fit the constraints listed above." - ], - "challengeSeed": [ - "let username = \"JackOfAllTrades\";", - "let userCheck = /change/; // Change this line", - "let result = userCheck.test(username);" - ], - "tests": [ - "assert(userCheck.test(\"JACK\"), 'message: Your regex should match JACK');", - "assert(!userCheck.test(\"J\"), 'message: Your regex should not match J');", - "assert(userCheck.test(\"Oceans11\"), 'message: Your regex should match Oceans11');", - "assert(userCheck.test(\"RegexGuru\"), 'message: Your regex should match RegexGuru');", - "assert(!userCheck.test(\"007\"), 'message: Your regex should not match 007');", - "assert(!userCheck.test(\"9\"), 'message: Your regex should not match 9');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db8367417b2b2512ba3", - "title": "Match Whitespace", - "description": [ - "The challenges so far have covered matching letters of the alphabet and numbers. You can also match the whitespace or spaces between letters.", - "You can search for whitespace using \\s, which is a lowercase s. This pattern not only matches whitespace, but also carriage return, tab, form feed, and new line characters. You can think of it as similar to the character class [ \\r\\t\\f\\n\\v].", - "
    let whiteSpace = \"Whitespace. Whitespace everywhere!\"
    let spaceRegex = /\\s/g;
    whiteSpace.match(spaceRegex);
    // Returns [\" \", \" \"]
    ", - "
    ", - "Change the regex countWhiteSpace to look for multiple whitespace characters in a string." - ], - "challengeSeed": [ - "let sample = \"Whitespace is important in separating words\";", - "let countWhiteSpace = /change/; // Change this line", - "let result = sample.match(countWhiteSpace);" - ], - "tests": [ - "assert(countWhiteSpace.global, 'message: Your regex should use the global flag.');", - "assert(\"Men are from Mars and women are from Venus.\".match(countWhiteSpace).length == 8, 'message: Your regex should find eight spaces in \"Men are from Mars and women are from Venus.\"');", - "assert(\"Space: the final frontier.\".match(countWhiteSpace).length == 3, 'message: Your regex should find three spaces in \"Space: the final frontier.\"');", - "assert(\"MindYourPersonalSpace\".match(countWhiteSpace) == null, 'message: Your regex should find no spaces in \"MindYourPersonalSpace\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db9367417b2b2512ba4", - "title": "Match Non-Whitespace Characters", - "description": [ - "You learned about searching for whitespace using \\s, with a lowercase s. You can also search for everything except whitespace.", - "Search for non-whitespace using \\S, which is an uppercase s. This pattern will not match whitespace, carriage return, tab, form feed, and new line characters. You can think of it being similar to the character class [^ \\r\\t\\f\\n\\v].", - "
    let whiteSpace = \"Whitespace. Whitespace everywhere!\"
    let nonSpaceRegex = /\\S/g;
    whiteSpace.match(nonSpaceRegex).length; // Returns 32
    ", - "
    ", - "Change the regex countNonWhiteSpace to look for multiple non-whitespace characters in a string." - ], - "challengeSeed": [ - "let sample = \"Whitespace is important in separating words\";", - "let countNonWhiteSpace = /change/; // Change this line", - "let result = sample.match(countNonWhiteSpace);" - ], - "tests": [ - "assert(countNonWhiteSpace.global, 'message: Your regex should use the global flag.');", - "assert(\"Men are from Mars and women are from Venus.\".match(countNonWhiteSpace).length == 35, 'message: Your regex should find 35 non-spaces in \"Men are from Mars and women are from Venus.\"');", - "assert(\"Space: the final frontier.\".match(countNonWhiteSpace).length == 23, 'message: Your regex should find 23 non-spaces in \"Space: the final frontier.\"');", - "assert(\"MindYourPersonalSpace\".match(countNonWhiteSpace).length == 21, 'message: Your regex should find 21 non-spaces in \"MindYourPersonalSpace\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db9367417b2b2512ba5", - "title": "Specify Upper and Lower Number of Matches", - "description": [ - "Recall that you use the plus sign + to look for one or more characters and the asterisk * to look for zero or more characters. These are convenient but sometimes you want to match a certain range of patterns.", - "You can specify the lower and upper number of patterns with quantity specifiers. Quantity specifiers are used with curly brackets ({ and }). You put two numbers between the curly brackets - for the lower and upper number of patterns.", - "For example, to match only the letter a appearing between 3 and 5 times in the string \"ah\", your regex would be /a{3,5}h/.", - "
    let A4 = \"aaaah\";
    let A2 = \"aah\";
    let multipleA = /a{3,5}h/;
    multipleA.test(A4); // Returns true
    multipleA.test(A2); // Returns false
    ", - "
    ", - "Change the regex ohRegex to match only 3 to 6 letter h's in the word \"Oh no\"." - ], - "challengeSeed": [ - "let ohStr = \"Ohhh no\";", - "let ohRegex = /change/; // Change this line", - "let result = ohRegex.test(ohStr);" - ], - "tests": [ - "assert(ohRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');", - "assert(!ohRegex.test(\"Ohh no\"), 'message: Your regex should not match \"Ohh no\"');", - "assert(ohRegex.test(\"Ohhh no\"), 'message: Your regex should match \"Ohhh no\"');", - "assert(ohRegex.test(\"Ohhhh no\"), 'message: Your regex should match \"Ohhhh no\"');", - "assert(ohRegex.test(\"Ohhhhh no\"), 'message: Your regex should match \"Ohhhhh no\"');", - "assert(ohRegex.test(\"Ohhhhhh no\"), 'message: Your regex should match \"Ohhhhhh no\"');", - "assert(!ohRegex.test(\"Ohhhhhhh no\"), 'message: Your regex should not match \"Ohhhhhhh no\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db9367417b2b2512ba6", - "title": "Specify Only the Lower Number of Matches", - "description": [ - "You can specify the lower and upper number of patterns with quantity specifiers using curly brackets. Sometimes you only want to specify the lower number of patterns with no upper limit.", - "To only specify the lower number of patterns, keep the first number followed by a comma.", - "For example, to match only the string \"hah\" with the letter a appearing at least 3 times, your regex would be /ha{3,}h/.", - "
    let A4 = \"haaaah\";
    let A2 = \"haah\";
    let A100 = \"h\" + \"a\".repeat(100) + \"h\";
    let multipleA = /ha{3,}h/;
    multipleA.test(A4); // Returns true
    multipleA.test(A2); // Returns false
    multipleA.test(A100); // Returns true
    ", - "
    ", - "Change the regex haRegex to match the word \"Hazzah\" only when it has four or more letter z's." - ], - "challengeSeed": [ - "let haStr = \"Hazzzzah\";", - "let haRegex = /change/; // Change this line", - "let result = haRegex.test(haStr);" - ], - "tests": [ - "assert(haRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');", - "assert(!haRegex.test(\"Hazzah\"), 'message: Your regex should not match \"Hazzah\"');", - "assert(!haRegex.test(\"Hazzzah\"), 'message: Your regex should not match \"Hazzzah\"');", - "assert(haRegex.test(\"Hazzzzah\"), 'message: Your regex should match \"Hazzzzah\"');", - "assert(haRegex.test(\"Hazzzzzah\"), 'message: Your regex should match \"Hazzzzzah\"');", - "assert(haRegex.test(\"Hazzzzzzah\"), 'message: Your regex should match \"Hazzzzzzah\"');", - "assert(haRegex.test(\"Ha\" + \"z\".repeat(30) + \"ah\"), 'message: Your regex should match \"Hazzah\" with 30 z\\'s in it.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7db9367417b2b2512ba7", - "title": "Specify Exact Number of Matches", - "description": [ - "You can specify the lower and upper number of patterns with quantity specifiers using curly brackets. Sometimes you only want a specific number of matches.", - "To specify a certain number of patterns, just have that one number between the curly brackets.", - "For example, to match only the word \"hah\" with the letter a 3 times, your regex would be /ha{3}h/.", - "
    let A4 = \"haaaah\";
    let A3 = \"haaah\";
    let A100 = \"h\" + \"a\".repeat(100) + \"h\";
    let multipleHA = /a{3}h/;
    multipleHA.test(A4); // Returns false
    multipleHA.test(A3); // Returns true
    multipleHA.test(A100); // Returns false
    ", - "
    ", - "Change the regex timRegex to match the word \"Timber\" only when it has four letter m's." - ], - "challengeSeed": [ - "let timStr = \"Timmmmber\";", - "let timRegex = /change/; // Change this line", - "let result = timRegex.test(timStr);" - ], - "tests": [ - "assert(timRegex.source.match(/{.*?}/).length > 0, 'message: Your regex should use curly brackets.');", - "assert(!timRegex.test(\"Timber\"), 'message: Your regex should not match \"Timber\"');", - "assert(!timRegex.test(\"Timmber\"), 'message: Your regex should not match \"Timmber\"');", - "assert(!timRegex.test(\"Timmmber\"), 'message: Your regex should not match \"Timmmber\"');", - "assert(timRegex.test(\"Timmmmber\"), 'message: Your regex should match \"Timmmmber\"');", - "assert(!timRegex.test(\"Ti\" + \"m\".repeat(30) + \"ber\"), 'message: Your regex should not match \"Timber\" with 30 m\\'s in it.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dba367417b2b2512ba8", - "title": "Check for All or None", - "description": [ - "Sometimes the patterns you want to search for may have parts of it that may or may not exist. However, it may be important to check for them nonetheless.", - "You can specify the possible existence of an element with a question mark, ?. This checks for zero or one of the preceding element. You can think of this symbol as saying the previous element is optional.", - "For example, there are slight differences in American and British English and you can use the question mark to match both spellings.", - "
    let american = \"color\";
    let british = \"colour\";
    let rainbowRegex= /colou?r/;
    rainbowRegex.test(american); // Returns true
    rainbowRegex.test(british); // Returns true
    ", - "
    ", - "Change the regex favRegex to match both the American English (favorite) and the British English (favourite) version of the word." - ], - "challengeSeed": [ - "let favWord = \"favorite\";", - "let favRegex = /change/; // Change this line", - "let result = favRegex.test(favWord);" - ], - "tests": [ - "assert(favRegex.source.match(/\\?/).length > 0, 'message: Your regex should use the optional symbol, ?.');", - "assert(favRegex.test(\"favorite\"), 'message: Your regex should match \"favorite\"');", - "assert(favRegex.test(\"favourite\"), 'message: Your regex should match \"favourite\"');", - "assert(!favRegex.test(\"fav\"), 'message: Your regex should not match \"fav\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dba367417b2b2512ba9", - "title": "Positive and Negative Lookahead", - "description": [ - "Lookaheads are patterns that tell JavaScript to look-ahead in your string to check for patterns further along. This can be useful when you want to search for multiple patterns over the same string.", - "There are two kinds of lookaheads: positive lookahead and negative lookahead.", - "A positive lookahead will look to make sure the element in the search pattern is there, but won't actually match it. A positive lookahead is used as (?=...) where the ... is the required part that is not matched.", - "On the other hand, a negative lookahead will look to make sure the element in the search pattern is not there. A negative lookahead is used as (?!...) where the ... is the pattern that you do not want to be there. The rest of the pattern is returned if the negative lookahead part is not present.", - "Lookaheads are a bit confusing but some examples will help.", - "
    let quit = \"qu\";
    let noquit = \"qt\";
    let quRegex= /q(?=u)/;
    let qRegex = /q(?!u)/;
    quit.match(quRegex); // Returns [\"q\"]
    noquit.match(qRegex); // Returns [\"q\"]
    ", - "A more practical use of lookaheads is to check two or more patterns in one string. Here is a (naively) simple password checker that looks for between 3 and 6 characters and at least one number:", - "
    let password = \"abc123\";
    let checkPass = /(?=\\w{3,6})(?=\\D*\\d)/;
    checkPass.test(password); // Returns true
    ", - "
    ", - "Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long and have two consecutive digits." - ], - "challengeSeed": [ - "let sampleWord = \"astronaut\";", - "let pwRegex = /change/; // Change this line", - "let result = pwRegex.test(sampleWord);" - ], - "tests": [ - "assert(pwRegex.source.match(/\\(\\?=.*?\\)\\(\\?=.*?\\)/) !== null, 'message: Your regex should use two positive lookaheads.');", - "assert(!pwRegex.test(\"astronaut\"), 'message: Your regex should not match \"astronaut\"');", - "assert(!pwRegex.test(\"airplanes\"), 'message: Your regex should not match \"airplanes\"');", - "assert(pwRegex.test(\"bana12\"), 'message: Your regex should match \"bana12\"');", - "assert(pwRegex.test(\"abc123\"), 'message: Your regex should match \"abc123\"');", - "assert(!pwRegex.test(\"123\"), 'message: Your regex should not match \"123\"');", - "assert(!pwRegex.test(\"1234\"), 'message: Your regex should not match \"1234\"');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dbb367417b2b2512baa", - "title": "Reuse Patterns Using Capture Groups", - "description": [ - "Some patterns you search for will occur multiple times in a string. It is wasteful to manually repeat that regex. There is a better way to specify when you have multiple repeat substrings in your string.", - "You can search for repeat substrings using capture groups. Parentheses, ( and ), are used to find repeat substrings. You put the regex of the pattern that will repeat in between the parentheses.", - "To specify where that repeat string will appear, you use a backslash (\\) and then a number. This number starts at 1 and increases with each additional capture group you use. An example would be \\1 to match the first group.", - "The example below matches any word that occurs twice separated by a space:", - "
    let repeatStr = \"regex regex\";
    let repeatRegex = /(\\w+)\\s\\1/;
    repeatRegex.test(repeatStr); // Returns true
    repeatStr.match(repeatRegex); // Returns [\"regex regex\", \"regex\"]
    ", - "Using the .match() method on a string will return an array with the string it matches, along with its capture group.", - "
    ", - "Use capture groups in reRegex to match numbers that are repeated only three times in a string, each separated by a space." - ], - "challengeSeed": [ - "let repeatNum = \"42 42 42\";", - "let reRegex = /change/; // Change this line", - "let result = reRegex.test(repeatNum);" - ], - "tests": [ - "assert(reRegex.source.match(/\\\\d/), 'message: Your regex should use the shorthand character class for digits.');", - "assert(reRegex.source.match(/\\\\\\d/g).length === 2, 'message: Your regex should reuse the capture group twice.');", - "assert(reRegex.source.match(/\\\\s/g).length === 2, 'message: Your regex should have two spaces separating the three numbers.');", - "assert(reRegex.test(\"42 42 42\"), 'message: Your regex should match \"42 42 42\".');", - "assert(reRegex.test(\"100 100 100\"), 'message: Your regex should match \"100 100 100\".');", - "assert.equal((\"42 42 42 42\").match(reRegex.source), null, 'message: Your regex should not match \"42 42 42 42\".');", - "assert.equal((\"42 42\").match(reRegex.source), null, 'message: Your regex should not match \"42 42\".');", - "assert(!reRegex.test(\"101 102 103\"), 'message: Your regex should not match \"101 102 103\".');", - "assert(!reRegex.test(\"1 2 3\"), 'message: Your regex should not match \"1 2 3\".');", - "assert(reRegex.test(\"10 10 10\"), 'message: Your regex should match \"10 10 10\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dbb367417b2b2512bab", - "title": "Use Capture Groups to Search and Replace", - "description": [ - "Searching is useful. However, you can make searching even more powerful when it also changes (or replaces) the text you match.", - "You can search and replace text in a string using .replace() on a string. The inputs for .replace() is first the regex pattern you want to search for. The second parameter is the string to replace the match or a function to do something.", - "
    let wrongText = \"The sky is silver.\";
    let silverRegex = /silver/;
    wrongText.replace(silverRegex, \"blue\");
    // Returns \"The sky is blue.\"
    ", - "You can also access capture groups in the replacement string with dollar signs ($).", - "
    \"Code Camp\".replace(/(\\w+)\\s(\\w+)/, '$2 $1');
    // Returns \"Camp Code\"
    ", - "
    ", - "Write a regex so that it will search for the string \"good\". Then update the replaceText variable to replace \"good\" with \"okey-dokey\"." - ], - "challengeSeed": [ - "let huhText = \"This sandwich is good.\";", - "let fixRegex = /change/; // Change this line", - "let replaceText = \"\"; // Change this line", - "let result = huhText.replace(fixRegex, replaceText);" - ], - "tests": [ - "assert(code.match(/\\.replace\\(.*\\)/), 'message: You should use .replace() to search and replace.');", - "assert(result == \"This sandwich is okey-dokey.\" && replaceText === \"okey-dokey\", 'message: Your regex should change \"This sandwich is good.\" to \"This sandwich is okey-dokey.\"');", - "assert(code.match(/result\\s*=\\s*huhText\\.replace\\(.*?\\)/), 'message: You should not change the last line.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - }, - { - "id": "587d7dbb367417b2b2512bac", - "title": "Remove Whitespace from Start and End", - "description": [ - "Sometimes whitespace characters around strings are not wanted but are there. Typical processing of strings is to remove the whitespace at the start and end of it.", - "
    ", - "Write a regex and use the appropriate string methods to remove whitespace at the beginning and end of strings.", - "Note
    The .trim() method would work here, but you'll need to complete this challenge using regular expressions." - ], - "challengeSeed": [ - "let hello = \" Hello, World! \";", - "let wsRegex = /change/; // Change this line", - "let result = hello; // Change this line" - ], - "tests": [ - "assert(result == \"Hello, World!\", 'message: result should equal to \"Hello, World!\"');", - "assert(!code.match(/\\.trim\\(.*?\\)/), 'message: You should not use the .trim() method.');", - "assert(!code.match(/result\\s*=\\s*\".*?\"/), 'message: The result variable should not be set equal to a string.');" - ], - "solutions": [], - "hints": [ - "You can use .replace() to remove the matched items by replacing them with an empty string." - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 1, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json b/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json deleted file mode 100644 index 4127daaeee..0000000000 --- a/packages/learn/seed/tmp/03-front-end-libraries/bootstrap.json +++ /dev/null @@ -1,2542 +0,0 @@ -{ - "name": "Bootstrap", - "order": 2, - "time": "5 hours", - "helpRoom": "Help", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" - } - ], - "challenges": [ - { - "id": "bad87fee1348bd9acdeb9212", - "title": "Introduction to the Bootstrap Challenges", - "description": [ - "", - "", - "Bootstrap is a front-end framework used to design responsive web pages and web applications. It takes a mobile-first approach to web development. Bootstrap includes pre-built CSS styles and classes, plus some JavaScript functionality.", - "", - "@@STEP@@", - "", - "", - "Bootstrap uses a responsive 12 column grid layout and has design templates for:

    • buttons
    • images
    • tables
    • forms
    • navigation

    This section introduces some of the ways to use Bootstrap in your web projects.", - "", - "@@STEP@@" - ], - "releasedOn": "", - "challengeSeed": [], - "tests": [], - "type": "Waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "bad87fee1348bd9acde08712", - "title": "Use Responsive Design with Bootstrap Fluid Containers", - "description": [ - "In the HTML5 and CSS section of freeCodeCamp we built a Cat Photo App. Now let's go back to it. This time, we'll style it using the popular Bootstrap responsive CSS framework.", - "Bootstrap will figure out how wide your screen is and respond by resizing your HTML elements - hence the name 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.", - "You can add Bootstrap to any app by adding the following code to the top of your HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"/>", - "In this case, we've already added it for you to this page behind the scenes. Note that using either > or /> to close the link tag is acceptable.", - "To get started, we should nest all of our HTML (except the link tag and the style element) in a div element with the class container-fluid." - ], - "challengeSeed": [ - "", - "", - "", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - "\"A", - "", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    " - ], - "tests": [ - "assert($(\"div\").hasClass(\"container-fluid\"), 'message: Your div element should have the class container-fluid.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div element has a closing tag.');", - "assert($(\".container-fluid\").children().length >= 8, 'message: Make sure you have nested all HTML elements after the closing style tag in .container-fluid.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Usa diseño adaptativo con los contenedores fluidos de Bootstrap", - "description": [ - "Ahora vamos de vuelta a nuestra aplicación de fotos de gatos. Esta vez, vamos a darle estilo utilizando la infraestructura CSS del popular Bootstrap.", - "Bootstrap determina qué tan ancha es la pantalla y adapta correspondientemente el tamaño de tus elementos HTML - por eso es que se llama Diseño adaptativo (responsive design).", - "Con diseño adaptativo, no hay necesidad de diseñar una versión móvil para tu sitio web. Se verá bien en dispositivos con pantallas de cualquier tamaño.", - "Puedes agregar Bootstrap a cualquier aplicación simplemente incluyendo el siguiente código al inicio de tu HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\"/>", - "En este caso, lo hemos agregado a esta página por ti.", - "Para iniciar, debemos anidar todo nuestro HTML en un elemento div con la clase container-fluid." - ] - }, - "fr": { - "title": "Un design adaptatif (responsive design) utilisant les conteneurs fluides de Bootstrap", - "description": [ - "Revenons à notre application de photos de chats. Cette fois-ci, nous allons lui donner un style grâce au renommé framework CSS Bootstrap.", - "Bootstrap saura reconnaître la largeur de notre écran et s'y adapter en redimensionnant les éléments HTML - d'où le nom Responsive Design (design adaptatif).", - "Avec le design responsive, il n'y a pas besoin de créer de version mobile de votre site. Il restera bien sur tous les appareils quelle que soit la taille de leurs écrans.", - "Vous pouvez ajouter Bootstrap à n'importe quelle application simplement en incluant le code suivant en haut de votre HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css\" integrity=\"sha384-8+rznmq/k0KZkJlZhnuPEVkbRD7tA0wcFEjY48dajGWn3Xc1MasJwS8/tJ7OEsKW\" crossorigin=\"anonymous\">/>", - "Ici, nous l'avons déjà ajouté à la page pour vous dans l'arrière-boutique.", - "Pour commencer, nous devons envelopper nos éléments HTML dans un élément div possédant la classe container-fluid" - ] - } - } - }, - { - "id": "bad87fee1348bd9acde08812", - "title": "Make Images Mobile Responsive", - "description": [ - "First, add a new image below the existing one. Set its src attribute to https://bit.ly/fcc-running-cats.", - "It would be great if this image could be exactly the width of our phone's screen.", - "Fortunately, with Bootstrap, all we need to do is add the img-responsive class to your image. Do this, and the image should perfectly fit the width of your page." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - " \"A", - "", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"img\").length === 2, 'message: You should have a total of two images.');", - "assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'message: Your new image should be below your old one and have the class img-responsive.');", - "assert(!$(\"img:eq(1)\").hasClass(\"smaller-image\"), 'message: Your new image should not have the class smaller-image.');", - "assert($(\"img:eq(1)\").attr(\"src\") === \"https://bit.ly/fcc-running-cats\", 'message: Your new image should have a src of https://bit.ly/fcc-running-cats.');", - "assert(code.match(//g).length === 2 && code.match(/img
    element has a closing angle bracket.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Haz que las imágenes sean adaptativas en dispositivos móviles", - "description": [ - "Primero, agrega una nueva imagen debajo que la que ya existe. Haz que su atributo src sea https://bit.ly/fcc-running-cats.", - "Sería genial si esta imagen fuera exactamente del tamaño de la pantalla de nuestro teléfono.", - "Afortunadamente, con Bootstrap, todo lo que tenemos que hacer es agregar la clase img-responsive a tu imagen. Hazlo, y verás que la imagen se ajustará perfectamente al ancho de tu página." - ] - }, - "fr": { - "title": "Rendre des images adaptatives aux appareils mobiles", - "description": [ - "It would be great if this image could be exactly the width of our phone's screen.", - "Fortunately, with Bootstrap, all we need to do is add the img-responsive class to your image. Do this, and the image should perfectly fit the width of your page.", - "D'abord, ajoutez une nouvelle image en dessous de celle qui eiste dejà. Changez l'attribut src en https://bit.ly/fcc-running-cats.", - "Ce serait absolument super si notre image pouvait être exactement de la largeur de l'écran du téléphone.", - "Heureusement, avec Bootstrap, il faut seulement ajouter la classe img-responsive à notre image. Faites le, et l'image devrait s'ajuster parfaitement à la largeur de la page." - ] - } - } - }, - { - "id": "bad87fee1348bd8acde08812", - "title": "Center Text with Bootstrap", - "description": [ - "Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class text-center to our h2 element.", - "Remember that you can add several classes to the same element by separating each of them with a space, like this:", - "<h2 class=\"red-text text-center\">your text</h2>" - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - " \"A", - "", - " \"Three", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"h2\").hasClass(\"text-center\"), 'message: Your h2 element should be centered by applying the class text-center');", - "assert($(\"h2\").hasClass(\"red-text\"), 'message: Your h2 element should still have the class red-text');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Centra el texto con Bootstrap", - "description": [ - "Ahora que estamos usando Bootstrap, podemos centrar nuestro elemento de encabezado para hacerlo verse mejor. Todo lo que necesitamos hacer es agregar la clase text-center a nuestro elemento h2.", - "Recuerda que puedes agregar varias clases a un mismo elemento separando cada una de ellas con un espacio, de esta forma:", - "<h2 class=\"red-text text-center\">your text</h2>" - ] - }, - "fr": { - "title": "Centrer du texte avec Bootstrap", - "description": [ - "Maintenant que wous utilisons Bootstrap, nous pouvons centrer notre entête pour qu'il ait une meilleure apparence. Nous devons seulement ajouter la classe text-center à notre élément h2.", - "Souvenez vous que vous pouvez utiliser plusieurs classes pour un même élément en les séparant avec un espace, comme ceci:", - "<h2 class=\"red-text text-center\">Votre texte</h2>" - ] - } - } - }, - { - "id": "bad87fee1348cd8acdf08812", - "title": "Create a Bootstrap Button", - "description": [ - "Bootstrap has its own styles for button elements, which look much better than the plain HTML ones.", - "Create a new button element below your large kitten photo. Give it the class btn and the text of \"Like\"." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - " \"A", - "", - " \"Three", - "", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert(new RegExp(\"like\",\"gi\").test($(\"button\").text()), 'message: Create a new button element with the text \"Like\".');", - "assert($(\"button\").hasClass(\"btn\"), 'message: Your new button should have the class btn.');", - "assert(code.match(/<\\/button>/g) && code.match(/
    ", - "By making them block elements with the additional class of btn-block, your button will stretch to fill your page's entire horizontal space and any elements following it will flow onto a \"new line\" below the block.", - "<button class=\"btn btn-block\">Submit</button>", - "This button would take up 100% of the available width.", - "", - "Note that these buttons still need the btn class.", - "Add Bootstrap's btn-block class to your Bootstrap button." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - " \"A", - "", - " \"Three", - " ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"button\").hasClass(\"btn\"), 'message: Your button should still have the class btn.');", - "assert($(\"button\").hasClass(\"btn-block\"), 'message: Your button should have the class btn-block.');", - "assert(code.match(/<\\/button>/g) && code.match(/", - "Haciéndolos bloquean elementos con la clase adicional de btn-block, el botón se amplía para llenar toda espacio horizontal de la página y los elementos siguientes fluirá sobre una \"nueva línea\" debajo del bloque .", - "<button class=\"btn btn-block\">Enviar</button>", - "Este botón llevaría hasta el 100% de la anchura disponible.", - "", - "Ten en cuenta que estos botones todavía necesitan la clase btn.", - "Agrega la clase de Bootstrap btn-block a tu botón Bootstrap." - ] - }, - "fr": { - "title": "Créer un bouton bloc Bootstrap", - "description": [ - "Normalement , vos éléments de button avec une classe de btn ne sont aussi larges que le texte qu'ils contiennent . Par exemple:", - "<button class=\"btn\">Soumettre</button>", - "Ce bouton ne serait plus large que le mot \"Soumettre\" .", - "", - "En leur faisant bloquer les éléments avec la classe supplémentaire de btn-block, votre bouton étirer pour remplir tout l'espace horizontal de votre page et tous les éléments suivants, il coulera sur une \"nouvelle ligne\" en dessous du bloc .", - "<button class=\"btn btn-block\">Soumettre</button>", - "Ce bouton prendrait 100% de la largeur disponible .", - "", - "Notez que ces boutons ont toujours besoin de la classe btn", - "Ajoutez la classe Bootstrap btn-block à votre bouton Bootstrap." - ] - } - } - }, - { - "id": "bad87fee1348cd8acef08811", - "title": "Taste the Bootstrap Button Color Rainbow", - "description": [ - "The btn-primary class is the main color you'll use in your app. It is useful for highlighting actions you want your user to take.", - "Add Bootstrap's btn-primary class to your button.", - "Note that this button will still need the btn and btn-block classes." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - "

    Click here for cat photos.

    ", - "", - " \"A", - "", - " \"Three", - " ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"button\").hasClass(\"btn-primary\"), 'message: Your button should have the class btn-primary.');", - "assert($(\"button\").hasClass(\"btn-block\") && $(\"button\").hasClass(\"btn\"), 'message: Your button should still have the btn and btn-block classes.');", - "assert(code.match(/<\\/button>/g) && code.match(/", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert(new RegExp(\"info\",\"gi\").test($(\"button\").text()), 'message: Create a new button element with the text \"Info\".');", - "assert($(\"button.btn-block.btn\").length > 1, 'message: Both of your Bootstrap buttons should have the btn and btn-block classes.');", - "assert($(\"button\").hasClass(\"btn-info\"), 'message: Your new button should have the class btn-info.');", - "assert(code.match(/<\\/button>/g) && code.match(/", - " ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert(new RegExp(\"Delete\",\"gi\").test($(\"button\").text()), 'message: Create a new button element with the text \"Delete\".');", - "assert($(\"button.btn-block.btn\").length > 2, 'message: All of your Bootstrap buttons should have the btn and btn-block classes.');", - "assert($(\"button\").hasClass(\"btn-danger\"), 'message: Your new button should have the class btn-danger.');", - "assert(code.match(/<\\/button>/g) && code.match(/", - " ", - " ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "" - ], - "tests": [ - "assert($(\"div.row:has(button)\").length > 0, 'message: Your buttons should all be nested within the same div element with the class row.');", - "assert($(\"div.col-xs-4:has(button)\").length > 2, 'message: Each of your Bootstrap buttons should be nested within its own div element with the class col-xs-4.');", - "assert(code.match(/<\\/button>/g) && code.match(/
    ", - " ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - " ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "" - ], - "tests": [ - "assert(!$(\"h2\").hasClass(\"red-text\"), 'message: Your h2 element should no longer have the class red-text.');", - "assert($(\"h2\").hasClass(\"text-primary\"), 'message: Your h2 element should now have the class text-primary.');", - "assert(!$(\"p\").css(\"font-family\").match(/monospace/i), 'message: Your paragraph elements should no longer use the font Monospace.');", - "assert(!$(\"img\").hasClass(\"smaller-image\"), 'message: Remove the smaller-image class from your top image.');", - "assert($(\".img-responsive\").length > 1, 'message: Add the img-responsive class to your top image.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Reemplaza el CSS personalizado por Bootstrap", - "description": [ - "Podemos limpiar nuestro código y hacer que nuestra aplicación de fotos de gatos se vea más convencional, usando los estilos pre-construidos de Bootstrap, en lugar de los estilos personalizados que creamos antes.", - "No te preocupes, luego habrá más tiempo para personalizar nuestro CSS.", - "Elimina las declaraciones CSS .red-text, p, y .smaller-image de tu elemento style, de forma que las únicas declaraciones que queden en tu elemento style sean h2 y thick-green-border.", - "Luego elimina el elemento p que contiene un enlace nulo. Después, elimina la clase red-text de tu elemento h2 y reemplázalo con la clase text-primary de Bootstrap.", - "Por último, elimina la clase \"smaller-image\" de tu primer elemento img y reemplázalo con la clase img-responsive." - ] - }, - "fr": { - "title": "Remplacez le CSS personnalisé par les styles Bootstrap", - "description": [ - "Nous pouvons nettoyer notre code et rendre le look de notre appli Cat Photos plus conventionnel en utilisant les styles intégrés à Bootstrap à la place des styles personnalisés que nous avons créés auparavant.", - "Ne vous inquiétez pas - nous auront beaucoup de temps pour personnaliser notre CSS plus tard.", - "Supprimez les déclarations CSS .red-text, p, et .smaller-image de votre élément style pour que les seules déclarations restantes dans l'élément style soient h2 et thick-green-border.", - "Ensuite supprimez l'élément p contenant un lien fantôme. Puis enlevez la classe red-text de votre élément h2 et remplacez la par la classe Bootstrap text-primary", - "Enfin, enlevez la classe \"smaller-image\" dde votre premier élément img et remplacez le par la classe img-responsive." - ] - } - } - }, - { - "id": "bad87fee1348bd9aedf08845", - "title": "Use a span to Target Inline Elements", - "description": [ - "You can use spans to create inline elements. Remember when we used the btn-block class to make the button fill the entire row?", - "", - "", - "That illustrates the difference between an \"inline\" element and a \"block\" element.", - "By using the inline span element, you can put several elements on the same line, and even style different parts of the same line differently.", - "Nest the word \"love\" in your \"Things cats love\" element below within a span element. Then give that span the class text-danger to make the text red.", - "Here's how you would do this with the \"Top 3 things cats hate\" element:", - "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>" - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - " \"A", - "", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"p span\") && $(\"p span\").length > 0, 'message: Your span element should be inside your p element.');", - "assert($(\"p span\") && $(\"p span\").text().match(/love/i) && !$(\"p span\").text().match(/Things cats/i), 'message: Your span element should have just the text love.');", - "assert($(\"span\").hasClass(\"text-danger\"), 'message: Your span element should have class text-danger.');", - "assert(code.match(/<\\/span>/g) && code.match(//g).length === code.match(/span element has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Usa span para elementos en línea", - "description": [ - "Puedes utilizar span para crear elementos en línea. ¿Recuerdas cuando usamos la clase btn-block para hacer que el botón llenara toda la línea?", - "Esta imagen ilustra la diferencia entre elementos en línea (inline) y elementos a nivel de bloque (block-level):", - "\"Un", - "Al usar el elemento span, puedes poner varios elementos juntos, e incluso darle diferentes estilos a partes diferentes del mismo elemento.", - "Anida la palabra \"love\" en tu elemento \"Things cats love\" dentro de un elemento span. Luego, asigna a ese elemento span la clase text-danger para hacer que el texto sea rojo.", - "Así es como lo harías con el elemento \"Top 3 things cats hate\":", - "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>" - ] - }, - "fr": { - "title": "Utiliser Spans pour les éléments \"Inline\"", - "description": [ - "Vous pouvez utiliser les spans pour créer des éléments inline. Vous rappelez vous quand nous avions utilisé la classe btn-block pour remplir la rangée entière?", - "Cette image illustre la différence entre les éléments inline (en ligne) et les éléments block-level (de blocs):", - "\"Un", - "En utilisant un élément span, vous pouvez mettre ensemble plusieurs éléments, et même donner un style différent à plusieurs parties d'un même élément", - "Nichez le mot \"love\" dans votre élément \"Things cats love\" en dessous dans un élément span; Ensuite donnez à ce span la classe text-danger pour rendre le texte rouge.", - "Il faudrait que vous fassiez ainsi pour l'élément \"Top 3 things cats hate\":", - "<p>Top 3 things cats <span class=\"text-danger\">hate:</span></p>" - ] - } - } - }, - { - "id": "bad87fee1348bd9aede08845", - "title": "Create a Custom Heading", - "description": [ - "We will make a simple heading for our Cat Photo App by putting the title and relaxing cat image 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.", - "Take for example Bootstrap's col-md-* class. Here, md means medium, and * is a number specifying how many columns wide the element should be. In this case, the column width of an element on a medium-sized screen, such as a laptop, is being specified.", - "In the Cat Photo App that we're building, we'll use col-xs-*, where xs means extra small (like an extra-small mobile phone screen), and * is the number of columns specifying how many columns wide the element should be.", - "Put the Like, Info and Delete buttons side-by-side by nesting all three of them within one <div class=\"row\"> element, then each of them within a <div class=\"col-xs-4\"> element.", - "In the Cat Photo App that we're building, we'll use col-xs-*, where xs means extra small (like an extra-small mobile phone screen), and * is the number of columns specifying how many columns wide the element should be.", - "Nest your first image and your h2 element within a single <div class=\"row\"> element. Nest your h2 element 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.", - "Notice how the image is now just the right size to fit along the text?" - ], - "challengeSeed": [ - "", - "", - "", - "", - "
    ", - "

    CatPhotoApp

    ", - "", - " \"A", - "", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.row:has(h2)\").length > 0 && $(\"div.row:has(img)\").length > 0, 'message: Your h2 element and topmost img element should both be nested together within a div element with the class row.');", - "assert($(\"div.col-xs-4:has(img)\").length > 0 && $(\"div.col-xs-4:has(div)\").length === 0, 'message: Nest your topmost img element within a div with the class col-xs-4.');", - "assert($(\"div.col-xs-8:has(h2)\").length > 0 && $(\"div.col-xs-8:has(div)\").length === 0, 'message: Nest your h2 element within a div with the class col-xs-8.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea un encabezado personalizado", - "description": [ - "Crearemos un encabezado simple para nuestra aplicación de fotos de gatos poniendo el título y la relajante imagen del gato en la misma línea.", - "Recuerda, Bootstrap usa un sistema de cuadrícula adaptativo, el cual facilita poner elementos en filas y especificar el ancho relativo de cada elemento. La mayoría de las clases de Bootstrap pueden aplicarse a un elemento div.", - "Aquí hay un diagrama del funcionamiento de la cuadrícula de 12 columnas Bootstrap:", - "\"una", - "En esta ilustración se está utilizando la clase col-md-*. Aquí, md significa mediano, y * es un número que especifica el número de columnas que debe tomar el ancho del elemento. En este caso, se especifica el ancho de columna de un elemento en una pantalla de tamaño mediano, como un computador portátil.", - "En la aplicación de fotos de gatos que estamos construyendo, usaremos col-xs-*, donde xs significa extra pequeño (como una pantalla extra-pequeña de un teléfono), y * especifica el número de columnas que debe tomar el ancho del elemento.", - "Anida tu primera imagen y tu elemento h2 dentro de un solo elemento <div class=\"row\">. Anida tu texto h2 dentro de un <div class=\"col-xs-8\"> y tu imagen en un <div class=\"col-xs-4\"> de tal forma que estén en la misma línea.", - "¿Te diste cuenta de que la imagen es ahora justamente del tamaño apropiado para el texto?" - ] - }, - "fr": { - "title": "Créer un entête personalisé", - "description": [ - "Notice how the image is now just the right size to fit along the text?", - "Nous allons réaliser un entête tout simple pour notre appli Cat Photo App en plaçant le titre et l'image de chat relaxante dans la même rangée.", - "Rappelez-vous, Bootstrap utilise un système de grille adaptative, qui rend facile le placement des éléments en rangées et la définition de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être appliquées à un élément div.", - "Voici un diagramme du fonctionnement de la grille à 12 colonnes de Bootstrap:", - "\"Une", - "Notez que dans cet exemple, on utilise la classe col-md-*. Ici md signifie medium, et * est un nombre spécifiant le nombre de colonnes en largeur que l'élément devrait avoir.", - "Enveloppez votre première image et votre élément h2 dans un seul élément <div class=\"row\">. Mettez l'élément h2 dans un <div class=\"col-xs-8\"> et votre image dans un <div class=\"col-xs-4\"> pour qu'ils soient sur la même ligne.", - "Voyez vous comme l'image est maintenant exactement ajustée à la bonne taille pour être à côté du texte?" - ] - } - } - }, - { - "id": "bad87fee1348bd9aedd08845", - "title": "Add Font Awesome Icons to our Buttons", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "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.", - "You can include Font Awesome in any app by adding the following code to the top of your HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\">", - "In this case, we've already added it for you to this page behind the scenes.", - "The i element was originally used to make other elements italic, but is now commonly used for icons. You can add the Font Awesome classes to the i element to turn it into an icon, for example:", - "<i class=\"fa fa-info-circle\"></i>", - "Note that the span element is also acceptable for use with icons.", - "Use Font Awesome to add a thumbs-up icon to your like button by giving it an i element with the classes fa and fa-thumbs-up; make sure to keep the text \"Like\" next to the icon." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"i\").is(\".fa.fa-thumbs-up\") || $(\"span\").is(\".fa.fa-thumbs-up\"), 'message: Add an i element with the classes fa and fa-thumbs-up.');", - "assert(($(\"i.fa-thumbs-up\").parent().text().match(/Like/gi) && $(\".btn-primary > i\").is(\".fa.fa-thumbs-up\")) || ($(\"span.fa-thumbs-up\").parent().text().match(/Like/gi) && $(\".btn-primary > span\").is(\".fa.fa-thumbs-up\")), 'message: Your fa-thumbs-up icon should be located within the Like button.');", - "assert($(\"button\").children(\"i\").length > 0 || $(\"button\").children(\"span\").length > 0, 'message: Nest your i element within your button element.');", - "assert(code.match(/<\\/i>|<\\/span>/g), 'message: Make sure your icon element has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Agrega iconos de Font Awesome a los botones", - "description": [ - "Font Awesome es una librería de iconos muy conveniente. Estos iconos son imágenes vectoriales, almacenadas en formato .svg, y son tratados como si fueran fuentes. Puedes especificar su tamaño usando pixeles, y tomarán el tamaño de fuente de su elemento HTML padre.", - "Puedes añadir Font Awesome a cualquier aplicación sólo incluyendo y agregando el siguiente código al comienzo de tu HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\"/>", - "En este caso, ya lo hemos agregado por tí a esta página tras bambalinas.", - "El elemento i originalmente era usado para hacer textos en itálicas, pero ahora comunmente se usa para iconos. Le agregas clases de Font Awesome al elemento i para convertirlo en un ícono, por ejemplo:", - "<i class=\"fa fa-info-circle\"></i>", - "Usa Font Awesome para agregar un icono de \"pulgar arriba\" thumbs-up a tu botón de like dándole un elemento i con las clases fa y fa-thumbs-up." - ] - }, - "fr": { - "title": "Ajouter des icônes Font Awesome à nos boutons", - "description": [ - "Font Awesome est une librairie d'icônes très pratique. Ces icones sont des images vectorielles, stockées en format .svg. Ces icônes sont traités exactemeent comme des polices. Vous pouvez choisir leur taille en pixel, et ils prendront la taille de police de leur élémment parent HTML.", - "Vous poyvez ajouter Font Awesome à n'importe quell application en ajoutant le code suivant en haut de votre HTML:", - "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css\" integrity=\"sha384-XdYbMnZ/QjLh6iI4ogqCTaIjrFk87ip+ekIjefZch0Y+PvJ8CDYtEs1ipDmPorQ+\" crossorigin=\"anonymous\">/>", - "Ici, nous l'avons déjà ajouté pour vous dans le back-office.", - "La balise i eétait utilisé à la base pour mettre les autres éléments en italique, mais maintenant elle est utilisée pour les icones. Vous ajoutez des classes Font Awesome à un élément i pour les les transformer en icones, par exemple:", - "<i class=\"fa fa-info-circle\"></i>", - "Utilisez Font Awesome pour ajouter un icone thumbs-up à votre bouton de like en lui donnant un élément i ayant les classes fa et fa-thumbs-up." - ] - } - } - }, - { - "id": "bad87fee1348bd9aedc08845", - "title": "Add Font Awesome Icons to all of our Buttons", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "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.", - "Use Font Awesome to add an info-circle icon to your info button and a trash icon to your delete button.", - "Note: The span element is an acceptable alternative to the i element for the directions below." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".btn-info > i\").is(\".fa.fa-info-circle\") || $(\".btn-info > span\").is(\".fa.fa-info-circle\"), 'message: You should add a <i class=\"fa fa-info-circle\"></i> within your info button element.');", - "assert($(\".btn-danger > i\").is(\".fa.fa-trash\") || $(\".btn-danger > span\").is(\".fa.fa-trash\"), 'message: You should add a <i class=\"fa fa-trash\"></i> within your delete button element.');", - "assert(code.match(/<\\/i>|<\\/span/g) && code.match(/<\\/i|<\\/span>/g).length > 2 && ($(\".btn-primary > i\").is(\".fa.fa-thumbs-up\") || $(\".btn-primary > span\").is(\".fa.fa-thumbs-up\")), 'message: Make sure each of your i elements has a closing tag and <i class=\"fa fa-thumbs-up\"></i> is in your like button element.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Agrega Font Awesome a todos los botones", - "description": [ - "Font Awesome es una librería de iconos muy conveniente. Estos iconos son imágenes vectoriales, almacenadas en formato .svg, y son tratados como si fueran fuentes. Puedes especificar su tamaño usando pixeles, y tomarán el tamaño de fuente de su elemento HTML padre.", - "Utiliza Font Awesome para agregar un icono info-circle a tu botón informativo y un icono trash a tu botón de eliminar." - ] - }, - "fr": { - "title": "Ajoutez des icones Font Awesome à tous nos boutons", - "description": [ - "Font Awesome est une librairie d'icônes très pratique. Ces icones sont des images vectorielles, stockées en format .svg. Ces icônes sont traités exactemeent comme des polices. Vous pouvez choisir leur taille en pixel, et ils prendront la taille de police de leur élémment parent HTML.", - "Utilisez Font Awesome pour ajouter un icone info-circle à votre bouton d'info et un icone trash à votre bouton de suppression." - ] - } - } - }, - { - "id": "bad87fee1348bd9aedb08845", - "title": "Responsively Style Radio Buttons", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "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.", - "Nest both your radio buttons within a <div class=\"row\"> element. Then nest each of them within a <div class=\"col-xs-6\"> element.", - "Note: As a reminder, radio buttons are input elements of type radio." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.row:has(input[type=\\\"radio\\\"])\").length > 0, 'message: Nest all of your radio buttons inside one div with the class row.');", - "assert($(\"div.col-xs-6:has(input[type=\\\"radio\\\"])\").length > 1, 'message: Nest each of your radio buttons inside its own div with the class col-xs-6.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea botones de opción con estilo adaptativo", - "description": [ - "¡Puedes utilizar las clases col-xs-* de Bootstrap en elementos form también! De esta forma, nuestros botones de opción estarán igualmente distribuidos en la página, sin importar qué tan ancha es la resolución de la pantalla.", - "Anida todos los botones de opción dentro de un elemento <div class=\"row\">. Luego, anida cada uno de ellos dentro de un elemento <div class=\"col-xs-6\">." - ] - }, - "fr": { - "title": "Donnez un style responsive à vos boutons radio", - "description": [ - "Vous pouvez utiliser la classe Bootstrap col-xs-* sur des éléments form. Comme ça, nos boutons radio serons disposés régulierement dans la page, quelle que soit la largeur de l'écran.", - "Nichez tous vous boutons radio dans un élément <div class=\"row\">. Ensuite, nichezchacun d'entre eux dans un élément <div class=\"col-xs-6\">" - ] - } - } - }, - { - "id": "bad87fee1348bd9aeda08845", - "title": "Responsively Style Checkboxes", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "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.", - "Nest all three of your checkboxes in a <div class=\"row\"> element. Then nest each of them in a <div class=\"col-xs-4\"> element." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - " ", - " ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.row:has(input[type=\\\"checkbox\\\"])\").length > 0, 'message: Nest all of your checkboxes inside one div with the class row.');", - "assert($(\"div.col-xs-4:has(input[type=\\\"checkbox\\\"])\").length > 2, 'message: Nest each of your checkboxes inside its own div with the class col-xs-4.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea casillas de selección con estilo adaptativo", - "description": [ - "¡Puedes utilizar las clases col-xs-* de Bootstrap en elementos form también! De esta forma, nuestros botones de opción estarán igualmente distribuidos en la página, sin importar qué tan ancha es la resolución de la pantalla.", - "Anida todas las casillas de selección en un elemento <div class=\"row\">. Luego, anida cada una de ellas en un elemento <div class=\"col-xs-4\">." - ] - }, - "fr": { - "title": "Donnez un style responsive à vos checkbox (cases de séléction)", - "description": [ - "Vous pouvez aussi utiliser la classe Bootstrap col-xs-* sur des éléments form! Comme ça, nos boutons radio serons disposés régulierement dans la page, quelle que soit la largeur de l'écran.", - "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.", - "Nichez toustes vos checkbox dans un élément <div class=\"row\">. Ensuite nichez chacun d'entre eux dans un élément <div class=\"col-xs-4\">" - ] - } - } - }, - { - "id": "bad87fee1348bd9aed908845", - "title": "Style Text Inputs as Form Controls", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "You can add the fa-paper-plane Font Awesome icon by adding <i class=\"fa fa-paper-plane\"></i> within your submit button element.", - "Give your form's text input field a class of form-control. Give your form's submit button the classes btn btn-primary. Also give this button the Font Awesome icon of fa-paper-plane.", - "All textual <input>, <textarea>, and <select> elements with the class .form-control have a width of 100%." - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"button[type=\\\"submit\\\"]\").hasClass(\"btn btn-primary\"), 'message: Give the submit button in your form the classes btn btn-primary.');", - "assert($(\"button[type=\\\"submit\\\"]:has(i.fa.fa-paper-plane)\").length > 0, 'message: Add a <i class=\"fa fa-paper-plane\"></i> within your submit button element.');", - "assert($(\"input[type=\\\"text\\\"]\").hasClass(\"form-control\"), 'message: Give the text input in your form the class form-control.');", - "assert(code.match(/<\\/i>/g) && code.match(/<\\/i/g).length > 3, 'message: Make sure each of your i elements has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Estiliza cajas de texto como controles de formulario", - "description": [ - "Puedes agregar el icono fa-paper-plane de Font Awesome incluyendo <i class=\"fa fa-paper-plane\"></i> dentro de tu elemento button de envío.", - "Dale a la entrada de texto de tu formulario la clase form-control. Dale al botón de envío de tu formulario las clases btn btn-primary. También, incluye en ese botón el icono fa-paper-plane de Font Awesome." - ] - }, - "fr": { - "title": "Donnez un style similaire au contrôles de formulaires à des zones de texte", - "description": [ - "Vous pouvez ajouter l'icone Font Awesome fa-paper-plane en ajoutant <i class=\"fa fa-paper-plane\"></i> à l'intérieur de votre button de soumission du formulaire.", - "Donnez aux entrées texte de votre formulaire une classe form-control. Donnez à votre bouton de soumission de formulaire les classes btn btn-primary. Donnez lui aussi un icone Font Awesome fa-paper-plane." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908845", - "title": "Line up Form Elements Responsively with Bootstrap", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css", - "raw": true - } - ], - "description": [ - "Now let's get your form input and your submission button on the same line. We'll do this the same way we have previously: by using a div element with the class row, and other div elements within it using the col-xs-* class.", - "Nest both your form's text input and submit button within a div with the class row. Nest your form's text input within a div with the class of col-xs-7. Nest your form's submit button in a div with the class col-xs-5.", - "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!" - ], - "challengeSeed": [ - "", - "", - "", - "
    ", - "
    ", - "
    ", - "

    CatPhotoApp

    ", - "
    ", - "
    ", - " \"A", - "
    ", - "
    ", - " \"Three", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "

    Things cats love:

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

    Top 3 things cats hate:

    ", - "
      ", - "
    1. flea treatment
    2. ", - "
    3. thunder
    4. ", - "
    5. other cats
    6. ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - "
    ", - "
    ", - " ", - " ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.row:has(input[type=\\\"text\\\"])\").length > 0 && $(\"div.row:has(button[type=\\\"submit\\\"])\").length > 0, 'message: Nest your form submission button and text input in a div with class row.');", - "assert($(\"div.col-xs-7:has(input[type=\\\"text\\\"])\").length > 0, 'message: Nest your form text input in a div with the class col-xs-7.');", - "assert($(\"div.col-xs-5:has(button[type=\\\"submit\\\"])\").length > 0, 'message: Nest your form submission button in a div with the class col-xs-5.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Alínea elementos de formulario de forma adaptativa con Bootstrap", - "description": [ - "Ahora vamos a poner el elemento input y el elemento button que dice submit de tu formulario en la misma línea. Lo haremos de la misma forma que lo hicimos anteriormente: usando un elemento div con la clase row, y otros elementos div dentro de ese, usando la clase col-xs-*.", - "Anida ambos, el elemento input y el elemento button que dice submit de tu formulario dentro de un div con la clase row. Anida el elemento input de tu formulario dentro de un div con cla clase col-xs-7. Anida el elemento button que dice submit de tu formulario en un elemento div con la clase col-xs-5.", - "¡Este es el último desafío que haremos con nuestra aplicación de fotos de gato por ahora. Esperamos que hayas disfrutado aprender acerca de Font Awesome, Bootstrap y diseño adaptativo!" - ] - }, - "fr": { - "title": "Aligner les éléments de formulaire de façon responsive avec Bootstrap", - "description": [ - "Maintenant mettons sur la même ligne l'élément input et le button de soumission du formulaire. Nous procéderons de la même façon que précedemment: en utilisant un élément div avec la classe row, et un un autre div à l'intérieur qui aura la classe col-xs-*.", - "Nichez à la fois l'input texte de votre formulaire et le button de soumission de formulaire à l'intérieur d'un div avec la classe row. Nichez l'input texte du formulaire dans un div ayant la classe col-xs-7. Nichez votre button de soumission de formulaire dans un div ayant la classe col-xs-5.", - "C'est le dernier challenge qui concerne notre application de photos de chats. Nous espérons que vous avez aimé apprendre Font Awesome, Bootstrap et du design adaptatif!" - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908846", - "title": "Create a Bootstrap Headline", - "description": [ - "Now let's build something from scratch to practice our HTML, CSS and Bootstrap skills.", - "We'll build a jQuery playground, which we'll soon put to use in our jQuery challenges.", - "To start with, create an h3 element, with the text jQuery Playground.", - "Color your h3 element with the text-primary Bootstrap class, and center it with the text-center Bootstrap class." - ], - "challengeSeed": [ - "", - "", - "" - ], - "tests": [ - "assert($(\"h3\") && $(\"h3\").length > 0, 'message: Add a h3 element to your page.');", - "assert(code.match(/<\\/h3>/g) && code.match(/

    /g).length === code.match(/

    h3 element has a closing tag.');", - "assert($(\"h3\").hasClass(\"text-primary\"), 'message: Your h3 element should be colored by applying the class text-primary');", - "assert($(\"h3\").hasClass(\"text-center\"), 'message: Your h3 element should be centered by applying the class text-center');", - "assert.isTrue((/jquery(\\s)+playground/gi).test($(\"h3\").text()), 'message: Your h3 element should have the text jQuery Playground.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea un encabezado con Bootstrap", - "description": [ - "Ahora vamos a comenzar un proyecto desde cero para practicar nuestras habilidades con HTML, CSS y Bootstrap.", - "Crearemos un área de juego con jQuery, el cual utilizaremos en nuestros desafíos con jQuery.", - "Para empezar, crea un elemento h3, con el texto jQuery Playground.", - "Ponle color a tu elemento h3 con la clase text-primary de Bootstrap, y céntrala con la clase text-center de Bootstrap." - ] - }, - "fr": { - "title": "Créer un entête Bootstrap", - "description": [ - "Maintenons, créons queqlque chose à partir de zéro pour pratiquer nos connaissances acquises sur HTML, CSS et Bootstrap.", - "Nous allons construire un terrain de jeu pour jQuery, que nous allons bientôt utiliser dans les challenges jQuery.", - "Pour commencer, créez un élément h3, contenant le texte jQuery Playground.", - "Colorez notre élément h3 avec la classe Bootstrap text-primary, et centrez le en utilisant la classe Bootstrap text-center" - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908746", - "title": "House our page within a Bootstrap container-fluid div", - "description": [ - "Now let's make sure all the content on your page is mobile-responsive.", - "Let's nest your h3 element within a div element with the class container-fluid." - ], - "challengeSeed": [ - "

    jQuery Playground

    ", - "", - "" - ], - "tests": [ - "assert($(\"div\").hasClass(\"container-fluid\"), 'message: Your div element should have the class container-fluid.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements has a closing tag.');", - "assert($(\"div\").children(\"h3\").length >0, 'message: Nest your h3 element inside a div element.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Aloja la página dentro de un elemento Div contenedor fluido de Bootstrap", - "description": [ - "Ahora asegurémonos de que todo el contenido en nuestra página pueda adaptarse a dispositivos móviles.", - "Anida tu elemento h3 dentro de un elemento div con la clase container-fluid." - ] - }, - "fr": { - "title": "Loger notre page dans un conteneur Bootstrap Fluid Div", - "description": [ - "Maintenant, assurons nous que tout le contenu de la page est mobile-responsive (adaptatif au téléphones mobiles).", - "Nichons notre element h3 à l'intérieur d'un élément div ayant la classe container-fluid." - ] - } - } - }, - { - "id": "bad87fee1348bd9bec908846", - "title": "Create a Bootstrap Row", - "description": [ - "Now we'll create a Bootstrap row for our inline elements.", - "Create a div element below the h3 tag, with a class of row." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "", - "
    ", - "" - ], - "tests": [ - "assert(($(\"div\").length > 1) && ($(\"div.row h3.text-primary\").length == 0) && ($(\"div.row + h3.text-primary\").length == 0) && ($(\"h3.text-primary + div.row\").length > 0), 'message: Add a div element below your h3 element.');", - "assert($(\"div\").hasClass(\"row\"), 'message: Your div element should have the class row');", - "assert($(\"div.container-fluid div.row\").length > 0, 'message: Your row div should be nested inside the container-fluid div');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div element has a closing tag.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea una fila en Bootstrap", - "description": [ - "Ahora crearemos una fila de Bootstrap con nuestros elementos en línea.", - "Crea un elemento div debajo de la etiqueta h3, con la clase row." - ] - }, - "fr": { - "title": "Créer une rangée (row) Bootstrap", - "description": [ - "Maintenant nous allons créer une rangée (row) Bootstrap pour nos éléments inline.", - "Créez un élément div en dessous de la balise h3, avec une classe row." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908847", - "title": "Split Your Bootstrap Row", - "description": [ - "Now that we have a Bootstrap Row, let's split it into two columns to house our elements.", - "Create two div elements within your row, both with the class col-xs-6." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "", - "", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.row > div.col-xs-6\").length > 1, 'message: Nest two div class=\"col-xs-6\" elements within your div class=\"row\" element.');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements have closing tags.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Parte tu fila en Bootstrap", - "description": [ - "Ahora que tenemos una fila en Bootstrap, vamos a partirla en dos columnas para alojar nuestros elementos.", - "Crea dos elementos div dentro de tu fila, ambos con la clase col-xs-6." - ] - }, - "fr": { - "title": "Séparer une rangée Bootstrap", - "description": [ - "Maintenant que nous avons une rangée Bootstrap, séparons la en deux colonnes pour placer nos éléments.", - "Créez deux éléments divdans votre rangée, chacun ayant la classe col-xs-6." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908848", - "title": "Create Bootstrap Wells", - "description": [ - "Bootstrap has a class called well that can create a visual sense of depth for your columns.", - "Nest one div element with the class well within each of your col-xs-6 div elements." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "
    ", - "", - "
    ", - "
    ", - "", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.col-xs-6\").not(\":has(>div.well)\").length < 1, 'message: Add a div element with the class well inside each of your div elements with the class \"col-xs-6\"');", - "assert($(\"div.row > div.col-xs-6\").length > 1, 'message: Nest both of your div elements with the class \"col-xs-6\" within your div element with the class \"row\".');", - "assert(code.match(/<\\/div>/g) && code.match(/
    /g).length === code.match(/
    div elements have closing tags.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea pozos en Bootstrap", - "description": [ - "Bootstrap tiene una clase llamada well que crea una sensación visual de profundidad para tus columnas.", - "Anida un elemento div con la clase well dentro de cada uno de tus elementos div que tienen la clase col-xs-6." - ] - }, - "fr": { - "title": "Créez un \"puit\" (well) Bootstrap", - "description": [ - "Bootstrap possède une classe appelée well qui peux créer une certaine profondeur pour vos colonnes.", - "Nichez un élément div avec la classe well dans chacun de vos éléments col-xs-6 div." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908849", - "title": "Add Elements within Your Bootstrap Wells", - "description": [ - "Now we're several div elements deep on each column of our row. This is as deep as we'll need to go. Now we can add our button elements.", - "Nest three button elements within each of your well div elements." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "
    ", - "
    ", - "", - "", - "", - "
    ", - "
    ", - "
    ", - "
    ", - "", - "", - "", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"div.well:eq(0)\").children(\"button\").length === 3 && $(\"div.well:eq(1)\").children(\"button\").length === 3, 'message: Nest three button elements within each of your div elements with class well.');", - "assert($(\"button\") && $(\"button\").length > 5, 'message: You should have a total of 6 button elements.');", - "assert(code.match(/<\\/button>/g) && code.match(/", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".btn\").length > 5, 'message: Apply the btn class to each of your button elements.');", - "assert($(\".btn-default\").length > 5, 'message: Apply the btn-default class to each of your button elements.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Aplica el estilo de botón predeterminado de Bootstrap", - "description": [ - "Bootstrap tiene otra clase de botón llamada btn-default.", - "Aplica las clases btn y btn-default a cada uno de tus elementos button." - ] - }, - "fr": { - "title": "Appliquer le style de bouton par défaut de Bootstrap", - "description": [ - "Bootstrap possède une autre classe de bouton appelée btn-default.", - "Appliquez les deux classes btn et btn-default à chacun de vos éléments button" - ] - } - }, - "guideUrl": "https://guide.freecodecamp.org/certificates/apply-the-default-bootstrap-button-style" - }, - { - "id": "bad87fee1348bd9aec908852", - "title": "Create a Class to Target with jQuery Selectors", - "description": [ - "Not every class needs to have corresponding CSS. Sometimes we create classes just for the purpose of selecting these elements more easily using jQuery.", - "Give each of your button elements the class target." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "
    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".target\").length > 5, 'message: Apply the target class to each of your button elements.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Crea una clase para usar con selectores de jQuery", - "description": [ - "No todas las clases necesitan tener un código CSS correspondiente. A veces creamos clases sólo con el propósito de seleccionar esos elementos más fácilmente usando jQuery.", - "Dale a cada uno de tus elementos button la clase target." - ] - }, - "fr": { - "title": "Créez une classe à cibler avec les sélécteurs jQuery", - "description": [ - "Toutes les classes ne nécéssitent pas d'avoir un code CSS qui leur correspondent. Parfois ous créons des classes dans le seul but de pouvoir sélectionner ces éléments plus facilement en utilisant jQuery.", - "Donnez à chacun de vos éléments button la classe target." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908853", - "title": "Add id Attributes to Bootstrap Elements", - "description": [ - "Recall that in addition to class attributes, you can give each of your elements an id attribute.", - "Each id must be unique to a specific element and used only once per page.", - "Let's give a unique id to each of our div elements of class well.", - "Remember that you can give an element an id like this:", - "<div class=\"well\" id=\"center-well\">", - "Give the well on the left the id of left-well. Give the well on the right the id of right-well." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "
    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".col-xs-6\").children(\"#left-well\") && $(\".col-xs-6\").children(\"#left-well\").length > 0, 'message: Give your left well the id of left-well.');", - "assert($(\".col-xs-6\").children(\"#right-well\") && $(\".col-xs-6\").children(\"#right-well\").length > 0, 'message: Give your right well the id of right-well.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Asígnales atributos de identificación (id) a tus elementos de Bootstrap", - "description": [ - "Recuerda que, además de los atributos de clase, también puedes darle a cada uno de tus elementos un atributo id.", - "Cada id debe ser único para un elemento específico y ser usado solamente una vez por página.", - "Vamos a darle un id único a cada uno de nuestros elementos div que tienen la clase well.", - "Recuerda que puedes darle a un elemento un id como el siguiente:", - "<div class=\"well\" id=\"center-well\">", - "Dale al pozo de la izquireda el id left-well. Al pozo de la derecha, dale un id right-well." - ] - }, - "fr": { - "title": "Ajouter des attributs ID à vos éléments Bootstrap", - "description": [ - "Rappelez vous qu'en plus des attributs classes, vous pouvez donnez à chacun de vos éléments un attribut id.", - "Chaque id doit être unique pour un élément donné et utilisé une seule fois par page.", - "Donnons un id unique à chacun de nos éléments div de classe well.", - "Rappelez vous que vous pouvez donner un id à un élément ainsi :", - "<div class=\"well\" id=\"center-well\">", - "Donnez au puit sur la gauche un id de left-well. Donnez au puit sur la droite un id de right-well." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908854", - "title": "Label Bootstrap Wells", - "description": [ - "For the sake of clarity, let's label both of our wells with their ids.", - "Above your left-well, inside its col-xs-6 div element, add a h4 element with the text #left-well.", - "Above your right-well, inside its col-xs-6 div element, add a h4 element with the text #right-well." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

    ", - "
    ", - "
    ", - "", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".col-xs-6\").children(\"h4\") && $(\".col-xs-6\").children(\"h4\").length > 1, 'message: Add an h4 element to each of your <div class=\"col-xs-6\"> elements.');", - "assert(new RegExp(\"#left-well\",\"gi\").test($(\"h4\").text()), 'message: One h4 element should have the text #left-well.');", - "assert(new RegExp(\"#right-well\",\"gi\").test($(\"h4\").text()), 'message: One h4 element should have the text #right-well.');", - "assert(code.match(/<\\/h4>/g) && code.match(/

    /g).length === code.match(/

    h4 elements have closing tags.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Etiqueta tus pozos de Bootstrap", - "description": [ - "Para que todo esté más claro, vamos a ponerle a todos nuestros pozos una etiqueta que sea igual a su id.", - "Sobre tu pozo de la izquierda, dentro de su elemento div que tiene la clase col-xs-6, agrega un elemento h4 con el texto #left-well.", - "Ahora, sobre tu pozo de la derecha, dentro de su elemento div que tiene la clase col-xs-6, agrega un elemento h4 con el texto #right-well." - ] - }, - "fr": { - "title": "Donner un nom aux puits Bootstrap", - "description": [ - "Au nom de la clarté, donnons un nom à nos deux puits en accord avec leur ids", - "Au dessus de votre puit de gauche, à l'intérieur de ses éléments col-xs-6 div, ajoutez un élément h4 ayant le texte #left-well.", - "Au dessus de votre puit de droite, à l'intérieur de ses éléments col-xs-6 div, ajoutez un élément h4 ayant le texte #right-well." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908855", - "title": "Give Each Element a Unique id", - "description": [ - "We will also want to be able to use jQuery to target each button by its unique id.", - "Give each of your buttons a unique id, starting with target1 and ending with target6.", - "Make sure that target1 to target3 are in #left-well, and target4 to target6 are in #right-well." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"#left-well\").children(\"#target1\") && $(\"#left-well\").children(\"#target1\").length > 0, 'message: One button element should have the id target1.');", - "assert($(\"#left-well\").children(\"#target2\") && $(\"#left-well\").children(\"#target2\").length > 0, 'message: One button element should have the id target2.');", - "assert($(\"#left-well\").children(\"#target3\") && $(\"#left-well\").children(\"#target3\").length > 0, 'message: One button element should have the id target3.');", - "assert($(\"#right-well\").children(\"#target4\") && $(\"#right-well\").children(\"#target4\").length > 0, 'message: One button element should have the id target4.');", - "assert($(\"#right-well\").children(\"#target5\") && $(\"#right-well\").children(\"#target5\").length > 0, 'message: One button element should have the id target5.');", - "assert($(\"#right-well\").children(\"#target6\") && $(\"#right-well\").children(\"#target6\").length > 0, 'message: One button element should have the id target6.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Dale a cada elemento un ID único", - "description": [ - "También quisiéramos referirnos a cada botón por su id utilizando jQuery.", - "Dale a cada uno de tus botones un id único, comenzando con target1 y terminando con target6.", - "Asegúrate que target1 a target3 queden en #left-well, mientras que target4 a target6 queden en #right-well." - ] - }, - "fr": { - "title": "Donner à chaque élément un ID unique", - "description": [ - "Nous désirerons aussi pouvoir être capable d'utiliser jQuery pour cibler chaque bouton suivant son id unique.", - "Donnez à chaque bouton un id unique, commençant par target1 et finissant par target6.", - "Assurez vous que target1 à target3 sont dans le #left-well, et que target4 à target6 sont dans le #right-well." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908856", - "title": "Label Bootstrap Buttons", - "description": [ - "Just like we labeled our wells, we want to label our buttons.", - "Give each of your button elements text that corresponds to its id's selector." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert(new RegExp(\"#target1\",\"gi\").test($(\"#target1\").text()), 'message: Give your button element with the id target1 the text #target1.');", - "assert(new RegExp(\"#target2\",\"gi\").test($(\"#target2\").text()), 'message: Give your button element with the id target2 the text #target2.');", - "assert(new RegExp(\"#target3\",\"gi\").test($(\"#target3\").text()), 'message: Give your button element with the id target3 the text #target3.');", - "assert(new RegExp(\"#target4\",\"gi\").test($(\"#target4\").text()), 'message: Give your button element with the id target4 the text #target4.');", - "assert(new RegExp(\"#target5\",\"gi\").test($(\"#target5\").text()), 'message: Give your button element with the id target5 the text #target5.');", - "assert(new RegExp(\"#target6\",\"gi\").test($(\"#target6\").text()), 'message: Give your button element with the id target6 the text #target6.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Etiqueta los botones con Bootstrap", - "description": [ - "De la misma forma en que etiquetamos nuestros pozos, ahora vamos a etiquetar nuestros botones.", - "Dale a cada uno de tus elementos button un texto que corresponda con su id." - ] - }, - "fr": { - "title": "Donnez un nom à vos boutons Bootstrap", - "description": [ - "De la même façon que nous avons donné un nom à nos puits, nous voulons nommer nos boutons.", - "Donnez à chaque élément button un texte qui corresponde à son id." - ] - } - } - }, - { - "id": "bad87fee1348bd9aec908857", - "title": "Use Comments to Clarify Code", - "description": [ - "When we start using jQuery, we will modify HTML elements without needing to actually change them in HTML.", - "Let's make sure that everyone knows they shouldn't actually modify any of this code directly.", - "Remember that you can start a comment with <!-- and end a comment with -->", - "Add a comment at the top of your HTML that says Only change code above this line." - ], - "challengeSeed": [ - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert(code.match(/^\\s*.*this line))\\s*.*this line.*\\s*-->/gi), 'message: Your comment should have the text Only change code above this line.');", - "assert(code.match(/-->.*\\n+.+/g), 'message: Be sure to close your comment with -->.');", - "assert(code.match(//g).length, 'message: You should have the same number of comment openers and closers.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "es": { - "title": "Usa elementos para explicar tu código", - "description": [ - "Cuando comencemos a usar jQuery, modificarmemos los elementos HTML sin necesidad de hacer cambios reales en el código HTML.", - "Vamos a asegurar que cualquier persona sepa que no debe modificar nada en este código directamente.", - "Recuerda que puedes iniciar un comentario usando <!-- y terminarlo usando -->", - "Agrega un comentario al inicio de tu código HTML que diga Only change code above this line." - ] - }, - "fr": { - "title": "Utiliser des commentaires pour clarifier son code", - "description": [ - "Quand nous commencerons à utiliser jQuery, nous modifierons les éléments HTML sans avoir besoin de les changer directement dans le fichier HTML.", - "Assurons nous que tout le monde sache qu'ils ne devraient pas modifier quoi que ce soit dans le code HTML.", - "Rappelez vous que vous pouvez commencer un commentaire avec <!-- et le finir avec -->", - "Ajoutez un commentaire en haut de l'HTML qui annonce Only change code above this line. (Changez seulement le code au dessus de cette ligne.)" - ] - } - } - } - ] -} \ No newline at end of file diff --git a/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json b/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json deleted file mode 100644 index 7b524b22f5..0000000000 --- a/packages/learn/seed/tmp/03-front-end-libraries/front-end-libraries-projects.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "name": "Front End Libraries Projects", - "order": 8, - "time": "150 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "bd7158d8c442eddfaeb5bd13", - "title": "Build a Random Quote Machine", - "description": [ - "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.", - "Here's a working example. Try not to look at its code.", - "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js", - "Once you're done, submit the URL to your working project with all its tests passing.", - "Remember to use the Read-Search-Ask method if you get stuck." - ], - "tests": [], - "type": "zipline", - "isRequired": true, - "challengeType": 3, - "translations": { - "es": { - "title": "Crea una máquina de frases aleatorias" - }, - "ru": { - "title": "Создайте генератор случайных цитат" - } - } - }, - { - "id": "bd7157d8c242eddfaeb5bd13", - "title": "Build a Markdown Previewer", - "description": [ - "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.", - "Here's a working example. Try not to look at its code.", - "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js", - "Once you're done, submit the URL to your working project with all its tests passing.", - "Remember to use the Read-Search-Ask method if you get stuck." - ], - "releasedOn": "January 10, 2017", - "tests": [], - "type": "zipline", - "isRequired": true, - "challengeType": 3, - "translations": { - "es": { - "title": "Crea una caja de recetas" - }, - "ru": { - "title": "Создайте хранилище рецептов" - } - } - }, - { - "id": "587d7dbc367417b2b2512bae", - "title": "Build a Drum Machine", - "description": [ - "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.", - "Here's a working example. Try not to look at its code.", - "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js", - "Once you're done, submit the URL to your working project with all its tests passing.", - "Remember to use the Read-Search-Ask method if you get stuck." - ], - "releasedOn": "February 17, 2017", - "tests": [], - "type": "zipline", - "isRequired": true, - "challengeType": 3, - "translations": { - "es": { - "title": "Crea un Juego de la vida" - }, - "ru": { - "title": "Создайте игру \"Жизнь\"" - } - } - }, - { - "id": "bd7158d8c442eddfaeb5bd17", - "title": "Build a JavaScript Calculator", - "description": [ - "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.", - "Here's a working example. Try not to look at its code.", - "Note On Calculator Logic: It should be noted that there are two main schools of thought on calculator input logic: immediate execution logic and formula logic. Our example utilizes formula logic and observes order of operation precedence, immediate execution does not. Either is acceptable, but please note that depending on which you choose, your calculator may yield different results than ours for certain equations (see below example). As long as your math can be verified by another production calculator, please do not consider this a bug.", - "EXAMPLE: 3 + 5 x 6 - 2 / 4 =
    • Immediate Execution Logic: 11.5
    • Formula/Expression Logic: 32.5
    ", - "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js", - "Once you're done, submit the URL to your working project with all its tests passing.", - "Remember to use the Read-Search-Ask method if you get stuck." - ], - "tests": [], - "type": "zipline", - "challengeType": 3, - "isRequired": true, - "translations": { - "es": { - "title": "Crea una calculadora JavaScript" - } - } - }, - { - "id": "bd7158d8c442eddfaeb5bd0f", - "title": "Build a Pomodoro Clock", - "description": [ - "Fulfill the user stories by getting all of the tests to pass. Use whichever libraries you need. Give it your own personal style.", - "Here's a working example. Try not to look at its code.", - "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js", - "Once you're done, submit the URL to your working project with all its tests passing.", - "Remember to use the Read-Search-Ask method if you get stuck." - ], - "tests": [], - "type": "zipline", - "isRequired": true, - "challengeType": 3, - "translations": { - "es": { - "title": "Crea un reloj pomodoro" - }, - "ru": { - "title": "Создайте таймер Pomodoro" - } - } - } - ] -} diff --git a/packages/learn/seed/tmp/03-front-end-libraries/jquery.json b/packages/learn/seed/tmp/03-front-end-libraries/jquery.json deleted file mode 100644 index 7e0018d9b2..0000000000 --- a/packages/learn/seed/tmp/03-front-end-libraries/jquery.json +++ /dev/null @@ -1,1549 +0,0 @@ -{ - "name": "jQuery", - "order": 3, - "time": "3 hours", - "helpRoom": "Help", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" - } - ], - "challenges": [ - { - "id": "5a61d23e84acdd9e42575aa3", - "title": "Introduction to jQuery", - "description": [ - "", - "", - "jQuery is one of the many libraries for JavaScript. It is designed to simplify scripting done on the client side.", - "", - "@@STEP@@", - "", - "", - "jQuery's most recognizable characteristic is its dollar sign ($) syntax. With it, you can easily manipulate elements, create animations and handle input events.", - "", - "@@STEP@@" - ], - "releasedOn": "", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "bad87fee1348bd9acdd08826", - "title": "Learn How Script Tags and Document Ready Work", - "description": [ - "Now we're ready to learn jQuery, the most popular JavaScript tool of all time.", - "Before we can start using jQuery, we need to add some things to our HTML.", - "First, add a script element at the top of your page. Be sure to close it on the following line.", - "Your browser will run any JavaScript inside a script element, including jQuery.", - "Inside your script element, add this code: $(document).ready(function() { to your script. Then close it on the following line (still inside your script element) with: });", - "We'll learn more about functions later. The important thing to know is that code you put inside this function will run as soon as your browser has loaded your page.", - "This is important because without your document ready function, your code may run before your HTML is rendered, which would cause bugs." - ], - "challengeSeed": [ - "", - "", - "", - "", - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert(code.match(/<\\/script\\s*>/g) && code.match(//g) && code.match(/<\\/script\\s*>/g).length === code.match(//g).length, 'message: Create a script element making sure it is valid and has a closing tag.');", - "assert(code.match(/\\$\\s*?\\(\\s*?document\\s*?\\)\\.ready\\s*?\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?\\{/g), 'message: You should add $(document).ready(function() { to the beginning of your script element.');", - "assert(code.match(/\\n*?\\s*?\\}\\s*?\\);/g), 'message: Close your $(document).ready(function() { function with });');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "de": { - "title": "Lerne, wie Script Tags und Document Ready funktionieren", - "description": [ - "Jetzt sind wir bereit jQuery zu lernen, das populärste JavaScript-Tool aller Zeiten. Mach dir über JavaScript keine Sorgen - über dieses werden wir bald sprechen.", - "Bevor wir jQuery nutzen können, müssen wir erst ein paar Dinge zu unserem HTML hinzufügen.", - "Füge als erstes ein script Element am Beginn deiner Seite ein. Vergewissere dich, dass du das Element in der nächsten Zeile geschlossen hast.", - "Dein Browser wird jegliches JavaScript, jQuery eingeschlossen, innerhalb eines script Elements ausführen.", - "Füge innerhalb deines script Elements folgenden Code hinzu: $(document).ready(function() {. Schließe ihn danach in der nächsten Zeile (noch immer innerhalb deines script Elements) mit: });", - "Wir werden später noch mehr über Funktionen lernen. Wichtig zu wissen ist, dass der Code innerhalb der Funktion ausgeführt wird, sobald der Browser die Seite geladen hat.", - "Das ist wichtig, denn ohne deine Document Ready Funktion könnte dein Code ausgeführt werden, bevor das HTML gerendert wurde - was zu Fehlern führen kann." - ] - }, - "es": { - "title": "Aprende cómo funcionan las etiquetas de programa y la función de documento listo.", - "description": [ - "Ahora estamos listos para aprender jQuery, la herramienta de JavaScript más popular de todos los tiempos. No te preocupes por JavaScript en si --lo cubriremos pronto.", - "Antes de que podamos comenzar a usar jQuery, tenemos que añadir algunas cosas a nuestro HTML.", - "En primer lugar, añade un elemento de programa script en la parte superior de la página. Asegúrate de cerrarlo en la línea siguiente. ", - "Tu navegador ejecutará todo JavaScript dentro de un elemento script, incluyendo jQuery.", - "Dentro de tu elemento script, agrega este código: $(document).ready(function () { A continuación, ciérralo en la línea siguiente (aún dentro de tu elemento script) con: })", - "Más adelante aprenderemos más acerca de funciones. Lo importante es saber que el código que pongas dentro de esta función (function) se ejecutará tan pronto como tu navegador haya cargado la página.", - "Esto es importante porque sin tu función de documento listo, tu código puede ejecutarse antes de que se haya presentado el HTML, lo que podría causar errores." - ] - }, - "fr": { - "title": "Apprendre comment fonctionnent les balises Script et Document Ready", - "description": [ - "Nous sommes maintenant prêt à apprendre jQuery, l'outil JavaScript le plus populaire de tout les temps. Ne vous inquiétez pas à propos de JavaScript lui-même, nous y viendrons bientôt.", - "Avant de pouvoir utiliser jQuery, nous avons besoin d'ajouter certaines choses à notre HTML.", - "Premièrement, ajoutez un élément script en haut de votre page. Assurez-vous de le fermer à la ligne suivante.", - "Votre navigateur exécutera JavaScript à l'intérieur de l'élement script, y compris jQuery.", - "Á l'intérieur de votre élement script, ajoutez ce code : $(document).ready(function() { à votre script. Puis fermez-le à la ligne suivante (toujours à l'intérieur de votre élement script avec: });", - "Nous en apprendrons plus sur les functions plus tard. Le plus important à savoir est que le code à l'intérieur de cette function sera exécuté dès que le navigateur aura chargé votre page.", - "Ceci est important car sans votre document ready function, votre code pourrait être exécuté avant que votre HTML soit affiché, ce qui pourrait causer des problèmes." - ] - } - } - }, - { - "id": "bad87fee1348bd9bedc08826", - "title": "Target HTML Elements with Selectors Using jQuery", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.0/animate.css" - } - ], - "description": [ - "Now we have a document ready function.", - "Now let's write our first jQuery statement. All jQuery functions start with a $, usually referred to as a dollar sign operator, or as bling.", - "jQuery often selects an HTML element with a selector, then does something to that element.", - "For example, let's make all of your button elements bounce. Just add this code inside your document ready function:", - "$(\"button\").addClass(\"animated bounce\");", - "Note that we've already included both the jQuery library and the Animate.css library in the background so that you can use them in the editor. So you are using jQuery to apply the Animate.css bounce class to your button elements." - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - "", - " });", - "fcces", - "", - "", - "", - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"button\").hasClass(\"animated\") && $(\"button\").hasClass(\"bounce\"), 'message: Use the jQuery addClass() function to give the classes animated and bounce to your button elements.');", - "assert(!code.match(/class.*animated/g), 'message: Only use jQuery to add these colors to the element.');", - "assert(code.match(/\\$\\(document\\)\\.ready\\(function.*(\\s|\\n)*.*button.*.addClass.*\\);/g), 'message: Your jQuery code should be within the $(document).ready(); function.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "de": { - "title": "HTML-Elemente mit Selektoren durch jQuery auswählen", - "description": [ - "Jetzt haben wir eine Document Ready Funktion.", - "Lass uns unser erstes jQuery Statement schreiben. Alle jQuery Funktionen starten mit einem $, für gewöhnlich als Dollar-Zeichen Operator bezeichnet.", - "jQuery wählt oft HTML-Elemente mit einem Selektor aus, um dann mit diesen Elementen etwas zu machen.", - "Zum Beispiel, lasse alle deine Button Elemente hüpfen. Dazu musst du nur folgenden Code in deine Document Ready Funktion hinzufügen:", - "$(\"button\").addClass(\"animated bounce\");", - "Beachte, dass wir bereits jQuery und Animate.css im Hintergrund hinzugefügt haben, damit du diese im Editor nutzen kannst. Du nutzt also jQuery um die bounce Klasse von Animate.css zu deinen Button Elementen hinzuzufügen." - ] - }, - "es": { - "title": "Elige elementos HTML usando selectores y jQuery", - "description": [ - "Ya tenemos una función de documento listo.", - "Ahora vamos a escribir nuestra primera instrucción jQuery. Todas las funciones de jQuery comienzan con un $, al que suele referirse como operador dólar, o simplemente como bling. ", - "jQuery a menudo selecciona un elemento HTML con un selector, y luego le hace algo a ese elemento.", - "Por ejemplo, hagamos que todos tus elementos button reboten. Sólo tienes que añadir este código dentro de la función de documento listo: ", - "$(\"button\").addClass(\"animated bounce\")", - "Ten en cuenta que ya hemos incluido tanto la biblioteca jQuery como la biblioteca Animate.css en segundo plano para que pueda utilizarlos en el editor. Así que estás usando jQuery para aplicar la clase bounce de Animate.css a tus elementos button." - ] - }, - "fr": { - "title": "Cibler des élements HTML par sélecteurs avec jQuery", - "description": [ - "Nous avons maintenant un document ready function.", - "Nous allons à présent écrire notre première expression jQuery. Chaque fonction jQuery commence avec un $, habituellement nommé opérateur dollar, ou bling.", - "jQuery sélectionne souvent un élément HTML à l'aide d'un selector, puis fait quelque chose à cet élement.", - "Par exemple, faisons en sorte que tous nos button rebondissent. Ajoutez juste ce code à l'intérieur de votre $(document).ready(function(){:", - "$(\"button\").addClass(\"animated bounce\");", - "Notez que nous avons déjà inclus à la fois la librairie jQuery et la librairie Animate.css en amont donc nous pouvons les utiliser dans l'éditeur. Donc, vous utilisez jQuery pour appliquer la classe bounce d'Animate.css à vos éléments button.", - "De plus, assurez-vous d'utiliser $(\"button\").addClass(\"animated bounce\"); et non $('button').addClass(\"animated bounce\"); car les apostrophes ne passeront pas nos tests." - ] - } - } - }, - { - "id": "bad87fee1348bd9aedc08826", - "title": "Target Elements by Class Using jQuery", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.0/animate.css" - } - ], - "description": [ - "You see how we made all of your button elements bounce? We selected them with $(\"button\"), then we added some CSS classes to them with .addClass(\"animated bounce\");.", - "You just used jQuery's .addClass() function, which allows you to add classes to elements.", - "First, let's target your div elements with the class well by using the $(\".well\") selector.", - "Note that, just like with CSS declarations, you type a . before the class's name.", - "Then use jQuery's .addClass() function to add the classes animated and shake.", - "For example, you could make all the elements with the class text-primary shake by adding the following to your document ready function:", - "$(\".text-primary\").addClass(\"animated shake\");" - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").addClass(\"animated bounce\");", - " });", - "fcces", - "", - "", - "", - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\".well\").hasClass(\"animated\") && $(\".well\").hasClass(\"shake\"), 'message: Use the jQuery addClass() function to give the classes animated and shake to all your elements with the class well.');", - "assert(!code.match(/class\\.\\*animated/g), 'message: Only use jQuery to add these classes to the element.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "de": { - "title": "Elemente anhand von Klassen mit jQuery auswählen", - "description": [ - "Siehst du, wie wir alle deine Button Elemente hüpfen haben lassen? Wir haben sie mit $(\"button\") ausgewählt, dann CSS-Klassen mit .addClass(\"animated bounce\"); hinzugefügt.", - "Du hast gerade jQuery's .addClass() Funktion genutzt, die dir erlaubt, Klassen zu Elemente hinzuzufügen.", - "Wähle als erstes deine div Elemente mit der Klasse well, indem du den $(\".well\") Selektor nutzt.", - "Bedenke, dass du - genauso wie bei CSS-Deklarationen - einen . vor den Namen der Klasse setzen musst.", - "Dann nutze die jQuery Funktion .addClass() um die Klassen animated und shake hinzuzufügen.", - "Zum Beispiel könntest du alle Elemente mit der Klasse text-primary schütteln lassen, indem du folgendes zu deiner Document Ready Funktion hinzufügst:", - "$(\".text-primary\").addClass(\"animated shake\");" - ] - }, - "es": { - "title": "Elige elementos por su clase usando jQuery", - "description": [ - "¿Viste como hicimos rebotar todos tus elementos button? Los seleccionamos con $(\"button\"), y luego les añadimos algunas clases CSS con .addClass(\"animated bounce\");. ", - "Acabas de usar la función addClass() de jQuery, que te permite añadir clases a los elementos.", - "En primer lugar, apuntemos a tus elementos div que tengan la clase well usando el selector $(\".well\").", - "Ten en cuenta que, al igual que con las declaraciones CSS, escribes un . antes del nombre de la clase.", - "A continuación, utiliza la función .addClass() de jQuery para agregar las clases animated y shake.", - "Por ejemplo, podrías hacer que todos los elementos con la clase text-primary se sacudieran añadiendo lo siguiente a tu función de documento listo:", - "$(\".text-primary\").addClass(\"animated shake\");" - ] - }, - "fr": { - "title": "Cibler les élements par Classe avec jQuery", - "description": [ - "Voyez comment nous avons fait rebondir tous nos éléments button? Nous les avons sélectionné avec $(\"button\"), puis nous leur avons ajouté des classes CSS avec .addClass(\"animated bounce\");.", - "Vous venez d'utiliser la fonction jQuery .addClass(), ce qui nous permet d'ajouter des classes aux éléments.", - "Tout d'abord, ciblons nos éléments div qui ont la classe well en utilisant le sélecteur $(\".well\").", - "Notez que, tout comme les expressions CSS, vous ajoutez un . avant le nom de la classe.", - "Puis, vous utilisez la fonction jQuery .addClass() pour ajouter les classes animated et shake.", - "Par exemple, vous pouvez faire en sorte que tous les éléments avec la classe text-primary s'agitent en ajoutant le code suivant à votre document ready function:", - "$(\".text-primary\").addClass(\"animated shake\");" - ] - } - } - }, - { - "id": "bad87fee1348bd9aeda08826", - "title": "Target Elements by id Using jQuery", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.0/animate.css" - } - ], - "description": [ - "You can also target elements by their id attributes.", - "First target your button element with the id target3 by using the $(\"#target3\") selector.", - "Note that, just like with CSS declarations, you type a # before the id's name.", - "Then use jQuery's .addClass() function to add the classes animated and fadeOut.", - "Here's how you'd make the button element with the id target6 fade out:", - "$(\"#target6\").addClass(\"animated fadeOut\")." - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").addClass(\"animated bounce\");", - " $(\".well\").addClass(\"animated shake\");", - "", - " });", - "fcces", - "", - "", - "", - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert($(\"#target3\").hasClass(\"animated\"), 'message: Select the button element with the id of target3 and use the jQuery addClass() function to give it the class of animated.');", - "assert(($(\"#target3\").hasClass(\"fadeOut\") || $(\"#target3\").hasClass(\"fadeout\")) && code.match(/\\$\\(\\s*.#target3.\\s*\\)/g), 'message: Target the element with the id target3 and use the jQuery addClass() function to give it the class fadeOut.');", - "assert(!code.match(/class.*animated/g), 'message: Only use jQuery to add these classes to the element.');" - ], - "type": "waypoint", - "challengeType": 0, - "translations": { - "de": { - "title": "Elemente anhand der id mit jQuery auswählen", - "description": [ - "Du kannst Elemente auch anhand deren ID-Attributs auswählen.", - "Wähle als erstes dein Button Element mit der ID target3, indem du den $(\"#target3\") Selektor nutzt.", - "Bedenke, dass du - genauso wie bei CSS-Deklarationen - eine # vor den Namen der Klasse setzen musst.", - "Dann nutze die jQuery Funktion .addClass() um die Klassen animated und fadeOut hinzuzufügen.", - "So könntest du das Button Element mit der ID target6 ausblenden lassen:", - "$(\"#target6\").addClass(\"animated fadeOut\")." - ] - }, - "es": { - "title": "Elige elementos por id usando jQuery", - "description": [ - "También puedes elegir un elemento por su atributo id.", - "Primero selecciona tu elemento button con el id target3 mediante el uso del selector $(\"#target3\").", - "Ten en cuenta que, al igual que con las declaraciones CSS, debes escribir un # antes de la identificación.", - "A continuación, utiliza la función .addClass() de jQuery para agregar las clases animated y fadeOut.", - "He aquí cómo haces que desaparezca el elemento button con la identificación target6:", - "$(\"#target6\").addClass(\"animated fadeOut\")." - ] - }, - "fr": { - "title": "Cibler les éléments par id avec jQuery", - "description": [ - "Vous pouvez également cibler les éléments à l'aide de leurs attributs id.", - "Premièrement, cibler votre élément button avec l'id target3 en utilisant le sélecteur $(\"#target\").", - "Notez que, tout comme les expressions CSS, vous ajoutez un # avant le nom de l'id.", - "Puis, utilisez la fonction jQuery .addClass() afin d'ajouter les classes animated et fadeOut.", - "Voici comment vous pouvez faire en sorte que l'élément button avec l'id target6 disparaisse en fondu:", - "$(\"#target6\").addClass(\"animated fadeOut\")." - ] - } - } - }, - { - "id": "bad87fee1348bd9aeda08726", - "title": "Delete Your jQuery Functions", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.0/animate.css" - } - ], - "description": [ - "These animations were cool at first, but now they're getting kind of distracting.", - "Delete all three of these jQuery functions from your document ready function, but leave your document ready function itself intact." - ], - "challengeSeed": [ - "fccss", - " $(document).ready(function() {", - " $(\"button\").addClass(\"animated bounce\");", - " $(\".well\").addClass(\"animated shake\");", - " $(\"#target3\").addClass(\"animated fadeOut\");", - "", - " });", - "fcces", - "", - "", - "", - "
    ", - "

    jQuery Playground

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

    #left-well

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

    #right-well

    ", - "
    ", - " ", - " ", - " ", - "
    ", - "
    ", - "
    ", - "
    " - ], - "tests": [ - "assert(code.match(/\\{\\s*\\}\\);/g), 'message: Delete all three of your jQuery functions from your document ready function.');", - "assert(code.match(/", - "" - ], - "tests": [ - "assert($('body').children('h1').length == 1, 'message: The body should have one h1 element.');", - "assert($('h1').text() == \"Learning D3\", 'message: The h1 element should have the text \"Learning D3\" in it.');", - "assert(code.match(/d3/g), 'message: Your code should access the d3 object.');", - "assert(code.match(/\\.select/g), 'message: Your code should use the select method.');", - "assert(code.match(/\\.append/g), 'message: Your code should use the append method.');", - "assert(code.match(/\\.text/g), 'message: Your code should use the text method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa6367417b2b2512bc3", - "title": "Select a Group of Elements with D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "D3 also has the selectAll() method to select a group of elements. It returns an array of HTML nodes for all the items in the document that match the input string. Here's an example to select all the anchor tags in a document:", - "const anchors = d3.selectAll(\"a\");", - "Like the select() method, selectAll() supports method chaining, and you can use it with other methods.", - "
    ", - "Select all of the li tags in the document, and change their text to \"list item\" by chaining the .text() method." - ], - "challengeSeed": [ - "", - "
      ", - "
    • Example
    • ", - "
    • Example
    • ", - "
    • Example
    • ", - "
    ", - " ", - "" - ], - "tests": [ - "assert($('li').text().match(/list item/g).length == 3, 'message: There should be 3 li elements on the page, and the text in each one should say \"list item\". Capitalization and spacing should match exactly.');", - "assert(code.match(/d3/g), 'message: Your code should access the d3 object.');", - "assert(code.match(/\\.selectAll/g), 'message: Your code should use the selectAll method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa7367417b2b2512bc4", - "title": "Work with Data in D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The D3 library focuses on a data-driven approach. When you have a set of data, you can apply D3 methods to display it on the page. Data comes in many formats, but this challenge uses a simple array of numbers.", - "The first step is to make D3 aware of the data. The data() method is used on a selection of DOM elements to attach the data to those elements. The data set is passed as an argument to the method.", - "A common workflow pattern is to create a new element in the document for each piece of data in the set. D3 has the enter() method for this purpose.", - "When enter() is combined with the data() method, it looks at the selected elements from the page and compares them to the number of data items in the set. If there are fewer elements than data items, it creates the missing elements.", - "Here is an example that selects a ul element and creates a new list item based on the number of entries in the array:", - "
    <body>
    <ul></ul>
    <script>
    const dataset = [\"a\", \"b\", \"c\"];
    d3.select(\"ul\").selectAll(\"li\")
    .data(dataset)
    .enter()
    .append(\"li\")
    .text(\"New item\");
    </script>
    </body>
    ", - "It may seem confusing to select elements that don't exist yet. This code is telling D3 to first select the ul on the page. Next, select all list items, which returns an empty selection. Then the data() method reviews the dataset and runs the following code three times, once for each item in the array. The enter() method sees there are no li elements on the page, but it needs 3 (one for each piece of data in dataset). New li elements are appended to the ul and have the text \"New item\".", - "
    ", - "Select the body node, then select all h2 elements. Have D3 create and append an h2 tag for each item in the dataset array. The text in the h2 should say \"New Title\". Your code should use the data() and enter() methods." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('h2').length == 9, 'message: Your document should have 9 h2 elements.');", - "assert($('h2').text().match(/New Title/g).length == 9, 'message: The text in the h2 elements should say \"New Title\". The capitalization and spacing should match exactly.');", - "assert(code.match(/\\.data/g), 'message: Your code should use the data() method.');", - "assert(code.match(/\\.enter/g), 'message: Your code should use the enter() method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa7367417b2b2512bc5", - "title": "Work with Dynamic Data in D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last two challenges cover the basics of displaying data dynamically with D3 using the data() and enter() methods. These methods take a data set and, together with the append() method, create a new DOM element for each entry in the data set.", - "In the previous challenge, you created a new h2 element for each item in the dataset array, but they all contained the same text, \"New Title\". This is because you have not made use of the data that is bound to each of the h2 elements.", - "The D3 text() method can take a string or a callback function as an argument:", - "selection.text((d) => d)", - "In the example above, the parameter d refers to a single entry in the dataset that a selection is bound to.", - "Using the current example as context, the first h2 element is bound to 12, the second h2 element is bound to 31, the third h2 element is bound to 22, and so on.", - "
    ", - "Change the text() method so that each h2 element displays the corresponding value from the dataset array with a single space and \"USD\". For example, the first heading should be \"12 USD\"." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('h2').eq(0).text() == \"12 USD\", 'message: The first h2 should have the text \"12 USD\".');", - "assert($('h2').eq(1).text() == \"31 USD\", 'message: The second h2 should have the text \"31 USD\".');", - "assert($('h2').eq(2).text() == \"22 USD\", 'message: The third h2 should have the text \"22 USD\".');", - "assert($('h2').eq(3).text() == \"17 USD\", 'message: The fourth h2 should have the text \"17 USD\".');", - "assert($('h2').eq(4).text() == \"25 USD\", 'message: The fifth h2 should have the text \"25 USD\".');", - "assert($('h2').eq(5).text() == \"18 USD\", 'message: The sixth h2 should have the text \"18 USD\".');", - "assert($('h2').eq(6).text() == \"29 USD\", 'message: The seventh h2 should have the text \"29 USD\".');", - "assert($('h2').eq(7).text() == \"14 USD\", 'message: The eighth h2 should have the text \"14 USD\".');", - "assert($('h2').eq(8).text() == \"9 USD\", 'message: The ninth h2 should have the text \"9 USD\".');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa7367417b2b2512bc6", - "title": "Add Inline Styling to Elements", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "D3 lets you add inline CSS styles on dynamic elements with the style() method.", - "The style() method takes a comma-separated key-value pair as an argument. Here's an example to set the selection's text color to blue:", - "selection.style(\"color\",\"blue\");", - "
    ", - "Add the style() method to the code in the editor to make all the displayed text have a font-family of verdana." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('h2').css('font-family') == 'verdana', 'message: Your h2 elements should have a font-family of verdana.');", - "assert(code.match(/\\.style/g), 'message: Your code should use the style() method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa7367417b2b2512bc7", - "title": "Change Styles Based on Data", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "D3 is about visualization and presentation of data. It's likely you'll want to change the styling of elements based on the data. You can use a callback function in the style() method to change the styling for different elements.", - "For example, you may want to color a data point blue if has a value less than 20, and red otherwise. You can use a callback function in the style() method and include the conditional logic. The callback function uses the d parameter to represent the data point:", - "
    selection.style(\"color\", (d) => {
    /* Logic that returns the color based on a condition */
    });
    ", - "The style() method is not limited to setting the color - it can be used with other CSS properties as well.", - "
    ", - "Add the style() method to the code in the editor to set the color of the h2 elements conditionally. Write the callback function so if the data value is less than 20, it returns \"red\", otherwise it returns \"green\".", - "Note
    You can use if-else logic, or the ternary operator." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('h2').eq(0).css('color') == \"rgb(255, 0, 0)\", 'message: The first h2 should have a color of red.');", - "assert($('h2').eq(1).css('color') == \"rgb(0, 128, 0)\", 'message: The second h2 should have a color of green.');", - "assert($('h2').eq(2).css('color') == \"rgb(0, 128, 0)\", 'message: The third h2 should have a color of green.');", - "assert($('h2').eq(3).css('color') == \"rgb(255, 0, 0)\", 'message: The fourth h2 should have a color of red.');", - "assert($('h2').eq(4).css('color') == \"rgb(0, 128, 0)\", 'message: The fifth h2 should have a color of green.');", - "assert($('h2').eq(5).css('color') == \"rgb(255, 0, 0)\", 'message: The sixth h2 should have a color of red.');", - "assert($('h2').eq(6).css('color') == \"rgb(0, 128, 0)\", 'message: The seventh h2 should have a color of green.');", - "assert($('h2').eq(7).css('color') == \"rgb(255, 0, 0)\", 'message: The eighth h2 should have a color of red.');", - "assert($('h2').eq(8).css('color') == \"rgb(255, 0, 0)\", 'message: The ninth h2 should have a color of red.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa7367417b2b2512bc8", - "title": "Add Classes with D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "Using a lot of inline styles on HTML elements gets hard to manage, even for smaller apps. It's easier to add a class to elements and style that class one time using CSS rules. D3 has the attr() method to add any HTML attribute to an element, including a class name.", - "The attr() method works the same way that style() does. It takes comma-separated values, and can use a callback function. Here's an example to add a class of \"container\" to a selection:", - "selection.attr(\"class\", \"container\");", - "
    ", - "Add the attr() method to the code in the editor and put a class of bar on the div elements." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('div').attr('class') == \"bar\", 'message: Your div elements should have a class of bar.');", - "assert(code.match(/\\.attr/g), 'message: Your code should use the attr() method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa8367417b2b2512bc9", - "title": "Update the Height of an Element Dynamically", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The previous challenges covered how to display data from an array and how to add CSS classes. You can combine these lessons to create a simple bar chart. There are two steps to this:", - "1) Create a div for each data point in the array", - "2) Give each div a dynamic height, using a callback function in the style() method that sets height equal to the data value", - "Recall the format to set a style using a callback function:", - "selection.style(\"cssProperty\", (d) => d)", - "
    ", - "Add the style() method to the code in the editor to set the height property for each element. Use a callback function to return the value of the data point with the string \"px\" added to it." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('div').eq(0).css('height') == '12px', 'message: The first div should have a height of 12 pixels.');", - "assert($('div').eq(1).css('height') == '31px', 'message: The second div should have a height of 31 pixels.');", - "assert($('div').eq(2).css('height') == '22px', 'message: The third div should have a height of 22 pixels.');", - "assert($('div').eq(3).css('height') == '17px', 'message: The fourth div should have a height of 17 pixels.');", - "assert($('div').eq(4).css('height') == '25px', 'message: The fifth div should have a height of 25 pixels.');", - "assert($('div').eq(5).css('height') == '18px', 'message: The sixth div should have a height of 18 pixels.');", - "assert($('div').eq(6).css('height') == '29px', 'message: The seventh div should have a height of 29 pixels.');", - "assert($('div').eq(7).css('height') == '14px', 'message: The eighth div should have a height of 14 pixels.');", - "assert($('div').eq(8).css('height') == '9px', 'message: The ninth div should have a height of 9 pixels.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa8367417b2b2512bca", - "title": "Change the Presentation of a Bar Chart", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last challenge created a bar chart, but there are a couple of formatting changes that could improve it:", - "1) Add space between each bar to visually separate them, which is done by adding a margin to the CSS for the bar class", - "2) Increase the height of the bars to better show the difference in values, which is done by multiplying the value by a number to scale the height", - "
    ", - "First, add a margin of 2px to the bar class in the style tag. Next, change the callback function in the style() method so it returns a value 10 times the original data value (plus the \"px\").", - "Note
    Multiplying each data point by the same constant only alters the scale. It's like zooming in, and it doesn't change the meaning of the underlying data." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('div').eq(0).css('height') == '120px' && $('div').eq(0).css('margin-right') == '2px', 'message: The first div should have a height of 120 pixels and a margin of 2 pixels.');", - "assert($('div').eq(1).css('height') == '310px' && $('div').eq(1).css('margin-right') == '2px', 'message: The second div should have a height of 310 pixels and a margin of 2 pixels.');", - "assert($('div').eq(2).css('height') == '220px' && $('div').eq(2).css('margin-right') == '2px', 'message: The third div should have a height of 220 pixels and a margin of 2 pixels.');", - "assert($('div').eq(3).css('height') == '170px' && $('div').eq(3).css('margin-right') == '2px', 'message: The fourth div should have a height of 170 pixels and a margin of 2 pixels.');", - "assert($('div').eq(4).css('height') == '250px' && $('div').eq(4).css('margin-right') == '2px', 'message: The fifth div should have a height of 250 pixels and a margin of 2 pixels.');", - "assert($('div').eq(5).css('height') == '180px' && $('div').eq(5).css('margin-right') == '2px', 'message: The sixth div should have a height of 180 pixels and a margin of 2 pixels.');", - "assert($('div').eq(6).css('height') == '290px' && $('div').eq(6).css('margin-right') == '2px', 'message: The seventh div should have a height of 290 pixels and a margin of 2 pixels.');", - "assert($('div').eq(7).css('height') == '140px' && $('div').eq(7).css('margin-right') == '2px', 'message: The eighth div should have a height of 140 pixels and a margin of 2 pixels.');", - "assert($('div').eq(8).css('height') == '90px' && $('div').eq(8).css('margin-right') == '2px', 'message: The ninth div should have a height of 90 pixels and a margin of 2 pixels.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa8367417b2b2512bcb", - "title": "Learn About SVG in D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "SVG stands for Scalable Vector Graphics.", - "Here \"scalable\" means that, if you zoom in or out on an object, it would not appear pixelated. It scales with the display system, whether it's on a small mobile screen or a large TV monitor.", - "SVG is used to make common geometric shapes. Since D3 maps data into a visual representation, it uses SVG to create the shapes for the visualization. SVG shapes for a web page must go within an HTML svg tag.", - "CSS can be scalable when styles use relative units (such as vh, vw, or percentages), but using SVG is more flexible to build data visualizations.", - "
    ", - "Add an svg node to the body using append(). Give it a width attribute set to the provided w constant and a height attribute set to the provided h constant using the attr() method for each. You'll see it in the output because there's a background-color of pink applied to it in the style tag.", - "Note
    Width and height attributes do not have units. This is the building block of scaling - the element will always have a 5:1 width to height ratio, no matter what the zoom level is." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('svg').length == 1, 'message: Your document should have 1 svg element.');", - "assert($('svg').attr('width') == '500', 'message: The svg element should have a width attribute set to 500.');", - "assert($('svg').attr('height') == '100', 'message: The svg element should have a height attribute set to 100.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa8367417b2b2512bcc", - "title": "Display Shapes with SVG", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last challenge created an svg element with a given width and height, which was visible because it had a background-color applied to it in the style tag. The code made space for the given width and height.", - "The next step is to create a shape to put in the svg area. There are a number of supported shapes in SVG, such as rectangles and circles. They are used to display data. For example, a rectangle (<rect>) SVG shape could create a bar in a bar chart.", - "When you place a shape into the svg area, you can specify where it goes with x and y coordinates. The origin point of (0, 0) is in the upper-left corner. Positive vales for x push the shape to the right, and positive values for y push the shape down from the origin point.", - "To place a shape in the middle of the 500 (width) x 100 (height) svg from last challenge, the x coordinate would be 250 and the y coordinate would be 50.", - "An SVG rect has four attributes. There are the x and y coordinates for where it is placed in the svg area. It also has a height and width to specify the size.", - "
    ", - "Add a rect shape to the svg using append(), and give it a width attribute of 25 and height attribute of 100. Also, give the rect x and y attributes each set to 0." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').length == 1, 'message: Your document should have 1 rect element.');", - "assert($('rect').attr('width') == '25', 'message: The rect element should have a width attribute set to 25.');", - "assert($('rect').attr('height') == '100', 'message: The rect element should have a height attribute set to 100.');", - "assert($('rect').attr('x') == '0', 'message: The rect element should have an x attribute set to 0.');", - "assert($('rect').attr('y') == '0', 'message: The rect element should have a y attribute set to 0.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa8367417b2b2512bcd", - "title": "Create a Bar for Each Data Point in the Set", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last challenge added only one rectangle to the svg element to represent a bar. Here, you'll combine what you've learned so far about data(), enter(), and SVG shapes to create and append a rectangle for each data point in dataset.", - "A previous challenge showed the format for how to create and append a div for each item in dataset:", - "
    d3.select(\"body\").selectAll(\"div\")
    .data(dataset)
    .enter()
    .append(\"div\")
    ", - "There are a few differences working with rect elements instead of divs. The rects must be appended to an svg element, not directly to the body. Also, you need to tell D3 where to place each rect within the svg area. The bar placement will be covered in the next challenge.", - "
    ", - "Use the data(), enter(), and append() methods to create and append a rect for each item in dataset. The bars should display all on top of each other, this will be fixed in the next challenge." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').length == 9, 'message: Your document should have 9 rect elements.');", - "assert(code.match(/\\.data/g), 'message: Your code should use the data() method.');", - "assert(code.match(/\\.enter/g), 'message: Your code should use the enter() method.');", - "assert(code.match(/\\.append/g), 'message: Your code should use the append() method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa9367417b2b2512bce", - "title": "Dynamically Set the Coordinates for Each Bar", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last challenge created and appended a rectangle to the svg element for each point in dataset to represent a bar. Unfortunately, they were all stacked on top of each other.", - "The placement of a rectangle is handled by the x and y attributes. They tell D3 where to start drawing the shape in the svg area. The last challenge set them each to 0, so every bar was placed in the upper-left corner.", - "For a bar chart, all of the bars should sit on the same vertical level, which means the y value stays the same (at 0) for all bars. The x value, however, needs to change as you add new bars. Remember that larger x values push items farther to the right. As you go through the array elements in dataset, the x value should increase.", - "The attr() method in D3 accepts a callback function to dynamically set that attribute. The callback function takes two arguments, one for the data point itself (usually d) and one for the index of the data point in the array. The second argument for the index is optional. Here's the format:", - "
    selection.attr(\"property\", (d, i) => {
    /*
    * d is the data point value
    * i is the index of the data point in the array
    */
    })
    ", - "It's important to note that you do NOT need to write a for loop or use forEach() to iterate over the items in the data set. Recall that the data() method parses the data set, and any method that's chained after data() is run once for each item in the data set.", - "
    ", - "Change the x attribute callback function so it returns the index times 30.", - "Note
    Each bar has a width of 25, so increasing each x value by 30 adds some space between the bars. Any value greater than 25 would work in this example." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').eq(0).attr('x') == '0', 'message: The first rect should have an x value of 0.');", - "assert($('rect').eq(1).attr('x') == '30', 'message: The second rect should have an x value of 30.');", - "assert($('rect').eq(2).attr('x') == '60', 'message: The third rect should have an x value of 60.');", - "assert($('rect').eq(3).attr('x') == '90', 'message: The fourth rect should have an x value of 90.');", - "assert($('rect').eq(4).attr('x') == '120', 'message: The fifth rect should have an x value of 120.');", - "assert($('rect').eq(5).attr('x') == '150', 'message: The sixth rect should have an x value of 150.');", - "assert($('rect').eq(6).attr('x') == '180', 'message: The seventh rect should have an x value of 180.');", - "assert($('rect').eq(7).attr('x') == '210', 'message: The eighth rect should have an x value of 210.');", - "assert($('rect').eq(8).attr('x') == '240', 'message: The ninth rect should have an x value of 240.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa9367417b2b2512bcf", - "title": "Dynamically Change the Height of Each Bar", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The height of each bar can be set to the value of the data point in the array, similar to how the x value was set dynamically.", - "
    selection.attr(\"property\", (d, i) => {
    /*
    * d is the data point value
    * i is the index of the data point in the array
    */
    })
    ", - "
    ", - "Change the callback function for the height attribute to return the data value times 3.", - "Note
    Remember that multiplying all data points by the same constant scales the data (like zooming in). It helps to see the differences between bar values in this example." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').eq(0).attr('height') == '36', 'message: The first rect should have a height of 36.');", - "assert($('rect').eq(1).attr('height') == '93', 'message: The second rect should have a height of 93.');", - "assert($('rect').eq(2).attr('height') == '66', 'message: The third rect should have a height of 66.');", - "assert($('rect').eq(3).attr('height') == '51', 'message: The fourth rect should have a height of 51.');", - "assert($('rect').eq(4).attr('height') == '75', 'message: The fifth rect should have a height of 75.');", - "assert($('rect').eq(5).attr('height') == '54', 'message: The sixth rect should have a height of 54.');", - "assert($('rect').eq(6).attr('height') == '87', 'message: The seventh rect should have a height of 87.');", - "assert($('rect').eq(7).attr('height') == '42', 'message: The eighth rect should have a height of 42.');", - "assert($('rect').eq(8).attr('height') == '27', 'message: The ninth rect should have a height of 27.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa9367417b2b2512bd0", - "title": "Invert SVG Elements", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "You may have noticed the bar chart looked like it's upside-down, or inverted. This is because of how SVG uses (x, y) coordinates.", - "In SVG, the origin point for the coordinates is in the upper-left corner. An x coordinate of 0 places a shape on the left edge of the SVG area. A y coordinate of 0 places a shape on the top edge of the SVG area. Higher x values push the rectangle to the right. Higher y values push the rectangle down.", - "To make the bars right-side-up, you need to change the way the y coordinate is calculated. It needs to account for both the height of the bar and the total height of the SVG area.", - "The height of the SVG area is 100. If you have a data point of 0 in the set, you would want the bar to start at the bottom of the SVG area (not the top). To do this, the y coordinate needs a value of 100. If the data point value were 1, you would start with a y coordinate of 100 to set the bar at the bottom. Then you need to account for the height of the bar of 1, so the final y coordinate would be 99.", - "The y coordinate that is y = heightOfSVG - heightOfBar would place the bars right-side-up.", - "
    ", - "Change the callback function for the y attribute to set the bars right-side-up. Remember that the height of the bar is 3 times the data value d.", - "Note
    In general, the relationship is y = h - m * d, where m is the constant that scales the data points." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').eq(0).attr('y') == h - (dataset[0] * 3), 'message: The first rect should have a y value of 64.');", - "assert($('rect').eq(1).attr('y') == h - (dataset[1] * 3), 'message: The second rect should have a y value of 7.');", - "assert($('rect').eq(2).attr('y') == h - (dataset[2] * 3), 'message: The third rect should have a y value of 34.');", - "assert($('rect').eq(3).attr('y') == h - (dataset[3] * 3), 'message: The fourth rect should have a y value of 49.');", - "assert($('rect').eq(4).attr('y') == h - (dataset[4] * 3), 'message: The fifth rect should have a y value of 25.');", - "assert($('rect').eq(5).attr('y') == h - (dataset[5] * 3), 'message: The sixth rect should have a y value of 46.');", - "assert($('rect').eq(6).attr('y') == h - (dataset[6] * 3), 'message: The seventh rect should have a y value of 13.');", - "assert($('rect').eq(7).attr('y') == h - (dataset[7] * 3), 'message: The eighth rect should have a y value of 58.');", - "assert($('rect').eq(8).attr('y') == h - (dataset[8] * 3), 'message: The ninth rect should have a y value of 73.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fa9367417b2b2512bd1", - "title": "Change the Color of an SVG Element", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The bars are in the right position, but they are all the same black color. SVG has a way to change the color of the bars.", - "In SVG, a rect shape is colored with the fill attribute. It supports hex codes, color names, and rgb values, as well as more complex options like gradients and transparency.", - "
    ", - "Add an attr() method to set the \"fill\" of all the bars to the color \"navy\"." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('rect').css('fill') == \"rgb(0, 0, 128)\", 'message: The bars should all have a fill color of navy.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faa367417b2b2512bd2", - "title": "Add Labels to D3 Elements", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "D3 lets you label a graph element, such as a bar, using the SVG text element.", - "Like the rect element, a text element needs to have x and y attributes, to place it on the SVG canvas. It also needs to access the data to display those values.", - "D3 gives you a high level of control over how you label your bars.", - "
    ", - "The code in the editor already binds the data to each new text element. First, append text nodes to the svg. Next, add attributes for the x and y coordinates. They should be calculated the same way as the rect ones, except the y value for the text should make the label sit 3 units higher than the bar. Finally, use the D3 text() method to set the label equal to the data point value.", - "Note
    For the label to sit higher than the bar, decide if the y value for the text should be 3 greater or 3 less than the y value for the bar." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('text').eq(0).text() == '12' && $('text').eq(0).attr('y') == '61', 'message: The first text element should have a label of 12 and a y value of 61.');", - "assert($('text').eq(1).text() == '31' && $('text').eq(1).attr('y') == '4', 'message: The second text element should have a label of 31 and a y value of 4.');", - "assert($('text').eq(2).text() == '22' && $('text').eq(2).attr('y') == '31', 'message: The third text element should have a label of 22 and a y value of 31.');", - "assert($('text').eq(3).text() == '17' && $('text').eq(3).attr('y') == '46', 'message: The fourth text element should have a label of 17 and a y value of 46.');", - "assert($('text').eq(4).text() == '25' && $('text').eq(4).attr('y') == '22', 'message: The fifth text element should have a label of 25 and a y value of 22.');", - "assert($('text').eq(5).text() == '18' && $('text').eq(5).attr('y') == '43', 'message: The sixth text element should have a label of 18 and a y value of 43.');", - "assert($('text').eq(6).text() == '29' && $('text').eq(6).attr('y') == '10', 'message: The seventh text element should have a label of 29 and a y value of 10.');", - "assert($('text').eq(7).text() == '14' && $('text').eq(7).attr('y') == '55', 'message: The eighth text element should have a label of 14 and a y value of 55.');", - "assert($('text').eq(8).text() == '9' && $('text').eq(8).attr('y') == '70', 'message: The ninth text element should have a label of 9 and a y value of 70.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faa367417b2b2512bd3", - "title": "Style D3 Labels", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "D3 methods can add styles to the bar labels. The fill attribute sets the color of the text for a text node. The style() method sets CSS rules for other styles, such as \"font-family\" or \"font-size\".", - "
    ", - "Set the font-size of the text elements to 25px, and the color of the text to red." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('text').css('fill') == 'rgb(255, 0, 0)', 'message: The labels should all have a fill color of red.');", - "assert($('text').css('font-size') == '25px', 'message: The labels should all have a font-size of 25 pixels.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faa367417b2b2512bd4", - "title": "Add a Hover Effect to a D3 Element", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "It's possible to add effects that highlight a bar when the user hovers over it with the mouse. So far, the styling for the rectangles is applied with the built-in D3 and SVG methods, but you can use CSS as well.", - "You set the CSS class on the SVG elements with the attr() method. Then the :hover pseudo-class for your new class holds the style rules for any hover effects.", - "
    ", - "Use the attr() method to add a class of bar to all the rect elements. This changes the fill color of the bar to brown when you mouse over it." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('rect').attr('class') == \"bar\", 'message: Your rect elements should have a class of bar.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faa367417b2b2512bd6", - "title": "Add a Tooltip to a D3 Element", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "A tooltip shows more information about an item on a page when the user hovers over that item. There are several ways to add a tooltip to a visualization, this challenge uses the SVG title element.", - "title pairs with the text() method to dynamically add data to the bars.", - "
    ", - "Append a title element under each rect node. Then call the text() method with a callback function so the text displays the data value." - ], - "challengeSeed": [ - "", - "", - " ", - "" - ], - "tests": [ - "assert($('title').length == 9, 'message: Your code should have 9 title elements.');", - "assert($('title').eq(0).text() == '12', 'message: The first title element should have tooltip text of 12.');", - "assert($('title').eq(1).text() == '31', 'message: The second title element should have tooltip text of 31.');", - "assert($('title').eq(2).text() == '22', 'message: The third title element should have tooltip text of 22.');", - "assert($('title').eq(3).text() == '17', 'message: The fourth title element should have tooltip text of 17.');", - "assert($('title').eq(4).text() == '25', 'message: The fifth title element should have tooltip text of 25.');", - "assert($('title').eq(5).text() == '18', 'message: The sixth title element should have tooltip text of 18.');", - "assert($('title').eq(6).text() == '29', 'message: The seventh title element should have tooltip text of 29.');", - "assert($('title').eq(7).text() == '14', 'message: The eighth title element should have tooltip text of 14.');", - "assert($('title').eq(8).text() == '9', 'message: The ninth title element should have tooltip text of 9.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fab367417b2b2512bd7", - "title": "Create a Scatterplot with SVG Circles", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "A scatter plot is another type of visualization. It usually uses circles to map data points, which have two values each. These values tie to the x and y axes, and are used to position the circle in the visualization.", - "SVG has a circle tag to create the circle shape. It works a lot like the rect elements you used for the bar chart.", - "
    ", - "Use the data(), enter(), and append() methods to bind dataset to new circle elements that are appended to the SVG canvas." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('circle').length == 10, 'message: Your code should have 10 circle elements.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fab367417b2b2512bd8", - "title": "Add Attributes to the Circle Elements", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The last challenge created the circle elements for each point in the dataset, and appended them to the SVG canvas. But D3 needs more information about the position and size of each circle to display them correctly.", - "A circle in SVG has three main attributes. The cx and cy attributes are the coordinates. They tell D3 where to position the center of the shape on the SVG canvas. The radius (r attribute) gives the size of the circle.", - "Just like the rect y coordinate, the cy attribute for a circle is measured from the top of the SVG canvas, not from the bottom.", - "All three attributes can use a callback function to set their values dynamically. Remember that all methods chained after data(dataset) run once per item in dataset. The d parameter in the callback function refers to the current item in dataset, which is an array for each point. You use bracket notation, like d[0], to access the values in that array.", - "
    ", - "Add cx, cy, and r attributes to the circle elements. The cx value should be the first number in the array for each item in dataset. The cy value should be based off the second number in the array, but make sure to show the chart right-side-up and not inverted. The r value should be 5 for all circles." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('circle').length == 10, 'message: Your code should have 10 circle elements.');", - "assert($('circle').eq(0).attr('cx') == '34' && $('circle').eq(0).attr('cy') == '422' && $('circle').eq(0).attr('r') == '5', 'message: The first circle element should have a cx value of 34, a cy value of 422, and an r value of 5.');", - "assert($('circle').eq(1).attr('cx') == '109' && $('circle').eq(1).attr('cy') == '220' && $('circle').eq(1).attr('r') == '5', 'message: The second circle element should have a cx value of 109, a cy value of 220, and an r value of 5.');", - "assert($('circle').eq(2).attr('cx') == '310' && $('circle').eq(2).attr('cy') == '380' && $('circle').eq(2).attr('r') == '5', 'message: The third circle element should have a cx value of 310, a cy value of 380, and an r value of 5.');", - "assert($('circle').eq(3).attr('cx') == '79' && $('circle').eq(3).attr('cy') == '89' && $('circle').eq(3).attr('r') == '5', 'message: The fourth circle element should have a cx value of 79, a cy value of 89, and an r value of 5.');", - "assert($('circle').eq(4).attr('cx') == '420' && $('circle').eq(4).attr('cy') == '280' && $('circle').eq(4).attr('r') == '5', 'message: The fifth circle element should have a cx value of 420, a cy value of 280, and an r value of 5.');", - "assert($('circle').eq(5).attr('cx') == '233' && $('circle').eq(5).attr('cy') == '355' && $('circle').eq(5).attr('r') == '5', 'message: The sixth circle element should have a cx value of 233, a cy value of 355, and an r value of 5.');", - "assert($('circle').eq(6).attr('cx') == '333' && $('circle').eq(6).attr('cy') == '404' && $('circle').eq(6).attr('r') == '5', 'message: The seventh circle element should have a cx value of 333, a cy value of 404, and an r value of 5.');", - "assert($('circle').eq(7).attr('cx') == '222' && $('circle').eq(7).attr('cy') == '167' && $('circle').eq(7).attr('r') == '5', 'message: The eighth circle element should have a cx value of 222, a cy value of 167, and an r value of 5.');", - "assert($('circle').eq(8).attr('cx') == '78' && $('circle').eq(8).attr('cy') == '180' && $('circle').eq(8).attr('r') == '5', 'message: The ninth circle element should have a cx value of 78, a cy value of 180, and an r value of 5.');", - "assert($('circle').eq(9).attr('cx') == '21' && $('circle').eq(9).attr('cy') == '377' && $('circle').eq(9).attr('r') == '5', 'message: The tenth circle element should have a cx value of 21, a cy value of 377, and an r value of 5.');" - ], - "solutions": [], - "hints": [ - "The cy attribute should be the second number of the data point array subtracted from the height of the SVG." - ], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fab367417b2b2512bd9", - "title": "Add Labels to Scatter Plot Circles", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "You can add text to create labels for the points in a scatter plot.", - "The goal is to display the comma-separated values for the first (x) and second (y) fields of each item in dataset.", - "The text nodes need x and y attributes to position it on the SVG canvas. In this challenge, the y value (which determines height) can use the same value that the circle uses for its cy attribute. The x value can be slightly larger than the cx value of the circle, so the label is visible. This will push the label to the right of the plotted point.", - "
    ", - "Label each point on the scatter plot using the text elements. The text of the label should be the two values separated by a comma and a space. For example, the label for the first point is \"34, 78\". Set the x attribute so it's 5 units more than the value you used for the cx attribute on the circle. Set the y attribute the same way that's used for the cy value on the circle." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('text').length == 10, 'message: Your code should have 10 text elements.');", - "assert($('text').eq(0).text() == '34, 78' && $('text').eq(0).attr('x') == '39' && $('text').eq(0).attr('y') == '422', 'message: The first label should have text of \"34, 78\", an x value of 39, and a y value of 422.');", - "assert($('text').eq(1).text() == '109, 280' && $('text').eq(1).attr('x') == '114' && $('text').eq(1).attr('y') == '220', 'message: The second label should have text of \"109, 280\", an x value of 114, and a y value of 220.');", - "assert($('text').eq(2).text() == '310, 120' && $('text').eq(2).attr('x') == '315' && $('text').eq(2).attr('y') == '380', 'message: The third label should have text of \"310, 120\", an x value of 315, and a y value of 380.');", - "assert($('text').eq(3).text() == '79, 411' && $('text').eq(3).attr('x') == '84' && $('text').eq(3).attr('y') == '89', 'message: The fourth label should have text of \"79, 411\", an x value of 84, and a y value of 89.');", - "assert($('text').eq(4).text() == '420, 220' && $('text').eq(4).attr('x') == '425' && $('text').eq(4).attr('y') == '280', 'message: The fifth label should have text of \"420, 220\", an x value of 425, and a y value of 280.');", - "assert($('text').eq(5).text() == '233, 145' && $('text').eq(5).attr('x') == '238' && $('text').eq(5).attr('y') == '355', 'message: The sixth label should have text of \"233, 145\", an x value of 238, and a y value of 355.');", - "assert($('text').eq(6).text() == '333, 96' && $('text').eq(6).attr('x') == '338' && $('text').eq(6).attr('y') == '404', 'message: The seventh label should have text of \"333, 96\", an x value of 338, and a y value of 404.');", - "assert($('text').eq(7).text() == '222, 333' && $('text').eq(7).attr('x') == '227' && $('text').eq(7).attr('y') == '167', 'message: The eighth label should have text of \"222, 333\", an x value of 227, and a y value of 167.');", - "assert($('text').eq(8).text() == '78, 320' && $('text').eq(8).attr('x') == '83' && $('text').eq(8).attr('y') == '180', 'message: The ninth label should have text of \"78, 320\", an x value of 83, and a y value of 180.');", - "assert($('text').eq(9).text() == '21, 123' && $('text').eq(9).attr('x') == '26' && $('text').eq(9).attr('y') == '377', 'message: The tenth label should have text of \"21, 123\", an x value of 26, and a y value of 377.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fab367417b2b2512bda", - "title": "Create a Linear Scale with D3", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The bar and scatter plot charts both plotted data directly onto the SVG canvas. However, if the height of a bar or one of the data points were larger than the SVG height or width values, it would go outside the SVG area.", - "In D3, there are scales to help plot data. Scales are functions that tell the program how to map a set of raw data points onto the pixels of the SVG canvas.", - "For example, say you have a 100x500-sized SVG canvas and you want to plot Gross Domestic Product (GDP) for a number of countries. The set of numbers would be in the billion or trillion-dollar range. You provide D3 a type of scale to tell it how to place the large GDP values into that 100x500-sized area.", - "It's unlikely you would plot raw data as-is. Before plotting it, you set the scale for your entire data set, so that the x and y values fit your canvas width and height.", - "D3 has several scale types. For a linear scale (usually used with quantitative data), there is the D3 method scaleLinear():", - " const scale = d3.scaleLinear()", - "By default, a scale uses the identity relationship. The value of the input is the same as the value of the output. A separate challenge covers how to change this.", - "
    ", - "Change the scale variable to create a linear scale. Then set the output variable to the scale called with an input argument of 50." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('h2').text() == '50', 'message: The text in the h2 should be 50.');", - "assert(code.match(/\\.scaleLinear/g), 'message: Your code should use the scaleLinear() method.');", - "assert(output == 50 && code.match(/scale\\(\\s*?50\\s*?\\)/g), 'message: The output variable should call scale with an argument of 50.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fac367417b2b2512bdb", - "title": "Set a Domain and a Range on a Scale", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "By default, scales use the identity relationship - the input value maps to the output value. But scales can be much more flexible and interesting.", - "Say a data set has values ranging from 50 to 480. This is the input information for a scale, and is also known as the domain.", - "You want to map those points along the x axis on the SVG canvas, between 10 units and 500 units. This is the output information, which is also known as the range.", - "The domain() and range() methods set these values for the scale. Both methods take an array of at least two elements as an argument. Here's an example:", - "
    // Set a domain
    // The domain covers the set of input values
    scale.domain([50, 480]);
    // Set a range
    // The range covers the set of output values
    scale.range([10, 500]);
    scale(50) // Returns 10
    scale(480) // Returns 500
    scale(325) // Returns 323.37
    scale(750) // Returns 807.67
    d3.scaleLinear()
    ", - "Notice that the scale uses the linear relationship between the domain and range values to figure out what the output should be for a given number. The minimum value in the domain (50) maps to the minimum value (10) in the range.", - "
    ", - "Create a scale and set its domain to [250, 500] and range to [10, 150].", - "Note
    You can chain the domain() and range() methods onto the scale variable." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert(code.match(/\\.domain/g), 'message: Your code should use the domain() method.');", - "assert(JSON.stringify(scale.domain()) == JSON.stringify([250, 500]), 'message: The domain() of the scale should be set to [250, 500].');", - "assert(code.match(/\\.range/g), 'message: Your code should use the range() method.');", - "assert(JSON.stringify(scale.range()) == JSON.stringify([10, 150]), 'message: The range() of the scale should be set to [10, 150].');", - "assert($('h2').text() == '-102', 'message: The text in the h2 should be -102.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fac367417b2b2512bdc", - "title": "Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The D3 methods domain() and range() set that information for your scale based on the data. There are a couple methods to make that easier.", - "Often when you set the domain, you'll want to use the minimum and maximum values within the data set. Trying to find these values manually, especially in a large data set, may cause errors.", - "D3 has two methods - min() and max() to return this information. Here's an example:", - "
    const exampleData = [34, 234, 73, 90, 6, 52];
    d3.min(exampleData) // Returns 6
    d3.max(exampleData) // Returns 234
    ", - "A dataset may have nested arrays, like the [x, y] coordinate pairs that were in the scatter plot example. In that case, you need to tell D3 how to calculate the maximum and minimum.", - "Fortunately, both the min() and max() methods take a callback function.", - "In this example, the callback function's argument d is for the current inner array. The callback needs to return the element from the inner array (the x or y value) over which you want to compute the maximum or minimum. Here's an example for how to find the min and max values with an array of arrays:", - "
    const locationData = [[1, 7],[6, 3],[8, 3]];
    // Returns the smallest number out of the first elements
    const minX = d3.min(locationData, (d) => d[0]);
    // minX compared 1, 6, and 8 and is set to 1
    ", - "
    ", - "The positionData variable holds a 3-dimensional (3D) array. Use a D3 method to find the maximum value of the z coordinate (the third value) from the arrays and save it in the output variable.", - "Note
    Fun fact - D3 can plot 3D arrays." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert(output == 8 && $('h2').text() == '8', 'message: The text in the h2 should be 8.');", - "assert(code.match(/\\.max/g), 'message: Your code should use the max() method.')" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fac367417b2b2512bdd", - "title": "Use Dynamic Scales", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "The D3 min() and max() methods are useful to help set the scale.", - "Given a complex data set, one priority is to set the scale so the visualization fits the SVG container's width and height. You want all the data plotted inside the SVG canvas so it's visible on the web page.", - "The example below sets the x-axis scale for scatter plot data. The domain() method passes information to the scale about the raw data values for the plot. The range() method gives it information about the actual space on the web page for the visualization.", - "In the example, the domain goes from 0 to the maximum in the set. It uses the max() method with a callback function based on the x values in the arrays. The range uses the SVG canvas' width (w), but it includes some padding, too. This puts space between the scatter plot dots and the edge of the SVG canvas.", - "
    const dataset = [
    [ 34, 78 ],
    [ 109, 280 ],
    [ 310, 120 ],
    [ 79, 411 ],
    [ 420, 220 ],
    [ 233, 145 ],
    [ 333, 96 ],
    [ 222, 333 ],
    [ 78, 320 ],
    [ 21, 123 ]
    ];
    const w = 500;
    const h = 500;

    // Padding between the SVG canvas boundary and the plot
    const padding = 30;
    const xScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, (d) => d[0])])
    .range([padding, w - padding]);
    ", - "The padding may be confusing at first. Picture the x-axis as a horizontal line from 0 to 500 (the width value for the SVG canvas). Including the padding in the range() method forces the plot to start at 30 along that line (instead of 0), and end at 470 (instead of 500).", - "
    ", - "Use the yScale variable to create a linear y-axis scale. The domain should start at zero and go to the maximum y value in the set. The range should use the SVG height (h) and include padding.", - "Note
    Remember to keep the plot right-side-up. When you set the range for the y coordinates, the higher value (height minus padding) is the first argument, and the lower value is the second argument." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert(output == 30 && $('h2').text() == '30', 'message: The text in the h2 should be 30.');", - "assert(JSON.stringify(yScale.domain()) == JSON.stringify([0, 411]), 'message: The domain() of yScale should be equivalent to [0, 411].');", - "assert(JSON.stringify(yScale.range()) == JSON.stringify([470, 30]), 'message: The range() of yScale should be equivalent to [470, 30].');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fac367417b2b2512bde", - "title": "Use a Pre-Defined Scale to Place Elements", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "With the scales set up, it's time to map the scatter plot again. The scales are like processing functions that turn the x and y raw data into values that fit and render correctly on the SVG canvas. They keep the data within the screen's plotting area.", - "You set the coordinate attribute values for an SVG shape with the scaling function. This includes x and y attributes for rect or text elements, or cx and cy for circles. Here's an example:", - "
    shape
    .attr(\"x\", (d) => xScale(d[0]))
    ", - "Scales set shape coordinate attributes to place the data points onto the SVG canvas. You don't need to apply scales when you display the actual data value, for example, in the text() method for a tooltip or label.", - "
    ", - "Use xScale and yScale to position both the circle and text shapes onto the SVG canvas. For the circles, apply the scales to set the cx and cy attributes. Give them a radius of 5 units, too.", - "For the text elements, apply the scales to set the x and y attributes. The labels should be offset to the right of the dots. To do this, add 10 units to the x data value before passing it to the xScale." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert($('circle').length == 10, 'message: Your code should have 10 circle elements.');", - "assert(Math.round($('circle').eq(0).attr('cx')) == '91' && Math.round($('circle').eq(0).attr('cy')) == '368' && $('circle').eq(0).attr('r') == '5', 'message: The first circle element should have a cx value of approximately 91 and a cy value of approximately 368 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(1).attr('cx')) == '159' && Math.round($('circle').eq(1).attr('cy')) == '181' && $('circle').eq(1).attr('r') == '5', 'message: The second circle element should have a cx value of approximately 159 and a cy value of approximately 181 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(2).attr('cx')) == '340' && Math.round($('circle').eq(2).attr('cy')) == '329' && $('circle').eq(2).attr('r') == '5', 'message: The third circle element should have a cx value of approximately 340 and a cy value of approximately 329 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(3).attr('cx')) == '131' && Math.round($('circle').eq(3).attr('cy')) == '60' && $('circle').eq(3).attr('r') == '5', 'message: The fourth circle element should have a cx value of approximately 131 and a cy value of approximately 60 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(4).attr('cx')) == '440' && Math.round($('circle').eq(4).attr('cy')) == '237' && $('circle').eq(4).attr('r') == '5', 'message: The fifth circle element should have a cx value of approximately 440 and a cy value of approximately 237 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(5).attr('cx')) == '271' && Math.round($('circle').eq(5).attr('cy')) == '306' && $('circle').eq(5).attr('r') == '5', 'message: The sixth circle element should have a cx value of approximately 271 and a cy value of approximately 306 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(6).attr('cx')) == '361' && Math.round($('circle').eq(6).attr('cy')) == '351' && $('circle').eq(6).attr('r') == '5', 'message: The seventh circle element should have a cx value of approximately 361 and a cy value of approximately 351 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(7).attr('cx')) == '261' && Math.round($('circle').eq(7).attr('cy')) == '132' && $('circle').eq(7).attr('r') == '5', 'message: The eighth circle element should have a cx value of approximately 261 and a cy value of approximately 132 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(8).attr('cx')) == '131' && Math.round($('circle').eq(8).attr('cy')) == '144' && $('circle').eq(8).attr('r') == '5', 'message: The ninth circle element should have a cx value of approximately 131 and a cy value of approximately 144 after applying the scales. It should also have an r value of 5.');", - "assert(Math.round($('circle').eq(9).attr('cx')) == '79' && Math.round($('circle').eq(9).attr('cy')) == '326' && $('circle').eq(9).attr('r') == '5', 'message: The tenth circle element should have a cx value of approximately 79 and a cy value of approximately 326 after applying the scales. It should also have an r value of 5.');", - "assert($('text').length == 10, 'message: Your code should have 10 text elements.');", - "assert(Math.round($('text').eq(0).attr('x')) == '100' && Math.round($('text').eq(0).attr('y')) == '368', 'message: The first label should have an x value of approximately 100 and a y value of approximately 368 after applying the scales.');", - "assert(Math.round($('text').eq(1).attr('x')) == '168' && Math.round($('text').eq(1).attr('y')) == '181', 'message: The second label should have an x value of approximately 168 and a y value of approximately 181 after applying the scales.');", - "assert(Math.round($('text').eq(2).attr('x')) == '350' && Math.round($('text').eq(2).attr('y')) == '329', 'message: The third label should have an x value of approximately 350 and a y value of approximately 329 after applying the scales.');", - "assert(Math.round($('text').eq(3).attr('x')) == '141' && Math.round($('text').eq(3).attr('y')) == '60', 'message: The fourth label should have an x value of approximately 141 and a y value of approximately 60 after applying the scales.');", - "assert(Math.round($('text').eq(4).attr('x')) == '449' && Math.round($('text').eq(4).attr('y')) == '237', 'message: The fifth label should have an x value of approximately 449 and a y value of approximately 237 after applying the scales.');", - "assert(Math.round($('text').eq(5).attr('x')) == '280' && Math.round($('text').eq(5).attr('y')) == '306', 'message: The sixth label should have an x value of approximately 280 and a y value of approximately 306 after applying the scales.');", - "assert(Math.round($('text').eq(6).attr('x')) == '370' && Math.round($('text').eq(6).attr('y')) == '351', 'message: The seventh label should have an x value of approximately 370 and a y value of approximately 351 after applying the scales.');", - "assert(Math.round($('text').eq(7).attr('x')) == '270' && Math.round($('text').eq(7).attr('y')) == '132', 'message: The eighth label should have an x value of approximately 270 and a y value of approximately 132 after applying the scales.');", - "assert(Math.round($('text').eq(8).attr('x')) == '140' && Math.round($('text').eq(8).attr('y')) == '144', 'message: The ninth label should have an x value of approximately 140 and a y value of approximately 144 after applying the scales.');", - "assert(Math.round($('text').eq(9).attr('x')) == '88' && Math.round($('text').eq(9).attr('y')) == '326', 'message: The tenth label should have an x value of approximately 88 and a y value of approximately 326 after applying the scales.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fad367417b2b2512bdf", - "title": "Add Axes to a Visualization", - "required": [ - { - "src": "https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js" - } - ], - "description": [ - "Another way to improve the scatter plot is to add an x-axis and a y-axis.", - "D3 has two methods axisLeft() and axisBottom() to render the y and x axes, respectively. (Axes is the plural form of axis). Here's an example to create the x-axis based on the xScale in the previous challenges:", - "const xAxis = d3.axisBottom(xScale);", - "The next step is to render the axis on the SVG canvas. To do so, you can use a general SVG component, the g element. The g stands for group.", - "Unlike rect, circle, and text, an axis is just a straight line when it's rendered. Because it is a simple shape, using g works.", - "The last step is to apply a transform attribute to position the axis on the SVG canvas in the right place. Otherwise, the line would render along the border of SVG canvas and wouldn't be visible.", - "SVG supports different types of transforms, but positioning an axis needs translate. When it's applied to the g element, it moves the whole group over and down by the given amounts. Here's an example:", - "
    const xAxis = d3.axisBottom(xScale);

    svg.append(\"g\")
    .attr(\"transform\", \"translate(0, \" + (h - padding) + \")\")
    .call(xAxis);
    ", - "The above code places the x-axis at the bottom of the SVG canvas. Then it's passed as an argument to the call() method.", - "The y-axis works is the same way, except the translate argument is in the form (x, 0). Because translate is a string in the attr() method above, you can use concatenation to include variable values for its arguments.", - "
    ", - "The scatter plot now has an x-axis. Create a y-axis in a variable named yAxis using the axisLeft() method. Then render the axis using a g element. Make sure to use a transform attribute to translate the axis by the amount of padding units right, and 0 units down. Remember to call() the axis." - ], - "challengeSeed": [ - "", - " ", - "" - ], - "tests": [ - "assert(code.match(/\\.axisLeft\\(yScale\\)/g), 'message: Your code should use the axisLeft() method with yScale passed as the argument.');", - "assert($('g').eq(1).attr('transform').match(/translate\\(60\\s*?,\\s*?0\\)/g), 'message: The y-axis g element should have a transform attribute to translate the axis by (60, 0).');", - "assert(code.match(/\\.call\\(yAxis\\)/g), 'message: Your code should call the yAxis.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json b/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json deleted file mode 100644 index 2dd425bd2d..0000000000 --- a/packages/learn/seed/tmp/04-data-visualization/json-apis-and-ajax.json +++ /dev/null @@ -1,693 +0,0 @@ -{ - "name": "JSON APIs and AJAX", - "order": 2, - "time": "2 hours", - "helpRoom": "Help", - "required": [ - { - "link": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" - } - ], - "challenges": [ - { - "id": "587d7fad367417b2b2512be0", - "title": "Introduction to the JSON APIs and AJAX Challenges", - "description": [ - "", - "", - "Similar to how User Interfaces help people use programs, Application Programming Interfaces (APIs) help programs interact with other programs. APIs are tools that computers use to communicate with one another, in part to send and receive data. You can use API functionality in your page once you understand how to make requests and process data from it. Programmers often use AJAX technologies when working with APIs.

    The term AJAX originated as an acronym for Asynchronous JavaScript And XML. It refers to a group of technologies that make asynchronous requests to a server to transfer data, then load any returned data into the page. An asynchronous process has a couple key properties. The browser does not stop loading a page to wait for the server's response. Also, the browser inserts updated data into part of the page without having to refresh the entire page.

    User experience benefits from asynchronous processes in several ways. Pages load faster since the browser isn't waiting for the server to respond in the middle of a page render. Requests and transfers happen in the background, without interrupting what the user is doing. When the browser receives new data, only the necessary area of the page refreshes. These qualities especially enhance the user experience for single page applications.

    The data transferred between the browser and server is often in a format called JavaScript Object Notation (JSON). JSON resembles JavaScript object literal syntax, except that it's transferred as a string. Once received, it can be converted into an object and used in a script.

    This section covers how to transfer and use data using AJAX technologies with a freeCodeCamp API.", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7fad367417b2b2512be1", - "title": "Handle Click Events with JavaScript using the onclick property", - "description": [ - "You want your code to execute only once your page has finished loading. For that purpose, you can attach a JavaScript event to the document called DOMContentLoaded. Here's the code that does this:", - "
    document.addEventListener('DOMContentLoaded',function() {

    });
    ", - "You can implement event handlers that go inside of the DOMContentLoaded function. You can implement an onclick event handler which triggers when the user clicks on the element with id getMessage, by adding the following code:", - "
    document.getElementById('getMessage').onclick=function(){};
    ", - "
    ", - "Add a click event handler inside of the DOMContentLoaded function for the element with id of getMessage." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/document\\.getElementById\\(\\s*?('|\")getMessage\\1\\s*?\\)/g), 'message: Your code should use the document.getElementById method to select the getMessage element.');", - "assert(typeof document.getElementById('getMessage').onclick === 'function', 'message: Your code should add an onclick event handler.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fad367417b2b2512be2", - "title": "Change Text with click Events", - "description": [ - "When the click event happens, you can use JavaScript to update an HTML element.", - "For example, when a user clicks the \"Get Message\" button, it changes the text of the element with the class message to say \"Here is the message\".", - "This works by adding the following code within the click event:", - "document.getElementsByClassName('message')[0].innerHTML=\"Here is the message\";", - "
    ", - "Add code inside the onclick event handler to change the text inside the message element to say \"Here is the message\"." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/document\\.getElementsByClassName\\(\\s*?('|\")message\\1\\s*?\\)\\[0\\]\\.innerHTML\\s*?=\\s*?('|\")Here is the message\\2/g), 'message: Your code should use the document.getElementsByClassName method to select the element with class message and set its innerHTML to the given string.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fae367417b2b2512be3", - "title": "Get JSON with the JavaScript XMLHttpRequest Method", - "description": [ - "You can also request data from an external source. This is where APIs come into play.", - "Remember that APIs - or Application Programming Interfaces - are tools that computers use to communicate with one another. You'll learn how to update HTML with the data we get from APIs using a technology called AJAX.", - "Most web APIs transfer data in a format called JSON. JSON stands for JavaScript Object Notation.", - "JSON syntax looks very similar to JavaScript object literal notation. JSON has object properties and their current values, sandwiched between a { and a }.", - "These properties and their values are often referred to as \"key-value pairs\".", - "However, JSON transmitted by APIs are sent as bytes, and your application receives it as a string. These can be converted into JavaScript objects, but they are not JavaScript objects by default. The JSON.parse method parses the string and constructs the JavaScript object described by it.", - "You can request the JSON from freeCodeCamp's Cat Photo API. Here's the code you can put in your click event to do this:", - "
    req=new XMLHttpRequest();
    req.open(\"GET\",'/json/cats.json',true);
    req.send();
    req.onload=function(){
    json=JSON.parse(req.responseText);
    document.getElementsByClassName('message')[0].innerHTML=JSON.stringify(json);
    };
    ", - "Here's a review of what each piece is doing. The JavaScript XMLHttpRequest object has a number of properties and methods that are used to transfer data. First, an instance of the XMLHttpRequest object is created and saved in the req variable.", - "Next, the open method initializes a request - this example is requesting data from an API, therefore is a \"GET\" request. The second argument for open is the URL of the API you are requesting data from. The third argument is a Boolean value where true makes it an asynchronous request.", - "The send method sends the request. Finally, the onload event handler parses the returned data and applies the JSON.stringify method to convert the JavaScript object into a string. This string is then inserted as the message text.", - "
    ", - "Update the code to create and send a \"GET\" request to the freeCodeCamp Cat Photo API. Then click the \"Get Message\" button. Your AJAX function will replace the \"The message will go here\" text with the raw JSON output from the API." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/new\\s+?XMLHttpRequest\\(\\s*?\\)/g), 'message: Your code should create a new XMLHttpRequest.');", - "assert(code.match(/\\.open\\(\\s*?('|\")GET\\1\\s*?,\\s*?('|\")\\/json\\/cats\\.json\\2\\s*?,\\s*?true\\s*?\\)/g), 'message: Your code should use the open method to initialize a \"GET\" request to the freeCodeCamp Cat Photo API.');", - "assert(code.match(/\\.send\\(\\s*\\)/g), 'message: Your code should use the send method to send the request.');", - "assert(code.match(/\\.onload\\s*=\\s*function\\(\\s*?\\)\\s*?{/g), 'message: Your code should have an onload event handler set to a function.');", - "assert(code.match(/JSON\\.parse\\(.*\\.responseText\\)/g), 'message: Your code should use the JSON.parse method to parse the responseText.');", - "assert(code.match(/document\\.getElementsByClassName\\(\\s*?('|\")message\\1\\s*?\\)\\[0\\]\\.innerHTML\\s*?=\\s*?JSON\\.stringify\\(.+?\\)/g), 'message: Your code should get the element with class message and change its inner HTML to the string of JSON data.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fae367417b2b2512be4", - "title": "Access the JSON Data from an API", - "description": [ - "In the previous challenge, you saw how to get JSON data from the freeCodeCamp Cat Photo API.", - "Now you'll take a closer look at the returned data to better understand the JSON format. Recall some notation in JavaScript:", - "
    [ ] -> Square brackets represent an array
    { } -> Curly brackets represent an object
    \" \" -> Double quotes represent a string. They are also used for key names in JSON
    ", - "Understanding the structure of the data that an API returns is important because it influences how you retrieve the values you need.", - "On the right, click the \"Get Message\" button to load the freeCodeCamp Cat Photo API JSON into the HTML.", - "The first and last character you see in the JSON data are square brackets [ ]. This means that the returned data is an array. The second character in the JSON data is a curly { bracket, which starts an object. Looking closely, you can see that there are three separate objects. The JSON data is an array of three objects, where each object contains information about a cat photo.", - "You learned earlier that objects contain \"key-value pairs\" that are separated by commas. In the Cat Photo example, the first object has \"id\":0 where \"id\" is a key and 0 is its corresponding value. Similarly, there are keys for \"imageLink\", \"altText\", and \"codeNames\". Each cat photo object has these same keys, but with different values.", - "Another interesting \"key-value pair\" in the first object is \"codeNames\":[\"Juggernaut\",\"Mrs. Wallace\",\"ButterCup\"]. Here \"codeNames\" is the key and its value is an array of three strings. It's possible to have arrays of objects as well as a key with an array as a value.", - "Remember how to access data in arrays and objects. Arrays use bracket notation to access a specific index of an item. Objects use either bracket or dot notation to access the value of a given property. Here's an example that prints the \"altText\" of the first cat photo - note that the parsed JSON data in the editor is saved in a variable called json:", - "
    console.log(json[0].altText);
    // Prints \"A white cat wearing a green helmet shaped melon on its head.\"
    ", - "
    ", - "For the cat with the \"id\" of 2, print to the console the second value in the codeNames array. You should use bracket and dot notation on the object (which is saved in the variable json) to access the value." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/(?:json\\[2\\]\\.codeNames\\[1\\]|json\\[2\\]\\[('|\")codeNames\\1\\]\\[1\\])/g), 'message: Your code should use bracket and dot notation to access the proper code name, and print \"Loki\" to the console.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fae367417b2b2512be5", - "title": "Convert JSON Data to HTML", - "description": [ - "Now that you're getting data from a JSON API, you can display it in the HTML.", - "You can use a forEach method to loop through the data since the cat photo objects are held in an array. As you get to each item, you can modify the HTML elements.", - "First, declare an html variable with var html = \"\";.", - "Then, loop through the JSON, adding HTML to the variable that wraps the key names in strong tags, followed by the value. When the loop is finished, you render it.", - "Here's the code that does this:", - "
    json.forEach(function(val) {
    var keys = Object.keys(val);
    html += \"<div class = 'cat'>\";
    keys.forEach(function(key) {
    html += \"<strong>\" + key + \"</strong>: \" + val[key] + \"<br>\";
    });
    html += \"</div><br>\";
    });
    ", - "
    ", - "Add a forEach method to loop over the JSON data and create the HTML elements to display it.", - "Here is some example JSON", - "
    [
    {
    \"id\":0,
    \"imageLink\":\"https://s3.amazonaws.com/freecodecamp/funny-cat.jpg\",
    \"altText\":\"A white cat wearing a green helmet shaped melon on its head. \",
    \"codeNames\":[
    \"Juggernaut\",
    \"Mrs. Wallace\",
    \"Buttercup\"
    ]
    }
    ]
    " - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/html\\s+?(\\+=|=\\shtml\\s\\+)/g), 'message: Your code should store the data in the html variable');", - "assert(code.match(/json\\.forEach/g), 'message: Your code should use a forEach method to loop over the JSON data from the API.');", - "assert(code.match(/.+<\\/strong>/g), 'message: Your code should wrap the key names in strong tags.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fae367417b2b2512be6", - "title": "Render Images from Data Sources", - "description": [ - "The last few challenges showed that each object in the JSON array contains an imageLink key with a value that is the URL of a cat's image.", - "When you're looping through these objects, you can use this imageLink property to display this image in an img element.", - "Here's the code that does this:", - "html += \"<img src = '\" + val.imageLink + \"' \" + \"alt='\" + val.altText + \"'>\";", - "
    ", - "Add code to use the imageLink and altText properties in an img tag." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/val\\.imageLink/g), 'message: You should use the imageLink property to display the images.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7fae367417b2b2512be7", - "title": "Pre-filter JSON to Get the Data You Need", - "description": [ - "If you don't want to render every cat photo you get from the freeCodeCamp Cat Photo API, you can pre-filter the JSON before looping through it.", - "Given that the JSON data is stored in an array, you can use the filter method to filter out the cat whose \"id\" key has a value of 1.", - "Here's the code to do this:", - "
    json = json.filter(function(val) {
    return (val.id !== 1);
    });
    ", - "
    ", - "Add code to filter the json data to remove the cat with the \"id\" value of 1." - ], - "challengeSeed": [ - "", - "", - "

    Cat Photo Finder

    ", - "

    ", - " The message will go here", - "

    ", - "

    ", - " ", - "

    " - ], - "tests": [ - "assert(code.match(/json\\.filter/g), 'message: Your code should use the filter method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faf367417b2b2512be8", - "title": "Get Geolocation Data to Find A User's GPS Coordinates", - "description": [ - "Another cool thing you can do is access your user's current location. Every browser has a built in navigator that can give you this information.", - "The navigator will get the user's current longitude and latitude.", - "You will see a prompt to allow or block this site from knowing your current location. The challenge can be completed either way, as long as the code is correct.", - "By selecting allow, you will see the text on the output phone change to your latitude and longitude.", - "Here's code that does this:", - "
    if (navigator.geolocation){
    navigator.geolocation.getCurrentPosition(function(position) {
    document.getElementById('data').innerHTML=\"latitude: \"+ position.coords.latitude + \"<br>longitude: \" + position.coords.longitude;
    });
    }
    ", - "First, it checks if the navigator.geolocation object exists. If it does, the getCurrentPosition method on that object is called, which initiates an asynchronous request for the user's position. If the request is successful, the callback function in the method runs. This function accesses the position object's values for latitude and longitude using dot notation and updates the HTML.", - "
    ", - "Add the example code inside the script tags to check a user's current location and insert it into the HTML." - ], - "challengeSeed": [ - "", - "

    You are here:

    ", - "
    ", - "", - "
    " - ], - "tests": [ - "assert(code.match(/navigator\\.geolocation\\.getCurrentPosition/g), 'message: Your code should use navigator.geolocation to access the user's current location.');", - "assert(code.match(/position\\.coords\\.latitude/g), 'message: Your code should use position.coords.latitude to display the user's latitudinal location.');", - "assert(code.match(/position\\.coords\\.longitude/g), 'message: Your code should use position.coords.longitude to display the user's longitudinal location.');", - "assert(code.match(/document\\.getElementById\\(\\s*?('|\")data\\1\\s*?\\)\\.innerHTML/g), 'message: You should display the user's position within the data div element.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - }, - { - "id": "587d7faf367417b2b2512be9", - "title": "Post Data with the JavaScript XMLHttpRequest Method", - "description": [ - "In the previous examples, you received data from an external resource. You can also send data to an external resource, as long as that resource supports AJAX requests and you know the URL.", - "JavaScript's XMLHttpRequest method is also used to post data to a server. Here's an example:", - "
    req=new XMLHttpRequest();
    req.open(\"POST\",url,true);
    req.setRequestHeader('Content-Type','text/plain');
    req.onreadystatechange=function(){
    if(req.readyState==4 && req.status==200){
    document.getElementsByClassName('message')[0].innerHTML=req.responseText;
    }
    };
    req.send(userName);
    ", - "You've seen several of these methods before. Here the open method initializes the request as a \"POST\" to the given URL of the external resource, and uses the true Boolean to make it asynchronous.", - "The setRequestHeader method sets the value of an HTTP request header, which contains information about the sender and the request. It must be called after the open method, but before the send method. The two parameters are the name of the header and the value to set as the body of that header.", - "Next, the onreadystatechange event listener handles a change in the state of the request. A readyState of 4 means the operation is complete, and a status of 200 means it was a successful request. The document's HTML can be updated.", - "Finally, the send method sends the request with the userName value, which was given by the user in the input field.", - "
    ", - "Update the code to create and send a \"POST\" request. Then enter your name in input box and click \"Send Message\". Your AJAX function will replace \"Reply from Server will be here.\" with the reply of the server. In this case, it is your name appended with \" loves cats\"." - ], - "challengeSeed": [ - "", - "", - "

    Cat Friends

    ", - "

    ", - " Reply from Server will be here", - "

    ", - "

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

    " - ], - "tests": [ - "assert(code.match(/new\\s+?XMLHttpRequest\\(\\s*?\\)/g), 'message: Your code should create a new XMLHttpRequest.');", - "assert(code.match(/\\.open\\(\\s*?('|\")POST\\1\\s*?,\\s*?url\\s*?,\\s*?true\\s*?\\)/g), 'message: Your code should use the open method to initialize a \"POST\" request to the server.');", - "assert(code.match(/\\.setRequestHeader\\(\\s*?('|\")Content-Type\\1\\s*?,\\s*?('|\")text\\/plain\\2\\s*?\\)/g), 'message: Your code should use the setRequestHeader method.');", - "assert(code.match(/\\.onreadystatechange\\s*?=/g), 'message: Your code should have an onreadystatechange event handler set to a function.');", - "assert(code.match(/document\\.getElementsByClassName\\(\\s*?('|\")message\\1\\s*?\\)\\[0\\]\\.innerHTML\\s*?=\\s*?.+?\\.responseText/g), 'message: Your code should get the element with class message and change its inner HTML to the responseText.');", - "assert(code.match(/\\.send\\(\\s*?userName\\s*?\\)/g), 'message: Your code should use the send method.');" - ], - "solutions": [], - "hints": [], - "type": "waypoint", - "releasedOn": "Feb 17, 2017", - "challengeType": 0, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json b/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json deleted file mode 100644 index eca6eab092..0000000000 --- a/packages/learn/seed/tmp/05-apis-and-microservices/api-and-microservice-projects.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "name": "API and Microservice Projects", - "order": 4, - "time": "150 hours", - "helpRoom": "HelpBackend", - "challenges": [ - { - "id": "bd7158d8c443edefaeb5bdef", - "title": "Timestamp Microservice", - "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://curse-arrow.glitch.me/.", - "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "I can pass a string as a parameter, and it will check to see whether that string contains either a unix timestamp or a natural language date (example: January 1, 2016).", - "testString": "" - }, - { - "text": "If it does, it returns both the Unix timestamp and the natural language form of that date.", - "testString": "" - }, - { - "text": "If it does not contain a date or Unix timestamp, it returns null for those properties.", - "testString": "" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "isRequired": true, - "releasedOn": "January 1, 2016", - "translations": { - "es": { - "title": "Microservicio de Marca Temporal" - } - } - }, - { - "id": "bd7158d8c443edefaeb5bdff", - "title": "Request Header Parser Microservice", - "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://dandelion-roar.glitch.me/.", - "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "I can get the IP address, language and operating system for my browser.", - "testString": "" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "isRequired": true, - "releasedOn": "January 1, 2016", - "translations": { - "es": { - "title": "Microservicio para analizar el encabezado de una petición" - } - } - }, - { - "id": "bd7158d8c443edefaeb5bd0e", - "title": "URL Shortener Microservice", - "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://thread-paper.glitch.me/.", - "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "I can pass a URL as a parameter and I will receive a shortened URL in the JSON response.", - "testString": "" - }, - { - "text": "If I pass an invalid URL that doesn't follow the valid http://www.example.com format, the JSON response will contain an error instead.", - "testString": "" - }, - { - "text": "When I visit that shortened URL, it will redirect me to my original link.", - "testString": "" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "isRequired": true, - "releasedOn": "January 1, 2016", - "translations": { - "es": { - "title": "Microservicio para acortar URLs" - } - } - }, - { - "id": "5a8b073d06fa14fcfde687aa", - "title": "Exercise Tracker", - "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://fuschia-custard.glitch.me/.", - "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "I can create a user by posting form data username to /api/exercise/new-user and returned will be an object with username and _id.", - "testString": "" - }, - { - "text": "I can get an array of all users by getting api/exercise/users with the same info as when creating a user.", - "testString": "" - }, - { - "text": "I can add an exercise to any user by posting form data userId(_id), description, duration, and optionally date to /api/exercise/add. If no date supplied it will use current date. App will return the user object with the exercise fields added.", - "testString": "" - }, - { - "text": "I can retrieve a full exercise log of any user by getting /api/exercise/log with a parameter of userId(_id). App will return the user object with added array log and count (total exercise count).", - "testString": "" - }, - { - "text": "I can retrieve part of the log of any user by also passing along optional parameters of from & to or limit. (Date format yyyy-mm-dd, limit = int)", - "testString": "" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "isRequired": true, - "releasedOn": "February 17, 2017", - "translations": { - "es": { - "title": "Capa de abstracción para buscar imágenes" - } - } - }, - { - "id": "bd7158d8c443edefaeb5bd0f", - "title": "File Metadata Microservice", - "description": [ - "Build a full stack JavaScript app that is functionally similar to this: https://purple-paladin.glitch.me/.", - "Working on this project will involve you writing your code on Glitch on our starter project. After completing this project you can copy your public glitch url (to the homepage of your app) into this screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.", - "Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "I can submit a FormData object that includes a file upload.", - "testString": "" - }, - { - "text": "When I submit something, I will receive the file size in bytes within the JSON response.", - "testString": "" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "isRequired": true, - "releasedOn": "January 1, 2016", - "translations": { - "es": { - "title": "Microservicio de metadatos de archivos" - } - } - } - ] -} diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json b/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json deleted file mode 100644 index ebb11edba5..0000000000 --- a/packages/learn/seed/tmp/05-apis-and-microservices/basic-node-and-express.json +++ /dev/null @@ -1,310 +0,0 @@ -{ - "name": "Basic Node and Express", - "order": 2, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7fb0367417b2b2512bec", - "title": "Introduction to the Basic Node and Express Challenges", - "description": [ - "", - "", - "Node.js is a JavaScript tool that allows developers to write backend (server-side) programs in JavaScript. Node.js comes with a handful of built-in modules—small, independent programs—that help facilitate this purpose. Some of the core modules include:

    • HTTP: a module that acts as a server
    • File System: a module that reads and modifies files
    • Path: a module for working with directory and file paths
    • Assertion Testing: a module that checks code against prescribed constraints

    Express, while not included with Node.js, is another module often used with it. Express runs between the server created by Node.js and the frontend pages of a web application. Express also handles an application's routing. Routing directs users to the correct page based on their interaction with the application.

    While there are alternatives to using Express, its simplicity makes it a good place to begin when learning the interaction between a backend powered by Node.js and the frontend.", - "", - "@@STEP@@", - "", - "", - "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7fb0367417b2b2512bed", - "title": "Meet the Node console", - "description": [ - "During the development process, it is important to be able to check what’s going on in your code. Node is just a JavaScript environment. Like client side JavaScript, you can use the console to display useful debug information. On your local machine, you would see the console output in a terminal. On Glitch you can open the logs in the lower part of the screen. You can toggle the log panel with the button ‘Logs’ (top-left, under the app name).", - "To get started, just print the classic \"Hello World\" in the console. We recommend to keep the log panel open while working at these challenges. Reading the logs you can be aware of the nature of the errors that may occur." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"Hello World\" should be in the console", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/hello-console').then(data => { assert.isTrue(data.passed, '\"Hello World\" is not in the server console'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb0367417b2b2512bee", - "title": "Start a Working Express Server", - "description": [ - "In the first two lines of the file myApp.js you can see how it’s easy to create an Express app object. This object has several methods, and we will learn many of them in these challenges. One fundamental method is app.listen(port). It tells your server to listen on a given port, putting it in running state. You can see it at the bottom of the file. It is inside comments because for testing reasons we need the app to be running in background. All the code that you may want to add goes between these two fundamental parts. Glitch stores the port number in the environemet variable process.env.PORT. Its value is 3000.", - "Let’s serve our first string! In Express, routes takes the following structure: app.METHOD(PATH, HANDLER). METHOD is an http method in lowercase. PATH is a relative path on the server (it can be a string, or even a regular expression). HANDLER is a function that Express calls when the route is matched.", - "Handlers take the form function(req, res) {...}, where req is the request object, and res is the response object. For example, the handler", - "
    function(req, res) {
    res.send('Response String');
    }
    ", - "will serve the string 'Response String'.", - "Use the app.get() method to serve the string Hello Express, to GET requests matching the / root path. Be sure that your code works by looking at the logs, then see the results in your browser, clicking the button ‘Show Live’ in the Glitch UI." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Your app should serve the string 'Hello Express'", - "testString": "getUserInput => $.get(getUserInput('url')).then(data => { assert.equal(data, 'Hello Express', 'Your app does not serve the text \"Hello Express\"'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb0367417b2b2512bef", - "title": "Serve an HTML File", - "description": [ - "We can respond with a file using the method res.sendFile(path).", - "You can put it inside the app.get('/', ...) route handler. Behind the scenes this method will set the appropriate headers to instruct your browser on how to handle the file you want to send, according to its type. Then it will read and send the file. This method needs an absolute file path. We recommend you to use the Node global variable __dirname to calculate the path.", - "e.g. absolutePath = __dirname + relativePath/file.ext.", - "The file to send is /views/index.html. Try to ‘Show Live’ your app, you should see a big HTML heading (and a form that we will use later…), with no style applied.", - "Note: You can edit the solution of the previous challenge, or create a new one. If you create a new solution, keep in mind that Express evaluates the routes from top to bottom. It executes the handler for the first match. You have to comment out the preceding solution, or the server will keep responding with a string." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Your app should serve the file views/index.html", - "testString": "getUserInput => $.get(getUserInput('url')).then(data => { assert.match(data, /

    .*<\\/h1>/, 'Your app does not serve the expected HTML'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb0367417b2b2512bf0", - "title": "Serve Static Assets", - "description": [ - "An HTML server usually has one or more directories that are accessible by the user. You can place there the static assets needed by your application (stylesheets, scripts, images). In Express you can put in place this functionality using the middleware express.static(path), where the parameter is the absolute path of the folder containing the assets. If don’t know what a middleware is, don’t worry. We’ll discuss about it later in details. Basically middlewares are functions that intercept route handlers, adding some kind of information. A middleware needs to be mounted using the method app.use(path, middlewareFunction). The first path argument is optional. If you don’t pass it, the middleware will be executed for all the requests.", - "Mount the express.static() middleware for all the requests with app.use(). The absolute path to the assets folder is __dirname + /public.", - "Now your app should be able to serve a CSS stylesheet. From outside the public folder will appear mounted to the root directory. Your front-page should look a little better now!" - ], - "challengeSeed": [], - "tests": [ - { - "text": "Your app should serve asset files from the /public directory", - "testString": "getUserInput => $.get(getUserInput('url') + '/style.css').then(data => { assert.match(data, /body\\s*\\{[^\\}]*\\}/, 'Your app does not serve static assets'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb1367417b2b2512bf1", - "title": "Serve JSON on a Specific Route", - "description": [ - "While an HTML server serves (you guessed it!) HTML, an API serves data. A REST (REpresentational State Transfer) API allows data exchange in a simple way, without the need for clients to know any detail about the server. The client only needs to know where the resource is (the URL), and the action it wants to perform on it (the verb). The GET verb is used when you are fetching some information, without modifying anything. These days, the preferred data format for moving information around the web is JSON. Simply put, JSON is a convenient way to represent a JavaScript object as a string, so it can be easily transmitted.", - "Let's create a simple API by creating a route that responds with JSON at the path /json. You can do it as usual, with the app.get() method. Inside the route handler use the method res.json(), passing in an object as an argument. This method closes the request-response loop, returning the data. Behind the scenes it converts a valid JavaScript object into a string, then sets the appropriate headers to tell your browser that you are serving JSON, and sends the data back. A valid object has the usual structure {key: data}. Data can ba a number, a string, a nested object or an array. Data can also be a variable or the result of a function call; in which case it will be evaluated before being converted into a string.", - "Serve the object {\"message\": \"Hello json\"} as a response in JSON format, to the GET requests to the route /json. Then point your browser to your-app-url/json, you should see the message on the screen." - ], - "challengeSeed": [], - "tests": [ - { - "text": "The endpoint /json should serve the json object {\"message\": \"Hello json\"}", - "testString": "getUserInput => $.get(getUserInput('url') + '/json').then(data => { assert.equal(data.message, 'Hello json', 'The \\'/json\\' endpoint does not serve the right data'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb1367417b2b2512bf2", - "title": "Use the .env File", - "description": [ - "The .env file is a hidden file that is used to pass environment variables to your application. This file is secret, no one but you can access it, and it can be used to store data that you want to keep private or hidden. For example, you can store API keys from external services or your database URI. You can also use it to store configuration options. By setting configuration options, you can change the behavior of your application, without the need to rewrite some code.", - "The environment variables are accessible from the app as process.env.VAR_NAME. The process.env object is a global Node object, and variables are passed as strings. By convention, the variable names are all uppercase, with words separated by an underscore. The .env is a shell file, so you don’t need to wrap names or values in quotes. It is also important to note that there cannot be space around the equals sign when you are assigning values to your variables, e.g. VAR_NAME=value. Usually, you will put each variable definition on a separate line.", - "Let's add an environment variable as a configuration option. Store the variable MESSAGE_STYLE=uppercase in the .env file. Then tell the GET /json route handler that you created in the last challenge to transform the response object’s message to uppercase if process.env.MESSAGE_STYLE equals uppercase. The response object should become {\"message\": \"HELLO JSON\"}." - ], - "challengeSeed": [], - "tests": [ - { - "text": "The response of the endpoint /json should change according to the environment variable MESSAGE_STYLE", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/use-env-vars').then(data => { assert.isTrue(data.passed, 'The response of \"/json\" does not change according to MESSAGE_STYLE'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb1367417b2b2512bf3", - "title": "Implement a Root-Level Request Logger Middleware", - "description": [ - "Before we introduced the express.static() middleware function. Now it’s time to see what middleware is, in more detail. Middleware functions are functions that take 3 arguments: the request object, the response object, and the next function in the application’s request-response cycle. These functions execute some code that can have side effects on the app, and usually add informations to the request or response objects. They can also end the cycle sending the response, when some condition is met. If they don’t send the response, when they are done they start the execution of the next function in the stack. This is triggered calling the 3rd argument next(). More information in the express documentation.", - "Look at the following example :", - "
    function(req, res, next) {
    console.log(\"I'm a middleware...\");
    next();
    }
    ", - "Let’s suppose we mounted this function on a route. When a request matches the route, it displays the string “I’m a middleware…”. Then it executes the next function in the stack.", - "In this exercise we are going to build a root-level middleware. As we have seen in challenge 4, to mount a middleware function at root level we can use the method app.use(<mware-function>). In this case the function will be executed for all the requests, but you can also set more specific conditions. For example, if you want a function to be executed only for POST requests, you could use app.post(<mware-function>). Analogous methods exist for all the http verbs (GET, DELETE, PUT, …).", - "Build a simple logger. For every request, it should log in the console a string taking the following format: method path - ip. An example would look like: GET /json - ::ffff:127.0.0.1. Note that there is a space between method and path and that the dash separating path and ip is surrounded by a space on either side. You can get the request method (http verb), the relative route path, and the caller’s ip from the request object, using req.method, req.path and req.ip. Remember to call next() when you are done, or your server will be stuck forever. Be sure to have the ‘Logs’ opened, and see what happens when some request arrives…", - "Hint: Express evaluates functions in the order they appear in the code. This is true for middleware too. If you want it to work for all the routes, it should be mounted before them." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Root level logger middleware should be active", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/root-middleware-logger').then(data => { assert.isTrue(data.passed, 'root-level logger is not working as expected'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb1367417b2b2512bf4", - "title": "Chain Middleware to Create a Time Server", - "description": [ - "Middleware can be mounted at a specific route using app.METHOD(path, middlewareFunction). Middleware can also be chained inside route definition.", - "Look at the following example:", - "
    app.get('/user', function(req, res, next) {
    req.user = getTheUserSync(); // Hypotetical synchronous operation
    next();
    }, function(req, res) {
    res.send(req.user);
    })
    ", - "This approach is useful to split the server operations into smaller units. That leads a to a better app structure, and the possibility to reuse code in different places. This approach can also be used to perform some validation on the data. At each point of the middleware stack you can block the execution of the current chain and pass control to functions specifically designed to handle errors. Or you can pass control to the next matching route, to handle special cases. We will see how in the advanced Express section.", - "In the route app.get('/now', ...) chain a middleware function and the final handler. In the middleware function you should add the current time to the request object in the req.time key. You can use new Date().toString(). In the handler, respond with a JSON object, taking the structure {time: req.time}.", - "Hint: The test will not pass if you don’t chain the middleware. If you mount the function somewhere else, the test will fail, even if the output result is correct." - ], - "challengeSeed": [], - "tests": [ - { - "text": "The /now endpoint should have mounted middleware", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/chain-middleware-time').then(data => { assert.equal(data.stackLength, 2, '\"/now\" route has no mounted middleware'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "The /now endpoint should return a time that is +/- 20 secs from now", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/chain-middleware-time').then(data => { var now = new Date(); assert.isAtMost(Math.abs(new Date(data.time) - now), 20000, 'the returned time is not between +- 20 secs from now'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb2367417b2b2512bf5", - "title": "Get Route Parameter Input from the Client", - "description": [ - "When building an API, we have to allow users to comunicate us what they want to get from our service. For example, if the client is requesting information about a user stored in the database, they need a way to let us know which user they're interested in. One possible way to achieve this result is using route parameters. Route parameters are named segments of the URL, delimited by slashes (/). Each segment captures the value of the part of the URL which matches its position. The captured values can be found in the req.params object.", - "
    route_path: '/user/:userId/book/:bookId'
    actual_request_URL: '/user/546/book/6754'
    req.params: {userId: '546', bookId: '6754'}
    ", - "Build an echo server, mounted at the route GET /:word/echo. Respond with a JSON object, taking the structure {echo: word}. You can find the word to be repeated at req.params.word. You can test your route from your browser's address bar, visiting some matching routes, e.g. your-app-rootpath/freecodecamp/echo" - ], - "challengeSeed": [], - "tests": [ - { - "text": "Test 1 : Your echo server should repeat words correctly", - "testString": "getUserInput => $.get(getUserInput('url') + '/eChOtEsT/echo').then(data => { assert.equal(data.echo, 'eChOtEsT', 'Test 1: the echo server is not working as expected') }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "Test 2 : Your echo server should repeat words correctly", - "testString": "getUserInput => $.get(getUserInput('url') + '/ech0-t3st/echo').then(data => { assert.equal(data.echo, 'ech0-t3st', 'Test 2: the echo server is not working as expected') }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb2367417b2b2512bf6", - "title": "Get Query Parameter Input from the Client", - "description": [ - "Another common way to get input from the client is by encoding the data after the route path, using a query string. The query string is delimited by a question mark (?), and includes field=value couples. Each couple is separated by an ampersand (&). Express can parse the data from the query string, and populate the object req.query. Some characters cannot be in URLs, they have to be encoded in a different format before you can send them. If you use the API from JavaScript, you can use specific methods to encode/decode these characters.", - "
    route_path: '/library'
    actual_request_URL: '/library?userId=546&bookId=6754'
    req.query: {userId: '546', bookId: '6754'}
    ", - "Build an API endpoint, mounted at GET /name. Respond with a JSON document, taking the structure { name: 'firstname lastname'}. The first and last name parameters should be encoded in a query string e.g. ?first=firstname&last=lastname.", - "TIP: In the following exercise we are going to receive data from a POST request, at the same /name route path. If you want you can use the method app.route(path).get(handler).post(handler). This syntax allows you to chain different verb handlers on the same path route. You can save a bit of typing, and have cleaner code." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Test 1 : Your API endpoint should respond with the correct name", - "testString": "getUserInput => $.get(getUserInput('url') + '/name?first=Mick&last=Jagger').then(data => { assert.equal(data.name, 'Mick Jagger', 'Test 1: \"GET /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "Test 2 : Your APi endpoint should respond with the correct name", - "testString": "getUserInput => $.get(getUserInput('url') + '/name?last=Richards&first=Keith').then(data => { assert.equal(data.name, 'Keith Richards', 'Test 2: \"GET /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb2367417b2b2512bf7", - "title": "Use body-parser to Parse POST Requests", - "description": [ - "Besides GET there is another common http verb, it is POST. POST is the default method used to send client data with HTML forms. In the REST convention POST is used to send data to create new items in the database (a new user, or a new blog post). We don’t have a database in this project, but we are going to learn how to handle POST requests anyway.", - "In these kind of requests the data doesn’t appear in the URL, it is hidden in the request body. This is a part of the HTML request, also called payload. Since HTML is text based, even if you don’t see the data, it doesn’t mean that they are secret. The raw content of an HTTP POST request is shown below:", - "
    POST /path/subpath HTTP/1.0
    From: john@example.com
    User-Agent: someBrowser/1.0
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 20
    name=John+Doe&age=25
    ", - "As you can see the body is encoded like the query string. This is the default format used by HTML forms. With Ajax we can also use JSON to be able to handle data having a more complex structure. There is also another type of encoding: multipart/form-data. This one is used to upload binary files.", - "In this exercise we will use an urlencoded body.", - "To parse the data coming from POST requests, you have to install a package: the body-parser. This package allows you to use a series of middleware, which can decode data in different formats. See the docs here.", - "Install the body-parser module in your package.json. Then require it at the top of the file. Store it in a variable named bodyParser.", - "The middleware to handle url encoded data is returned by bodyParser.urlencoded({extended: false}). extended=false is a configuration option that tells the parser to use the classic encoding. When using it, values can be only strings or arrays. The extended version allows more data flexibility, but it is outmatched by JSON. Pass to app.use() the function returned by the previous method call. As usual, the middleware must be mounted before all the routes which need it." - ], - "challengeSeed": [], - "tests": [ - { - "text": "The 'body-parser' middleware should be mounted", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/add-body-parser').then(data => { assert.isAbove(data.mountedAt, 0, '\"body-parser\" is not mounted correctly') }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb2367417b2b2512bf8", - "title": "Get Data from POST Requests", - "description": [ - "Mount a POST handler at the path /name. It’s the same path as before. We have prepared a form in the html frontpage. It will submit the same data of exercise 10 (Query string). If the body-parser is configured correctly, you should find the parameters in the object req.body. Have a look at the usual library example:", - "
    route: POST '/library'
    urlencoded_body: userId=546&bookId=6754
    req.body: {userId: '546', bookId: '6754'}
    ", - "Respond with the same JSON object as before: {name: 'firstname lastname'}. Test if your endpoint works using the html form we provided in the app frontpage.", - "Tip: There are several other http methods other than GET and POST. And by convention there is a corrispondence between the http verb, and the operation you are going to execute on the server. The conventional mapping is:", - "POST (sometimes PUT) - Create a new resource using the information sent with the request,", - "GET - Read an existing resource without modifying it,", - "PUT or PATCH (sometimes POST) - Update a resource using the data sent,", - "DELETE => Delete a resource.", - "There are also a couple of other methods which are used to negotiate a connection with the server. Except from GET, all the other methods listed above can have a payload (i.e. the data into the request body). The body-parser middleware works with these methods as well." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Test 1 : Your API endpoint should respond with the correct name", - "testString": "getUserInput => $.post(getUserInput('url') + '/name', {first: 'Mick', last: 'Jagger'}).then(data => { assert.equal(data.name, 'Mick Jagger', 'Test 1: \"POST /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "Test 2 : Your API endpoint should respond with the correct name", - "testString": "getUserInput => $.post(getUserInput('url') + '/name', {first: 'Keith', last: 'Richards'}).then(data => { assert.equal(data.name, 'Keith Richards', 'Test 2: \"POST /name\" route does not behave as expected') }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json b/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json deleted file mode 100644 index dc28fbf1d7..0000000000 --- a/packages/learn/seed/tmp/05-apis-and-microservices/managing-packages-with-npm.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "name": "Managing Packages with npm", - "order": 1, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7fb3367417b2b2512bfa", - "title": "Introduction to the Managing Packages with npm Challenges", - "description": [ - "", - "", - "The Node Package Manager (npm) is a command-line tool used by developers to share and control modules (or packages) of JavaScript code written for use with Node.js.

    When starting a new project, npm generates a package.json file. This file lists the package dependencies for your project. Since npm packages are regularly updated, the package.json file allows you to set specific version numbers for each dependency. This ensures that updates to a package don't break your project.

    npm saves packages in a folder named node_modules. These packages can be installed in two ways:

    1. globally in a root node_modules folder, accessible by all projects.
    2. locally within a project's own node_modules folder, accessible only to that project.

    Most developers prefer to install packages local to each project to create a separation between the dependencies of different projects.", - "", - "@@STEP@@", - "", - "", - "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7fb3367417b2b2512bfb", - "title": "How to Use package.json, the Core of Any Node.js Project or npm Package", - "description": [ - "The file package.json is the center of any Node.js project or npm package. It stores information about your project just like the -section in a HTML document describes the content of a webpage. The package.json consists of a single JSON-object where information is stored in \"key\": value-pairs. There are only two required fields in a minimal package.json - name and version - but it’s a good practice to provide additional information about your project that could be useful to future users or maintainers.", - "The author-field", - "If you go to the Glitch project that you set up previously and look at on the left side of your screen, you’ll find the file tree where you can see an overview of the various files in your project. Under the file tree’s back-end section, you’ll find package.json - the file that we’ll be improving in the next couple of challenges.", - "One of the most common pieces of information in this file is the author-field that specifies who’s the creator of a project. It can either be a string or an object with contact details. The object is recommended for bigger projects but in our case, a simple string like the following example will do.", - "\"author\": \"Jane Doe\",", - "Instructions", - "Add your name to the author-field in the package.json of your Glitch project.", - "Remember that you’re writing JSON.", - "All field-names must use double-quotes (\"), e.g. \"author\"", - "All fields must be separated with a comma (,)" - ], - "challengeSeed": [], - "tests": [ - { - "text": "package.json should have a valid \"author\" key", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.author, '\"author\" is missing'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb3367417b2b2512bfc", - "title": "Add a Description to Your package.json", - "description": [ - "The next part of a good package.json is the description-field, where a short but informative description about your project belongs.", - "If you some day plan to publishing a package to npm, remember that this is the string that should sell your idea to the user when they decide whether to install your package or not. However, that’s not the only use case for the description: Since it’s a great way to summarize what a project does, it’s just as important for your normal Node.js-projects to help other developers, future maintainers or even your future self understand the project quickly.", - "Regardless of what you plan for your project, a description is definitely recommended. Let’s add something similar to this:", - "\"description\": \"A project that does something awesome\",", - "Instructions", - "Add a description to the package.json in your Glitch project.", - "Remember to use double-quotes for field-names (\") and commas (,) to separate fields." - ], - "challengeSeed": [], - "tests": [ - { - "text": "package.json should have a valid \"description\" key", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.description, '\"description\" is missing'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb4367417b2b2512bfd", - "title": "Add Keywords to Your package.json", - "description": [ - "The keywords-field is where you can describe your project using related keywords.", - "Example", - "\"keywords\": [ \"descriptive\", \"related\", \"words\" ],", - "As you can see, this field is structured as an array of double-quoted strings.", - "Instructions", - "Add an array of suitable strings to the keywords-field in the package.json of your Glitch project.", - "One of the keywords should be freecodecamp." - ], - "challengeSeed": [], - "tests": [ - { - "text": "package.json should have a valid \"keywords\" key", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.keywords, '\"keywords\" is missing'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"keywords\" field should be an Array", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.isArray(packJson.keywords, '\"keywords\" is not an array'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"keywords\" should include \"freecodecamp\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.include(packJson.keywords, 'freecodecamp', '\"keywords\" does not include \"freecodecamp\"'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb4367417b2b2512bfe", - "title": "Add a License to Your package.json", - "description": [ - "TODO: This challenge could be used to inspire more people to develop OSS - we should really improve this description.", - "The license-field is where you inform users of your project what they are allowed to do with it.", - "Some common licenses for open source projects include MIT and BSD. http://choosealicense.com is a great resource if you want to learn more about what license could fit your project.", - "License information is not required. Copyright laws in most countries will give you ownership of what you create by default. However, it’s always a good practice to explicitly state what users can and can’t do.", - "Example", - "\"license\": \"MIT\",", - "Instructions", - "Fill the license-field in the package.json of your Glitch project as you find suitable." - ], - "challengeSeed": [], - "tests": [ - { - "text": "package.json should have a valid \"license\" key", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.license, '\"license\" is missing'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb4367417b2b2512bff", - "title": "Add a Version to Your package.json", - "description": [ - "The version is together with name one of the required fields in a package.json. This field describes the current version of your project.", - "Example", - "\"version\": \"1.2\",", - "Instructions", - "Add a version to the package.json in your Glitch project." - ], - "challengeSeed": [], - "tests": [ - { - "text": "package.json should have a valid \"version\" key", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.version, '\"version\" is missing'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb4367417b2b2512c00", - "title": "Expand Your Project with External Packages from npm", - "description": [ - "One of the biggest reasons to use a package manager is their powerful dependency management. Instead of manually having to make sure that you get all dependencies whenever you set up a project on a new computer, npm automatically installs everything for you. But how can npm know exactly what your project needs? Meet the dependencies-section of your package.json.", - "In the dependencies-section, packages your project require are stored using the following format:", - "\"dependencies\": {", - " \"package-name\": \"version\",", - " \"express\": \"4.14.0\"", - "}", - "Instructions", - "Add version 2.14.0 of the package moment to the dependencies-field of your package.json", - "Moment is a handy library for working with time and dates." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"dependencies\" should include \"moment\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"moment\" version should be \"2.14.0\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.14\\.0/, 'Wrong version of \"moment\" installed. It should be 2.14.0'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb5367417b2b2512c01", - "title": "Manage npm Dependencies By Understanding Semantic Versioning", - "description": [ - "Versions of the npm packages in the dependencies-section of your package.json follow what’s called Semantic Versioning (SemVer), an industry standard for software versioning aiming to make it easier to manage dependencies. Libraries, frameworks or other tools published on npm should use SemVer in order to clearly communicate what kind of changes that projects who depend on the package can expect if they update.", - "SemVer doesn’t make sense in projects without public APIs - so unless your project is similar to the examples above, use another versioning format.", - "So why do you need to understand SemVer?", - "Knowing SemVer can be useful when you develop software that use external dependencies (which you almost always do). One day, your understanding of these numbers will save you from accidentally introducing breaking changes to your project without understanding why things “that worked yesterday” suddenly doesn’t.", - "This is how Semantic Versioning works according to the official website:", - "Given a version number MAJOR.MINOR.PATCH, increment the:", - "MAJOR version when you make incompatible API changes,", - "MINOR version when you add functionality in a backwards-compatible manner, and", - "PATCH version when you make backwards-compatible bug fixes.", - "This means that PATCHes are bug fixes and MINORs add new features but neither of them break what worked before. Finally, MAJORs add changes that won’t work with earlier versions.", - "Example", - "A semantic version number: 1.3.8", - "Instructions", - "In the dependencies-section of your package.json, change the version of moment to match MAJOR version 2, MINOR version 10 and PATCH version 2" - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"dependencies\" should include \"moment\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"moment\" version should be \"2.10.2\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.10\\.2/, 'Wrong version of \"moment\". It should be 2.10.2'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb5367417b2b2512c02", - "title": "Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency", - "description": [ - "In the last challenge, we told npm to only include a specific version of a package. That’s a useful way to freeze your dependencies if you need to make sure that different parts of your project stay compatible with each other. But in most use cases you don’t want to miss bug fixes, since they often include important security patches and (hopefully) don’t break things in doing so.", - "To allow a npm dependency to get updated to the latest PATCH-version, you can prefix the dependency’s version with the tilde-character (~). In package.json, our current rule for how npm may upgrade moment is to use a specific version only (2.10.2), but we want to allow the latest 2.10.x-version.", - "Example", - "\"some-package-name\": \"~1.3.8\" allows updates to any 1.3.x version.", - "Instructions", - "Use the tilde-character (~) to prefix the version of moment in your dependencies and allow npm to update it to any new PATCH release.", - "Note that the version numbers themselves not should be changed." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"dependencies\" should include \"moment\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"moment\" version should match \"~2.10.2\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\~2\\.10\\.2/, 'Wrong version of \"moment\". It should be ~2.10.2'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb5367417b2b2512c03", - "title": "Use the Caret-Character to Use the Latest Minor Version of a Dependency", - "description": [ - "Similar to how the tilde (~) we learned about in the last challenge allow npm to install the latest PATCH for a dependency, the caret (^) allows npm to install future updates as well. The difference is that the caret will allow both MINOR updates and PATCHes.", - "At the moment, your current version of moment should be ~2.10.2 which allows npm to install to the latest 2.10.x-version. If we instead were to use the caret (^) as our version prefix, npm would instead be allowed to update to any 2.x.x-version.", - "Example", - "\"some-package-name\": \"^1.3.8\" allows updates to any 1.x.x version.", - "Instructions", - "Use the caret-character (^) to prefix the version of moment in your dependencies and allow npm to update it to any new MINOR release.", - "Note that the version numbers themselves not should be changed." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"dependencies\" should include \"moment\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"moment\" version should match \"^2.x.x\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\^2\\./, 'Wrong version of \"moment\". It should be ^2.10.2'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb5367417b2b2512c04", - "title": "Remove a Package from Your Dependencies", - "description": [ - "Now you’ve tested a few ways you can manage dependencies of your project by using the package.json's dependencies-section. You’ve included external packages by adding them to the file and even told npm what types of versions you want by using special characters as the tilde (~) or the caret (^).", - "But what if you want to remove an external package that you no longer need? You might already have guessed it - Just remove the corresponding \"key\": value-pair for that from your dependencies.", - "This same method applies to removing other fields in your package.json as well", - "Instructions", - "Remove the package moment from your dependencies.", - "Make sure you have the right amount of commas after removing it." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"dependencies\" should not include \"moment\"", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.notProperty(packJson.dependencies, 'moment', '\"dependencies\" still includes \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json b/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json deleted file mode 100644 index ac2aabd911..0000000000 --- a/packages/learn/seed/tmp/05-apis-and-microservices/mongodb-and-mongoose.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "name": "MongoDB and Mongoose", - "order": 3, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "587d7fb5367417b2b2512c05", - "title": "Introduction to the MongoDB and Mongoose Challenges", - "description": [ - "", - "", - "MongoDB is a database that stores data records (documents) for use by an application. Mongo is a non-relational, \"NoSQL\" database. This means Mongo stores all data associated within one record, instead of storing it across many preset tables as in a SQL database. Some benefits of this storage model are:

    • Scalability: by default, non-relational databases are split (or \"sharded\") across many systems instead of only one. This makes it easier to improve performance at a lower cost.
    • Flexibility: new datasets and properties can be added to a document without the need to make a new table for that data.
    • Replication: copies of the database run in parallel so if one goes down, one of the copies becomes the new primary data source.

    While there are many non-relational databases, Mongo's use of JSON as its document storage structure makes it a logical choice when learning backend JavaScript. Accessing documents and their properties is like accessing objects in JavaScript.

    Mongoose.js is an npm module for Node.js that allows you to write objects for Mongo as you would in JavaScript. This can make is easier to construct documents for storage in Mongo.", - "", - "@@STEP@@", - "", - "", - "Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d7fb5367437b2b2512c05", - "title": "Create an online database using mLab", - "description": [ - [ - "", - "", - "For the following challenges, we are going to start using MongoDB to store our data. To simplify the configuration, we are going to use mLab.

    mLab is a MongoDB Database-as-a-Service platform, which basically means that they configure and host the database for you, making it so the only responsibility you have is to populate your database with what matters: data!
    In the following steps, we are going to show you how to:
    • Create an mLab account.
    • Create a free online database.
    • Create a new admin user on the database, so you can access it.
    • Get the mLab URI, which you will use in your application to connect to your database.
    Let's start by going to mLab by clicking the button below.", - "https://mlab.com/" - ], - [ - "", - "", - "Once you open the mLab page, you should sign up for a new account.
    • Click the Sign Up button in the top right corner to open the registration page.
    • Fill the registration form with your information and send it.
    • You should be logged into your new, unverified account.
    • In the top of the screen, a message should appear asking to send you an e-mail for account verification. Send and confirm it.
    • After you confirm your account, click Create new in the MongoDB Deployments section.
    ", - "" - ], - [ - "", - "", - "Now we are going to create the actual database you are going to be using.
    • Choose a Cloud Provider from the available list.
    • Select the Sandbox plan type, which is the only one with no cost, and press Continue.
    • Select a region for your Sandbox, from the available list, and press Continue.
    • Input a name for your database. This name will be used in the URI for your database. After that, press Continue.
    A summary of all your choices should appear, allowing you to change any information provided in the previous steps. Press Submit Order to confirm the information.", - "" - ], - [ - "", - "", - "After you confirmed your configuration, a new sandbox should have been created in the MongoDB Deployments section. We are now going to create an administrator, so you can use the database in your application.
    • Click the newly-created database.
    • Click the Users section.
    • Click the Add database user button.
    • Input an username and password for your administrator. Do not mark it as read-only or you will not be able to add any information to the database with this user.
    ", - "" - ], - [ - "", - "", - "Almost done! We have created our new database and created an user to access it, so we just need to find a way to use it in our applications.
    • In your database page, you should see some instructions about connecting using the standard MongoDB URI.
    • The line should look like this mongodb://dbuser:dbpassword@ds0$PORT$.mlab.com:$PORT$/$DATABASE-NAME$.
    • Copy this URI and substitute dbuser and dbpassword with the information for the user you previously created in the database.
    • That's it! This is the URI you will add to your application to connect to your database. Keep this URI safe somewhere, so you can use it later!
    • Feel free to create separate databases for different applications, if they don't have an use for the same data. You just need to create the sandbox, user and obtain the new URI.
    ", - "" - ] - ], - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "translations": {} - }, - { - "id": "587d7fb6367417b2b2512c06", - "title": "Install and Set Up Mongoose", - "description": [ - "Add mongodb and mongoose to the project’s package.json. Then require mongoose. Store your mLab database URI in the private .env file as MONGO_URI. Connect to the database using mongoose.connect()" - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"mongodb\" dependency should be in package.json", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/file/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'mongodb'); }, xhr => { throw new Error(xhr.responseText); })" - }, - { - "text": "\"mongoose\" dependency should be in package.json", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/file/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'mongoose'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb6367417b2b2512c07", - "title": "Create a Model", - "description": [ - "First of all we need a Schema. Each schema maps to a MongoDB collection. It defines the shape of the documents within that collection.", - "Schemas are building block for Models. They can be nested to create complex models, but in this case we’ll keep things simple.", - "A model allows you to create instances of your objects, called documents.", - "Create a person having this prototype :", - "- Person Prototype -", - "--------------------", - "name : string [required]", - "age : number", - "favoriteFoods : array of strings (*) ", - "Use the mongoose basic schema types. If you want you can also add", - "more fields, use simple validators like required or unique,", - "and set default values. See the mongoose docs.", - "[C]RUD Part I - CREATE", - "Note: Glitch is a real server, and in real servers the interactions with the db happen in handler functions. These function are executed when some event happens (e.g. someone hits an endpoint on your API). We’ll follow the same approach in these exercises. The done() function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating or deleting. It’s following the Node convention and should be called as done(null, data) on success, or done(err) on error.", - "Warning - When interacting with remote services, errors may occur !", - "/* Example */", - "var someFunc = function(done) {", - " //... do something (risky) ...", - " if(error) return done(error);", - " done(null, result);", - "};" - ], - "challengeSeed": [], - "tests": [ - { - "text": "Creating an instance from a mongoose schema should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/mongoose-model', {name: 'Mike', age: 28, favoriteFoods: ['pizza', 'cheese']}).then(data => { assert.equal(data.name, 'Mike', '\"model.name\" is not what expected'); assert.equal(data.age, '28', '\"model.age\" is not what expected'); assert.isArray(data.favoriteFoods, '\"model.favoriteFoods\" is not an Array'); assert.include(data.favoriteFoods, 'pizza', '\"model.favoriteFoods\" does not include the expected items'); assert.include(data.favoriteFoods, 'cheese', '\"model.favoriteFoods\" does not include the expected items'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb6367417b2b2512c09", - "title": "Create and Save a Record of a Model", - "description": [ - "Create a document instance using the Person constructor you build before. Pass to the constructor an object having the fields name, age, and favoriteFoods. Their types must be conformant to the ones in the Person Schema. Then call the method document.save() on the returned document instance. Pass to it a callback using the Node convention. This is a common pattern, all the following CRUD methods take a callback function like this as the last argument.", - "/* Example */", - "// ...", - "person.save(function(err, data) {", - "// ...do your stuff here...", - "});" - ], - "challengeSeed": [], - "tests": [ - { - "text": "Creating and saving a db item should succeed", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/create-and-save-person').then(data => { assert.isString(data.name, '\"item.name\" should be a String'); assert.isNumber(data.age, '28', '\"item.age\" should be a Number'); assert.isArray(data.favoriteFoods, '\"item.favoriteFoods\" should be an Array'); assert.equal(data.__v, 0, 'The db item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb7367417b2b2512c0a", - "title": "Create Many Records with model.create()", - "description": [ - "Sometimes you need to create many instances of your models, e.g. when seeding a database with initial data. Model.create() takes an array of objects like [{name: 'John', ...}, {...}, ...] as the first argument, and saves them all in the db. Create many people with Model.create(), using the function argument arrayOfPeople." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Creating many db items at once should succeed", - "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/create-many-people', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'John', age: 24, favoriteFoods: ['pizza', 'salad']}, {name: 'Mary', age: 21, favoriteFoods: ['onions', 'chicken']}])}).then(data => { assert.isArray(data, 'the response should be an array'); assert.equal(data.length, 2, 'the response does not contain the expected number of items'); assert.equal(data[0].name, 'John', 'The first item is not correct'); assert.equal(data[0].__v, 0, 'The first item should be not previously edited'); assert.equal(data[1].name, 'Mary', 'The second item is not correct'); assert.equal(data[1].__v, 0, 'The second item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb7367417b2b2512c0b", - "title": "Use model.find() to Search Your Database", - "description": [ - "Find all the people having a given name, using Model.find() -> [Person]", - "In its simplest usage, Model.find() accepts a query document (a JSON object ) as the first argument, then a callback. It returns an array of matches. It supports an extremely wide range of search options. Check it in the docs. Use the function argument personName as search key." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Find all items corresponding to a criteria should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-all-by-name', {name: 'r@nd0mN4m3', age: 24, favoriteFoods: ['pizza']}).then(data => { assert.isArray(data, 'the response should be an Array'); assert.equal(data[0].name, 'r@nd0mN4m3', 'item.name is not what expected'); assert.equal(data[0].__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb7367417b2b2512c0c", - "title": "Use model.findOne() to Return a Single Matching Document from Your Database", - "description": [ - "Model.findOne() behaves like .find(), but it returns only one document (not an array), even if there are items. It is especially useful when searching by properties that you have declared as unique. Find just one person which has a certain food in her favorites, using Model.findOne() -> Person. Use the function argument food as search key." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Find one item should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-one-by-food', {name: 'Gary', age: 46, favoriteFoods: ['chicken salad']}).then(data => { assert.equal(data.name, 'Gary', 'item.name is not what expected'); assert.deepEqual(data.favoriteFoods, ['chicken salad'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb7367417b2b2512c0d", - "title": "Use model.findById() to Search Your Database By _id", - "description": [ - "When saving a document, mongodb automatically adds the field _id, and set it to a unique alphanumeric key. Searching by _id is an extremely frequent operation, so moongose provides a dedicated method for it. Find the (only!!) person having a given _id, using Model.findById() -> Person. Use the function argument personId as search key." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Find an item by Id should succeed", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/find-by-id').then(data => { assert.equal(data.name, 'test', 'item.name is not what expected'); assert.equal(data.age, 0, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['none'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'The item should be not previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb8367417b2b2512c0e", - "title": "Perform Classic Updates by Running Find, Edit, then Save", - "description": [ - "In the good old days this was what you needed to do if you wanted to edit a document and be able to use it somehow e.g. sending it back in a server response. Mongoose has a dedicated updating method : Model.update(). It is binded to the low-level mongo driver. It can bulk edit many documents matching certain criteria, but it doesn’t send back the updated document, only a ‘status’ message. Furthermore it makes model validations difficult, because it just directly calls the mongo driver.", - "Find a person by _id ( use any of the above methods ) with the parameter personId as search key. Add “hamburger” to the list of her favoriteFoods (you can use Array.push()). Then - inside the find callback - save() the updated Person.", - "[*] Hint: This may be tricky if in your Schema you declared favoriteFoods as an Array, without specifying the type (i.e. [String]). In that casefavoriteFoods defaults to Mixed type, and you have to manually mark it as edited using document.markModified('edited-field'). (http://mongoosejs.com/docs/schematypes.html - #Mixed )" - ], - "challengeSeed": [], - "tests": [ - { - "text": "Find-edit-update an item should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-edit-save', {name:'Poldo', age: 40, favoriteFoods:['spaghetti']}).then(data => { assert.equal(data.name, 'Poldo', 'item.name is not what expected'); assert.equal(data.age, 40, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['spaghetti', 'hamburger'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 1, 'The item should be previously edited'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb8367417b2b2512c0f", - "title": "Perform New Updates on a Document Using model.findOneAndUpdate()", - "description": [ - "Recent versions of mongoose have methods to simplify documents updating. Some more advanced features (i.e. pre/post hooks, validation) behave differently with this approach, so the Classic method is still useful in many situations. findByIdAndUpdate() can be used when searching by Id.", - "Find a person by Name and set her age to 20. Use the function parameter personName as search key.", - "Hint: We want you to return the updated document. o do that you need to pass the options document { new: true } as the 3rd argument to findOneAndUpdate(). By default these methods return the unmodified object." - ], - "challengeSeed": [], - "tests": [ - { - "text": "findOneAndUpdate an item should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/find-one-update', {name:'Dorian Gray', age: 35, favoriteFoods:['unknown']}).then(data => { assert.equal(data.name, 'Dorian Gray', 'item.name is not what expected'); assert.equal(data.age, 20, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['unknown'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0, 'findOneAndUpdate does not increment version by design !!!'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb8367417b2b2512c10", - "title": "Delete One Document Using model.findByIdAndRemove", - "description": [ - "Delete one person by her _id. You should use one of the methods findByIdAndRemove() or findOneAndRemove(). They are like the previous update methods. They pass the removed document to the cb. As usual, use the function argument personId as search key." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Deleting an item should succeed", - "testString": "getUserInput => $.post(getUserInput('url') + '/_api/remove-one-person', {name:'Jason Bourne', age: 36, favoriteFoods:['apples']}).then(data => { assert.equal(data.name, 'Jason Bourne', 'item.name is not what expected'); assert.equal(data.age, 36, 'item.age is not what expected'); assert.deepEqual(data.favoriteFoods, ['apples'], 'item.favoriteFoods is not what expected'); assert.equal(data.__v, 0); assert.equal(data.count, 0, 'the db items count is not what expected'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb8367417b2b2512c11", - "title": "Delete Many Documents with model.remove()", - "description": [ - "Model.remove() is useful to delete all the documents matching given criteria. Delete all the people whose name is “Mary”, using Model.remove(). Pass to it a query ducument with the “name” field set, and of course a callback.", - "Note: Model.remove() doesn’t return the deleted document, but a JSON object containing the outcome of the operation, and the number of items affected. Don’t forget to pass it to the done() callback, since we use it in tests." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Deleting many items at once should succeed", - "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/remove-many-people', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'Mary', age: 16, favoriteFoods: ['lollipop']}, {name: 'Mary', age: 21, favoriteFoods: ['steak']}])}).then(data => { assert.isTrue(!!data.ok, 'The mongo stats are not what expected'); assert.equal(data.n, 2, 'The number of items affected is not what expected'); assert.equal(data.count, 0, 'the db items count is not what expected'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "587d7fb9367417b2b2512c12", - "title": "Chain Search Query Helpers to Narrow Search Results", - "description": [ - "If you don’t pass the callback as the last argument to Model.find() (or to the other search methods), the query is not executed. You can store the query in a variable for later use. This kind of object enables you to build up a query using chaining syntax. The actual db search is executed when you finally chain the method .exec(). Pass your callback to this last method. There are many query helpers, here we’ll use the most ‘famous’ ones.", - "Find people who like \"burrito\". Sort them by name, limit the results to two documents, and hide their age. Chain .find(), .sort(), .limit(), .select(), and then .exec(). Pass the done(err, data) callback to exec()." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Chaining query helpers should succeed", - "testString": "getUserInput => $.ajax({url: getUserInput('url') + '/_api/query-tools', type: 'POST', contentType:'application/json', data: JSON.stringify([{name: 'Pablo', age: 26, favoriteFoods: ['burrito', 'hot-dog']}, {name: 'Ashley', age: 32, favoriteFoods: ['steak', 'burrito']}, {name: 'Mario', age: 51, favoriteFoods: ['burrito', 'prosciutto']} ]) }).then(data => { assert.isArray(data, 'the response should be an Array'); assert.equal(data.length, 2, 'the data array length is not what expected'); assert.notProperty(data[0], 'age', 'The returned first item has too many properties'); assert.equal(data[0].name, 'Ashley', 'The returned first item name is not what expected'); assert.notProperty(data[1], 'age', 'The returned second item has too many properties'); assert.equal(data[1].name, 'Mario', 'The returned second item name is not what expected');}, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - } - ] -} diff --git a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json b/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json deleted file mode 100644 index 2b57838734..0000000000 --- a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/advanced-express-tools.json +++ /dev/null @@ -1,740 +0,0 @@ -{ - "name": "Advanced Node and Express", - "order": 3, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "5895f6fff9fc0f352b528e62", - "title": "Advanced Node/Express Introduction", - "description": [ - "", - "", - "Authentication is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.
    The most common and easiest to use authentication middleware for Node.js is Passport. It is easy to learn, light-weight, and extremely flexible allowing for many strategies, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of Pug and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "5895f700f9fc0f352b528e63", - "title": "Set up a Template Engine", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "A template engine enables you to use static template files (such as those written in Pug) in your app. At runtime, the template engine replaces variables in a template file with actual values which can be supplied by your server, and transforms the template into a static HTML file that is then sent to the client. This approach makes it easier to design an HTML page and allows for displaying of variables on the page without needing to make an API call from the client.", - "To set up Pug for use in your project, you will need to add it as a dependency first in your package.json. \"pug\": \"^0.1.0\"", - "Now to tell Node/Express to use the templating engine you will have to tell your express app to set 'pug' as the 'view-engine'. app.set('view engine', 'pug')", - "Lastly, you should change your response to the request for the index route to res.render with the path to the view views/pug/index.pug.", - "If all went as planned, you should refresh your apps home page and see a small message saying you're successfully rending the Pug from our Pug file! Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Pug is a dependency", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'pug', 'Your project should list \"pug\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "View engine is Pug", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")view engine('|\"),( |)('|\")pug('|\")/gi, 'Your project should set Pug as a view engine'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Pug is working", - "testString": "getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-success-message/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70bf9fc0f352b528e64", - "title": "Use a Template Engine's Powers", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "One of the greatest features of using a template engine is being able to pass variables from the server to the template file before rendering it to HTML.", - "In your Pug file, you're about to use a variable by referencing the variable name as #{variable_name} inline with other text on an element or by using an equal side on the element without a space such as p= variable_name which sets that p elements text to equal the variable.", - "We strongly recommend looking at the syntax and structure of Pug here on their Githubs README. Pug is all about using whitespace and tabs to show nested elements and cutting down on the amount of code needed to make a beautiful site.", - "Looking at our pug file 'index.pug' included in your project, we used the variables title and message", - "To pass those alone from our server, you will need to add an object as a second argument to your res.render with the variables and their value. For example, pass this object along setting the variables for your index view: {title: 'Hello', message: 'Please login'", - "It should look like: res.render(process.cwd() + '/views/pug/index', {title: 'Hello', message: 'Please login'});", - "Now refresh your page and you should see those values rendered in your view in the correct spot as layed out in your index.pug file! Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Pug render variables correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-variable(\"|')>Please login/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70cf9fc0f352b528e65", - "title": "Set up Passport", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "It's time to set up Passport so we can finally start allowing a user to register or login to an account! In addition to Passport, we will use Express-session to handle sessions. Using this middleware saves the session id as a cookie in the client and allows us to access the session data using that id on the server. This way we keep personal account information out of the cookie used by the client to verify to our server they are authenticated and just keep the key to access the data stored on the server.", - "To set up Passport for use in your project, you will need to add it as a dependency first in your package.json. \"passport\": \"^0.3.2\"", - "In addition, add Express-session as a dependency now as well. Express-session has a ton of advanced features you can use but for now we're just going to use the basics! \"express-session\": \"^1.15.0\"", - "You will need to set up the session settings now and initialize Passport. Be sure to first create the variables 'session' and 'passport' to require 'express-session' and 'passport' respectively.", - "To set up your express app to use use the session we'll define just a few basic options. Be sure to add 'SESSION_SECRET' to your .env file and give it a random value. This is used to compute the hash used to encrypt your cookie!", - "
    app.use(session({\n  secret: process.env.SESSION_SECRET,\n  resave: true,\n  saveUninitialized: true,\n}));
    ", - "As well you can go ahead and tell your express app to use 'passport.initialize()' and 'passport.session()'. (For example, app.use(passport.initialize());)", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Passort and Express-session are dependencies", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport', 'Your project should list \"passport\" as a dependency'); assert.property(packJson.dependencies, 'express-session', 'Your project should list \"express-session\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Dependencies correctly required", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport(\"|')/gi, 'You should have required passport'); assert.match(data, /require.*(\"|')express-session(\"|')/gi, 'You should have required express-session'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Express app uses new dependencies", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.initialize/gi, 'Your express app should use \"passport.initialize()\"'); assert.match(data, /passport.session/gi, 'Your express app should use \"passport.session()\"'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Session and session secret correctly set up", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /secret:( |)process.env.SESSION_SECRET/gi, 'Your express app should have express-session set up with your secret as process.env.SESSION_SECRET'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70cf9fc0f352b528e66", - "title": "Serialization of a User Object", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Serialization and deserialization are important concepts in regards to authentication. To serialize an object means to convert its contents into a small key essentially that can then be deserialized into the original object. This is what allows us to know whos communicated with the server without having to send the authentication data like username and password at each request for a new page.", - "To set this up properly, we need to have a serialize function and a deserialize function. In passport we create these with passport.serializeUser( OURFUNCTION ) and passport.deserializeUser( OURFUNCTION )", - "The serializeUser is called with 2 arguments, the full user object and a callback used by passport. Returned in the callback should be a unique key to identify that user- the easiest one to use being the users _id in the object as it should be unique as it generated by MongoDb. Similarly deserializeUser is called with that key and a callback function for passport as well, but this time we have to take that key and return the users full object to the callback. To make a query search for a Mongo _id you will have to create const ObjectID = require('mongodb').ObjectID;, and then to use it you call new ObjectID(THE_ID). Be sure to add MongoDB as a dependency. You can see this in the examples below:", - "
    passport.serializeUser((user, done) => {\n   done(null, user._id);\n });

    passport.deserializeUser((id, done) => {\n        db.collection('users').findOne(\n            {_id: new ObjectID(id)},\n            (err, doc) => {\n                done(null, doc);\n            }\n        );\n    });
    ", - "NOTE: This deserializeUser will throw an error until we set up the DB in the next step so comment out the whole block and just call done(null, null) in the function deserializeUser.", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Serialize user function correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.serializeUser/gi, 'You should have created your passport.serializeUser function'); assert.match(data, /null, user._id/gi, 'There should be a callback in your serializeUser with (null, user._id)'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Deserialize user function correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.deserializeUser/gi, 'You should have created your passport.deserializeUser function'); assert.match(data, /null,( |)null/gi, 'There should be a callback in your deserializeUser with (null, null) for now'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "MongoDB is a dependency", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'mongodb', 'Your project should list \"mongodb\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Mongodb properly required including the ObjectId", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')mongodb(\"|')/gi, 'You should have required mongodb'); assert.match(data, /new ObjectID.*id/gi, 'Even though the block is commented out, you should use new ObjectID(id) for when we add the database'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70cf9fc0f352b528e67", - "title": "Implement the Serialization of a Passport User", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Right now we're not loading an actually users object since we haven't set up our database. This can be done many different ways, but for our project we will connect to the database once when we start the server and keep a persistent connection for the full life-cycle of the app.", - "To do this, add MongoDB as a dependency and require it in your server. (const mongo = require('mongodb').MongoClient;)", - "Now we want to the connect to our database then start listening for requests. The purpose of this is to not allow requests before our database is connected or if there is a database error. To accomplish you will want to encompass your serialization and your app listener in the following:", - "
    mongo.connect(process.env.DATABASE, (err, db) => {\n    if(err) {\n        console.log('Database error: ' + err);\n    } else {\n        console.log('Successful database connection');\n\n        //serialization and app.listen\n\n}});
    ", - "You can now uncomment the block in deserializeUser and remove your done(null, null). Be sure to set DATABASE in your .env file to your database's connection string (for example: DATABASE=mongodb://admin:pass@mlab.com:12345/my-project). You can set up a free database on mLab. Congratulations- you've finished setting up serialization!", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Database connection is present", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /mongo.connect/gi, 'You should have created a connection to your database'); assert.match(data, /mongo.connect[^]*app.listen[^]*}[^]*}/gi, 'You should have your app.listen nested at within your database connection at the bottom'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Deserialization is now correctly using the DB and done(null, null) is erased", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.notMatch(data, /null,( |)null/gi, 'The callback in deserializeUser of (null, null) should be completely removed for the db block uncommented out'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70df9fc0f352b528e68", - "title": "Authentication Strategies", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "A strategy is a way of authenticating a user. You can use a strategy for allowing users to authenticate based on locally saved information (if you have them register first) or from a variety of providers such as Google or Github. For this project we will set up a local strategy. To see a list of the 100's of strategies, visit Passports site here.", - "Add passport-local as a dependency and add it to your server as follows: const LocalStrategy = require('passport-local');", - "Now you will have to tell passport to use an instantiated LocalStartegy object with a few settings defined. Make sure this as well as everything from this point on is encapsulated in the database connection since it relies on it!
    passport.use(new LocalStrategy(\n  function(username, password, done) {\n    db.collection('users').findOne({ username: username }, function (err, user) {\n      console.log('User '+ username +' attempted to log in.');\n      if (err) { return done(err); }\n      if (!user) { return done(null, false); }\n      if (password !== user.password) { return done(null, false); }\n      return done(null, user);\n    });\n  }\n));
    This is defining the process to take when we try to authenticate someone locally. First it tries to find a user in our database with the username entered, then it checks for the password to match, then finally if no errors have popped up that we checked for, like an incorrect password, the users object is returned and they are authenticated.", - "Many strategies are set up using different settings, general it is easy to set it up based on the README in that strategies repository though. A good example of this is the Github strategy where we don't need to worry about a username or password because the user will be sent to Github's auth page to authenticate and as long as they are logged in and agree then Github returns their profile for us to use.", - "In the next step we will set up how to actually call the authentication strategy to validate a user based on form data! Submit your page when you think you've got it right up to this point." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Passport-local is a dependency", - "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-local', 'Your project should list \"passport-local \" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Passport-local correctly required and setup", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport-local(\"|')/gi, 'You should have required passport-local'); assert.match(data, /new LocalStrategy/gi, 'You should have told passport to use a new strategy'); assert.match(data, /findOne/gi, 'Your new local strategy should use the findOne query to find a username based on the inputs'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70df9fc0f352b528e69", - "title": "How to Use Passport Strategies", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "In the index.pug file supplied there is actually a login form. It has previously been hidden because of the inline javascript if showLogin with the form indented after it. Before showLogin as a variable was never defined, it never rendered the code block containing the form. Go ahead and on the res.render for that page add a new variable to the object showLogin: true. When you refresh your page, you should then see the form! This form is set up to POST on /login so this is where we should set up to accept the POST and authenticate the user.", - "For this challenge you should add the route /login to accept a POST request. To authenticate on this route you need to add a middleware to do so before then sending a response. This is done by just passing another argument with the middleware before your function(req,res) with your response! The middleware to use is passport.authenticate('local').", - "passport.authenticate can also take some options as an argument such as: { failureRedirect: '/' } which is incredibly useful so be sure to add that in as well. As a response after using the middleware (which will only be called if the authentication middleware passes) should be to redirect the user to /profile and that route should render the view 'profile.pug'.", - "If the authentication was successful, the user object will be saved in req.user.", - "Now at this point if you enter a username and password in the form, it should redirect to the home page / and in the console of your server should be 'User {USERNAME} attempted to log in.' since we currently cannot login a user who isn't registered.", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "All steps correctly implemented in the server.js", - "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showLogin:( |)true/gi, 'You should be passing the variable \"showLogin\" as true to your render function for the homepage'); assert.match(data, /failureRedirect:( |)('|\")\\/('|\")/gi, 'Your code should include a failureRedirect to the \"/\" route'); assert.match(data, /login[^]*post[^]*local/gi, 'You should have a route for login which accepts a POST and passport.authenticates local'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "A POST request to /login correctly redirects to /", - "testString": "getUserInput => $.post(getUserInput('url')+ '/login') .then(data => { assert.match(data, /Home page/gi, 'A login attempt at this point should redirect to the homepage since we do not have any registered users'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70df9fc0f352b528e6a", - "title": "Create New Middleware", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "As in, any user can just go to /profile whether they authenticated or not by typing in the url. We want to prevent this by checking if the user is authenticated first before rendering the profile page. This is the perfect example of when to create a middleware.", - "The challenge here is creating the middleware function ensureAuthenticated(req, res, next), which will check if a user is authenticated by calling passports isAuthenticated on the request which in turn checks for req.user is to be defined. If it is then next() should be called, otherwise we can just respond to the request with a redirect to our homepage to login. An implementation of this middleware is:", - "
    function ensureAuthenticated(req, res, next) {\n  if (req.isAuthenticated()) {\n      return next();\n  }\n  res.redirect('/');\n};
    ", - "Now add ensureAuthenticated as a middleware to the request for the profile page before the argument to the get request containing the function that renders the page.", - "
    app.route('/profile')\n  .get(ensureAuthenticated, (req,res) => {\n       res.render(process.cwd() + '/views/pug/profile');\n  });
    ", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Middleware ensureAuthenticated should be implemented and on our /profile route", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /ensureAuthenticated[^]*req.isAuthenticated/gi, 'Your ensureAuthenticated middleware should be defined and utilize the req.isAuthenticated function'); assert.match(data, /profile[^]*get[^]*ensureAuthenticated/gi, 'Your ensureAuthenticated middleware should be attached to the /profile route'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "A Get request to /profile correctly redirects to / since we are not authenticated", - "testString": "getUserInput => $.get(getUserInput('url')+ '/profile') .then(data => { assert.match(data, /Home page/gi, 'An attempt to go to the profile at this point should redirect to the homepage since we are not logged in'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "5895f70ef9fc0f352b528e6b", - "title": "How to Put a Profile Together", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Now that we can ensure the user accessing the /profile is authenticated, we can use the information contained in 'req.user' on our page!", - "Go ahead and pass the object containing the variable username equaling 'req.user.username' into the render method of the profile view. Then go to your 'profile.pug' view and add the line h2.center#welcome Welcome, #{username}! creating the h2 element with the class 'center' and id 'welcome' containing the text 'Welcome, ' and the username!", - "Also in the profile, add a link to /logout. That route will host the logic to unauthenticate a user. a(href='/logout') Logout", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Correctly added a Pug render variable to /profile", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /\\/views\\/pug\\/profile[^]*username:( |)req.user.username/gi, 'You should be passing the variable username with req.user.username into the render function of the profile page'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58965611f9fc0f352b528e6c", - "title": "Logging a User Out", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Creating the logout logic is easy. The route should just unauthenticate the user and redirect to the home page instead of rendering any view.", - "In passport, unauthenticating a user is as easy as just calling req.logout(); before redirecting.", - "
    app.route('/logout')\n  .get((req, res) => {\n      req.logout();\n      res.redirect('/');\n  });
    ", - "You may have noticed we also we're not handling missing pages (404), the common way to handle this in Node is with the following middleware. Go ahead and add this in after all your other routes:", - "
    app.use((req, res, next) => {\n  res.status(404)\n    .type('text')\n    .send('Not Found');\n});
    ", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Logout route", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /req.logout/gi, 'You should be call req.logout() in youre /logout route'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Logout should redirect to the home page /", - "testString": "getUserInput => $.get(getUserInput('url')+ '/logout') .then(data => { assert.match(data, /Home page/gi, 'When a user logs out they should be redirected to the homepage'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58966a17f9fc0f352b528e6d", - "title": "Registration of New Users", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Now we need to allow a new user on our site to register an account. On the res.render for the home page add a new variable to the object passed along- showRegistration: true. When you refresh your page, you should then see the registration form that was already created in your index.pug file! This form is set up to POST on /register so this is where we should set up to accept the POST and create the user object in the database.", - "The logic of the registration route should be as follows: Register the new user > Authenticate the new user > Redirect to /profile", - "The logic of step 1, registering the new user, should be as follows: Query database with a findOne command > if user is returned then it exists and redirect back to home OR if user is undefined and no error occurs then 'insertOne' into the database with the username and password and as long as no errors occur then call next to go to step 2, authenticating the new user, which we've already written the logic for in our POST /login route.", - "
    app.route('/register')\n  .post((req, res, next) => {\n      db.collection('users').findOne({ username: req.body.username }, function (err, user) {\n          if(err) {\n              next(err);\n          } else if (user) {\n              res.redirect('/');\n          } else {\n              db.collection('users').insertOne(\n                {username: req.body.username,\n                 password: req.body.password},\n                (err, doc) => {\n                    if(err) {\n                        res.redirect('/');\n                    } else {\n                        next(null, user);\n                    }\n                }\n              )\n          }\n      })},\n    passport.authenticate('local', { failureRedirect: '/' }),\n    (req, res, next) => {\n        res.redirect('/profile');\n    }\n);
    ", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Register route and display on home", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showRegistration:( |)true/gi, 'You should be passing the variable \"showRegistration\" as true to your render function for the homepage'); assert.match(data, /register[^]*post[^]*findOne[^]*username:( |)req.body.username/gi, 'You should have a route accepted a post request on register that querys the db with findone and the query being \"username: req.body.username\"'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Registering should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/register',data: {username: 'freeCodeCampTester', password: 'freeCodeCampTester'},crossDomain: true, type: 'POST', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, 'I should be able to register and it direct me to my profile. CLEAR YOUR DATABASE if this test fails (each time until its right!)'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Login should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/login',data: {username: 'freeCodeCampTester', password: 'freeCodeCampTester'}, type: 'POST', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, 'Login should work if previous test was done successfully and redirect successfully to the profile. Check your work and clear your DB'); assert.match(data, /freeCodeCampTester/gi, 'The profile should properly display the welcome to the user logged in'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Logout should work", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/logout', type: 'GET', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Logout should redirect to home'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Profile should no longer work after logout", - "testString": "getUserInput => $.ajax({url: getUserInput('url')+ '/profile', type: 'GET', crossDomain: true, xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, 'Profile should redirect to home when we are logged out now again'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58a25c98f9fc0f352b528e7f", - "title": "Hashing Your Passwords", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Going back to the information security section you may remember that storing plaintext passwords is never okay. Now it is time to implement BCrypt to solve this issue.", - "
    Add BCrypt as a dependency and require it in your server. You will need to handle hashing in 2 key areas: where you handle registering/saving a new account and when you check to see that a password is correct on login.", - "Currently on our registeration route, you insert a user's password into the database like the following: password: req.body.password. An easy way to implement saving a hash instead is to add the following before your database logic var hash = bcrypt.hash(req.body.password, 12); and replacing the req.body.password in the database saving with just password: hash.", - "Finally on our authentication strategy we check for the following in our code before completing the process: if (password !== user.password) { return done(null, false); }. After making the previous changes, now user.password is a hash. Before making a change to the existing code, notice how the statement is checking if the password is NOT equal then return non-authenticated. With this in mind your code could look as follows to properly check the password entered against the hash: if (!bcrypt.compare(password, user.password)) { return done(null, false); }", - "That is all it takes to implement one of the most important security features when you have to store passwords! Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "BCrypt is a dependency", - "testString": " getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'bcrypt', 'Your project should list \"bcrypt\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "BCrypt correctly required and implemented", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')bcrypt(\"|')/gi, 'You should have required bcrypt'); assert.match(data, /bcrypt.hash/gi, 'You should use hash the password in the registration'); assert.match(data, /bcrypt.compare/gi, 'You should compare the password to the hash in your strategy'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589690e6f9fc0f352b528e6e", - "title": "Clean Up Your Project with Modules", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Right now everything you have is in your server.js file. This can lead to hard to manage code that isn't very expandable.", - "Create 2 new files: Routes.js and Auth.js", - "Both should start with the following code:
    module.exports = function (app, db) {\n\n\n}
    ", - "Now in the top of your server file, require these files like such: const routes = require('./routes.js');", - "Right after you establish a successful connect with the database instantiate each of them like such: routes(app, db)", - "Finally, take all of the routes in your server and paste them into your new files and remove them from your server file. Also take the ensureAuthenticated since we created that middleware function for routing specifically. You will have to now correctly add the dependencies in that are used, such as const passport = require('passport');, at the very top above the export line in your routes.js file.", - "Keep adding them until no more errors exist, and your server file no longer has any routing!", - "Now do the same thing in your auth.js file with all of the things related to authentication such as the serialization and the setting up of the local strategy and erase them from your server file. Be sure to add the dependencies in and call auth(app,db) in the server in the same spot. Be sure to have auth(app, db) before routes(app, db) since our registration route depends on passport being initiated!", - "Congratulations- you're at the end of this section of Advanced Node and Express and have some beautiful code to show for it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of the completed project here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Modules present", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|').\\/routes.js(\"|')/gi, 'You should have required your new files'); assert.match(data, /mongo.connect[^]*routes/gi, 'Your new modules should be called after your connection to the database'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589a69f5f9fc0f352b528e6f", - "title": "Social Authentication with OAuth", - "description": [ - [ - "", - "", - "OAuth 2.0 is the industry-standard authorization and is used across the internet for social login such as letting you login to freeCodeCamp with your Github account.
    Implementing social login with passport using OAuth is extremely easy to do because of the 300+ modules already on npm for adding new strategies to your app. In addition to the ease of installation, it is also easier to use because you do not have to deal with a separate registration or any user input.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe. Be sure to enter your database in the .env file- it can be the same one from last project since you'll be using a new collection!", - "" - ] - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "589a69f5f9fc0f352b528e70", - "title": "Implementation of Social Authentication", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "The basic path this kind of authentication will follow in your app is:
    1. User clicks a button or link sending them to our route to authenticate using a specific strategy (EG. Github)
    2. Your route calls passport.authenticate('github') which redirects them to Github.
    3. The page the user lands on, on Github, allows them to login if they aren't already then asks them to approve access to their profile from our app.
    4. The user is then returned to our app at a specific callback url with their profile if they approved.
    5. They are now authenticated and your app should check if it is a returning profile, or save it in your database if it is not.
    ", - "Strategies with OAuth require you to have at least a Client ID and a Client Secret which is a way for them to verify who the authentication request is coming from and if it is valid. These are obtained from the site you are trying to implement authentication with, such as Github, and are unique to your app- THEY ARE NOT TO BE SHARED and should never be uploaded to a public repository or written directly in your code. A common practice is to put them in your .env file and reference them like: process.env.GITHUB_CLIENT_ID. For this challenge we're going to use the Github strategy.", - "Obtaining your Client ID and Secret from Github is done in your account profile settings under 'developer settings', then 'OAuth applications'. Click 'Register a new application', name your app, paste in the url to your glitch homepage (Not the project code's url), and lastly for the callback url, paste in the same url as the homepage but with '/auth/github/callback' added on. This is where users will be redirected to for us to handle after authenticating on Github. Save the returned information as 'GITHUB_CLIENT_ID' and 'GITHUB_CLIENT_SECRET' in your .env file.", - "On your remixed project, create 2 routes accepting GET requests: /auth/github and /auth/github/callback. The first should only call passport to authenticate 'github' and the second should call passport to authenticate 'github' with a failure redirect to '/' and then if that is successful redirect to '/profile' (similar to our last project).", - "An example of how '/auth/github/callback' should look is similar to how we handled a normal login in our last project:
    app.route('/login')\n  .post(passport.authenticate('local', { failureRedirect: '/' }), (req,res) => { \n    res.redirect('/profile'); \n  });
    ", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Route /auth/github correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")\\/auth\\/github('|\")[^]*get.*passport.authenticate.*github/gi, 'Route auth/github should only call passport.authenticate with github'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Route /auth/github/callback correct", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|\")\\/auth\\/github\\/callback('|\")[^]*get.*passport.authenticate.*github.*failureRedirect:( |)(\"|')\\/(\"|')/gi, 'Route auth/github/callback should accept a get request and call passport.authenticate for github with a failure redirect to home'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589a69f5f9fc0f352b528e71", - "title": "Implementation of Social Authentication II", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "The last part of setting up your Github authentication is to create the strategy itself. For this, you will need to add the dependency of 'passport-github' to your project and require it as GithubStrategy like const GitHubStrategy = require('passport-github').Strategy;.", - "To set up the Github strategy, you have to tell passport to use an instantiated GithubStrategy, which accepts 2 arguments: An object (containing clientID, clientSecret, and callbackURL) and a function to be called when a user is successfully authenticated which we will determine if the user is new and what fields to save initially in the user's database object. This is common across many strategies but some may require more information as outlined in that specific strategy's github README; for example, Google requires a scope as well which determines what kind of information your request is asking returned and asks the user to approve such access. The current strategy we are implementing has its usage outlined here, but we're going through it all right here on freeCodeCamp!", - "Here's how your new strategy should look at this point:
    passport.use(new GitHubStrategy({\n    clientID: process.env.GITHUB_CLIENT_ID,\n    clientSecret: process.env.GITHUB_CLIENT_SECRET,\n    callbackURL: /*INSERT CALLBACK URL ENTERED INTO GITHUB HERE*/\n  },\n  function(accessToken, refreshToken, profile, cb) {\n      console.log(profile);\n      //Database logic here with callback containing our user object\n  }\n));
    ", - "Your authentication won't be successful yet, and actually throw an error, without the database logic and callback, but it should log to your console your Github profile if you try it!", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Dependency added", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-github', 'Your project should list \"passport-github\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Dependency required", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*(\"|')passport-github(\"|')/gi, 'You should have required passport-github'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Github strategy setup correctly thus far", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.use.*new GitHubStrategy/gi, 'Passport should use a new GitHubStrategy'); assert.match(data, /callbackURL:( |)(\"|').*(\"|')/gi, 'You should have a callbackURL'); assert.match(data, /process.env.GITHUB_CLIENT_SECRET/g, 'You should use process.env.GITHUB_CLIENT_SECRET'); assert.match(data, /process.env.GITHUB_CLIENT_ID/g, 'You should use process.env.GITHUB_CLIENT_ID'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589a8eb3f9fc0f352b528e72", - "title": "Implementation of Social Authentication III", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "The final part of the strategy is handling the profile returned from Github. We need to load the users database object if it exists or create one if it doesn't and populate the fields from the profile, then return the user's object. Github supplies us a unique id within each profile which we can use to search with to serialize the user with (already implemented). Below is an example implementation you can use in your project- it goes within the function that is the second argument for the new strategy, right below the console.log(profile); currently is:", - "
    db.collection('socialusers').findAndModify(\n    {id: profile.id},\n    {},\n    {$setOnInsert:{\n        id: profile.id,\n        name: profile.displayName || 'John Doe',\n        photo: profile.photos[0].value || '',\n        email: profile.emails[0].value || 'No public email',\n        created_on: new Date(),\n        provider: profile.provider || ''\n    },$set:{\n        last_login: new Date()\n    },$inc:{\n        login_count: 1\n    }},\n    {upsert:true, new: true},\n    (err, doc) => {\n        return cb(null, doc.value);\n    }\n);
    ", - "With a findAndModify, it allows you to search for an object and update it, as well as upsert the object if it doesn't exist and receive the new object back each time in our callback function. In this example, we always set the last_login as now, we always increment the login_count by 1, and only when we insert a new object(new user) do we populate the majority of the fields. Something to notice also is the use of default values. Sometimes a profile returned won't have all the information filled out or it will have been chosen by the user to remain private; so in this case we have to handle it to prevent an error.", - "You should be able to login to your app now- try it! Submit your page when you think you've got it right. If you're running into errors, you can check out an example of this mini-project's finished code here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Github strategy setup complete", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /GitHubStrategy[^]*db.collection/gi, 'Strategy should use now use the database to search for the user'); assert.match(data, /GitHubStrategy[^]*socialusers/gi, 'Strategy should use \"socialusers\" as db collection'); assert.match(data, /GitHubStrategy[^]*return cb/gi, 'Strategy should return the callback function \"cb\"'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc820f9fc0f352b528e73", - "title": "Socket.IO Introduction", - "description": [ - [ - "", - "", - "Socket.IO enables real-time, reliable, speedy communication between your server and clients from all devices and browsers. It listens for connects on your server that come from the client which connects with a single javascript statement. The whole library is based on emitting, broadcasting, and recieving events that contain an event name and some data which can include things like strings, objects, arrays, and even blobs like files or video. This is used for all sorts of purposes including instant messaging online, real-time analytics, streaming, and document collaboration.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe.", - "" - ], - [ - "", - "", - "To set up this project to get started now in the .env file:
    1. Create a random session secret
    2. Fill in the database (it may be the same as the last few projects since this will use a new collection)
    3. Obtain another set of Github OAuth credentials with the callback once again pointed at '/auth/github/callback' and add it in
    ", - "" - ], - [ - "", - "", - "A few changes have been made to this starter.
    Instead of app.listen, you now have
    const http = require('http').Server(app);\n\nhttp.listen(process.env.PORT || 3000);
    This is required because for the initial handshake between the server and client, http is used. Setting up our server like this allows us to have both processes use a single port.
    Also, we have declared const sessionStore = new session.MemoryStore(); and used sessionStore as the store in our express session. In our previous apps we have not done this because by default it is done automattically. It is not this way so we can reference/use the sessionStore in other parts of our code now. In addition, we've given our session a key to reference it easier.", - "" - ] - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false - }, - { - "id": "589fc830f9fc0f352b528e74", - "title": "Set up the Enviroment", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Add Socket.IO as a dependency and require/instanciate it in your server defined as 'io' with the http server as an argument. const io = require('socket.io')(http);", - "The first thing needing to be handled is listening for a new connection from the client. The on keyword does just that- listen for a specific event. It requires 2 arguments: a string containing the title of the event thats emitted, and a function with which the data is passed though. In the case of our connection listener, we use socket to define the data in the second argument. A socket is an individual client who is connected.", - "For listening for connections on our server, add the following between the comments in your project:
    io.on('connection', socket => {\n  console.log('A user has connected');\n});
    ", - "Now for the client to connect, you just need to add the following to your client.js which is loaded by the page after you've authenticated:
    /*global io*/\nvar socket = io();
    The comment supresses the error you would normally see since 'io' is not defined in the file. We've already added a reliable CDN to the Socket.IO library on the page in chat.pug.", - "Now try loading up your app and authenticate and you should see in your server console 'A user has connected'!", - "Note
    io() works only when connecting to a socket hosted on the same url/server. For connecting to an external socket hosted elsewhere, you would use io.connect('URL');.", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Socket.IO is a dependency", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'socket.io', 'Your project should list \"socket.io\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Socket.IO has been properly required and instanciated", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /io.*=.*require.*('|\")socket.io('|\").*http/gi, 'You should correctly require and instanciate socket.io as io.');}, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Socket.IO should be listening for connections", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.on.*('|\")connection('|\").*socket/gi, 'io should listen for \"connection\" and socket should be the 2nd arguments variable'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Your client should connect to your server", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.*=.*io/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc831f9fc0f352b528e75", - "title": "Communicate by Emitting", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Emit is the most common way of communicating you will use. When you emit something from the server to 'io', you send an event's name and data to all the connected sockets. A good example of this concept would be emiting the current count of connected users each time a new user connects!", - "
    Start by adding a variable to keep track of the users just before where you are currently listening for connections. var currentUsers = 0;", - "Now when someone connects you should increment the count before emiting the count so you will want to add the incrementer within the connection listener. ++currentUsers;", - "Finally after incrementing the count, you should emit the event(still within the connection listener). The event should be named 'user count' and the data should just be the 'currentUsers'. io.emit('user count', currentUsers);", - "
    Now you can implement a way for your client to listen for this event! Similarly to listening for a connection on the server you will use the on keyword.
    socket.on('user count', function(data){\n  console.log(data);\n});
    ", - "Now try loading up your app and authenticate and you should see in your client console '1' representing the current user count! Try loading more clients up and authenticating to see the number go up.", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "currentUsers is defined", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /currentUsers/gi, 'You should have variable currentUsers defined');}, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Server emits the current user count at each new connection", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|\")user count('|\").*currentUsers/gi, 'You should emit \"user count\" with data currentUsers'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Your client is listening for 'user count' event", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user count('|\")/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc831f9fc0f352b528e76", - "title": "Handle a Disconnect", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "You may notice that up to now you have only been increasing the user count. Handling a user disconnecting is just as easy as handling the initial connect except the difference is you have to listen for it on each socket versus on the whole server.", - "
    To do this, add in to your existing connect listener a listener that listens for 'disconnect' on the socket with no data passed through. You can test this functionality by just logging to the console a user has disconnected. socket.on('disconnect', () => { /*anything you want to do on disconnect*/ });", - "To make sure clients continuously have the updated count of current users, you should decrease the currentUsers by 1 when the disconnect happens then emit the 'user count' event with the updated count!", - "Note
    Just like 'disconnect', all other events that a socket can emit to the server should be handled within the connecting listener where we have 'socket' defined.", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Server handles the event disconnect from a socket", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /socket.on.*('|\")disconnect('|\")/gi, ''); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Your client is listening for 'user count' event", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user count('|\")/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc831f9fc0f352b528e77", - "title": "Authentication with Socket.IO", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Currently, you cannot determine who is connected to your web socket. While 'req.user' containers the user object, thats only when your user interacts with the web server and with web sockets you have no req (request) and therefor no user data. One way to solve the problem of knowing who is connected to your web socket is by parsing and decoding the cookie that contains the passport session then deserializing it to obtain the user object. Luckily, there is a package on NPM just for this that turns a once complex task into something simple!", - "
    Add 'passport.socketio' as a dependency and require it as 'passportSocketIo'.", - "Now we just have to tell Socket.IO to use it and set the options. Be sure this is added before the existing socket code and not in the existing connection listener. For your server it should look as follows:
    io.use(passportSocketIo.authorize({\n  cookieParser: cookieParser,\n  key:          'express.sid',\n  secret:       process.env.SESSION_SECRET,\n  store:        sessionStore\n}));
    You can also optionally pass 'success' and 'fail' with a function that will be called after the authentication process completes when a client trys to connect.", - "The user object is now accessable on your socket object as socket.request.user. For example, now you can add the following: console.log('user ' + socket.request.user.name + ' connected'); and it will log to the server console who has connected!", - "Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here." - ], - "challengeSeed": [], - "tests": [ - { - "text": "passportSocketIo is a dependency", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passportSocketIo', 'Your project should list \"passportSocketIo\" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "passportSocketIo is properly required", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /passportSockerIo.*=.*require.*('|\")passportSocketIo('|\")/gi, 'You should correctly require and instanciate socket.io as io.');}, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "passportSocketIo is properly setup", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.use.*passportSocketIo.authorize/gi, 'You should have told io to use passportSockIo.authorize with the correct options'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc832f9fc0f352b528e78", - "title": "Announce New Users", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Many chat rooms are able to annouce when a user connects or disconnects and then display that to all of the connected users in the chat. Seeing as though you already are emitting an event on connect and disconnect, you will just have to modify this event to support such feature. The most logical way of doing so is sending 3 pieces of data with the event: name of the user connected/disconnected, the current user count, and if that name connected or disconnected.", - "
    Change the event name to 'user' and as the data pass an object along containing fields 'name', 'currentUsers', and boolean 'connected' (to be true if connection, or false for disconnection of the user sent). Be sure to make the change to both points we had the 'user count' event and set the disconnect one to sent false for field 'connected' instead of true like the event emitted on connect. io.emit('user', {name: socket.request.user.name, currentUsers, connected: true});", - "Now your client will have all the nesesary information to correctly display the current user count and annouce when a user connects or disconnects! To handle this event on the client side we should listen for 'user' and then update the current user count by using jQuery to change the text of #num-users to '{NUMBER} users online', as well as append a <li> to the unordered list with id 'messages' with '{NAME} has {joined/left} the chat.'.", - "An implementation of this could look like the following:
    socket.on('user', function(data){\n  $('#num-users').text(data.currentUsers+' users online');\n  var message = data.name;\n  if(data.connected) {\n    message += ' has joined the chat.';\n  } else {\n    message += ' has left the chat.';\n  }\n  $('#messages').append($('<li>').html('<b>'+ message +'<\\/b>'));\n});
    ", - "Submit your page when you think you've got it right." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Event 'user' is emitted with name, currentUsers, and connected", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|\")user('|\").*name.*currentUsers.*connected/gi, 'You should have an event emitted named user sending name, currentUsers, and connected'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Client properly handling and displaying the new data from event 'user'", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user('|\")[^]*num-users/gi, 'You should change the text of #num-users within on your client within the \"user\" even listener to show the current users connected'); assert.match(data, /socket.on.*('|\")user('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"user\" event listener to annouce a user came or went'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "589fc832f9fc0f352b528e79", - "title": "Send and Display Chat Messages", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "It's time you start allowing clients to send a chat message to the server to emit to all the clients! Already in your client.js file you should see there is already a block of code handling when the messgae form is submitted! ($('form').submit(function(){ /*logic*/ });)", - "
    Within the code you're handling the form submit you should emit an event after you define 'messageToSend' but before you clear the text box #m. The event should be named 'chat message' and the data should just be 'messageToSend'. socket.emit('chat message', messageToSend);", - "Now on your server you should be listening to the socket for the event 'chat message' with the data being named 'message'. Once the event is recieved it should then emit the event 'chat message' to all sockets io.emit with the data being an object containing 'name' and 'message'.", - "On your client now again, you should now listen for event 'chat message' and when recieved, append a list item to #messages with the name a colon and the message!", - "At this point the chat should be fully functional and sending messages across all clients! Submit your page when you think you've got it right. If you're running into errors, you can check out the project up to this point here for the server and here for the client." - ], - "challengeSeed": [], - "tests": [ - { - "text": "Server listens for 'chat message' then emits it properly", - "testString": "getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /socket.on.*('|\")chat message('|\")[^]*io.emit.*('|\")chat message('|\").*name.*message/gi, 'Your server should listen to the socket for \"chat message\" then emit to all users \"chat message\" with name and message in the data object'); }, xhr => { throw new Error(xhr.statusText); })" - }, - { - "text": "Client properly handling and displaying the new data from event 'chat message'", - "testString": "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")chat message('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"chat message\" event listener to display the new message'); }, xhr => { throw new Error(xhr.statusText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "translations": {} - }, - { - "id": "58a0b2caf9fc0f352b528e7a", - "title": "Continuing Your Live Chat", - "description": [ - [ - "", - "", - "From this point, you could choose to implement a plethora of features with just the knowledge you have learned up to this point! Some ideas you could choose to continue this project on with include, but aren't limited to the following:
    • Displaying the users profile picture next to the messages
    • Displaying a time stamp on messages
    • Saving the most recent messages so when a new user connects they can see the most recent messages sent before they connected
    • Add a sidebar showing active users
    • Create a {user} is typing feature
    • Turn the client into a React component you can add to any of your previous projects
    ", - "" - ] - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false - } - ] -} diff --git a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/information-security-with-helmetjs.json b/packages/learn/seed/tmp/06-information-security-and-quality-assurance/information-security-with-helmetjs.json deleted file mode 100644 index c18a2949bb..0000000000 --- a/packages/learn/seed/tmp/06-information-security-and-quality-assurance/information-security-with-helmetjs.json +++ /dev/null @@ -1,373 +0,0 @@ -{ - "name": "Information Security with HelmetJS", - "order": 1, - "time": "5 hours", - "helpRoom": "HelpBackend", - "challenges": [ - { - "id": "58af07504bbe015e85a91dbd", - "title": "Introduction to Information Security with HelmetJS Challenges", - "description": [ - "", - "", - "HelmetJS is a type of middleware for Express-based applications that automatically sets HTTP headers to prevent sensitive information from unintentially being passed between the server and client. While HelmetJS does not account for all situations, it does include support for common ones like Content Security Policy, XSS Filtering, and HTTP Strict Transport Security, among others. HelmetJS can be installed on an Express project from npm, after which each layer of protection can be configured to best fit the project.

    Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing.
    Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!", - "", - "@@STEP@@" - ], - "releasedOn": "Feb 17, 2017", - "challengeSeed": [], - "tests": [], - "type": "waypoint", - "challengeType": 7, - "isRequired": false, - "translations": {} - }, - { - "id": "587d8247367417b2b2512c36", - "title": "Install and Require Helmet", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Helmet helps you secure your Express apps by setting various HTTP headers. Install the package, then require it." - ], - "challengeSeed": [], - "tests": [ - { - "text": "\"helmet\" dependency should be in package.json", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'helmet'); }, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "releasedOn": "Feb 17, 2017", - "translations": {} - }, - { - "id": "587d8247367417b2b2512c37", - "title": "Hide Potentially Dangerous Information Using helmet.hidePoweredBy()", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Hackers can exploit known vulnerabilities in Express/Node if they see that your site is powered by Express. X-Powered-By: Express is sent in every request coming from Express by default. The helmet.hidePoweredBy() middleware will remove the X-Powered-By header. You can also explicitly set the header to something else, to throw people off. e.g. app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))" - ], - "challengeSeed": [], - "tests": [ - { - "text": "helmet.hidePoweredBy() middleware should be mounted correctly", - "testString": "getUserInput => $.get(getUserInput('url') + '/_api/app-info').then(data => { assert.include(data.appStack, 'hidePoweredBy'); assert.notEqual(data.headers['x-powered-by'], 'Express')}, xhr => { throw new Error(xhr.responseText); })" - } - ], - "solutions": [], - "hints": [], - "challengeType": 2, - "releasedOn": "Feb 17, 2017", - "translations": {} - }, - { - "id": "587d8247367417b2b2512c38", - "title": "Mitigate the Risk of Clickjacking with helmet.frameguard()", - "description": [ - "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.", - "Your page could be put in a or