JavaScript DOM Tutorial – How to Build a Calculator App in JS

JavaScript is an incredibly versatile language that allows you to build all kinds of interactive applications right in the browser. In this tutorial, we‘ll harness the power of JavaScript and the Document Object Model (DOM) to create a fully functional calculator app from scratch.

Whether you‘re a beginner looking to solidify your JavaScript fundamentals or an intermediate developer wanting to practice your DOM manipulation skills, building a calculator is a fun and practical project. So let‘s get started!

What is the DOM?

Before we dive into building our calculator, it‘s important to understand what the DOM is and how it allows us to interact with elements on a webpage.

The Document Object Model, or DOM for short, is a programming interface for web documents. It represents the HTML or XML document as a tree structure where each node is an object representing a part of the document.

The DOM allows you to access, modify, add or delete elements and content using a scripting language like JavaScript. You can think of the DOM as a bridge between your web page and your scripts.

Here‘s a simplified representation of the DOM tree for an HTML document:

       document
         /  \
        /    \
       /      \
      /        \
   <html>     <head>
    /  \
   /    \
  /      \
<body>  <title>
 |         |
 |        text
<div>
  |
  |
 <p>
  |
 text

With the DOM, you can select individual elements (like a <p> tag), access or modify their attributes and content, create new elements, and remove existing ones. This allows you to dynamically update the webpage in response to user interactions or other events.

Now that we have a basic understanding of the DOM, let‘s start building our calculator app!

Setting Up the HTML Structure

The first step is to create the HTML skeleton for our calculator. We‘ll need a container element to hold the entire calculator, an input field to display the numbers and results, and buttons for the digits, operators, and other functions.

Here‘s the HTML code for our calculator:

<div class="calculator">
  <input type="text" class="calculator-screen" value="" disabled />

  <div class="calculator-keys">
    <button type="button" class="operator" value="+">+</button>
    <button type="button" class="operator" value="-">-</button>
    <button type="button" class="operator" value="*">×</button>
    <button type="button" class="operator" value="/">÷</button>

    <button type="button" value="7">7</button>
    <button type="button" value="8">8</button>
    <button type="button" value="9">9</button>

    <button type="button" value="4">4</button>
    <button type="button" value="5">5</button>
    <button type="button" value="6">6</button>

    <button type="button" value="1">1</button>
    <button type="button" value="2">2</button>
    <button type="button" value="3">3</button>

    <button type="button" value="0">0</button>
    <button type="button" class="decimal" value=".">.</button>
    <button type="button" class="all-clear" value="all-clear">AC</button>

    <button type="button" class="equal-sign operator" value="=">=</button>
  </div>
</div>

We‘ve used semantic class names like calculator-screen, operator, and equal-sign to make it easier to select and manipulate these elements with JavaScript later.

Styling with CSS

Next, let‘s add some CSS to make our calculator look nice. We‘ll style the calculator container, buttons, and input field to resemble a real calculator.

.calculator {
  border: 1px solid #ccc;
  border-radius: 5px;
  width: 400px;
}

.calculator-screen {
  width: 100%;
  height: 80px;
  border: none;
  background-color: #252525;
  color: #fff;
  text-align: right;
  padding-right: 20px;
  padding-left: 10px;
  font-size: 4rem;
}

button {
  height: 60px;
  font-size: 2rem!important;
}

.equal-sign {
  height: 98%;
  grid-area: 2 / 4 / 6 / 5;
}

.calculator-keys {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 20px;
  padding: 20px;
}

This CSS code sets a fixed width for the calculator, styles the input field to have a dark background and white text, and uses CSS Grid to layout the buttons in a 4×4 grid. The equal sign button spans multiple rows to make it larger.

Adding JavaScript Functionality

Now comes the fun part – making our calculator actually work! We‘ll use JavaScript to select elements, attach event listeners, and perform the calculations.

First, let‘s select the necessary elements using querySelector and querySelectorAll:

const calculator = document.querySelector(‘.calculator‘);
const keys = calculator.querySelector(‘.calculator-keys‘);
const display = document.querySelector(‘.calculator-screen‘);

Next, we‘ll attach a click event listener to the keys container to handle button clicks:

keys.addEventListener(‘click‘, event => {
  const { target } = event;
  const { value } = target;
  if (!target.matches(‘button‘)) {
    return;
  }

  switch (value) {
    case ‘+‘:
    case ‘-‘:
    case ‘*‘:
    case ‘/‘:
    case ‘=‘:
      handleOperator(value);
      break;
    case ‘.‘:
      inputDecimal();
      break;
    case ‘all-clear‘:
      resetCalculator();
      break;
    default:
      if (Number.isInteger(parseFloat(value))) {
        inputDigit(value);
      }
  }
});

This event listener checks if the clicked target is a button, then calls the appropriate function based on the button‘s value using a switch statement.

Here are the functions to handle different calculator behaviors:

function inputDigit(digit) {
  const displayValue = display.value;
  display.value = displayValue === ‘0‘ ? digit : displayValue + digit;
}

function inputDecimal() {
  if (!display.value.includes(‘.‘)) {
    display.value += ‘.‘;
  }
}

function resetCalculator() {
  display.value = ‘0‘;
  calculator.dataset.firstValue = ‘‘;
  calculator.dataset.operator = ‘‘;
  calculator.dataset.modValue = ‘‘;
}

function handleOperator(nextOperator) {
  const firstValue = calculator.dataset.firstValue;
  const operator = calculator.dataset.operator;
  const modValue = display.value;

  if (firstValue &&  operator && previousKeyType !== ‘operator‘) {
    const currentValue = display.value;
    const result = calculate(firstValue, operator, currentValue);

    display.value = roundResult(result);
    calculator.dataset.firstValue = display.value;
  } else {
    calculator.dataset.firstValue = display.value;
  }

  calculator.dataset.modValue = modValue;
  calculator.dataset.operator = nextOperator;
}

function calculate(firstNumber, operator, secondNumber) {
  firstNumber = parseFloat(firstNumber);
  secondNumber = parseFloat(secondNumber);

  if (operator === ‘+‘) return firstNumber + secondNumber;
  if (operator === ‘-‘) return firstNumber - secondNumber;  
  if (operator === ‘*‘) return firstNumber * secondNumber;
  if (operator === ‘/‘) return firstNumber / secondNumber;
}

function roundResult(number) {
  return Math.round(number * 1000) / 1000;
}

The inputDigit() function updates the display when a digit button is clicked. It appends the digit to the current value, unless the current value is ‘0‘, in which case it replaces it.

The inputDecimal() function adds a decimal point to the current value, but only if there isn‘t already a decimal point present.

resetCalculator() clears the display and resets all stored values when the "AC" button is clicked.

The handleOperator() function is called when an operator button is clicked. It stores the first value and the selected operator, then updates the display with the new value entered after the operator. When the equal sign is clicked, it performs the calculation using the calculate() helper function.

Finally, roundResult() rounds the calculation result to a maximum of 3 decimal places to avoid long floating-point numbers.

And with that, we have a fully functional calculator! You can now enter numbers, perform basic arithmetic operations, and clear the calculator using the "AC" button.

Suggested Improvements

While our calculator is working great, there‘s always room for improvement! Here are a few suggestions to take your calculator to the next level:

  1. Add keyboard support: Allow users to input numbers and perform calculations using their keyboard in addition to clicking buttons.

  2. Implement more advanced operations: Extend the calculator‘s functionality with exponentiation, square roots, trigonometric functions, etc.

  3. Improve error handling: Display helpful messages for edge cases like dividing by zero or exceeding the maximum input length.

  4. Add CSS animations and transitions to create a smoother, more engaging user experience.

Feel free to experiment and customize the calculator to make it your own!

Conclusion

Congratulations, you‘ve built a working calculator app using nothing but HTML, CSS, and JavaScript!

In this tutorial, we covered the fundamentals of DOM manipulation, including:

  • Selecting elements with querySelector and querySelectorAll
  • Modifying element attributes and content
  • Attaching event listeners to respond to user interactions
  • Performing calculations and updating the display dynamically

I hope this project helped solidify your understanding of the DOM and how it allows you to create interactive experiences on the web. Keep practicing and building projects to further sharpen your JavaScript skills.

Now go forth and calculate!

Similar Posts