Javascript Calculator07

Hi All,
I was planning to ask for help with button onclick handlers, but after many hours I have numbers and decimal buttons operational. Maybe the way I’m doing it isn’t ideal so please let me know your thoughts. You will see a lot console.log() statements. I left them in to show my work. My goal is to only use JS and rewrite with jQuery etc. later on.

Here are my questions:

  1. I didn’t want to write HTML onclicks for each <button> so I used .forEach() then abandoned that for a for loop. Would .forEach() be better? I was considering a .reduce()function/object to keep track of the math and am curious about using objects here…everywhere actually. They intrigue me.
  2. Scope of variables also killing me…along with some basics of {{}{}}. Any advice on how to break down projects into easier problems to solve? I feel like I’m making it too hard.
  3. Generally is there anything you all can see on here that doesn’t make sense? I’m more interested in learning than completing the project quickly, so any perspectives you have are welcomed.

These projects are so different from the JS we learn in the curriculum.

https://codepen.io/Magopolis/pen/dyRNOYN

Your code so far

const time = new Date().toLocaleTimeString();
const str1 = document.getElementById("display");
const str2 = document.getElementById("display2");
var buttons = document.querySelectorAll('button');
const AC = document.getElementById("clear");
const disp = document.getElementById("display");
document.getElementById("time").innerHTML = new Date().toLocaleTimeString();
var decOk = true;

testScope.addEventListener("click", function() {
  console.log("Hi guys.");
  if (decOk) {
    console.log(decOk + "?")
  str1.innerHTML += "."
    decOk = false;
  }
  console.log(decOk + "!")
  console.log("Decimal Not OK");
});

for (let i =0; i < buttons.length; i++) {
 
  buttons[i].addEventListener("click", function(e) {
 
     //console.log(decOk);
 let punch = e.target.value;
    
  if (!isNaN(punch) && str1.innerHTML === "0") {
    str1.innerHTML = "" + punch; 
  } else if (!isNaN(punch)){
   str1.innerHTML += punch;
  } else if (punch === "." && decOk == true) {
   
    str1.innerHTML += ".";
    console.log("still " + decOk)
    decOk = false;
    console.log(decOk);
  }
    else if(!decOk)
    {
  
    testScope.innerHTML = punch;
    console.log(decOk);
    str1.innerHTML += "";
    decOk = false;}
       console.log("still " + decOk);
  
  }) 
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36

Challenge: Build a JavaScript Calculator

Link to the challenge:

Instead of adding an event listener (which is using the same function) to every button you might think about just adding one listener to the div that wraps all the buttons. This is called event delegation which can be a much more efficient use of resources.

1 Like

Wow! I’ll check it out.
…so in (evt.target.nodeName === 'li'), “nodeName” is synonymous with tagName? Also curious about how event.target knows…or…where the logic is that tells us that “evt”, “e”, or whatever we write before .target is the “event”. Must be written into the prototype .target method? or into the .addEventListener(), same as .forEach lets you write “el” or “l” or “item”.

I was inspired to try .forEach() because it has a .this arg I could explore. This event delegation looks like rendering with React which I plan to do in a future rewrite-less typed HTML. I don’t know how I would render this way with buttons because mine go like:

<div id="keys" class="btn grid-container">
    <button  id="NaN" value="" class="" ></button>
    <button  id="NaN" value="" class="" ></button>
    <button  id="NaN" value="" class="" ></button>
    <button  id="NaN" value="" class="" ></button>
    <button  id="Num" value="" class=""></button>
    <button  id="Num" value="" class="" ></button>
    <button  id="Num" value="" class="" ></button>
    <button  id="NaN" value="" class="" ></button>

Its not just 10 <li>. I could use class selectors or… Im gonna have to read this a few more times.

Here is my current objectivization of the <button>. I studied the forEach some more and did a console.log(this); inside the callback, returning “this:”

<button value="x" class="etc etc" id="multiply">x</button> //!!!

full code for the obj is:

const operationKeys = document.getElementsByClassName("operations");

operationKeys.forEach(function assignClick(element, index, operationKeys) {
  element.addEventListener("click", function(event) {
    let punch = event.target.value;
    if(currentString.length > 0) {
      prevString = currentString;
      decOk = true;
      lastPunch.push(this.value);
      console.log('z is ok');
      logArr.push(currentString);
      logArr.push(event.target.value);
      theLog = logArr.toString().replace(commaRegex, " ");
      str2.innerHTML = logArr.toString().replace(commaRegex, " ");
      str1.innerHTML = "0";
      currentString = "";
      
      console.log(this);
    }
  })
}, this.value) // this.value returns 'x'. Probably will be useful in the handling the evaluation. thinking about using a .reduce() obj with accumulator and binding the thisArg

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.