diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json
index 83ee788c6e6..ffca5cb5bbe 100644
--- a/client/i18n/locales/english/intro.json
+++ b/client/i18n/locales/english/intro.json
@@ -308,9 +308,12 @@
],
"note": "Note: Some browser extensions, such as ad-blockers and script-blockers can interfere with the tests. If you face issues, we recommend disabling extensions that modify or block the content of pages while taking the course.",
"blocks": {
- "build-a-caesars-cipher-project": {
- "title": "Build a Caesars Cipher Project",
- "intro": ["", ""]
+ "build-a-pokemon-search-app-project": {
+ "title": "Build a Pokémon Search App Project",
+ "intro": [
+ "This is one of the required projects to earn your certification.",
+ "For this project, you will build a Pokémon search app."
+ ]
},
"build-a-cash-register-project": {
"title": "Build a Cash Register Project",
diff --git a/curriculum/challenges/_meta/build-a-cash-register-project/meta.json b/curriculum/challenges/_meta/build-a-cash-register-project/meta.json
index def44814400..3ef5daf5280 100644
--- a/curriculum/challenges/_meta/build-a-cash-register-project/meta.json
+++ b/curriculum/challenges/_meta/build-a-cash-register-project/meta.json
@@ -11,7 +11,7 @@
"superBlock": "2022/javascript-algorithms-and-data-structures",
"challengeOrder": [
{
- "id": "aa2e6f85cab2ab736c9a9b24",
+ "id": "657bdcc3a322aae1eac38392",
"title": "Build a Cash Register"
}
]
diff --git a/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json b/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json
index 0661800593c..34ae372652d 100644
--- a/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json
+++ b/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json
@@ -11,7 +11,7 @@
"superBlock": "2022/javascript-algorithms-and-data-structures",
"challengeOrder": [
{
- "id": "aaa48de84e1ecc7c742e1124",
+ "id": "657bdc55a322aae1eac3838f",
"title": "Build a Palindrome Checker"
}
]
diff --git a/curriculum/challenges/_meta/build-a-pokemon-search-app-project/meta.json b/curriculum/challenges/_meta/build-a-pokemon-search-app-project/meta.json
new file mode 100644
index 00000000000..3f31f22cee8
--- /dev/null
+++ b/curriculum/challenges/_meta/build-a-pokemon-search-app-project/meta.json
@@ -0,0 +1,18 @@
+{
+ "name": "Build a Pokémon Search App Project",
+ "isUpcomingChange": true,
+ "dashedName": "build-a-pokemon-search-app-project",
+ "usesMultifileEditor": true,
+ "helpCategory": "JavaScript",
+ "order": 99,
+ "time": "30 hours",
+ "template": "",
+ "required": [],
+ "superBlock": "2022/javascript-algorithms-and-data-structures",
+ "challengeOrder": [
+ {
+ "id": "6555c1d3e11a1574434cf8b5",
+ "title": "Build a Pokémon Search App Project"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json b/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json
index b2834477473..246eff50e45 100644
--- a/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json
+++ b/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json
@@ -11,7 +11,7 @@
"superBlock": "2022/javascript-algorithms-and-data-structures",
"challengeOrder": [
{
- "id": "a7f4d8f2483413a6ce226cac",
+ "id": "657bdc8ba322aae1eac38390",
"title": "Build a Roman Numeral Converter"
}
]
diff --git a/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json b/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json
index e58ca6577f3..d3303e31e41 100644
--- a/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json
+++ b/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json
@@ -11,7 +11,7 @@
"superBlock": "2022/javascript-algorithms-and-data-structures",
"challengeOrder": [
{
- "id": "aff0395860f5d3034dc0bfc9",
+ "id": "657bdcb9a322aae1eac38391",
"title": "Build a Telephone Number Validator"
}
]
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-caesars-cipher-project/caesars-cipher.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-caesars-cipher-project/caesars-cipher.md
deleted file mode 100644
index 46c493ad260..00000000000
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-caesars-cipher-project/caesars-cipher.md
+++ /dev/null
@@ -1,88 +0,0 @@
----
-id: 56533eb9ac21ba0edf2244e2
-title: Build a Caesars Cipher
-challengeType: 5
-forumTopicId: 16003
-dashedName: build-a-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.
-
-# --hints--
-
-`rot13("SERR PBQR PNZC")` should decode to the string `FREE CODE CAMP`
-
-```js
-assert(rot13('SERR PBQR PNZC') === 'FREE CODE CAMP');
-```
-
-`rot13("SERR CVMMN!")` should decode to the string `FREE PIZZA!`
-
-```js
-assert(rot13('SERR CVMMN!') === 'FREE PIZZA!');
-```
-
-`rot13("SERR YBIR?")` should decode to the string `FREE LOVE?`
-
-```js
-assert(rot13('SERR YBIR?') === 'FREE LOVE?');
-```
-
-`rot13("GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.")` should decode to the string `THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.`
-
-```js
-assert(
- rot13('GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.') ===
- 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.'
-);
-```
-
-# --seed--
-
-## --seed-contents--
-
-```js
-function rot13(str) {
- return str;
-}
-
-rot13("SERR PBQR PNZC");
-```
-
-# --solutions--
-
-```js
-var lookup = {
- 'A': 'N','B': 'O','C': 'P','D': 'Q',
- 'E': 'R','F': 'S','G': 'T','H': 'U',
- 'I': 'V','J': 'W','K': 'X','L': 'Y',
- 'M': 'Z','N': 'A','O': 'B','P': 'C',
- 'Q': 'D','R': 'E','S': 'F','T': 'G',
- 'U': 'H','V': 'I','W': 'J','X': 'K',
- 'Y': 'L','Z': 'M'
-};
-
-function rot13(encodedStr) {
- var codeArr = encodedStr.split(""); // String to Array
- var decodedArr = []; // Your Result goes here
- // Only change code below this line
-
- decodedArr = codeArr.map(function(letter) {
- if(lookup.hasOwnProperty(letter)) {
- letter = lookup[letter];
- }
- return letter;
- });
-
- // Only change code above this line
- return decodedArr.join(""); // Array to String
-}
-```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-cash-register-project/cash-register.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-cash-register-project/cash-register.md
index c98d513eb13..42d7560639e 100644
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-cash-register-project/cash-register.md
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-cash-register-project/cash-register.md
@@ -1,31 +1,203 @@
---
-id: aa2e6f85cab2ab736c9a9b24
+id: 657bdcc3a322aae1eac38392
title: Build A Cash Register
-challengeType: 5
+challengeType: 14
forumTopicId: 16012
dashedName: build-a-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.
+Here you'll build a cash register app that will return change to the customer based on the price of the item, the amount of cash provided by the customer, and the amount of cash in the cash drawer. You'll also need to show different messages to the user in different scenarios, such as when the customer provides too little cash or when the cash drawer doesn't have enough to issue the correct change.
-`cid` is a 2D array listing available currency.
+There are a few variables you'll need to use in your code:
-The `checkCashRegister()` function should always return an object with a `status` key and a `change` key.
+- `price`: the price of the item as a floating point number.
+- `cash`: the amount of cash provided by the customer for the item, which is provided via an `input` element on the page.
+- `cid`: cash-in-drawer, a 2D array listing available currency in the cash drawer.
-Return `{status: "INSUFFICIENT_FUNDS", change: []}` if cash-in-drawer is less than the change due, or if you cannot return the exact change.
+If you'd like to test your application with different values for `price` and `cid`, make sure to declare them with the `let` keyword so they can be reassigned by our tests.
-Return `{status: "CLOSED", change: [...]}` with cash-in-drawer as the value for the key `change` if it is equal to the change due.
+Your application should show different messages depending on the price of the item, the amount of cash provided by the customer, and the amount of cash in the drawer:
-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.
+- `Status: INSUFFICIENT_FUNDS`: if `cash-in-drawer` is less than the change due, or if you cannot return the exact change.
+- `Status: CLOSED`: if `cash-in-drawer` is equal to the change due.
+- `Status: OPEN`: if `cash-in-drawer` is greater than the change due and you can return change, with the change due in coins and bills sorted in highest to lowest order.
-
Currency Unit
Amount
Penny
$0.01 (PENNY)
Nickel
$0.05 (NICKEL)
Dime
$0.1 (DIME)
Quarter
$0.25 (QUARTER)
Dollar
$1 (ONE)
Five Dollars
$5 (FIVE)
Ten Dollars
$10 (TEN)
Twenty Dollars
$20 (TWENTY)
One-hundred Dollars
$100 (ONE HUNDRED)
+| Currency Unit | Amount |
+|:-------------------:|:------------------:|
+| Penny | $0.01 (PENNY) |
+| Nickle | $0.05 (NICKEL) |
+| Dime | $0.1 (DIME) |
+| Quarter | $0.25 (QUARTER) |
+| Dollar | $1 (ONE) |
+| Five Dollars | $5 (FIVE) |
+| Ten Dollars | $10 (TEN) |
+| Twenty Dollars | $20 (TWENTY) |
+| One Hundred Dollars | $100 (ONE HUNDRED) |
-See below for an example of a cash-in-drawer array:
+**Objective:** Build an app that is functionally similar to https://cash-register.freecodecamp.rocks
+
+**User Stories:**
+
+1. You should have an `input` element with an `id` of `cash`
+1. You should have a `div` element with an `id` of `change-due`
+1. You should have a `button` element with an `id` of `purchase-btn`
+1. When the value in the `#cash` element is less than `price`, an alert should appear with the text `Customer does not have enough money to purchase the item`
+1. When the value in the `#cash` element is equal to `price`, the value in the `#change-due` element should be `No change due - customer paid with exact cash`
+1. When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: OPEN QUARTER: $0.5`
+1. When `price` is `3.26`, the value in the `#cash` element is `100`, `cid` is `[["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04`
+1. When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: INSUFFICIENT_FUNDS`
+1. When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: INSUFFICIENT_FUNDS`
+1. When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: CLOSED QUARTER: $0 DIME: $0 NICKEL: $0 PENNY: $0.5`
+
+Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding!
+
+# --hints--
+
+You should have an `input` element with an `id` of `cash`.
```js
-[
+const el = document.getElementById('cash');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'input');
+```
+
+You should have a `div` element with an `id` of `change-due`.
+
+```js
+const el = document.getElementById('change-due');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'div');
+```
+
+You should have a `button` element with an `id` of `purchase-btn`.
+
+```js
+const el = document.getElementById('purchase-btn');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
+```
+
+When the value in the `#cash` element is less than `price`, an alert should appear with the text `Customer does not have enough money to purchase the item`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+let alertMessage;
+window.alert = (message) => alertMessage = message; // Override alert and store message
+// set price and customer cash
+price = 20;
+cashInput.value = '10';
+
+purchaseBtn.click();
+assert.strictEqual(alertMessage.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'customer does not have enough money to purchase the item');
+```
+
+When the value in the `#cash` element is equal to `price`, the value in the `#change-due` element should be `No change due - customer paid with exact cash`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price and customer cash
+price = 11.95;
+cashInput.value = '11.95';
+
+purchaseBtn.click();
+assert.strictEqual(changeDueDiv.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'no change due - customer paid with exact cash');
+```
+
+When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: OPEN QUARTER: $0.5`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price, customer cash, and cid
+price = 19.5;
+cashInput.value = 20;
+cid = [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.1], ['QUARTER', 4.25], ['ONE', 90], ['FIVE', 55], ['TEN', 20], ['TWENTY', 60], ['ONE HUNDRED', 100]];
+
+const expected = ['Status: OPEN', 'QUARTER: $0.5'];
+purchaseBtn.click();
+assert.isTrue(expected.every(str => changeDueDiv.innerText.trim().toLowerCase().includes(str.toLowerCase())));
+```
+
+When `price` is `3.26`, the value in the `#cash` element is `100`, `cid` is `[["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: OPEN TWENTY: $60 TEN: $20 FIVE: $15 ONE: $1 QUARTER: $0.5 DIME: $0.2 PENNY: $0.04`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price, customer cash, and cid
+price = 3.26;
+cashInput.value = 100;
+cid = [['PENNY', 1.01], ['NICKEL', 2.05], ['DIME', 3.1], ['QUARTER', 4.25], ['ONE', 90], ['FIVE', 55], ['TEN', 20], ['TWENTY', 60], ['ONE HUNDRED', 100]];
+
+const expected = ['Status: OPEN', 'TWENTY: $60', 'TEN: $20', 'FIVE: $15', 'ONE: $1', 'QUARTER: $0.5', 'DIME: $0.2', 'PENNY: $0.04'];
+purchaseBtn.click();
+assert.isTrue(expected.every(str => changeDueDiv.innerText.trim().toLowerCase().includes(str.toLowerCase())));
+```
+
+When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: INSUFFICIENT_FUNDS`
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price, customer cash, and cid
+price = 19.5;
+cashInput.value = 20;
+cid = [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]];
+
+purchaseBtn.click();
+assert.strictEqual(changeDueDiv.innerText.trim().toLowerCase(), 'status: insufficient_funds');
+```
+
+When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: INSUFFICIENT_FUNDS`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price, customer cash, and cid
+price = 19.5;
+cashInput.value = 20;
+cid = [['PENNY', 0.01], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 1], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]];
+
+purchaseBtn.click();
+assert.strictEqual(changeDueDiv.innerText.trim().toLowerCase(), 'status: insufficient_funds');
+```
+
+When `price` is `19.5`, the value in the `#cash` element is `20`, `cid` is `[["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]`, and the `#purchase-btn` element is clicked, the value in the `#change-due` element should be `Status: CLOSED QUARTER: $0 DIME: $0 NICKEL: $0 PENNY: $0.5`.
+
+```js
+const cashInput = document.getElementById('cash');
+const purchaseBtn = document.getElementById('purchase-btn');
+const changeDueDiv = document.getElementById('change-due');
+// set price, customer cash, and cid
+price = 19.5;
+cashInput.value = 20;
+cid = [['PENNY', 0.5], ['NICKEL', 0], ['DIME', 0], ['QUARTER', 0], ['ONE', 0], ['FIVE', 0], ['TEN', 0], ['TWENTY', 0], ['ONE HUNDRED', 0]];
+
+const expected = ['Status: OPEN', 'QUARTER: $0', 'DIME: $0', 'NICKEL: $0', 'PENNY: $0.5'];
+purchaseBtn.click();
+assert.isTrue(expected.every(str => changeDueDiv.innerText.trim().toLowerCase().includes(str.toLowerCase())));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+```
+
+```css
+
+```
+
+```js
+let price = 1.87;
+let cid = [
["PENNY", 1.01],
["NICKEL", 2.05],
["DIME", 3.1],
@@ -35,218 +207,353 @@ See below for an example of a cash-in-drawer array:
["TEN", 20],
["TWENTY", 60],
["ONE HUNDRED", 100]
-]
-```
+];
-# --hints--
-
-`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.
-
-```js
-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]'
-);
-```
-
-`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]]}`.
-
-```js
-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]] }
-);
-```
-
-`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]]}`.
-
-```js
-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]
- ]
- }
-);
-```
-
-`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: []}`.
-
-```js
-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: [] }
-);
-```
-
-`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: []}`.
-
-```js
-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: [] }
-);
-```
-
-`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]]}`.
-
-```js
-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]
- ]
- }
-);
-```
-
-# --seed--
-
-## --seed-contents--
-
-```js
-function checkCashRegister(price, cash, cid) {
- let change;
- return change;
-}
-
-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--
-```js
-const denom = [
- { name: "ONE HUNDRED", val: 100 },
- { name: "TWENTY", val: 20 },
- { name: "TEN", val: 10 },
- { name: "FIVE", val: 5 },
- { name: "ONE", val: 1 },
- { name: "QUARTER", val: 0.25 },
- { name: "DIME", val: 0.1 },
- { name: "NICKEL", val: 0.05 },
- { name: "PENNY", val: 0.01 },
-];
+```html
+
+
+
+
+
+
+
+ Cash Register
+
+
+
+
+
+
`)
+ .join("")}
+ `;
+};
+
+purchaseBtn.addEventListener("click", checkResults);
+
+cash.addEventListener("keydown", (e) => {
+ if (e.key === "Enter") {
+ checkResults();
+ }
+});
+
+updateUI();
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/palindrome-checker.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/palindrome-checker.md
index 5f7ca896a8c..fab7b30012e 100644
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/palindrome-checker.md
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-palindrome-checker-project/palindrome-checker.md
@@ -1,125 +1,453 @@
---
-id: aaa48de84e1ecc7c742e1124
+id: 657bdc55a322aae1eac3838f
title: Build A Palindrome Checker
-challengeType: 5
+challengeType: 14
forumTopicId: 16004
dashedName: build-a-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.
+A palindrome is a word or phrase that can be read the same way forwards and backwards, 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.
+**Objective:** Build an app that is functionally similar to https://palindrome-checker.freecodecamp.rocks
-We'll also pass strings with special symbols, such as `2A3*3a2`, `2A3 3a2`, and `2_A3*3#A2`.
+**User Stories:**
+
+1. You should have an `input` element with an `id` of `text-input`
+1. You should have a `button` element with an `id` of `check-btn`
+1. You should have a `div` element with an `id` of `result`
+1. When you click on the `#check-btn` element without entering a value into the `#text-input` element, an alert should appear with the text `Please input a value`
+1. When the `#text-input` element only contains the letter `A` and the `#check-btn` element is clicked, the `#result` element should contain the text `A is a palindrome`
+1. When the `#text-input` element contains the text `eye` and the `#check-btn` element is clicked, the `#result` element should contain the text `eye is a palindrome`
+1. When the `#text-input` element contains the text `_eye` and the `#check-btn` element is clicked, the `#result` element should contain the text `eye is a palindrome`
+1. When the `#text-input` element contains the text `race car` and the `#check-btn` element is clicked, the `#result` element should contain the text `race car is a palindrome`
+1. When the `#text-input` element contains the text `not a palindrome` and the `#check-btn` element is clicked, the `#result` element should contain the text `not a palindrome is not a palindrome`
+1. When the `#test-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `A man, a plan, a canal. Panama is a palindrome`
+1. When the `#text-input` element contains the text `never odd or even` and the `#check-btn` element is clicked, the `#result` element should contain the text `never odd or even is a palindrome`
+1. When the `#text-input` element contains the text `nope` and the `#check-btn` element is clicked, the `#result` element should contain the text `nope is not a palindrome`
+1. When the `#text-input` element contains the text `almostomla` and the `#check-btn` element is clicked, the `#result` element should contain the text `almostomla is not a palindrome`
+1. When the `#text-input` element contains the text `My age is 0, 0 si ega ym.` and the `#check-btn` element is clicked, the `#result` element should contain the text `My age is 0, 0 si ega ym. is a palindrome`
+1. When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `1 eye for of 1 eye. is not a palindrome`
+1. When the `#text-input` element contains the text `0_0 (: /-\ :) 0-0` and the `#check-btn` element is clicked, the `#result` element should contain the text `0_0 (: /-\ :) 0-0 is a palindrome`
+1. When the `#text-input` element contains the text `five|\_/|four` and the `#check-btn` element is clicked, the `#result` element should contain the text `five|\_/|four is not a palindrome`
+
+Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding!
# --hints--
-`palindrome("eye")` should return a boolean.
+You should have an `input` element with an `id` of `text-input`.
```js
-assert(typeof palindrome('eye') === 'boolean');
+const el = document.getElementById('text-input');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'input');
```
-`palindrome("eye")` should return `true`.
+You should have a `button` element with an `id` of `check-btn`.
```js
-assert(palindrome('eye') === true);
+const el = document.getElementById('check-btn');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
```
-`palindrome("_eye")` should return `true`.
+You should have a `div` element with an `id` of `result`.
```js
-assert(palindrome('_eye') === true);
+const el = document.getElementById('result');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'div');
```
-`palindrome("race car")` should return `true`.
+When you click on the `#check-btn` element without entering a value into the `#text-input` element, an alert should appear with the text `Please input a value`.
```js
-assert(palindrome('race car') === true);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+let alertMessage;
+window.alert = (message) => alertMessage = message; // Override alert and store message
+
+inputEl.value = '';
+checkBtn.click();
+assert.strictEqual(alertMessage.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'please input a value');
```
-`palindrome("not a palindrome")` should return `false`.
+When the `#text-input` element only contains the letter `A` and the `#check-btn` element is clicked, the `#result` element should contain the text `A is a palindrome`.
```js
-assert(palindrome('not a palindrome') === false);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'A';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'a is a palindrome');
```
-`palindrome("A man, a plan, a canal. Panama")` should return `true`.
+When the `#text-input` element contains the text `eye` and the `#check-btn` element is clicked, the `#result` element should contain the text `eye is a palindrome`.
```js
-assert(palindrome('A man, a plan, a canal. Panama') === true);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'eye';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'eye is a palindrome');
```
-`palindrome("never odd or even")` should return `true`.
+When the `#text-input` element contains the text `_eye` and the `#check-btn` element is clicked, the `#result` element should contain the text `eye is a palindrome`.
```js
-assert(palindrome('never odd or even') === true);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = '_eye';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), '_eye is a palindrome');
```
-`palindrome("nope")` should return `false`.
+When the `#text-input` element contains the text `race car` and the `#check-btn` element is clicked, the `#result` element should contain the text `race car is a palindrome`.
```js
-assert(palindrome('nope') === false);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'race car';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'race car is a palindrome');
```
-`palindrome("almostomla")` should return `false`.
+When the `#text-input` element contains the text `not a palindrome` and the `#check-btn` element is clicked, the `#result` element should contain the text `not a palindrome is not a palindrome`.
```js
-assert(palindrome('almostomla') === false);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'not a palindrome';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'not a palindrome is not a palindrome');
```
-`palindrome("My age is 0, 0 si ega ym.")` should return `true`.
+When the `#test-input` element contains the text `A man, a plan, a canal. Panama` and the `#check-btn` element is clicked, the `#result` element should contain the text `A man, a plan, a canal. Panama is a palindrome`.
```js
-assert(palindrome('My age is 0, 0 si ega ym.') === true);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'A man, a plan, a canal. Panama';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'a man, a plan, a canal. panama is a palindrome');
```
-`palindrome("1 eye for of 1 eye.")` should return `false`.
+When the `#text-input` element contains the text `never odd or even` and the `#check-btn` element is clicked, the `#result` element should contain the text `never odd or even is a palindrome`.
```js
-assert(palindrome('1 eye for of 1 eye.') === false);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'never odd or even';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'never odd or even is a palindrome');
```
-`palindrome("0_0 (: /-\ :) 0-0")` should return `true`.
+When the `#text-input` element contains the text `nope` and the `#check-btn` element is clicked, the `#result` element should contain the text `nope is not a palindrome`.
```js
-assert(palindrome('0_0 (: /- :) 0-0') === true);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'nope';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'nope is not a palindrome');
```
-`palindrome("five|\_/|four")` should return `false`.
+When the `#text-input` element contains the text `almostomla` and the `#check-btn` element is clicked, the `#result` element should contain the text `almostomla is not a palindrome`.
```js
-assert(palindrome('five|_/|four') === false);
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'almostomla';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'almostomla is not a palindrome');
+```
+
+When the `#text-input` element contains the text `My age is 0, 0 si ega ym.` and the `#check-btn` element is clicked, the `#result` element should contain the text `My age is 0, 0 si ega ym. is a palindrome`.
+
+```js
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'My age is 0, 0 si ega ym.';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'my age is 0, 0 si ega ym. is a palindrome');
+```
+
+When the `#text-input` element contains the text `1 eye for of 1 eye.` and the `#check-btn` element is clicked, the `#result` element should contain the text `1 eye for of 1 eye. is not a palindrome`.
+
+```js
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = '1 eye for of 1 eye.';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), '1 eye for of 1 eye. is not a palindrome');
+```
+
+When the `#text-input` element contains the text `0_0 (: /-\ :) 0-0` and the `#check-btn` element is clicked, the `#result` element should contain the text `0_0 (: /-\ :) 0-0 is a palindrome`.
+
+```js
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = '0_0 (: /-\ :) 0-0';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), '0_0 (: /-\ :) 0-0 is a palindrome');
+```
+
+When the `#text-input` element contains the text `five|\_/|four` and the `#check-btn` element is clicked, the `#result` element should contain the text `five|\_/|four is not a palindrome`.
+
+```js
+const inputEl = document.getElementById('text-input');
+const checkBtn = document.getElementById('check-btn');
+const resultEl = document.getElementById('result');
+
+inputEl.value = 'five|\_/|four';
+checkBtn.click();
+assert.strictEqual(resultEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'five|\_/|four is not a palindrome');
```
# --seed--
## --seed-contents--
-```js
-function palindrome(str) {
- return true;
-}
+```html
+
+```
+
+```css
+
+```
+
+```js
-palindrome("eye");
```
# --solutions--
-```js
-function palindrome(str) {
- var string = str.toLowerCase().split(/[^A-Za-z0-9]/gi).join('');
- var aux = string.split('');
- if (aux.join('') === aux.reverse().join('')){
- return true;
- }
+```html
+
+
+
+
+
+
+
+ Palindrome Checker
+
+
+
+
+
+
Is it a Palindrome?
+
+
+
+
+
+
+
+
+ 💡
+ A palindrome is a word or sentence that's spelled the same
+ way both forward and backward, ignoring punctuation, case, and
+ spacing.
+
+
+
+
+
+
+```
- return false;
+```css
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
+ background-color: #0a0a23;
+ color: #ffffff;
+}
+
+.container {
+ width: 100%;
+ min-height: 100vh;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+}
+
+.freecodecamp-logo {
+ height: 30px;
+ margin-bottom: 20px;
+}
+
+.title {
+ text-align: center;
+ padding: 10px 0;
+ font-size: 2.5rem;
+ margin-bottom: 20px;
+}
+
+.palindrome-div {
+ width: min(100vw, 450px);
+ min-height: 100px;
+ border-radius: 20px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ padding: 20px;
+ margin: 10px 0;
+ background-color: white;
+ box-shadow: 0 6px 6px #002ead;
+}
+
+label {
+ color: #0a0a23;
+ margin-bottom: 20px;
+}
+
+.palindrome-btn {
+ width: 90px;
+ border: none;
+ padding: 10px;
+ border-radius: 15px;
+ background-color: #5a01a7;
+ color: #fff;
+ cursor: pointer;
+}
+
+.palindrome-input {
+ height: 30px;
+ width: 250px;
+ text-align: center;
+ font-size: 1.2rem;
+ margin: 10px;
+ border: none;
+ border-bottom: 2px solid #5a01a7;
+}
+
+.palindrome-input:focus {
+ border-bottom: 3px solid #5a01a7;
+}
+
+.palindrome-input::placeholder {
+ text-align: center;
+}
+
+.user-input {
+ font-size: 1.4rem;
+ margin-top: 10px;
+ text-align: center;
+}
+
+.results-div {
+ overflow-y: auto;
+ word-wrap: break-word;
+ min-height: 50px;
+ color: black;
+}
+
+.hidden {
+ display: none;
+}
+
+.palindrome-definition-div {
+ width: min(100vw, 450px);
+ font-size: 1.3rem;
+ min-height: 140px;
+ background-color: #00471b;
+ margin-top: 20px;
+ padding: 20px;
+ border-radius: 20px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.palindrome-definition {
+ vertical-align: middle;
+ text-align: center;
}
```
+
+```js
+const userInput = document.getElementById("text-input");
+const checkPalindromeBtn = document.getElementById("check-btn");
+const resultDiv = document.getElementById("result");
+
+const checkForPalindrome = (input) => {
+ const originalInput = input; // Store for later output
+
+ if (input === "") {
+ alert("Please input a value");
+ return;
+ }
+
+ // Remove the previous result
+ resultDiv.replaceChildren();
+
+ const lowerCaseStr = input.replace(/[^A-Za-z0-9]/gi, "").toLowerCase();
+ let resultMsg = `${originalInput} ${
+ lowerCaseStr === [...lowerCaseStr].reverse().join("") ? "is" : "is not"
+ } a palindrome.`;
+
+ const pTag = document.createElement("p");
+ pTag.className = "user-input";
+ pTag.innerHTML = resultMsg;
+ resultDiv.appendChild(pTag);
+
+ // Show the result.
+ resultDiv.classList.remove("hidden");
+};
+
+checkPalindromeBtn.addEventListener("click", () => {
+ checkForPalindrome(userInput.value);
+ userInput.value = "";
+});
+
+userInput.addEventListener("keydown", (e) => {
+ if (e.key === "Enter") {
+ checkForPalindrome(userInput.value);
+ userInput.value = "";
+ }
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-pokemon-search-app-project/build-a-pokemon-search-app.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-pokemon-search-app-project/build-a-pokemon-search-app.md
new file mode 100644
index 00000000000..6dc56cecce7
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-pokemon-search-app-project/build-a-pokemon-search-app.md
@@ -0,0 +1,796 @@
+---
+id: 6555c1d3e11a1574434cf8b5
+title: Build a Pokémon Search App
+challengeType: 14
+forumTopicId: 16003
+dashedName: build-a-pokemon-search-app
+---
+
+# --description--
+
+In this project, you'll build an app that will search for Pokémon by name or ID and display the results to the user. To retrieve the Pokémon data and images, you'll use freeCodeCamp's PokéAPI Proxy.
+
+**Objective:** Build an app that is functionally similar to https://pokemon-search-app.freecodecamp.rocks
+
+**User Stories:**
+
+1. You should have an `input` element with an `id` of `search-input`
+1. You should have a `button` element with an `id` of `search-button`
+1. You should have an element with an `id` of `pokemon-name`
+1. You should have an element with an `id` of `pokemon-id`
+1. You should have an element with an `id` of `weight`
+1. You should have an element with an `id` of `height`
+1. You should have an element with an `id` of `types`
+1. You should have an element with an `id` of `hp`
+1. You should have an element with an `id` of `attack`
+1. You should have an element with an `id` of `defense`
+1. You should have an element with an `id` of `special-attack`
+1. You should have an element with an `id` of `special-defense`
+1. You should have an element with an `id` of `speed`
+1. When the `#search-input` element contains the value `Red` and the `#search-button` element is clicked, an alert should appear with the text `Pokémon not found`
+1. When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, the values in the `#pokemon-name`, `#pokemon-id`, `#weight`, `#height`, `#hp`, `#attack`, `#defense`, `#special-attack`, and `#special-defense` elements should be `PIKACHU`, `#25` or `25`, `Weight: 60` or `60`, `Height: 4` or `4`, `35`, `55`, `40`, `50`, `50`, and `90`, respectively
+1. When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, you should add an `img` element with the `id` of `sprite` and the `src` set to the Pokémon's `front_default` sprite to the page
+1. When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, the `#types` element should contain a single inner element with the value `ELECTRIC`
+1. When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, the values in the `#pokemon-name`, `#pokemon-id`, `#weight`, `#height`, `#hp`, `#attack`, `#defense`, `#special-attack`, and `#special-defense` elements should be `GENGAR`, `#94` or `94`, `Weight: 405` or `405`, `Height: 15` or `15`, `60`, `65`, `60`, `130`, `75`, and `110`, respectively
+1. When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, you should add an `img` element with the `id` of `sprite` and the `src` set to the Pokémon's `front_default` sprite to the page
+1. When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, the `#types` element should contain a two inner element with the text values `GHOST` and `POISON`, respectively
+
+Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding!
+
+# --hints--
+
+You should have an `input` element with an `id` of `search-input` and is **required**.
+
+```js
+const el = document.getElementById('search-input');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'input');
+assert.isTrue(el?.required);
+```
+
+You should have a `button` element with an `id` of `search-button`.
+
+```js
+const el = document.getElementById('search-button');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
+```
+
+You should have an element with an `id` of `pokemon-name`.
+
+```js
+const el = document.getElementById('pokemon-name');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `pokemon-id`.
+
+```js
+const el = document.getElementById('pokemon-id');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `weight`.
+
+```js
+const el = document.getElementById('weight');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `height`.
+
+```js
+const el = document.getElementById('height');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `types`.
+
+```js
+const el = document.getElementById('types');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `hp`.
+
+```js
+const el = document.getElementById('hp');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `attack`.
+
+```js
+const el = document.getElementById('attack');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `defense`.
+
+```js
+const el = document.getElementById('defense');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `special-attack`.
+
+```js
+const el = document.getElementById('special-attack');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `special-defense`.
+
+```js
+const el = document.getElementById('special-defense');
+assert.exists(el);
+```
+
+You should have an element with an `id` of `speed`.
+
+```js
+const el = document.getElementById('speed');
+assert.exists(el);
+```
+
+When the `#search-input` element contains the value `Red` and the `#search-button` element is clicked, an alert should appear with the text `Pokémon not found`.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ let alertMessage;
+ window.alert = (message) => alertMessage = message; // Override alert and store message
+ searchInput.value = 'Red';
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/red'); // Fetch from proxy to simulate network delay
+
+ if (!res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow the alert to trigger
+
+ assert.include(['pokémon not found', 'pokemon not found'], alertMessage.trim().replace(/[.,?!]+$/g, '').toLowerCase());
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, the values in the `#pokemon-name`, `#pokemon-id`, `#weight`, `#height`, `#hp`, `#attack`, `#defense`, `#special-attack`, and `#special-defense` elements should be `PIKACHU`, `#25` or `25`, `Weight: 60` or `60`, `Height: 4` or `4`, `35`, `55`, `40`, `50`, `50`, and `90`, respectively.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ searchInput.value = 'Pikachu';
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/pikachu'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+
+ const pokemonName = document.getElementById('pokemon-name');
+ const pokemonID = document.getElementById('pokemon-id');
+ const weight = document.getElementById('weight');
+ const height = document.getElementById('height');
+ const hp = document.getElementById('hp');
+ const attack = document.getElementById('attack');
+ const defense = document.getElementById('defense');
+ const specialAttack = document.getElementById('special-attack');
+ const specialDefense = document.getElementById('special-defense');
+ const speed = document.getElementById('speed');
+
+ assert.strictEqual(pokemonName.innerText.trim().toLowerCase(), 'pikachu');
+ assert.include(['#25', '25'], pokemonID.innerText.trim());
+ assert.include(['weight: 60', '60'], weight.innerText.trim().toLowerCase());
+ assert.include(['height: 4', '4'], height.innerText.trim().toLowerCase());
+ assert.strictEqual(hp.innerText.trim(), '35');
+ assert.strictEqual(attack.innerText.trim(), '55');
+ assert.strictEqual(defense.innerText.trim(), '40');
+ assert.strictEqual(specialAttack.innerText.trim(), '50');
+ assert.strictEqual(specialDefense.innerText.trim(), '50');
+ assert.strictEqual(speed.innerText.trim(), '90');
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, you should add an `img` element with the `id` of `sprite` and the `src` set to the Pokémon's `front_default` sprite to the page.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ searchInput.value = 'Pikachu';
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/pikachu'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+
+ const sprite = document.getElementById('sprite');
+ assert.isTrue(sprite.src.endsWith('sprites/pokemon/25.png'));
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `Pikachu` and the `#search-button` element is clicked, the `#types` element should contain a single inner element with the value `ELECTRIC`.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ const typesEl = document.getElementById('types');
+ searchInput.value = 'Pikachu';
+ typesEl.innerHTML = ''; // Clear types element before test
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/pikachu'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+
+ assert.lengthOf(typesEl.children, 1);
+ assert.strictEqual(typesEl?.children[0]?.innerText.trim().toLowerCase(), 'electric');
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, the values in the `#pokemon-name`, `#pokemon-id`, `#weight`, `#height`, `#hp`, `#attack`, `#defense`, `#special-attack`, and `#special-defense` elements should be `GENGAR`, `#94` or `94`, `Weight: 405` or `405`, `Height: 15` or `15`, `60`, `65`, `60`, `130`, `75`, and `110`, respectively.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ searchInput.value = '94';
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/94'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+
+ const pokemonName = document.getElementById('pokemon-name');
+ const pokemonID = document.getElementById('pokemon-id');
+ const weight = document.getElementById('weight');
+ const height = document.getElementById('height');
+ const hp = document.getElementById('hp');
+ const attack = document.getElementById('attack');
+ const defense = document.getElementById('defense');
+ const specialAttack = document.getElementById('special-attack');
+ const specialDefense = document.getElementById('special-defense');
+ const speed = document.getElementById('speed');
+
+ assert.strictEqual(pokemonName.innerText.trim().toLowerCase(), 'gengar');
+ assert.include(['#94', '94'], pokemonID.innerText.trim());
+ assert.include(['weight: 405', '405'], weight.innerText.trim().toLowerCase());
+ assert.include(['height: 15', '15'], height.innerText.trim().toLowerCase());
+ assert.strictEqual(hp.innerText.trim(), '60');
+ assert.strictEqual(attack.innerText.trim(), '65');
+ assert.strictEqual(defense.innerText.trim(), '60');
+ assert.strictEqual(specialAttack.innerText.trim(), '130');
+ assert.strictEqual(specialDefense.innerText.trim(), '75');
+ assert.strictEqual(speed.innerText.trim(), '110');
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, you should add an `img` element with the `id` of `sprite` and the `src` set to the Pokémon's `front_default` sprite to the page.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ searchInput.value = '94';
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/94'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+
+ const sprite = document.getElementById('sprite');
+ assert.isTrue(sprite.src.endsWith('sprites/pokemon/94.png'));
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+When the `#search-input` element contains the value `94` and the `#search-button` element is clicked, the `#types` element should contain a two inner element with the text values `GHOST` and `POISON`, respectively.
+
+```js
+async () => {
+ try {
+ const searchInput = document.getElementById('search-input');
+ const searchButton = document.getElementById('search-button');
+ const typesEl = document.getElementById('types');
+ searchInput.value = '94';
+ typesEl.innerHTML = ''; // Clear types element before test
+ searchButton.click();
+
+ const res = await fetch('https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/94'); // Fetch from proxy to simulate network delay
+
+ if (res.ok) {
+ await new Promise(resolve => setTimeout(resolve, 50)); // Brief additional delay to allow UI to update
+ const targetTypes = ['ghost', 'poison'];
+
+ assert.lengthOf(typesEl.children, 2);
+ assert.sameMembers(['ghost', 'poison'], [...typesEl.children].map(el => el.innerText.trim().toLowerCase()));
+ }
+ } catch (err) {
+ throw new Error(err);
+ }
+};
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+```
+
+```css
+
+```
+
+```js
+
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+
+ Pokémon Search App
+
+
+
+
+
+
Pokémon Search App
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Base
+
Stats
+
+
+
HP:
+
+
+
+
Attack:
+
+
+
+
Defense:
+
+
+
+
Sp. Attack:
+
+
+
+
Sp. Defense:
+
+
+
+
Speed:
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+/* CSS reset */
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+* {
+ margin: 0;
+}
+
+body {
+ line-height: 1.5;
+}
+
+img {
+ display: block;
+}
+
+/* Project styling */
+
+body {
+ height: 100vh;
+ font-family: sans-serif;
+ background-color: #1b1b32;
+ color: #0a0a23;
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+
+.freecodecamp-logo {
+ height: 30px;
+ margin: 25px 0;
+}
+
+h1 {
+ color: #f5f6f7;
+ font-size: 1.7em;
+ text-align: center;
+}
+
+.container {
+ width: 325px;
+ margin: 25px 0;
+ background-color: #f5f6f7;
+ border: 1px solid #f5f6f7;
+ border-radius: 15px;
+ box-shadow: 10px 10px 0px 0px rgba(223, 220, 220, 0.75);
+}
+
+.output,
+#search-form {
+ display: flex;
+ justify-content: center;
+}
+
+#search-form {
+ flex-wrap: wrap;
+ margin: 10px 0;
+ padding: 5px;
+ border-radius: 8px 8px 0 0;
+ gap: 10px;
+}
+
+label {
+ align-self: center;
+}
+
+#search-input {
+ height: 40px;
+ padding-left: 10px;
+ width: 200px;
+}
+
+#search-button {
+ padding: 14px 0;
+ width: 80px;
+ border-radius: 20px;
+ text-align: center;
+ background-color: #7f21ab;
+ color: #f5f6f7;
+ outline: none;
+ border: none;
+}
+
+.output {
+ margin: 10px 0;
+ padding: 5px;
+ flex-direction: column;
+ align-items: center;
+}
+
+.top-container,
+.bottom-container {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ min-height: 325px;
+}
+
+.top-container {
+ margin-bottom: 10px;
+ padding: 10px;
+ background-color: #f0f1f7;
+}
+
+.name-and-id {
+ height: 28px;
+ font-size: 1.1em;
+ text-transform: capitalize;
+ margin-bottom: 5px;
+}
+
+.size {
+ height: 22px;
+ font-size: 0.85rem;
+}
+
+.sprite-container {
+ flex-grow: 2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+#sprite {
+ width: 180px;
+}
+
+#types {
+ min-height: 30px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ gap: 5px;
+}
+
+.type {
+ width: 66px;
+ padding: 5px;
+ font-size: 0.7rem;
+ text-align: center;
+ border-radius: 5px;
+ background-color: red;
+ text-transform: uppercase;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ width: 100%;
+ font-size: 1 rem;
+ color: #f5f6f7;
+ background-color: #7f21ab;
+}
+
+th:nth-child(even),
+td:nth-child(even) {
+ border-left: 5px solid #f5f6f7;
+}
+
+tr {
+ border-bottom: 5px solid #f5f6f7;
+}
+
+td,
+th {
+ text-align: center;
+ padding: 8px;
+}
+
+/* Special styling for Pokémon types */
+
+.normal {
+ background-color: #b7b7aa;
+}
+
+.fire {
+ background-color: #ff6f52;
+}
+
+.water {
+ background-color: #42a1ff;
+}
+
+.electric {
+ background-color: #fecc33;
+}
+
+.grass {
+ background-color: #78cc55;
+}
+
+.ice {
+ background-color: #66ccfe;
+}
+
+.fighting {
+ background-color: #d3887e;
+}
+
+.poison {
+ background-color: #c68bb7;
+}
+
+.ground {
+ background-color: #dfba52;
+}
+
+.flying {
+ background-color: #8899ff;
+}
+
+.psychic {
+ background-color: #ff66a3;
+}
+
+.bug {
+ background-color: #aabb23;
+}
+
+.rock {
+ background-color: #baaa66;
+}
+
+.ghost {
+ background-color: #9995d0;
+}
+
+.dragon {
+ background-color: #9e93f1;
+}
+
+.dark {
+ background-color: #b59682;
+}
+
+.steel {
+ background-color: #abaabb;
+}
+
+.fairy {
+ background-color: #ed99ed;
+}
+
+@media screen and (min-width: 550px) {
+ h1 {
+ font-size: 2em;
+ }
+
+ .container {
+ width: 450px;
+ }
+
+ #search-form,
+ .top-container,
+ .bottom-container {
+ width: 95%;
+ }
+
+ .type {
+ width: 75px;
+ }
+}
+```
+
+```js
+const pokemonID = document.getElementById("pokemon-id");
+const pokemonName = document.getElementById("pokemon-name");
+const spriteContainer = document.getElementById("sprite-container");
+const types = document.getElementById("types");
+const height = document.getElementById("height");
+const weight = document.getElementById("weight");
+const hp = document.getElementById("hp");
+const attack = document.getElementById("attack");
+const defense = document.getElementById("defense");
+const specialAttack = document.getElementById("special-attack");
+const specialDefense = document.getElementById("special-defense");
+const speed = document.getElementById("speed");
+const searchForm = document.getElementById("search-form");
+const searchInput = document.getElementById("search-input");
+
+const getPokemon = async () => {
+ try {
+ const pokemonNameOrId = searchInput.value.toLowerCase();
+ const response = await fetch(
+ `https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/${pokemonNameOrId}`,
+ );
+ const data = await response.json();
+
+ // Set Pokémon info
+ pokemonName.textContent = `${data.name.toUpperCase()}`;
+ pokemonID.textContent = `#${data.id}`;
+ weight.textContent = `Weight: ${data.weight}`;
+ height.textContent = `Height: ${data.height}`;
+ spriteContainer.innerHTML = `
+
+ `;
+
+ // Set stats
+ hp.textContent = data.stats[0].base_stat;
+ attack.textContent = data.stats[1].base_stat;
+ defense.textContent = data.stats[2].base_stat;
+ specialAttack.textContent = data.stats[3].base_stat;
+ specialDefense.textContent = data.stats[4].base_stat;
+ speed.textContent = data.stats[5].base_stat;
+
+ // Set types
+ types.innerHTML = data.types
+ .map(
+ (obj) => `${obj.type.name}`,
+ )
+ .join("");
+ } catch (err) {
+ resetDisplay();
+ alert("Pokémon not found");
+ console.log(`Pokémon not found: ${err}`);
+ }
+};
+
+const resetDisplay = () => {
+ const sprite = document.getElementById("sprite");
+ if (sprite) sprite.remove();
+
+ // reset stats
+ pokemonName.textContent = "";
+ pokemonID.textContent = "";
+ types.innerHTML = "";
+ height.textContent = "";
+ weight.textContent = "";
+ hp.textContent = "";
+ attack.textContent = "";
+ defense.textContent = "";
+ specialAttack.textContent = "";
+ specialDefense.textContent = "";
+ speed.textContent = "";
+};
+
+searchForm.addEventListener("submit", (e) => {
+ e.preventDefault();
+ getPokemon();
+});
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-roman-numeral-converter-project/roman-numeral-converter.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-roman-numeral-converter-project/roman-numeral-converter.md
index b3640a1200d..dfd440aa13a 100644
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-roman-numeral-converter-project/roman-numeral-converter.md
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-roman-numeral-converter-project/roman-numeral-converter.md
@@ -1,14 +1,14 @@
---
-id: a7f4d8f2483413a6ce226cac
+id: 657bdc8ba322aae1eac38390
title: Build A Roman Numeral Converter
-challengeType: 5
+challengeType: 14
forumTopicId: 16044
dashedName: build-a-roman-numeral-converter
---
# --description--
-Convert the given number into a roman numeral.
+Roman numerals are based on seven symbols and can be written using various combinations to represent Arabic numerals. For example:
| Roman numerals | Arabic numerals |
|----------------|-----------------|
@@ -26,190 +26,407 @@ Convert the given number into a roman numeral.
| IV | 4 |
| I | 1 |
-All roman numerals answers should be provided in upper-case.
+**Objective:** Build an app that is functionally similar to https://roman-numeral-converter.freecodecamp.rocks
+
+**User Stories:**
+
+1. You should have an `input` element with an `id` of `number`
+1. You should have a `button` element with an `id` of `convert-btn`
+1. You should have a `div` element with an `id` of `output`
+1. When you click on the `#convert-btn` element without entering a value into the `#number` element, the `#output` element should contain the text `Please enter a valid number`
+1. When the `#number` element contains the number `-1` and the `#convert-btn` element is clicked, the `#output` element should contain the text `Please enter a number greater than or equal to 1`
+1. When the `#number` element contains the number `4000` or greater and the `#convert-btn` element is clicked, the `#output` element should contain the text `Please enter a number less than or equal to 3999`
+1. When the `#number` element contains the number `9` and the `#convert-btn` element is clicked, the `#output` element should contain the text `IX`
+1. When the `#number` element contains the number `16` and the `#convert-btn` element is clicked, the `#output` element should contain the text `XVI`
+1. When the `#number` element contains the number `649` and the `#convert-btn` element is clicked, the `#output` element should contain the text `DCXLIX`
+1. When the `#number` element contains the number `1023` and the `#convert-btn` element is clicked, the `#output` element should contain the text `MXXIII`
+1. When the `#number` element contains the number `3999` and the `#convert-btn` element is clicked, the `#output` element should contain the text `MMMCMXCIX`
+
+Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding!
# --hints--
-`convertToRoman(2)` should return the string `II`.
+You should have an `input` element with an `id` of `number`.
```js
-assert.deepEqual(convertToRoman(2), 'II');
+const el = document.getElementById('number');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'input');
```
-`convertToRoman(3)` should return the string `III`.
+You should have a `button` element with an `id` of `convert-btn`.
```js
-assert.deepEqual(convertToRoman(3), 'III');
+const el = document.getElementById('convert-btn');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
```
-`convertToRoman(4)` should return the string `IV`.
+You should have a `div` element with an `id` of `output`.
```js
-assert.deepEqual(convertToRoman(4), 'IV');
+const el = document.getElementById('output');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'div');
```
-`convertToRoman(5)` should return the string `V`.
+When you click on the `#convert-btn` element without entering a value into the `#number` element, the `#output` element should contain the text `Please enter a valid number`.
```js
-assert.deepEqual(convertToRoman(5), 'V');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'please enter a valid number');
```
-`convertToRoman(9)` should return the string `IX`.
+When the `#number` element contains the number `-1` and the `#convert-btn` element is clicked, the `#output` element should contain the text `Please enter a number greater than or equal to 1`
```js
-assert.deepEqual(convertToRoman(9), 'IX');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '-1';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'please enter a number greater than or equal to 1');
```
-`convertToRoman(12)` should return the string `XII`.
+When the `#number` element contains the number `4000` or greater and the `#convert-btn` element is clicked, the `#output` element should contain the text `Please enter a number less than or equal to 3999`.
```js
-assert.deepEqual(convertToRoman(12), 'XII');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '4000';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'please enter a number less than or equal to 3999');
```
-`convertToRoman(16)` should return the string `XVI`.
+When the `#number` element contains the number `9` and the `#convert-btn` element is clicked, the `#output` element should contain the text `IX`.
```js
-assert.deepEqual(convertToRoman(16), 'XVI');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '9';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim(), 'IX');
```
-`convertToRoman(29)` should return the string `XXIX`.
+When the `#number` element contains the number `16` and the `#convert-btn` element is clicked, the `#output` element should contain the text `XVI`.
```js
-assert.deepEqual(convertToRoman(29), 'XXIX');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '16';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim(), 'XVI');
```
-`convertToRoman(44)` should return the string `XLIV`.
+When the `#number` element contains the number `649` and the `#convert-btn` element is clicked, the `#output` element should contain the text `DCXLIX`.
```js
-assert.deepEqual(convertToRoman(44), 'XLIV');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '649';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim(), 'DCXLIX');
```
-`convertToRoman(45)` should return the string `XLV`.
+When the `#number` element contains the number `1023` and the `#convert-btn` element is clicked, the `#output` element should contain the text `MXXIII`.
```js
-assert.deepEqual(convertToRoman(45), 'XLV');
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
+
+numberInputEl.value = '1023';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim(), 'MXXIII');
```
-`convertToRoman(68)` should return the string `LXVIII`
+When the `#number` element contains the number `3999` and the `#convert-btn` element is clicked, the `#output` element should contain the text `MMMCMXCIX`.
```js
-assert.deepEqual(convertToRoman(68), 'LXVIII');
-```
+const numberInputEl = document.getElementById('number');
+const convertBtnEl = document.getElementById('convert-btn');
+const outputEl = document.getElementById('output');
-`convertToRoman(83)` should return the string `LXXXIII`
-
-```js
-assert.deepEqual(convertToRoman(83), 'LXXXIII');
-```
-
-`convertToRoman(97)` should return the string `XCVII`
-
-```js
-assert.deepEqual(convertToRoman(97), 'XCVII');
-```
-
-`convertToRoman(99)` should return the string `XCIX`
-
-```js
-assert.deepEqual(convertToRoman(99), 'XCIX');
-```
-
-`convertToRoman(400)` should return the string `CD`
-
-```js
-assert.deepEqual(convertToRoman(400), 'CD');
-```
-
-`convertToRoman(500)` should return the string `D`
-
-```js
-assert.deepEqual(convertToRoman(500), 'D');
-```
-
-`convertToRoman(501)` should return the string `DI`
-
-```js
-assert.deepEqual(convertToRoman(501), 'DI');
-```
-
-`convertToRoman(649)` should return the string `DCXLIX`
-
-```js
-assert.deepEqual(convertToRoman(649), 'DCXLIX');
-```
-
-`convertToRoman(798)` should return the string `DCCXCVIII`
-
-```js
-assert.deepEqual(convertToRoman(798), 'DCCXCVIII');
-```
-
-`convertToRoman(891)` should return the string `DCCCXCI`
-
-```js
-assert.deepEqual(convertToRoman(891), 'DCCCXCI');
-```
-
-`convertToRoman(1000)` should return the string `M`
-
-```js
-assert.deepEqual(convertToRoman(1000), 'M');
-```
-
-`convertToRoman(1004)` should return the string `MIV`
-
-```js
-assert.deepEqual(convertToRoman(1004), 'MIV');
-```
-
-`convertToRoman(1006)` should return the string `MVI`
-
-```js
-assert.deepEqual(convertToRoman(1006), 'MVI');
-```
-
-`convertToRoman(1023)` should return the string `MXXIII`
-
-```js
-assert.deepEqual(convertToRoman(1023), 'MXXIII');
-```
-
-`convertToRoman(2014)` should return the string `MMXIV`
-
-```js
-assert.deepEqual(convertToRoman(2014), 'MMXIV');
-```
-
-`convertToRoman(3999)` should return the string `MMMCMXCIX`
-
-```js
-assert.deepEqual(convertToRoman(3999), 'MMMCMXCIX');
+numberInputEl.value = '3999';
+convertBtnEl.click();
+assert.strictEqual(outputEl.innerText.trim(), 'MMMCMXCIX');
```
# --seed--
## --seed-contents--
-```js
-function convertToRoman(num) {
- return num;
-}
+```html
+
+```
+
+```css
+
+```
+
+```js
-convertToRoman(36);
```
# --solutions--
-```js
-function convertToRoman(num) {
- 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]];
- var res = [];
- ref.forEach(function(p) {
- while (num >= p[1]) {
- res.push(p[0]);
- num -= p[1];
- }
- });
- return res.join('');
+```html
+
+
+
+
+
+
+
+
+
+ Roman Numeral Converter
+
+
+
+
+
Roman Numeral Converter
+
+
+
+
+
+
+```
+
+```css
+:root {
+ --gray-00: #ffffff;
+ --gray-05: #f5f6f7;
+ --gray-15: #d0d0d5;
+ --gray-75: #3b3b4f;
+ --gray-85: #1b1b32;
+ --gray-90: #0a0a23;
+ --error: #a94442;
+ --danger-color: #850000;
+ --danger-background: #ffadad;
+}
+
+*,
+::before,
+::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+}
+
+body {
+ min-height: 100vh;
+ padding: 50px 20px;
+ font-family: 'Lato', Helvetica, Arial, sans-serif;
+ font-size: 18px;
+ background-color: var(--gray-85);
+ color: var(--gray-05);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+
+.freecodecamp-logo {
+ height: 30px;
+ margin-bottom: 20px;
+}
+
+h1 {
+ text-align: center;
+ margin: 20px auto;
+ max-width: 350px;
+ font-family: 'Castoro Titling', cursive;
+}
+
+form {
+ color: var(--gray-05);
+ margin: auto 25px;
+ padding: 15px auto;
+ border: 3px solid var(--gray-05);
+ text-align: center;
+ width: 90%;
+ max-width: 500px;
+ background-color: var(--gray-75);
+}
+
+fieldset {
+ border: 0 none;
+ height: 100%;
+ padding: 25px;
+ margin: 10px 20px;
+}
+
+label {
+ display: inline-block;
+ font-size: 1.5rem;
+ margin-bottom: 10px;
+ font-weight: bold;
+}
+
+input {
+ display: block;
+ font-size: 2.5rem;
+ width: 100%;
+ height: 60px;
+ padding: 6px 12px;
+ margin: 10px 0;
+ line-height: 1.4;
+ color: white;
+ background-color: var(--gray-90);
+ border: 1px solid var(--gray-05);
+ outline: none;
+ outline-style: none;
+}
+
+button {
+ outline: none;
+ cursor: pointer;
+ margin-top: 15px;
+ text-decoration: none;
+ background-image: linear-gradient(#fecc4c, #ffac33);
+ border: 3px solid #feac32;
+ padding: 10px 16px;
+ font-size: 23px;
+ width: 100%;
+}
+
+.output {
+ color: white;
+ background-color: var(--gray-75);
+ border: 3px solid var(--gray-05);
+ font-size: 2.5rem;
+ width: 90%;
+ max-width: 500px;
+ min-height: 55px;
+ margin-top: 25px;
+ padding: 15px;
+ overflow-wrap: break-word;
+ text-align: center;
+}
+
+.alert {
+ font-size: 2rem;
+ background-color: var(--danger-background);
+ border: 3px solid var(--danger-color);
+ color: var(--danger-color);
+}
+
+.hidden {
+ display: none;
}
```
+
+```js
+const form = document.getElementById("form");
+const convertButton = document.getElementById("convert-btn");
+const output = document.getElementById("output");
+
+const convertToRoman = (num) => {
+ const 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],
+ ];
+ const res = [];
+
+ ref.forEach(function (arr) {
+ while (num >= arr[1]) {
+ res.push(arr[0]);
+ num -= arr[1];
+ }
+ });
+
+ return res.join("");
+};
+
+const isValid = (str, int) => {
+ let errText = "";
+
+ if (!str || str.match(/[e.]/g)) {
+ errText = "Please enter a valid number.";
+ } else if (int < 1) {
+ errText = "Please enter a number greater than or equal to 1.";
+ } else if (int > 3999) {
+ errText = "Please enter a number less than or equal to 3999.";
+ } else {
+ // No errors detected
+ return true;
+ }
+
+ // Handle error text and output styling
+ output.innerText = errText;
+ output.classList.add("alert");
+
+ return false;
+};
+
+const clearOutput = () => {
+ output.innerText = "";
+ output.classList.remove("alert");
+};
+
+form.addEventListener("submit", (e) => {
+ e.preventDefault();
+ updateUI();
+});
+
+convertButton.addEventListener("click", () => {
+ updateUI();
+});
+
+const updateUI = () => {
+ const numStr = document.getElementById("number").value;
+ const int = parseInt(numStr, 10);
+
+ output.classList.remove("hidden");
+
+ clearOutput();
+
+ if (isValid(numStr, int)) {
+ output.innerText = convertToRoman(int);
+ }
+};
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-telephone-number-validator-project/telephone-number-validator.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-telephone-number-validator-project/telephone-number-validator.md
index 282f77b4be9..f28f7a7b3b3 100644
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-telephone-number-validator-project/telephone-number-validator.md
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/build-a-telephone-number-validator-project/telephone-number-validator.md
@@ -1,217 +1,713 @@
---
-id: aff0395860f5d3034dc0bfc9
+id: 657bdcb9a322aae1eac38391
title: Build a Telephone Number Validator
-challengeType: 5
+challengeType: 14
forumTopicId: 16090
dashedName: build-a-telephone-number-validator
---
# --description--
-Return `true` if the passed string looks like a valid US phone number.
+In the US, phone numbers can be formatted in many ways. Here are some examples of valid formats for US phone numbers:
-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):
+
+Note that the area code is required. Also, if the country code is provided, you must confirm that the country code is `1`.
-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`.
+**Objective:** Build an app that is functionally similar to https://telephone-number-validator.freecodecamp.rocks
+
+**User Stories:**
+
+1. You should have an `input` element with an `id` of `user-input`
+1. You should have a `button` element with an `id` of `check-btn`
+1. You should have a `button` element with an `id` of `clear-btn`
+1. You should have a `div` element with an `id` of `results-div`
+1. When you click on the `#check-btn` element without entering a value into the `#user-input` element, an alert should appear with the text `Please provide a phone number`
+1. When you click on the `#clear-btn` element, the content within the `#results-div` element should be removed
+1. When the `#user-input` element contains `1 555-555-5555` and the `#check-btn` element is clicked, the `#results-div` element should contain the text `Valid US number: 1 555-555-5555`
+1. When the `#user-input` element contains `1 (555) 555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 (555) 555-5555`
+1. When the `#user-input` element contains `5555555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 5555555555`
+1. When the `#user-input` element contains `555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 555-555-5555`
+1. When the `#user-input` element contains `(555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: (555)555-5555`
+1. When the `#user-input` element contains `1(555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1(555)555-5555`
+1. When the `#user-input` element contains `555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 555-5555`
+1. When the `#user-input` element contains `5555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 5555555`
+1. When the `#user-input` element contains `1 555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 1 555)555-5555`
+1. When the `#user-input` element contains `1 555 555 5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 555 555 5555`
+1. When the `#user-input` element contains `1 456 789 4444` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 456 789 4444`
+1. When `#user-input` contains `123**&!!asdf#` and `#check-btn` is clicked, `#result-div` should contain the text `Invalid US number: 123**&!!asdf#`
+1. When the `#user-input` element contains `55555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 55555555`
+1. When the `#user-input` element contains `(6054756961)` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (6054756961)`
+1. When the `#user-input` element contains `2 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2 (757) 622-7382`
+1. When the `#user-input` element contains `0 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 0 (757) 622-7382`
+1. When the `#user-input` element contains `-1 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: -1 (757) 622-7382`
+1. When the `#user-input` element contains `2 757 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2 757 622-7382`
+1. When the `#user-input` element contains `10 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 10 (757) 622-7382`
+1. When the `#user-input` element contains `27576227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 27576227382`
+1. When the `#user-input` element contains `(275)76227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (275)76227382`
+1. When the `#user-input` element contains `2(757)6227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2(757)6227382`
+1. When the `#user-input` element contains `2(757)622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2(757)622-7382`
+1. When the `#user-input` element contains `555)-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 555)-555-5555`
+1. When the `#user-input` element contains `(555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (555-555-5555`
+1. When `#user-input` contains `(555)5(55?)-5555` and `#check-btn` is clicked, `#result-div` should contain the text `Invalid US number: (555)5(55?)-5555`
+1. When the `#user-input` element contains `55 55-55-555-5` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 55 55-55-555-5`
+1. When the `#user-input` element contains `11 555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 11 555-555-5555`
+
+Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding!
# --hints--
-`telephoneCheck("555-555-5555")` should return a boolean.
+You should have an `input` element with an `id` of `user-input`.
```js
-assert(typeof telephoneCheck('555-555-5555') === 'boolean');
+const el = document.getElementById('user-input');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'input');
```
-`telephoneCheck("1 555-555-5555")` should return `true`.
+You should have a `button` element with an `id` of `check-btn`.
```js
-assert(telephoneCheck('1 555-555-5555') === true);
+const el = document.getElementById('check-btn');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
```
-`telephoneCheck("1 (555) 555-5555")` should return `true`.
+You should have a `button` element with an `id` of `clear-btn`.
```js
-assert(telephoneCheck('1 (555) 555-5555') === true);
+const el = document.getElementById('clear-btn');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'button');
```
-`telephoneCheck("5555555555")` should return `true`.
+You should have a `div` element with an `id` of `results-div`.
```js
-assert(telephoneCheck('5555555555') === true);
+const el = document.getElementById('results-div');
+assert.strictEqual(el?.nodeName?.toLowerCase(), 'div');
```
-`telephoneCheck("555-555-5555")` should return `true`.
+When you click on the `#check-btn` element without entering a value into the `#user-input` element, an alert should appear with the text `Please provide a phone number`.
```js
-assert(telephoneCheck('555-555-5555') === true);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+let alertMessage;
+window.alert = (message) => alertMessage = message; // Override alert and store message
+
+userInput.value = '';
+checkBtn.click();
+assert.strictEqual(alertMessage.trim().replace(/[.,?!]+$/g, '').toLowerCase(), 'please provide a phone number');
```
-`telephoneCheck("(555)555-5555")` should return `true`.
+When you click on the `#clear-btn` element, the content within the `#results-div` element should be removed.
```js
-assert(telephoneCheck('(555)555-5555') === true);
+const resultsDiv = document.getElementById('results-div');
+const clearBtn = document.getElementById('clear-btn');
+
+resultsDiv.innerHTML = `Testing testing 123
+Ladies and gentlemen, we are floating in space.`;
+clearBtn.click();
+assert.isEmpty(resultsDiv.textContent);
```
-`telephoneCheck("1(555)555-5555")` should return `true`.
+When the `#user-input` element contains `1 555-555-5555` and the `#check-btn` element is clicked, the `#results-div` element should contain the text `Valid US number: 1 555-555-5555`.
```js
-assert(telephoneCheck('1(555)555-5555') === true);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1 555-555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 1 555-555-5555');
```
-`telephoneCheck("555-5555")` should return `false`.
+When the `#user-input` element contains `1 (555) 555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 (555) 555-5555`.
```js
-assert(telephoneCheck('555-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1 (555) 555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 1 (555) 555-5555');
```
-`telephoneCheck("5555555")` should return `false`.
+When the `#user-input` element contains `5555555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 5555555555`.
```js
-assert(telephoneCheck('5555555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '5555555555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 5555555555');
```
-`telephoneCheck("1 555)555-5555")` should return `false`.
+When the `#user-input` element contains `555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 555-555-5555`.
```js
-assert(telephoneCheck('1 555)555-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '555-555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 555-555-5555');
```
-`telephoneCheck("1 555 555 5555")` should return `true`.
+When the `#user-input` element contains `(555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: (555)555-5555`.
```js
-assert(telephoneCheck('1 555 555 5555') === true);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '(555)555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: (555)555-5555');
```
-`telephoneCheck("1 456 789 4444")` should return `true`.
+When the `#user-input` element contains `1(555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1(555)555-5555`.
```js
-assert(telephoneCheck('1 456 789 4444') === true);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1(555)555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 1(555)555-5555');
```
-`telephoneCheck("123**&!!asdf#")` should return `false`.
+When the `#user-input` element contains `555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 555-5555`.
```js
-assert(telephoneCheck('123**&!!asdf#') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 555-5555');
```
-`telephoneCheck("55555555")` should return `false`.
+When the `#user-input` element contains `5555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 5555555`.
```js
-assert(telephoneCheck('55555555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '5555555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 5555555');
```
-`telephoneCheck("(6054756961)")` should return `false`.
+When the `#user-input` element contains `1 555)555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 1 555)555-5555`.
```js
-assert(telephoneCheck('(6054756961)') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1 555)555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 1 555)555-5555');
```
-`telephoneCheck("2 (757) 622-7382")` should return `false`.
+When the `#user-input` element contains `1 555 555 5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 555 555 5555`.
```js
-assert(telephoneCheck('2 (757) 622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1 555 555 5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 1 555 555 5555');
```
-`telephoneCheck("0 (757) 622-7382")` should return `false`.
+When the `#user-input` element contains `1 456 789 4444` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Valid US number: 1 456 789 4444`.
```js
-assert(telephoneCheck('0 (757) 622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '1 456 789 4444';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'valid us number: 1 456 789 4444');
```
-`telephoneCheck("-1 (757) 622-7382")` should return `false`.
+When `#user-input` contains `123**&!!asdf#` and `#check-btn` is clicked, `#result-div` should contain the text `Invalid US number: 123**&!!asdf#`.
```js
-assert(telephoneCheck('-1 (757) 622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '123**&!!asdf#';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 123**&!!asdf#');
```
-`telephoneCheck("2 757 622-7382")` should return `false`.
+When the `#user-input` element contains `55555555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 55555555`.
```js
-assert(telephoneCheck('2 757 622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '55555555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 55555555');
```
-`telephoneCheck("10 (757) 622-7382")` should return `false`.
+When the `#user-input` element contains `(6054756961)` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (6054756961)`.
```js
-assert(telephoneCheck('10 (757) 622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '(6054756961)';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: (6054756961)');
```
-`telephoneCheck("27576227382")` should return `false`.
+When the `#user-input` element contains `2 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2 (757) 622-7382`.
```js
-assert(telephoneCheck('27576227382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '2 (757) 622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 2 (757) 622-7382');
```
-`telephoneCheck("(275)76227382")` should return `false`.
+When the `#user-input` element contains `0 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 0 (757) 622-7382`.
```js
-assert(telephoneCheck('(275)76227382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '0 (757) 622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 0 (757) 622-7382');
```
-`telephoneCheck("2(757)6227382")` should return `false`.
+When the `#user-input` element contains `-1 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: -1 (757) 622-7382`.
```js
-assert(telephoneCheck('2(757)6227382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '-1 (757) 622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: -1 (757) 622-7382');
```
-`telephoneCheck("2(757)622-7382")` should return `false`.
+When the `#user-input` element contains `2 757 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2 757 622-7382`.
```js
-assert(telephoneCheck('2(757)622-7382') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '2 757 622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 2 757 622-7382');
```
-`telephoneCheck("555)-555-5555")` should return `false`.
+When the `#user-input` element contains `10 (757) 622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 10 (757) 622-7382`.
```js
-assert(telephoneCheck('555)-555-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '10 (757) 622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 10 (757) 622-7382');
```
-`telephoneCheck("(555-555-5555")` should return `false`.
+When the `#user-input` element contains `27576227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 27576227382`.
```js
-assert(telephoneCheck('(555-555-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '27576227382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 27576227382');
```
-`telephoneCheck("(555)5(55?)-5555")` should return `false`.
+When the `#user-input` element contains `(275)76227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (275)76227382`.
```js
-assert(telephoneCheck('(555)5(55?)-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '(275)76227382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: (275)76227382');
```
-`telephoneCheck("55 55-55-555-5")` should return `false`.
+When the `#user-input` element contains `2(757)6227382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2(757)6227382`.
```js
-assert(telephoneCheck('55 55-55-555-5') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '2(757)6227382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 2(757)6227382');
```
-`telephoneCheck("11 555-555-5555")` should return `false`.
+When the `#user-input` element contains `2(757)622-7382` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 2(757)622-7382`.
```js
-assert(telephoneCheck('11 555-555-5555') === false);
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '2(757)622-7382';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 2(757)622-7382');
+```
+
+When the `#user-input` element contains `555)-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 555)-555-5555`.
+
+```js
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '555)-555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 555)-555-5555');
+```
+
+When the `#user-input` element contains `(555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: (555-555-5555`.
+
+```js
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '(555-555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: (555-555-5555');
+```
+
+When `#user-input` contains `(555)5(55?)-5555` and `#check-btn` is clicked, `#result-div` should contain the text `Invalid US number: (555)5(55?)-5555`.
+
+```js
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '(555)5(55?)-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: (555)5(55?)-5555');
+```
+
+When the `#user-input` element contains `55 55-55-555-5` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 55 55-55-555-5`.
+
+```js
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '55 55-55-555-5';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 55 55-55-555-5');
+```
+
+When the `#user-input` element contains `11 555-555-5555` and the `#check-btn` element is clicked, the `#result-div` element should contain the text `Invalid US number: 11 555-555-5555`.
+
+```js
+const userInput = document.getElementById('user-input');
+const checkBtn = document.getElementById('check-btn');
+const resultsDiv = document.getElementById('results-div');
+
+resultsDiv.innerHTML = '';
+userInput.value = '11 555-555-5555';
+checkBtn.click();
+assert.strictEqual(resultsDiv.innerText.trim().toLowerCase(), 'invalid us number: 11 555-555-5555');
```
# --seed--
## --seed-contents--
-```js
-function telephoneCheck(str) {
- return true;
-}
+```html
+
+```
+
+```css
+
+```
+
+```js
-telephoneCheck("555-555-5555");
```
# --solutions--
-```js
-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}$/;
+```html
+
+
+
+
+
+
+
+ Telephone Number Validator
+
+
+
+
+
+