The optimal method for selecting a button from a group of buttons on a calculator using pure JavaScript

I have developed an HTML/CSS code inspired by the Mac/Apple calculator design. It features buttons organized in 5 rows using flexbox.

You can view my code on this codepen:

<div class="wrapper">
  <div class="calheader">
      <h2>Simple Calculator</h2>
    </div>
  <div class="calculatorbox">
    <div class="calwindow">
      <!-- ENTRY BOX -->
     <div class="entry">
        <p id="answer"></p>
      </div>
      <div class="entryhistory">
        <p id="history"></p>
      </div>
    </div>
    <!-- BUTTONS \\-->
    <div class="calbuttons">
      <div class="row">
        <button id="clear" class="key topcolor" value="clear">C</button>
        <button class="key topcolor" value="plusminus"><sup>+</sup>/<sub>−</sub></button>
        <button class="key topcolor" value="%">%</button>
        <button id="divide" class="key orange" value="/">÷</button>
      </div>
      <div class="row">
        <button id="seven" class="key" value="7">7</button>
        <button id="eight" class="key" value="8">8</button>
        <button id="nine" class="key" value="9">9</button>
        <button id="multiply" class="key orange" value="*">×</button>
      </div>
      <div class="row">
        <button id="four" class="key" value="4">4</button>
        <button id="five" class="key" value="5">5</button>
        <button id="six" class="key" value="6">6</button>
        <button id="subtract" class="key orange" value="-">−</button>
      </div>
      <div class="row">
        <button id="one" class="key" value="1">1</button>
        <button id="two" class="key" value="2">2</button>
        <button id="three" class="key" value="3">3</button>
        <button id="add" class="key orange" value="+">+</button>
      </div>
      <div class="row">
        <button id="zero" class="key btnspan" value="0">0</button>
        <button id="decimal" class="key" value=".">.</button>
        <button id="equals" class="key orange" value="=">=</button>
      </div>
    </div>
  </div>
</div>

Currently, I am exploring how to individually select and apply the addEventListener function to each button element.

A different JavaScript tutorial I came across utilizes a simpler structure as shown below:

<div class="calculator-keys">
    
    <button type="button" class="operator" value="+">+</button>
    <button type="button" class="operator" value="-">-</button>
    <button type="button" class="operator" value="*">&times;</button>
    <button type="button" class="operator" value="/">&divide;</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>

The tutorial goes on to illustrate how to interact with these elements using JavaScript:

const keys = document.querySelector('.calculator-keys');

keys.addEventListener('click', (event) => {
  const { target } = event;
  console.log('digit', target.value);
});

In this context, the querySelector method is utilized to target all children within the calculator-keys class for interaction.

In my situation, I was able to implement this functionality only for the first row of buttons. If I proceed to use querySelectorAll, would it be necessary to employ .map(), .forEach(), or some other technique to effectively utilize addEventListener for each individual button?

Answer №1

querySelector only retrieves one element at a time, so you should utilize querySelectorAll instead. To accomplish this, you need to target all elements with the class key and then attach an event listener for each key.

 const keys = document.querySelectorAll('.key');

keys.forEach(item => {
 item.addEventListener('click', (event) => {
    const { target } = event;
    console.log('digit', target.value);
    });
});
<div class="wrapper">
  <div class="calheader">
      <h2>Simple Calculator</h2>
    </div>
  <div class="calculatorbox">
    <div class="calwindow">
      <!-- ENTRY BOX -->
     <div class="entry">
        <p id="answer"></p>
      </div>
      <div class="entryhistory">
        <p id="history"></p>
      </div>
    </div>
    <!-- BUTTONS \\-->
    <div class="calbuttons">
      <div class="row">
        <button id="clear" class="key topcolor" value="clear">C</button>
        <button class="key topcolor" value="plusminus"><sup>+</sup>/<sub>−</sub></button>
        <button class="key topcolor" value="%">%</button>
        <button id="divide" class="key orange" value="/">÷</button>
      </div>
      <div class="row">
        <button id="seven" class="key" value="7">7</button>
        <button id="eight" class="key" value="8">8</button>
        <button id="nine" class="key" value="9">9</button>
        <button id="multiply" class="key orange" value="*">×</button>
      </div>
      <div class="row">
        <button id="four" class="key" value="4">4</button>
        <button id="five" class="key" value="5">5</button>
        <button id="six" class="key" value="6">6</button>
        <button id="subtract" class="key orange" value="-">−</button>
      </div>
      <div class="row">
        <button id="one" class="key" value="1">1</button>
        <button id="two" class="key" value="2">2</button>
        <button id="three" class="key" value="3">3</button>
        <button id="add" class="key orange" value="+">+</button>
      </div>
      <div class="row">
        <button id="zero" class="key btnspan" value="0">0</button>
        <button id="decimal" class="key" value=".">.</button>
        <button id="equals" class="key orange" value="=">=</button>
      </div>
    </div>
  </div>
</div>

Answer №2

Event delegation in the DOM refers to handling events that bubble up from multiple elements. This approach simplifies code, particularly when adding or removing elements, and also helps conserve memory.

Here are some examples of event delegation:

  1. JavaScript Event Delegation

  2. DOM Events

If you're using Javascript and have a list of buttons with the class 'key', you can utilize the following code snippet to attach an EventListener to each button.

let buttons = document.getElementsByClassName('key');
for(let i = 0; i<buttons.length; i++){
   buttons[i].addEventListener('click', () => {
      /*add your code here*/
   });
}

Answer №3

To convert a NodeList to an array using querySelectoAll, you can iterate through the buttons and add an eventListener.

let buttons = document.querySelectorAll('.btn');
let arrButtons = Array.from(buttons);

console.log(arrButtons)

for(button of arrButtons){
  button.addEventListener('click', () => {
    console.log('event');
  })
}
<button class="btn">Go!</button>
<button class="btn">Go!</button>
<button class="btn">Go!</button>
<button class="btn">Go!</button>

Answer №4

A highly recommended approach is to utilize event delegation. By doing so, you avoid the need to individually attach event listeners to each button and instead only attach it to their parent container.

const calcKeys = document.querySelector(".calculator-keys");

// Event listener only added to the parent container
calcKeys.addEventListener("click", (event) => {

  // Ignoring clicks from non-button elements
  if (event.target.nodeName !== "BUTTON") return;

  console.log(event.target.value);
});
<div class="calculator-keys">
  <button type="button" class="operator" value="+">+</button>
  <button type="button" class="operator" value="-">-</button>
  <button type="button" class="operator" value="*">&times;</button>
  <button type="button" class="operator" value="/">&divide;</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="AC">AC</button>

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adhering button for sliding side panel

Check out my JSFiddle HERE to see what I have done. I would really appreciate it if someone could help me figure out how to make the show button float with the sidr panel :) <style type="text/css"> #panel { position: fixed; top: 50%; r ...

Update a separate React component in response to the interaction with a different React component

Currently, I am working with a react component named Interest Category that showcases an initial set of Interest categories. Another react component called CreateInterestCategoryDialog, which functions as a modal, is responsible for creating a new entity I ...

Utilize pg-promise for inserting data with customized formatting using the placeholders :name and :

After reviewing the pg-promise documentation, I came across this code snippet: const obj = { one: 1, two: 2 }; db.query('INSERT INTO table(${this:name}) VALUES(${this:csv})', obj); //=> INSERT INTO table("one"," ...

Tips for seamlessly embedding Youtube iframes within Angular2 components. Resolving issues with unsafe value errors

ERROR: There seems to be an issue in the ./HomeComponent class HomeComponent - inline template:23:84. It is caused by using an unsafe value in a resource URL context. About my homeData model { id: 1, title: '2017 Super Bowl', graphic: 'ht ...

The second jQueryUI datepicker instance flickers and vanishes when the show() function is triggered

I currently have two jQueryUI datepickers integrated into my webpage. The initialization code for both is as follows: jQuery("#departureDate").datepicker({ beforeShow: function() { getDatesForCalendar("outbound"); }, numberOfMonths: 3 ...

Error: The reference to 'ko' is not defined while loading with jQuery

After numerous attempts, I am still encountering the ReferenceError: ko is not defined issue while trying to load KnockoutJS using jQuery's getScript function. Below is the code snippet I have been testing to see if everything is functioning correctl ...

Tips for confirming date is earlier than current date in Reactjs?

Looking for guidance on how to ensure a date selected by a user is always before the current date when using Material UI in my project. For instance, if it's January 6th, 2021 and the user selects either January 5th or 6th that would be acceptable. Ho ...

Utilizing a dictionary for comparing with an API response in order to generate an array of unique objects by eliminating duplicates

I currently have a React component that utilizes a dictionary to compare against an API response for address state. The goal is to map only the states that are returned back as options in a dropdown. Below is the mapping function used to create an array o ...

tips on utilizing the JSON information transmitted from the backend

$.ajax({ url: '{{ URL('reports/groupsUsersGet') }}', dataType: "json", data: { group_id : $('#group').val(), }, success: function(data) { <li>"i need to insert variable here"</li> }, error: function (data) ...

Node.js Binary Search Tree - Error: Identifier Not Found

A program run through node.js has been developed to create a binary search tree with various methods like insert, remove, and print. The program is divided into two separate files: Tree.js, which exports the functions Tree() along with its methods and test ...

Python Selenium : Struggling to locate element using ID "principal"

As part of my daily work, I am currently working on developing a Python Script that can automate the process of filling out forms on various websites. However, I encountered an issue with Selenium while trying to interact with certain types of webforms. F ...

Is there a way to handle the 'No tables found' error when using pd.read_html?

The issue I am facing a challenge while creating multiple URLs from an API request and then using them in a loop to extract data from the FT website. The problem arises when some of these URLs do not feature an HTML table, resulting in a No tables found er ...

Obtain text content using JQuery and AJAX rather than retrieving the value

I am struggling with a dynamic table that needs to perform calculations before submitting, requiring the presence of values. However, I want to submit the text from the options instead of the values. Despite trying various approaches, none of them seem to ...

The AngularJS 2 TypeScript application has been permanently relocated

https://i.stack.imgur.com/I3RVr.png Every time I attempt to launch my application, it throws multiple errors: The first error message reads as follows: SyntaxError: class is a reserved identifier in the class thumbnail Here's the snippet of code ...

The image is experiencing difficulty loading from the Express static directory

Having some trouble with image loading... I've noticed that images are loading fine from the local folder, but not from the uploads folder which is set to be static. I've been attempting to upload a file from the browser. The upload and save pr ...

execute the code when the device is not an iPad

if ( (navigator.userAgent.indexOf('/iPadi') != -1) ) { } This conditional statement is used to identify whether the user's device is an iPad, but I specifically want to execute the code only if it is not an iPad. I have a JQuery hover func ...

Is there a way to integrate jQuery and Javascript into a Firefox add-on?

Having trouble creating a new element on the page? After checking both the page and domain during onload, it seems that everything is in order. But how can you successfully create a new element in the correct window page? window.addEventListener("load", f ...

How to display only the thumbnail on WordPress archive page and remove the post excerpt

I am currently in the process of revamping my category archive to resemble a grid layout by utilizing custom CSS. I have successfully eliminated the elements I desired using code like this: .archive .entry-footer { display: none; } Now, I only have t ...

Design a layout featuring an array of boxes in varied sizes

Is it possible to create a grid layout with 3 columns containing div boxes of varying heights, all populated with content extracted from a database? ...

What are the steps to integrate MaterializeCss into Vue.js?

I prefer not to utilize Vue-Material or Vuetify. My choice is Materialize. Here's what I do: npm install materialize-css@next In my main.js file, where I define my new Vue App, I import Materialize like this: import 'materialize-css' Th ...