Calculator with Modules

Project Description

A basic calculator that uses export/import statements to share code with a JavaScript module file.

About modules in JavaScript

Developers use modules for the same reason thry use functions: to transform one big thing into several smaller things:

  • Functions: A function is a block of code within the programe file that performs a particular task.
  • Modules: A block of code in a seperate file that that performs a particular task.

Both functions and modules help you better organise and structure your codebase by dividing large programs into smaller, more manageable, more independent and more resusable chunks of code.

In summary, a module in JavaScript is file containing code that can be imported into another JavaScript file.

JavaScript uses two keywords to share and receive code across different files.

  • export: This makes code - variables, functions, objects or classes - accessible to other JavaScript files.
  • import: This is brings in code that is exported by a JavaScript module file.

Let's create a simple calculator in JavaScript to provide an example of modules.

Setting up the base web page

Your first task is to set up the base web page.

  1. In your portfolio/js folder, create a new sub-folder named calculator-modules.
  2. Download the following file to this new portfolio/js/calculator-modules folder.   index.html
  3. Give it the filename index.html.
  4. Update the website logo, favicon, <title> tag and the <footer> with your own details.

This file contains all the necessary HTML and CSS for this project.

Adding some JavaScript code

Now it's time to add the JavaScript code.

  1. In your portfolio/js/calculator-modules folder, create a new, empty file and name it app.js.
  2. At the bottom of your index.html web page, just before the closing </body> tag, link to the file that will hold your JavaScript code.
    <script src="app.js"></script>
    Save your index.html web page.
  3. Into your app.js file, copy-and-paste the JavaScript code below.
    const calculator = {
      displayValue: '0',
      firstOperand: null,
      waitingForSecondOperand: false,
      operator: null,
    };
    
    function inputDigit(digit) {
      const { displayValue, waitingForSecondOperand } = calculator;
    
      if (waitingForSecondOperand === true) {
        calculator.displayValue = digit;
        calculator.waitingForSecondOperand = false;
      } else {
        calculator.displayValue =
          displayValue === '0' ? digit : displayValue + digit;
      }
    }
    
    function inputDecimal(dot) {
      if (calculator.waitingForSecondOperand === true) {
        calculator.displayValue = '0.';
        calculator.waitingForSecondOperand = false;
        return;
      }
    
      if (!calculator.displayValue.includes(dot)) {
        calculator.displayValue += dot;
      }
    }
    
    function handleOperator(nextOperator) {
      const { firstOperand, displayValue, operator } = calculator;
      const inputValue = parseFloat(displayValue);
    
      if (operator && calculator.waitingForSecondOperand) {
        calculator.operator = nextOperator;
        return;
      }
    
      if (firstOperand == null && !isNaN(inputValue)) {
        calculator.firstOperand = inputValue;
      } else if (operator) {
        const currentValue = firstOperand || 0;
        const result = calculate(currentValue, inputValue, operator);
    
        calculator.displayValue = String(result);
        calculator.firstOperand = result;
      }
    
      calculator.waitingForSecondOperand = true;
      calculator.operator = nextOperator;
    }
    
    function calculate(firstOperand, secondOperand, operator) {
      if (operator === '+') {
        return firstOperand + secondOperand;
      } else if (operator === '-') {
        return firstOperand - secondOperand;
      } else if (operator === '*') {
        return firstOperand * secondOperand;
      } else if (operator === '/') {
        return firstOperand / secondOperand;
      }
    
      return secondOperand;
    }
    
    function resetCalculator() {
      calculator.displayValue = '0';
      calculator.firstOperand = null;
      calculator.waitingForSecondOperand = false;
      calculator.operator = null;
    }
    
    function updateDisplay() {
      const display = document.querySelector('.calculator-screen');
      display.value = calculator.displayValue;
    }
    
    updateDisplay();
    
    const keys = document.querySelector('.calculator-keys');
    keys.addEventListener('click', event => {
      const { target } = event;
      if (!target.matches('button')) {
        return;
      }
    
      if (target.classList.contains('operator')) {
        handleOperator(target.value);
        updateDisplay();
        return;
      }
    
      if (target.classList.contains('decimal')) {
        inputDecimal(target.value);
        updateDisplay();
        return;
      }
    
      if (target.classList.contains('all-clear')) {
        resetCalculator();
        updateDisplay();
        return;
      }
    
      inputDigit(target.value);
      updateDisplay();
    });
  4. Finally, save the app.js and index.html files.

Open your portfolio/js/calculator-modules/index.html file in a web browser and verify it works correctly.

Dividing the JavaScript code into files

Your task now is to remove some code from the apps.js file and place it in a separate file that will become a module.

  1. In VSCode, create a new empty file in your portfolio/js/calculator-modules folder and name it as follows:   perform-calculations.js
  2. Into this new perform-calculations.js file, cut-and-paste the calculate(firstOperand, secondOperand, operator) function from the app.js file.
  3. Save all your files.

If you test the calculator in your web browser, you can see it no longer works correctly.

Adding the import and export keywords

You will now add the export and import keywords to enable code to be shared between the files.

  1. In your perform-calculations.js file, add the export keyword before the function as follows:
    export function calculate(firstOperand, secondOperand, operator) {
  2. In the app.js file, at the very top of the file, add the following import statement:
    import { calculate } from './perform-calculations.js'
    Note that the import statement(s) must always be at the top of the file before any other code, are enclosed within braces { }.   If you were importing multiple items (variables, arrays, functions or whatever) from a module, you would separate the identifiers by commas. For example.
    import { sum, difference, product, quotient } from './some-file.js'
      It is also necessary to include the relative path. In this case, it is ./.
  3. At the bottom of your index.html web page, update the JavaScript links as follows.
    <script type="module" src="app.js"></script>
    <script type="module" src="perform-calculations.js"</script>
    The type="module" attribute ensures the code is loaded as a module and not a regular script.
  4. Save your files.

Modules must be loaded in a web server environment. They will not work if loaded from the regular file system.

Upload the calculator-modules folder as a sub-folder of the portfolio/js folder on your GitHub account.

Adding the Live Server extension to VSCode

A quick and simple way to display web pages on your computer in a web server environment is to install the Live Server extension to VSCode. Here are the steps:

  1. In VSCode, click the Extensions icon in the Toolbar at the left of the screen.
  2. Search for and then install the Live Server extension.

After installing the extension, you should see a link to it at the bottom-right of the VSCode window.

Live Server

Working with Live Server

To turn on Live Server, click the link at the bottom-right of the screen. You should see a message similar to the following.

Live Server

Also, the currently open web page in VSCode will open in your default web browser in a web server environment.

To display another web page in a server environment, right-click on the file in the VSCode Explorer panel and choose Open with Live Server.

Live Server

To turn off Live Server, click its link at the bottom-right of the screen.

Display your Calculator project with Live Server and verify the program logic works correctly.

Unfortunately, the links from the web page to any external CSS or JS files will not work. This is because Live Server accesses relative links relative to the VSCode workspace rather than to your regular file structure. The links will work, however, on other web server environments such as GitHub.

Running the Nodejs web server

Another option for running web pages on your computer in a server environment is to use the web-server app from Nodejs. Here are the steps.

  1. Install Nodejs following these instructions.
  2. Open a new command prompt and install the Nodejs web server by running this package manager command:
    npm install -g http-server
  3. Switch to the folder than contains your project's index.html web page. For exmple:
    c:\websites\portfolio\js\calculator-modules
  4. Start the server with the following command:
    http-server
  5. Open your browser and go to the address http://localhost:8080 and you should see your local website.