I struggled a bit with the in-browser solution for WorkAround Explorer project and thought I would post my solution here: GitHub - gabriel-cloud/WorkAround-Explorer
Cheers for this⌠just almost finished this. I have just got to and am struggling with the final extra challenge with rendering the formatted numbers. Any ideas?
Iâve just pushed it on GitHub. Howâs your file looking?
You beat me to it⌠I had to go do something else. I really struggled with this as I am not that familiar with using JS with the DOM syntax (I am just starting the building interacive websites course) and all the un familiar code and threw me a bit. When I saw your code I kicked myself! I did get it to work. One question⌠do you have a comma (,) after the I get ,230,000 etc?
Yeah. In utilities for (let i = integerNum.length - 3; i > 0; i -= 3)
With I >= 0 it incorrectly adds a comma at the beginning. Set i>0 and it should be fine.
For the number formatter, I went the route of using the built in Intl.NumberFormat function. I used this option because it can be made locale specific, and easier to write/implement.
Note: because this function adds the currency symbol, be sure to delete the â/$â from each output string in the â// Render them to the screen.â section found at the bottom of main.js.
**The solution looked like this: **
utilities.js:
export const formatNumber = new Intl.NumberFormat(âen-USâ, {
** style: âcurrencyâ,**
** currency: âUSDâ,**
** // These options are needed to round to whole numbers if thatâs what you want.**
** minimumFractionDigits: 0, **
** // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)**
** maximumFractionDigits: 0, **
** // (causes 2500.99 to be printed as $2,501)**
});
main.js:
// TODO: Add your import statements here.
import { getRoles, getCompanies } from â./modules/salaryData.jsâ;
import {
getAverageSalaryByRole,
getAverageSalaryByCompany,
getSalaryAtCompany,
getIndustryAverageSalary
} from â./modules/workAroundModule.jsâ;
import { formatNumber } from â./modules/utilities.jsâ;
// TODO: Get the companies and roles using the salaryData module.
const companies = getCompanies();
const roles = getRoles();
// Create input buttons for every company and role represented in the data.
renderInputButtons(companies, âcompanyâ);
renderInputButtons(roles, âroleâ);
// This function will create a new with radio
// inputs based on the data provided in the labels array.
function renderInputButtons(labels, groupName) {
const container = document.createElement(âsectionâ);
container.setAttribute(âidâ, ${groupName}Inputs
);
let header = document.createElement(âh3â);
header.innerText = Select a ${groupName}
;
container.appendChild(header);
labels.forEach(label => { // For each labelâŚ
// Create the radio input element.
let divElement = document.createElement('div');
divElement.setAttribute('class', 'option');
let inputElement = document.createElement('input');
inputElement.setAttribute('type', 'radio');
inputElement.setAttribute('name', groupName);
inputElement.setAttribute('value', label);
divElement.appendChild(inputElement);
// Create a label for that radio input element.
let labelElement = document.createElement('label');
labelElement.setAttribute('for', label);
labelElement.innerText = label;
divElement.appendChild(labelElement);
// Update the results when the input is selected.
inputElement.addEventListener('click', updateResults);
container.appendChild(divElement);
});
document.querySelector(âmainâ).prepend(container);
}
function updateResults(){
// Get the current selected company and role from the radio button inputs.
const company = document.querySelector(âinput[name=âcompanyâ]:checkedâ).value;
const role = document.querySelector(âinput[name=âroleâ]:checkedâ).value;
// If either the company or role is unselected, return.
if (!company || !role) { return; }
// TODO: Use the workAroundModule functions to calculate the needed data.
** const averageSalaryByRole = formatNumber.format(getAverageSalaryByRole(role));**
** const averageSalaryByCompany = formatNumber.format(getAverageSalaryByCompany(company));**
** const salary = formatNumber.format(getSalaryAtCompany(role, company));**
** const industryAverageSalary = formatNumber.format(getIndustryAverageSalary());**
** // Render them to the screen.**
** document.getElementById(âsalarySelectedâ).innerText = The salary for ${role}s at ${company} is ${salary}
;**
** document.getElementById(âsalaryAverageByRoleâ).innerText = The industry average salary for ${role} positions is ${averageSalaryByRole}
;**
** document.getElementById(âsalaryAverageByCompanyâ).innerText = The average salary at ${company} is ${averageSalaryByCompany}
;**
** document.getElementById(âsalaryAverageIndustryâ).innerText = The average salary in the Tech industry is ${industryAverageSalary}
;**
}
Hey guys!
I saw the built-in function too, but wrote it from scratch anyway!
utilities.js
function formatNumber(num){
//convert number to string with 2 decimal places
let cStr = num.toFixed(2).toString();
//this contains the new formatted number (it's gonna be reversed, gotta flip it at the end)
let nStr = [''];
//to easily keep track of digits
let idx = 1;
//iterate backwards through string
for(let i = cStr.length - 1; i >= 0; i--){
//push current digit to the array
//(you could use .charAt() but this seemed better)
nStr.push(cStr[i]);
//check if:
//index is a multiple of 3
//not at the last digit
//and after the decimal point
//if true add ','
if(idx % 3 === 0 && idx + 1 <= cStr.length && idx > 3){
nStr.push(',');
};
//increment index
idx++;
};
//reverse the array, join it's elements into a single string then return the value
return nStr.reverse().join('');
};
export {formatNumber};
Then I imported the module into main.js and added the function to the output:
// Render them to the screen.
document.getElementById('salarySelected').innerText = `The salary for ${role}s at ${company} is \$${formatNumber(salary)}`;
You can check the whole thing here,
and the working site here.
I think the formatNumber function you provide doesnât work, I found one on stack overflow works
export default function formatNumbers(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
Thank you for creating this post. It pushed me to explore the bonus section. I was also able to solve this by simply looking in StackOverflow. I found a javascript method that that formats dollars currency and includes the cents when needed with just a few lines of code. Below is my entire utilities file.
const formatNumber = (number) => {
let nf = new Intl.NumberFormat('en-US');
return nf.format(number);
}
export default formatNumber;
Here is my whole git repository. (GitHub - promoteglobal/WorkAround-Explorer: https://promoteglobal.github.io/WorkAround-Explorer/)
Thanks⌠I donât understand why there isnât a video follow along on this one. Iâm going to use your code to figure out where Iâve gone wrong.
check out my code it works : https://www.codecademy.com/workspaces/61ef2afe8f5e57a8e88cb54b
GITHUB: Codecademy export ¡ GitHub
SOLUTION YOUTUBE VIDEO: Javascript ES6 Codecademy WorkAround Explorer - YouTube
Hey, thanks so much for posting. I had a small issue with my code and couldnât figure out what was wrong. Your code was a huge help!!
Your welcome I try my best to help the community
i have problems to display details section
details section not shown
Hey, guys! I finally managed to complete this Task. I struggled a lot! To be honest, most of it was minor spelling or file path errors. If youâre having trouble take a look at my code. https://www.codecademy.com/workspaces/633cca99263c76afb409905c
Really like the way you deal with decimal!
thanks for posting! I got stuck on this assignment and there wasnât a video walkthrough nor solution code. Thanks for helping me get unstuck!
My overly complicated solutionâŚ
When I saw the code in the tip, I got
Here is my code from Utilities.js and main.js but the program still doesnât log the formatted number as it should:
const formatNumber = (number) => {
let integerNum = String(Math.floor(number));
let newNum = "";
for (let i = integerNum.length - 3; i > 0; i -= 3) {
newNum = integerNum.slice(0, i) + "," + integerNum.slice(i);
integerNum = newNum;
}
let decimal = String(number).split(".");
//handle case where the salary does not have a decimal
if (decimal[1] == true) {
return newNum + "." + decimal[1];
} else {
return number;
}
};
export default formatNumber;
Main.js
// TODO: Add your import statements here.
import {getRoles, getCompanies} from './modules/salaryData.js'
import {
getAverageSalaryByRole,
getAverageSalaryByCompany,
getSalaryAtCompany,
getIndustryAverageSalary,
} from './modules/workAroundModule.js';
import formatNumber from './modules/utilities.js';
// TODO: Get the companies and roles using the salaryData module.
const companies = getCompanies();
const roles = getRoles();
// Create input buttons for every company and role represented in the data.
renderInputButtons(companies, 'company');
renderInputButtons(roles, 'role');
// This function will create a new <section> with radio
// inputs based on the data provided in the labels array.
function renderInputButtons(labels, groupName) {
const container = document.createElement('section');
container.setAttribute('id', `${groupName}Inputs`);
let header = document.createElement('h3');
header.innerText = `Select a ${groupName}`;
container.appendChild(header);
labels.forEach(label => { // For each label...
// Create the radio input element.
let divElement = document.createElement('div');
divElement.setAttribute('class', 'option');
let inputElement = document.createElement('input');
inputElement.setAttribute('type', 'radio');
inputElement.setAttribute('name', groupName);
inputElement.setAttribute('value', label);
divElement.appendChild(inputElement);
// Create a label for that radio input element.
let labelElement = document.createElement('label');
labelElement.setAttribute('for', label);
labelElement.innerText = label;
divElement.appendChild(labelElement);
// Update the results when the input is selected.
inputElement.addEventListener('click', updateResults);
container.appendChild(divElement);
});
document.querySelector('main').prepend(container);
}
function updateResults(){
// Get the current selected company and role from the radio button inputs.
const company = document.querySelector("input[name='company']:checked").value;
const role = document.querySelector("input[name='role']:checked").value;
// If either the company or role is unselected, return.
if (!company || !role) { return; }
// TODO: Use the workAroundModule functions to calculate the needed data.
const averageSalaryByRole = formatNumber(getAverageSalaryByRole(role));
const averageSalaryByCompany = formatNumber(getAverageSalaryByCompany(company));
const salary = formatNumber(getSalaryAtCompany(role, company));
const industryAverageSalary = formatNumber(getIndustryAverageSalary());
// Render them to the screen.
document.getElementById('salarySelected').innerText = `The salary for ${role}s at ${company} is \$${salary}`;
document.getElementById('salaryAverageByRole').innerText = `The industry average salary for ${role} positions is \$${averageSalaryByRole}`;
document.getElementById('salaryAverageByCompany').innerText = `The average salary at ${company} is \$${averageSalaryByCompany}`;
document.getElementById('salaryAverageIndustry').innerText = `The average salary in the Tech industry is \$${industryAverageSalary}`;
}
Thank you! I cloned your solution and did comparisons to fix the (impenetrable) errors.
Paul.