Reputation: 85
I'm building a calculator and want to have each button send its value to the empty array called "storage". First of all, I can't get my code to run for each button and am not sure why this is. It's only running on the #1 button. Secondly, I'm unsure of how to go about sending the values to the array "storage". I know that JS has a .push(); method, but things aren't working for me.
Please, no JQuery, I want to get a good basis in plain JS first.
// Click on button and have number saved in array for later use
var spanVal = document.getElementsByClassName("num");
var storage = [];
function clickButton() {
var key = document.querySelector(".num");
key.onclick = logVal;
}
function logVal() {
for (var i = 0; i < spanVal.length; i++) {
console.log(spanVal[i].innerHTML);
}
}
clickButton();
/*storage.push();
console.log(storage);*/
#calculator {
max-width: 250px;
}
.keys span {
width: 50px;
height: 50px;
border-radius: 5px;
float: left;
margin: 8px;
font: bold 20px Arial, sans-serif;
text-align: center;
}
.grey {
background-color: grey;
}
.blue {
background-color: aqua;
}
.screen {
width: 180px;
height: 40px;
border-radius: 3px;
background-color: #ccc;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<div id="calculator">
<div class="keys">
<div class="screen"></div>
<span class="num grey">1</span>
<span class="num blue">2</span>
<span class="num grey">3</span>
<span class="num blue">4</span>
<span class="num grey">5</span>
<span class="num blue">6</span>
<span class="num grey">7</span>
<span class="num blue">8</span>
<span class="num grey">9</span>
<span class="num blue">0</span>
<span class="num grey operator">+</span>
<span class="num blue operator">-</span>
<span class="num grey operator">/</span>
<span class="num blue operator">*</span>
<span class="num grey operator">AC</span>
</div>
</div>
</head>
<body>
</body>
</html>
Upvotes: 0
Views: 2492
Reputation: 4820
well to start off
First of all, I can't get my code to run for each button and am not sure why this is
the function document.querySelector
returns a single item. if the query finds more than one, it will return the first one. You may want to use document.querySelectorAll
, iterate over the results, and using addEventListener
the second issue can be solved by pushing to the storage array inside the onclick handler.
EDIT: since the query returns a node list, not an array, use a for loop to iterate, instead of the forEach
function
the end result will look like:
var calcKeys = document.querySelectorAll('.num')
for (var i = 0; i < calcKeys.length; i++){
calcKeys[i].addEventListener('click', function(e){
storage.push(e.target.innerHTML)
})
})
Upvotes: 1
Reputation: 46
You can use a span to create the button with the innerHTML (the text inside the span) being the number:
<span id='btn1' class=number>1</span>
Trap the click event on that button.
onclick='go()';
When that event fires, you can use the event element's id (btn1) to push a value stored in the innerHTML of the span onto your array:
storage.push(document.getElementById(el).innerHTML);
You can add any number of span's for the rest of your numbers or buttons:
<span id=btn2 class=number>2</span>
Here's a working example:
<html>
<head>
<style>
div {
text-align:center;
padding:5px;
}
.number {
cursor:pointer;
width:30px;
height:30px;
background-color:silver;
border: solid 1px black;
text-align:center;
padding:5px;
margin:3px;
}
</style>
<script>
var storage = []; //this is your empty array called storage
document.addEventListener('click' , function(e){go(e)}); // i'm trapping the click event for my button
function go(e){
var el = e.target.id; // get the event element's id
storage.push(document.getElementById(el).innerHTML); // use that id to obtain the element with that id's document object reference and push it's innerHTML (or you could use another property on that object for this) and push it to the storage array.
console.log(storage); //display the storage array in the console window
}
</script>
</head>
<body>
<div>
<span id='btn1' class='number'>1</span>
<span id='btn2' class='number'>2</span>
<span id='btn3' class='number'>3</span>
</div>
<div>
<span id='btn4' class='number'>4</span>
<span id='btn5' class='number'>5</span>
<span id='btn6' class='number'>6</span>
</div>
<div>
<span id='btn7' class='number'>7</span>
<span id='btn8' class='number'>8</span>
<span id='btn9' class='number'>9</span>
</div>
<div>
<span id='btn0' class='number'>0</span>
</body>
Upvotes: 0
Reputation: 1424
This handles all of the keys, accounting for numbers vs operators and only attaches one event listener.
var nums = [];
var operators = [];
document
.querySelector('.keys')
.addEventListener('click', function(e) {
var key = e.target.innerHTML
if (! isNaN(Number(key))) {
nums.push(Number(key));
} else {
operators.push(key);
}
console.log('Nums:', nums);
console.log('Operators:', operators);
});
I attached the listener to the parent node, and we're getting the inner HTML of the 'clicked' span, and casting to an integer. These ints are getting pushed to the nums array, and it prints out the current value of the array on each click, you can do stuff with them here, or outside of listener.
JSBin. I fail super hard at posting bins. http://jsbin.com/wireboputu/1/edit?html,js,console,output
It's also handy to note that other implementations attach a listener to each span, which is kind of messy. Here we only attach one to the parent, and grab the details off the event object.
EDIT: Changed to account for operators / numbers. My first attempt would return undefined on operator keys. And my original title for this is not as simple as my first implementation, so took it away.
Upvotes: 2
Reputation: 46
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
#calculator {
max-width: 250px;
}
.keys span {
width: 50px;
height: 50px;
border-radius: 5px;
float: left;
margin: 8px;
font: bold 20px Arial, sans-serif;
text-align: center;
}
.grey {
background-color: grey;
}
.blue {
background-color: aqua;
}
.screen {
width: 180px;
height: 40px;
border-radius: 3px;
background-color: #ccc;
}
</style>
</head>
<body>
<div id="calculator">
<div class="keys">
<div class="screen"></div>
<span class="num grey">1</span>
<span class="num blue">2</span>
<span class="num grey">3</span>
<span class="num blue">4</span>
<span class="num grey">5</span>
<span class="num blue">6</span>
<span class="num grey">7</span>
<span class="num blue">8</span>
<span class="num grey">9</span>
<span class="num blue">0</span>
<span class="num grey operator">+</span>
<span class="num blue operator">-</span>
<span class="num grey operator">/</span>
<span class="num blue operator">*</span>
<span class="num grey operator">AC</span>
</div>
<button id="btn" onclick ="clickButton()">push values</button>
</div>
<script>
var x = 0;
var spanVal = document.getElementsByTagName("span");
var storageArr = [];
function clickButton() {
storageArr.push(spanVal[x].innerHTML)
x++;
alert(storageArr)
}
</script>
</body>
</html>
Upvotes: 0
Reputation: 26444
document.getElementsByClassName
returns an HTML collection. You need to iterate over each element in the collection and add the function to each key.
document.querySelector
returns only the first element. You need to use document.querySelectorAll
and iterate over the array.
Returns the first element within the document (using depth-first pre-order traversal of the document's nodes|by first element in document markup and iterating through sequential nodes by order of amount of child nodes) that matches the specified group of selectors.
var numbers = document.getElementsByClassName("num");
var storage = [];
You already defined a collection in numbers. You can simply iterate over the numbers with the forEach
method. There's no need to create a separate keys variable. The collection already exists.
numbers.forEach(function(number) {
number.addEventListener("click", function() {
storage.push(number.innerHTML);
});
});
Upvotes: 2