I am working on a simple calculator project
I am attempting to automate adding event listeners to the various numeric buttons (1-9).
The event listeners will listen to click events on the buttons leading to a change in the display section of the HTML (class = .display)
key value pairs being b1-b9 containing the various corresponding values.
I have come up with the below FOR EACH loop. For some reason it causes all numerical buttons to apply the number 9; which i believe is the cause of the for each loop.
I am unsure how to quite fix it. I have also come up with an alternative FOR loop that leads to another problem. pairs[Properties[i]].toString() returns undefined.
interestingly if i swap pairs[Properties[i]].toString() out to just i then the SAME issue occurs
Help really appreciated and thank you..
const pairs = {
b1: 1,
b2: 2,
b3: 3,
b4: 4,
b5: 5,
b6: 6,
b7: 7,
b8: 8,
b9: 9,
};
var Properties = Object.keys(pairs);
function loadButtons () {
for (var item in pairs) {
//for each key property in pairs
console.log(item);
let targetCell = document.querySelector("." + item.toString())
// querySelector only targets the FIRST element found
// in this case only 1 for that name
console.log(targetCell);
targetCell.addEventListener('click', () => {
// you want it to manipulate the display as and when clicked
var currentDisplay = document.querySelector(".display").innerHTML.toString();
newDisplay = currentDisplay + pairs[item].toString();
document.querySelector(".display").innerHTML = newDisplay;
})
// console.log(pairs[item]);
// // pairs[item] retrieves the value to that "key"
}
};
function alternative() {
var i;
var Properties = Object.keys(pairs);
for (i = 0; i < Properties.length; i++) {
let targetCell = document.querySelector("." + Properties[i].toString())
// querySelector only targets the FIRST element found
// in this case only 1 for that name
console.log(targetCell);
targetCell.addEventListener('click', () => {
// you want it to manipulate the display as and when clicked
var currentDisplay = document.querySelector(".display").innerHTML.toString();
newDisplay = currentDisplay + pairs[Properties[i]].toString();
document.querySelector(".display").innerHTML = newDisplay;
})
};
};
Expected should be clicking of 1 to add a string "1" to the current string of the calculator, so on .
You should use event delegation instead of looping over and attaching events to every button. Here's an example:
var keyboard = document.getElementById('keyboard'); var display = document.getElementById('display'); keyboard.addEventListener('click', function(ev) { var val = ev.target.id; if (ev.target.localName === 'button') { display.innerText += val; } });
.calculator { width: 300px; background: whitesmoke; } #display { height: 50px; background: #d2d2d2; border: 1px solid #9c9c9c; margin: 10px auto 10px; font-size: 20px; line-height: 50px; padding: 0 10px; } #keyboard { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; } button { font-size: 20px; padding: 20px; margin: 5px; cursor: pointer; }
<div class="calculator"> <div id="display" contenteditable="true" > </div> <div id="keyboard"> <button id="0">0</button> <button id="1">1</button> <button id="2">2</button> <button id="3">3</button> <button id="4">4</button> <button id="5">5</button> <button id="6">6</button> <button id="7">7</button> <button id="8">8</button> <button id="9">9</button> </div> </div>
i will do it this way but that not the only one i guess and there could be better ways.
const BUTTONS_NAMESVALUES={ //-- sound awful when a loop can do that! bt0:0,bt1:1,bt2:2,bt3:3,bt4:4,bt5:5,bt6:6,bt7:7,bt8:8,bt9:9 } function checkButtonValue(bt){ if(BUTTONS_NAMESVALUES[bt.id] !=null && BUTTONS_NAMESVALUES[bt.id] !='undefined'){ return bt.innerHTML; }return; } //a button may look like that <button id="bt1">1</button> //-- with listener: document.getElementById('bt1').addEventListener('click', function(e){ let chk=checkButtonValue(this); if(chk!=null && chk!='undefined' && chk!=''){ document.getElementById('calculatorScreen').innerHTML=''+document.getElementById('calculatorScreen').innerHTML+chk; } });
I hope that help. I just replace the class name '.display' who can easily be a source of error(because it's the name of a CSS property and anything is display in HTML+ using an id better in that case because it's a unique element and can't be mistaken, classes aren't) and is not very accurate(as i write a correct constante name who has some meaning instead of pairs who means really nothing ^^).
Neither i 've automated the code into a loop but that's the easy part who is ever in your script.
function onClick(item, pairs) {
return () => {
// you want it to manipulate the display as and when clicked
var currentDisplay = document.querySelector(".display").innerHTML.toString();
var newDisplay = currentDisplay + pairs[item].toString();
document.querySelector(".display").innerHTML = newDisplay;
}
}
var Properties = Object.keys(pairs);
function loadButtons () {
for (var item in pairs) {
//for each key property in pairs
console.log(item);
let targetCell = document.querySelector("." + item.toString())
// querySelector only targets the FIRST element found
// in this case only 1 for that name
console.log(targetCell);
targetCell.addEventListener('click', onClick(item, pairs))
// console.log(pairs[item]);
// // pairs[item] retrieves the value to that "key"
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.