JavaScript - Checkbox loop not totalling up prices correctly - javascript

When I click on the checkbox at the top, it puts a '0' in the total box, so I know that it is connected correctly, however I think there is a problem in the logic in the loop. One of the elements in html looks like this.
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) {
box.dataset.price = totalprice + box.dataset.price;
} //if
} //for
document.getElementsByName("total")[0].value = totalprice;
}
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input type="checkbox" name="event[]" value="11" data-price="35.00"></span>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>

You have no total in the code you provided.
I would personally use ID when only having one element and if more, use relative addressing and/or delegation
const form = document.getElementById('booking');
const total = document.getElementById('total');
document.getElementById("booking").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
} //if
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
<form id="booking" method="get">
<section id="book">
<h2>Select Events</h2>
<div class="item">
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input name="event[]" type="checkbox" value="11" data-price="35.00"></span>
</div>
<div class="item">
<span class="eventTitle">Ash</span>
<span class="eventStartDate">202</span>
<span class="eventEnd">2020-12-31</span>
<span class="catD">Exhib</span>
<span class="venueNa">The Biy</span>
<span class="eventPr">0.00</span>
<span class="chosen"><input type="checkbox" name="event[]" value="17" data-price="10.00"></span>
</div>
</section>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>
</form>

Related

Display Result Not Showing Up

Please help! I was trying to build a mini loan eligibility web app using JavaScript, but my problem is that the display result wasn't showing what it seems to show after clicking on the eligibility button.
Below are my HTML and JavaScript Code.
let Amount = document.querySelector("#amount").value;
let Duration = document.querySelector("#years").value;
let amt = parseInt(Amount);
let dura = parseInt(Duration);
let Message = document.querySelector("#result");
//const Income = parseInt(Amount.value);
//const Years = parseInt(Duration.value);
function eligibility(){
if(amt < parseInt(50000) ){
Message.textContent = "Please! You're not eligible for the loan";
// console.log('Try again')
} else if(amt >= parseInt(50000) ) {
Message.textContent = "Please Fill the form below and apply"
// console.log('Please Fill the form below and apply')
}
}
<html>
<form action="" role="form">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-plus"></span>
</span>
<input type="number" class="form-control" placeholder="Income" id="amount" required />
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-time"></span>
</span>
<input type="number" class="form-control" placeholder="Duration" id="years" required />
</div>
</div>
<button type="" class="btn btn-primary btn-block" onclick="eligibility()">Check Eligibility</button>
<div id="result">
</div>
</form>
</html>
The main issue was you need to declare those input values inside the function your calling on the button click. Or else they will all be set to the the value that they load up as (null)
I changed your some of your code and added comments throughout. Hope this helps
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<html>
<form action="" role="form">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-plus"></span>
</span>
<input type="number" class="form-control" placeholder="Income" id="amount" required />
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">
<span class="glyphicon glyphicon-time"></span>
</span>
<input type="number" class="form-control" placeholder="Duration" id="years" required />
</div>
</div>
<button type="" class="btn btn-primary btn-block" onclick="eligibility()">Check Eligibility</button>
<div id="result">
</div>
</form>
</html>
<script type="text/javascript">
//const Income = parseInt(Amount.value);
//const Years = parseInt(Duration.value);
function eligibility(){
//You need the declare these values inside the function (getting them globally will only get the value they are when page loads up)
let Amount = document.querySelector("#amount").value;
let Duration = document.querySelector("#years").value;
let amt = parseInt(Amount);
let dura = parseInt(Duration);
let Message = document.querySelector("#result");
if(amt < 50000){
Message.innerText = "Please! You're not eligible for the loan";
// console.log('Try again')
}
//Change this else-if to just an else since you are just checking for the exact opposite of your if statement
else{
Message.innerText = "Please Fill the form below and apply"
// console.log('Please Fill the form below and apply')
}
}
//Prevent form from submitted or else page will reload and no message would be shown
document.querySelector('form').addEventListener('submit', (e)=>{
e.preventDefault();
});
</script>
</html>

How to prevent checkbox loop and radio button loop from creating two separate price totals

I have a query selector for checkboxes which works fine and I replicated it for radio button, but I am running into the problem that they are both keeping separate totals. I tried to take the totalPrice variable out of both of them and place it outside so that it would be shared, but that created the problem of the price not being removed from unchecked checkboxes and radio buttons.
This is my current buggy code:
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
document.getElementById("bookingForm").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
}
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
document.getElementById("bookingForm").addEventListener("click", function(e) {
if (e.target.name === "delivery") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=radio]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
}
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="bookEvents">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<input type="radio" name="delivery" value="ticket" data-price="10">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
Just have one event handler and one loop
If you only have data-price on the elements you need to loop, then you can change
[...document.querySelectorAll('input[data-price][type=checkbox], input[data-price][type=radio]')].forEach(function(box) {
to
[...document.querySelectorAll('input[data-price]')].forEach(function(box) {
I just wonder why you have a only a single radio - it cannot be un-selected. Why not another checkbox?
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
form.addEventListener("click", function(e) {
if (e.target.name === "event[]" || e.target.name === "delivery") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=checkbox], input[data-price][type=radio]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
}
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="bookEvents">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<input type="radio" name="delivery" value="ticket" data-price="10">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>

Trying to total price with checkbox loop using JavaScript

My goal is when a checkbox is clicked it's data-price should be added to the total variable and then this variable should be shown in the total price text box, however, it currently doesn't update the value when a checkbox is clicked.
Here is an interactive example of how it currently works/looks:
const form = document.getElementById('bookingForm');
const total = document.getElementsByName[0]('total');
document.getElementById("bookingForm").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let total = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
total += +box.dataset.price;
} //if
})
document.querySelector("[name=total]").innerHTML = total.toFixed(2);
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="bookEvents">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
const form = document.getElementById('bookingForm');
const total = document.getElementsByName('total');
var chksBoxes = document.querySelectorAll('.chkEvent');
chksBoxes.forEach(function(chk) {
chk.addEventListener("click", function(e) {
var total = 0;
chksBoxes.forEach(function(box) {
if (box.checked)
total += +box.dataset.price
});
document.querySelector("[name=total]").value = total.toFixed(2);
});
});
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="bookEvents">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1 </span>
<span class='eventPrice'>Price: 10.50</span>
<span class='chosen'><input type='checkbox' class="chkEvent" name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2 </span>
<span class='eventPrice'>Price: 5.00</span>
<span class='chosen'><input type='checkbox' class="chkEvent" name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
For Input elements you should use value instead of innerHTML
const form = document.getElementById('bookingForm');
const total = document.getElementsByName('total')[0];
document.getElementById("bookingForm").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let total = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
total += +box.dataset.price;
} //if
})
document.querySelector("[name=total]").value = total.toFixed(2);
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="bookEvents">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
PS: You have a typo at line# 2 where document.getElementsByName[0]('total'); should actually be document.getElementsByName('total')[0];

Trying to check if any checkbox on the page is checked

I want to check if any checkbox on the website has been checked when text has been entered in the name text box. I know that the EventListener works for name since this works without the document.getElementsByName("event[]").checked, but how do I make it work for the checkboxes?
document.getElementsByName("name")[0].addEventListener('change', (event) => {
if (event.target.value.length != 0 && document.getElementsByName("event[]").checked ) {
window.alert("checked");
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="Events">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<input type="radio" name="delivery" value="ticket" data-price="10">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
<p>Name<input type="text" name="name"></p>
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
I'd suggest:
document.getElementsByName("name")[0].addEventListener('change', (event) => {
// here we used event.target.value.trim.length in order to guard against
// white-space strings being considered valid (if that's not a problem
// then the trim() method can be removed), and also we used:
// document.querySelector() to find the first of any <input> element
// with a type equal to 'checkbox' which is also checked;
// document.querySelector() returns either the first such element or null:
if (event.target.value.trim().length > 0 &&
document.querySelector('input[type=checkbox]:checked') !== null) {
window.alert("checked");
}
});
document.getElementsByName("name")[0].addEventListener('change', (event) => {
if (event.target.value.trim().length > 0 &&
document.querySelector('input[type=checkbox]:checked') !== null) {
window.alert("checked");
}
})
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="Events">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<input type="radio" name="delivery" value="ticket" data-price="10">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
<p>Name<input type="text" name="name"></p>
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
It's worth adding that your first line could be potentially simplified a little using document.querySelector() rather than using indices:
document.querySelector("input[name=name]").addEventListener('change', (event) => {
if (event.target.value.trim().length > 0 &&
document.querySelector('input[type=checkbox]:checked') !== null) {
window.alert("checked");
}
});
document.querySelector('input[name=name]').addEventListener('change', (event) => {
if (event.target.value.trim().length > 0 &&
document.querySelector('input[type=checkbox]:checked') !== null) {
window.alert("checked");
}
});
<form id="bookingForm" action="javascript:alert('form submitted');" method="get">
<section id="Events">
<h2>Select Events</h2>
<div class='item'>
<span class='eventTitle'>Event number 1</span>
<span class='eventPrice'>10.50</span>
<span class='chosen'><input type='checkbox' name='event[]' value='1' data-price='10.50'></span>
</div>
<div class='item'>
<span class='eventTitle'>Event number 2</span>
<span class='eventPrice'>5.00</span>
<span class='chosen'><input type='checkbox' name='event[]' value='2' data-price='5.00'></span>
</div>
<section id="Cost">
<input type="radio" name="delivery" value="ticket" data-price="10">
<h2>Total Price</h2>
Total Price <input type="text" name="total" size="12">
<p>Name<input type="text" name="name"></p>
</section>
<p><input type="submit" name="submit" value="Book"></p>
</section>
</form>
References:
CSS:
Attribute-selectors ([attribute=attribute-value]).
:checked.
JavaScript:
document.querySelector().
String.prototype.trim()
//--Get all checkboxes, you can have another way of fetching checkboxes
var checkBoxes = document.getElementsByTagName("input");
//--For each checkbox, check if it is selected
for (var i = 0; i < checkBoxes.length; i++) {
if (checkBoxes[i].checked == true) {
alert('checked');
}
}
Use document.querySelectorAll to get an array containing all the checkbox inputs in the document:
var checkboxes = document.querySelectorAll("input[type=checkbox]");
Then, to check if any of the checkboxes are checked:
var anyChecked = false;
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
anyChecked = true;
break;
}
}
Alternatively, if you want an array containing only the checkboxes that are checked, you can do the following:
var checkedCheckboxes = checkboxes.filter(checkbox => checkbox.checked);
document.getElementsByName("name")[0].addEventListener('change', (event) => {
if(event.target.value.length !== 0) {
// Get all checkboxes
const checkboxes = document.getElementsByName("event[]");
for(i=0; i<checkboxes.length; i++) {
// Check if checkbox is checked or not
if(checkboxes[i].checked) {
window.alert("checked");
}
}
}
})

jQuery arranged index input name[?]

I want after remove input arranged index input name, for example:
After remove input row222[2] others input name as: row000[0] & row111[1] & row333[2]
After remove input row333[3] others input name as: row000[0] & row111[1] & row222[2]
After remove input row111[3] others input name as: row000[0] & row222[1] & row333[2]
etc...
What do i do?
DEMO
My full code:
$(document).on('click', '.RemOve', function(e) {
e.preventDefault();
$(this).closest('.CloSe').remove();
$('.CloSe').each(function(idx) {
var Input = $($('.Change input'), this);
Input.each(function(i) {
var str = $(this).attr('name');
var currentIdx = parseInt(str.match(/\d+/)[0], 10);
$(this).attr('name', str.replace(currentIdx, idx));
})
});
$('.CloSe').each(function(){
$('.namein', this).empty().append($(this).find('input').prop('name'))
})
})
.RemOve{
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="CloSe">
<span class="Change">
<b class="namein">rows[0]</b>
<input type="text" name="rows000[0]"> // rows000[0]
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows[1]</b>
<input type="text" name="rows111[1]"> // rows111[1]
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows[2]</b>
<input type="text" name="rows222[2]"> // rows222[2]
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows[3]</b>
<input type="text" name="rows333[3]"> // rows333[3]
</span>
<span class="RemOve">Remove</span>
</div>
I've updated your code, check out here http://jsfiddle.net/chtvfkt2/1/
And I also commented on some of your codes. If there's a specific reason for using the commented codes, just uncomment and use it.
UPDATE
I'm a bit confused by your question. So I split the answers.
If you want to rename the rest of the elements after getting rid of one of them, take this below.
$(document).on('click', '.RemOve', function(e) {
//I see no point in using preventDefault() here ?
//e.preventDefault();
$(this).closest('.CloSe').remove();
$('.CloSe').each(function(idx, element) {
//var Input = $($('.Change input'), this);
//Improved :: better than using 'this'.
var Input = $($('.Change input'), element);
Input.each(function(i, el) {
//Improved :: No point using parseInt and str.replace ?
//var str = $(this).attr('name');
//var currentIdx = parseInt(str.match(/\d+/)[0], 10);
//$(this).attr('name', str.replace(currentIdx, idx));
var numb = i < 99 ? "rows00" + i : "rows0" + i;
if ( i > 100 ) {
numb = "rows" + i;
}
$(el).attr('name', numb);
})
});
$('.CloSe').each(function(){
$('.namein', this).empty().append($(this).find('input').prop('name'))
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="CloSe">
<span class="Change">
<b class="namein">rows000</b>
<input type="text" name="rows000">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows001</b>
<input type="text" name="rows001">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows002</b>
<input type="text" name="rows002">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows003</b>
<input type="text" name="rows003">
</span>
<span class="RemOve">Remove</span>
</div>
Or if you want to just chop one of them off and expect no changes, take this.
$(document).on('click', '.RemOve', function(e) {
$(this).closest('.CloSe').remove();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="CloSe">
<span class="Change">
<b class="namein">rows000</b>
<input type="text" name="rows000">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows001</b>
<input type="text" name="rows001">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows002</b>
<input type="text" name="rows002">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows003</b>
<input type="text" name="rows003">
</span>
<span class="RemOve">Remove</span>
</div>
FINAL UPDATE
Just replcaing display text was what you wanted, this code will do.
$(document).on('click', '.RemOve', function(e) {
$(this).closest('.CloSe').remove();
$('.CloSe').each(function(idx, element) {
//Improved :: better than using 'this'.
var Input = $($('.Change input'), element);
Input.each(function(i, el) {
var numb = i < 99 ? "rows00" + i : "rows0" + i;
if ( i > 100 ) {
numb = "rows" + i;
}
$(el).prev().text(numb);
})
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="CloSe">
<span class="Change">
<b class="namein">rows000</b>
<input type="text" name="rows000">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows001</b>
<input type="text" name="rows001">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows002</b>
<input type="text" name="rows002">
</span>
<span class="RemOve">Remove</span>
</div>
<div class="CloSe">
<span class="Change">
<b class="namein">rows003</b>
<input type="text" name="rows003">
</span>
<span class="RemOve">Remove</span>
</div>

Categories