JavaScript function for adding up checkboxes from a form - javascript

My previous question got closed for a typo, although I'm not sure why as there were more problems in my logic. However, I have edited the loop and I still can not get it working. I need to add up multiple items and enter the answer into the text box, however I cant seem to see a problem.
JavaScript
<script>
"use strict";
const form = document.getElementById('bookingForm');
const total = form.getElementById('total');
const checkboxes = form.querySelectorAll('input[data-price][type=checkbox]');
const cbamount = checkboxes.length;
document.getElementsByName('event[]')[0].onclick = function() {
totalPrice()
};
function totalPrice(){
let totalPrice = 0;
for (let i=0; i< cbamount; i++) {
const box = checkboxes[i];
if (box.checked) {
totalPrice += box.dataset.price;
}//if
}//for
}
document.getElementsByName("txtTotalPrice").value = totalprice;
HTML for the text box
<section id="checkCost">
<h2>Total cost</h2>
Total <input type="text" name="total" size="10" readonly="">
</section>
HTML for the item (there are multiple)
<span class="eventTitle">Winter</span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">Fam</span>
<span class="venueName">Disc</span>
<span class="eventPrice">0.00</span>
<span class="chosen"><input type="checkbox" name="event[]" value="12" data-price="0.00">

there were a number of errors involving case.
you were using form.getElementById instead of document.getElementById
same with form.querySelectorAll instead of document.querySelectorAll
also, you are using getElementsByName which returns an array, so return to only [0].
further: you will likely find an issue with the return being a string, and additional clicks will append to that string rather than adding as numbers.
also: you had document.getElementsByName("txtTotalPrice").value = totalprice;[SIC] outside of the function bracket so it was not being called at the right time.
the example works with minimal fixes though.
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
const checkboxes = document.querySelectorAll('input[data-price][type=checkbox]');
const cbamount = checkboxes.length;
document.getElementsByName('event[]')[0].onclick = function() {
totalPrice()
};
function totalPrice() {
let totalprice = 0;
for (let i = 0; i < cbamount; i++) {
const box = checkboxes[i];
if (box.checked) {
totalprice += box.dataset.price;
} //if
} //for
document.getElementsByName("txtTotalPrice")[0].value = totalprice;
}
<section id="checkCost">
<h2>Total cost</h2>
Total <input type="text" name="txtTotalPrice" size="10" value="-_-">
</section>
<span class="eventTitle">Winter</span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">Fam</span>
<span class="venueName">Disc</span>
<span class="eventPrice">0.00</span>
<span class="chosen"><input type="checkbox" name="event[]" value="12" data-price="0.00">

.getElementById() only works when called from document, you can't use it from another selection like you had - querySelector / querySelectorAll do work however, so I've used those
document.getElementsByName('event[]')[0] was only selecting the first input, because of [0] - getElementsByName returns a NodeList of elements, which is similar to an Array. I've just used the checkboxes selection you had already defined, as it targeting the same elements
document.getElementsByName("txtTotalPrice").value = totalprice was outside of the function it should have been called in, and so wasn't getting any value passsed to it
Also, it feels redundant that your inputs have a value of 0, but data-price set to your values; is there a reason you can't just use the value attribute here?
I've added a few extra input boxes, and changed the selector for your total input, just to better test this. Feel free to tell me if something isn't right with those
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
const checkboxes = form.querySelectorAll('input[data-price][type=checkbox]');
checkboxes.forEach((input) => {
input.addEventListener('click', totalPrice);
});
function totalPrice() {
let totalCost = 0;
for (let i = 0; i < checkboxes.length; i++) {
const box = checkboxes[i];
if (box.checked) {
totalCost += parseFloat(box.dataset.price);
}
}
/* Added a cleaner way to find totalCost, if wanted
let totalCost = [...checkboxes].reduce((total, box) => {
return box.checked ? total += parseFloat(box.dataset.price) : total;
}, 0);
*/
total.value = totalCost;
}
<section id="checkCost">
<h2>Total cost</h2>
Total: <input id="total" type="text" name="total" size="10" readonly>
</section>
<form id="bookingForm">
<span class="chosen"><input type="checkbox" name="event[]" value="1.00" data-price="1.00"></span>
<span class="chosen"><input type="checkbox" name="event[]" value="3.50" data-price="3.50"></span>
<span class="chosen"><input type="checkbox" name="event[]" value="5.25" data-price="5.25"></span>
</form>

Related

increment in the function name and id javascript

I have number of input types and buttons....every button on click increment the value in the relevant input types. But rather than creating a separate function for every button i want to do it by loop....where loop will increase in the function name and id......
<input type="number" id="s1"> <button onclick="increment_s1();">Add</button>
<input type="number" id="s2"> <button onclick="increment_s2()">Add</button>
<input type="number" id="s3"> <button onclick="increment_s3">Add</button>
here is JavaSc code
<script>
var i = 1;
for (i = 0; i < 5; i++) {
var data = 0;
document.getElementById("s"+i).innerText = data;
function ['increment_'+i]() {
data = data + 1;
document.getElementById("s"+i).placeholder = data;
i++;
}
}
</script>
You can't program the function name. You can set up a parameter in the function to make a difference. The param would be the identifier and you can put the whole input element id there.
After that, if you want to have the id s1, s2, and so on, you should initialize the i to start from 1 to 5 instead of 0 to less than 5.
Another thing is, you need to understand the role of placeholder and value attributes in input element. The placeholder works only when the value is empty and it doesn't count as the form value.
// This is for handling onclick
function increment(id) {
var elem = document.getElementById(id);
elem.value = parseInt(elem.value) + 1;
}
// This is to initialize the 0 values
for (var i = 1; i <= 5; i++) {
var data = 0;
document.getElementById("s"+i).value = data;
}
<input type="number" id="s1"> <button onclick="increment('s1');">Add</button>
<input type="number" id="s2"> <button onclick="increment('s2')">Add</button>
<input type="number" id="s3"> <button onclick="increment('s3')">Add</button>
<input type="number" id="s4"> <button onclick="increment('s4')">Add</button>
<input type="number" id="s5"> <button onclick="increment('s5')">Add</button>
What if you would like to generate whole input and button with loops? You can get them by adding div and use the innerHTML, i.e.
// This is for handling onclick
function increment(id) {
var elem = document.getElementById(id);
elem.value = parseInt(elem.value) + 1;
}
var divElem = document.querySelector('div');
// Set up empty first
divElem.innerHTML = "";
for(var i=1; i<=5; i++) {
// Create elements here
var innerElem = `<input type="number" id="s${i}" value="0"> <button onclick="increment('s${i}')">Add</button>`;
// Push them all into innerHTML
divElem.innerHTML += innerElem;
}
<div></div>
You can try these two workarounds. Perhaps you may need to learn more about basic HTML elements and their attributes also Javascript.

Created a delete function for a list, but not all checked items are deleting

I am currently taking Wes Boros JS 30 challenge and for this particular class, we created a list where we add foods we like. As an extra assignment, we are to create a select all function, an unselect all function, and a delete function. I was able to successfully create a select all function where once you click that button, it selects all the items on the current list. My issue is that the delete function I created deletes everything, except for one or two items. Those undeleted items still remain checked, but I have to click on the delete button again in order for it to delete. FYI: I local storage was incorporated in this exercise.
Can somebody help me out and also explain what I was doing wrong?
Here is a jsfiddle of it as well
Here is how I have my HTML set up:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<input type="button" onclick="selectAll()" value="Select All"/>
<input type="button" onclick="UnSelectAll()" value="Unselect All"/>
<input type="button" onclick="deleteItem()" value="delete Item"/>
</div>
</body>
</html>
Here is my Javascript:
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = JSON.parse(localStorage.getItem('items')) || [];
//DELETE FUNCTION
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
for(var i = 0; i < boxes.length; i++){
box = boxes[i];
txt = texts[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
//SELECT ALL FUNCTION
function selectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = true;
}
}
//UNSELECT ALL FUNCTION
function UnSelectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = false;
}
}
//ADD ITEM FUNCTIO
function addItem(e){
e.preventDefault()
const text = (this.querySelector('[name=item]')).value;
const item = {
text,
done: false
};
items.push(item);
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}
//DISPLAY THE HTML FUNCTION
function populateList(plates =[], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input class="chk" type="checkbox" name="item" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label class="txt" name="item" for="item${i}">${plate.text}</label>
</li>
`
}).join('');
}
function toggleDone(e){
if(!e.target.matches('input')) return;
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
addItems.addEventListener('submit', addItem)
itemsList.addEventListener('click', toggleDone)
populateList(items, itemsList);
//DELETE ITEM EVENT HANDLER
itemsList.addEventListener('click', deleteItem);
The reason why your delete function wasn't working properly it's because Node.childNodes returns a live NodeList which means when you use removeChild on each element in the collection the other elements gets rearranged and the length of list get's smaller causing you to skip some of them so you should convert your html collection to an array using Array.from
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
arrbox = Array.from(boxes)
arrtext = Array.from(texts)
for(var i = 0; i < arrbox.length; i++){
var box = arrbox[i];
var txt = arrtext[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
Here is working jsfiddle

How to fix Javascript multiplication onchange

I'm not sure why my code isn't multiplying the two numbers when I change them. Once I enter a number in the Multiplier field, the onchange function continues adding values and if its a null value, it enters "NaN"
<body>
<h1>Mutiply</h1>
<p>Multiplicand: <input type="text" id="multiplicand" value="0" onchange="multiply()"></p>
<p>Multiplier: <input type="text"/ id="multiplier" value="0" onchange="multiply()"></p> <br>
<div>
<p><span id="showMulipicand">0</span>
×
<span id="showMultiplier">0</span> = <span id="showProduct">0</span></p>
</div>
<script src="multiply.js"></script>
multiply() {
var multiplicand = document.getElementById('multiplicand').value;
var multiplier = document.getElementById('multiplier').value;
var showProduct = parseInt(multiplicand) * parseInt(multiplier);
var p = document.getElementById('showProduct');
p.innerHTML += showProduct;
}
You are appending the result to the content of your p tag.
If you just want to show the result, you have to override the innerHTML instead of appending to it.
p.innerHTML = showProduct;
Also, if you want to update the result as you type, use the oninput event instead of onchange which will only trigger when you leave the <input> field.
If you also want to update the multiplier and multiplicand fields, just do the same as for the product:
document.getElementById('showMulipicand').innerHTML = multiplicand;
To avoid NaN problems, when you read the multiplier/multiplicand from the <input>, do a logical or with 0, this way, if the field is blank, its value will be 0.
You should also change the <input> type from text to number.
Here is the code for showing the multiplication result:
function multiply() {
const multiplicand = document.getElementById('multiplicand').value || 0;
const multiplier = document.getElementById('multiplier').value || 0;
const product = parseInt(multiplicand) * parseInt(multiplier);
document.getElementById('showMulipicand').innerHTML = multiplicand;
document.getElementById('showMultiplier').innerHTML = multiplier;
document.getElementById('showProduct').innerHTML = product;
}
<h1>Mutiply</h1>
<p>Multiplicand: <input type="number" id="multiplicand" value="0" oninput="multiply()"></p>
<p>Multiplier: <input type="number" id="multiplier" value="0" oninput="multiply()"></p>
<p>
<span id="showMulipicand">0</span> ×
<span id="showMultiplier">0</span> = <span id="showProduct">0</span>
</p>

Updating Values in HTML output based on changing input

I currently have a set of fields and radio buttons that take in some user input. Here is an example:
<div id="age">
<input type="number" name="age1" value=60>
</div>
I am displaying all the inputted values and want the display to change when the user modifies the input. This is my attempt:
var inputElements = document.querySelectorAll('input');
for(var i = 0, len = inputElements.length ; i < len ; i++) {
inputElements[i].addEventListener('input', updateDisplay());
}
function updateDisplay () {
console.log("test");
var age = document.querySelector('input[name="age1"]').value;
document.getElementById("ageComparison").innerHTML = age;
}
I know that the program enters the method since the "test" message is printed to the console; however, I don't see any change in display according to changes in input. Would appreciate any help.
While creating the eventlistener, you're just calling updateDisplay. Remove the ().
Also, you did not put '#ageComparison' element in your code.
html:
<div id="age">
<input type="number" name="age1" value=60>
</div>
<div id="ageComparison">
</div>
js:
var inputElements = document.querySelectorAll('input');
for (var i = 0; i < inputElements.length; i++) {
inputElements[i].addEventListener('input', updateDisplay);
}
function updateDisplay() {
console.log("test");
var age = document.querySelector('input[name=age1]').value;
document.getElementById("ageComparison").innerHTML = age;
}
Example: https://jsfiddle.net/m6r871t6/
Try avoiding the inner double quotes
var age = document.querySelector('input[name=age1]').value;
try using
inputElements[i].addEventListener('change', updateDisplay())

5 radio buttons fill up randomly?

Hi I am trying to make five buttons as you can see and I want a function when you push "click me" it will fill up the five button randomly.
It's like a random generator for stats for a game.
I don't know if I'm doing it all wrong but I think I need some other coding for this.
Can anyone that can help me?
This is what I have:
<button onclick='myFunction()'>click me</button>
<div id="demo">
<Input type = radio Name = r1>
<Input type = radio Name = r2>
<Input type = radio Name = r3>
<Input type = radio Name = r4>
<Input type = radio Name = r5>
</div>
<script type="text/javascript">
function myFunction() {
document.getElementById('demo').innerHTML = '';
var num = 3;
var noOfButtons = Math.floor(Math.random() * num);
console.log(noOfButtons);
for (var i = 0; i < noOfButtons; i++) {
var box = document.createElement();
document.getElementById('demo');
}
}
</script>
not exactly sure what your looking for. I threw this JSFiddle together. Take a look and see if its what you're looking for.
<button id='button1'>click me</button>
<div id="demo">
<input type='radio' id='r1'>
<input type='radio' id='r2'>
<input type='radio' id='r3'>
<input type='radio' id='r4'>
<input type='radio' id='r5'>
</div>
.
var button1 = document.getElementById('button1');
button1.onclick = function () {
var noOfButtons = 5;
var pick = Math.floor(Math.random() * noOfButtons) + 1;
var radioBtn = document.getElementById('r' + pick);
radioBtn.checked = true;
}
[edit]
I think what you're trying to do is randomly check a finite number of radios, in which case there's no need to set demo's html to ''. I added the class myRadios to the tags of your radios (just in case there are other radios on the page that you don't want to include in the random checking), and then used the following function:
function myFunction() {
var radios = document.getElementsByClassName('myRadios');
for (var i=0; i<radios.length; i++)
{
radios[i].checked = ( (Math.random()*10) > 5) ? true : false;
}
}
Here is a a working fiddle. Let me know if this is the functionality you were looking for or if you have any questions about how it works :)

Categories