WorkAround explorer - Solution

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

21 Likes

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?

1 Like

I’ve just pushed it on GitHub. How’s your file looking?

1 Like

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.

1 Like

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};**

}

1 Like

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.

2 Likes

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/)

3 Likes

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

4 Likes

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!!

1 Like

Your welcome I try my best to help the community

1 Like

i have problems to display details sectiondetails 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! :slight_smile:

const formatNumber = number => { const stringNumber = number.toString(); // Convert given number to string format; let formatedNumberReversed = []; // Array to store new number in reverse order; let formatedNumber = []; let dot; // Variable to store index of point where decimal places start; let arrayOfCommas = []; // Array to store indexes of places where dots should be added; // Finding and storing index of point where decimal places start: for (let i = 0; i < stringNumber.length; i++) { if (stringNumber[i] === '.') { dot = i; } }; // Ensuring there is a value assigned to dot variable (in case the number has no decimals): if (dot) { dot = dot; } else { dot = stringNumber.length; }; // Storing indexes where commas should be added. Loop should stop at index 1 to prevent new number starting with a comma: for (let i = dot - 3; i >= 1; i -= 3) { arrayOfCommas.push(i); }; // Populating array with number and commas added in reverse order: for (let i = stringNumber.length - 1; i >= 0; i--) { formatedNumberReversed.push(stringNumber[i]); if (arrayOfCommas.includes(i)) { formatedNumberReversed.push(','); }; }; // Reversing order of array to get correct order: for (let i = formatedNumberReversed.length - 1; i >= 0; i--) { formatedNumber.push(formatedNumberReversed[i]); } // Converting array to string: return formatedNumber.join(''); } export {formatNumber};

My overly complicated solution… :stuck_out_tongue:
When I saw the code in the tip, I got :hot_face:

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.