How to sum value of checked changed checkbox jquery? - javascript

I have a table, each checkbox contains a value, and I want to sum value of the checkbox.
Example:
Candy and Water is checked : count = 2 , Candy, food and water is checked : count = 5 , checkbox is unchecked : count = 0 .
I think i must two event , event of each checkbox (.checkbox1) and event of checkbox (.check_all).
Javascript
var count = 0;
$(".checkbox1").change(function() {
var table_abc = document.getElementsByClassName("checkbox1");
for (var i = 0; table_abc[i]; ++i) {
if (table_abc[i].checked) {
count += table_abc[i].value;
}
}
});
alert(count);
HTML
<table id="div_table">
<thead>
<tr>
<th><input type="checkbox" class="check_all" id="chk_all" /></th>
<th>Check All</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" class="checkbox1" id="candy" value="2" /></td>
<td>Candy</td>
</tr>
<tr>
<td><input type="checkbox" class="checkbox1" id="food" value="3" /></td>
<td>Food</td>
</tr>
<tr>
<td><input type="checkbox" class="checkbox1" id="water" value="0" /></td>
<td>Water</td>
</tr>
</tbody>
</table>
But it seems not working. Can you tell me how to wrong?

here is your script, a little bit improved
i'm using here the jquery .prop() method to get the checked property of each element,
and instead of performing concatenation directly with the value of count
you have to use Number(number) or parseInt(number,base) in order to tell js engine, hey i want it to be an arithmetic operation and not a concatenation
here is your snippet of code improved :
$(document).ready(function(){
var count;
$(".checkbox1").change(function() {
count = 0;
var table_abc = $('.checkbox1');
for (var i = 0; i < table_abc.length ; ++i) {
if ($(table_abc[i]).prop('checked')) {
count += parseInt($(table_abc[i]).val(),10);
}
}
console.log(count);
});
});
we are logging to the screen the value of count each time a checkbox(with class checkbox1) state is changed

First I moved declaration of variable count inside the change function to avoid invalid value in repeating the checked-unchecked
Then you should cast the value of checkbox to a numeric so your summation gives correct values
check this fiddle, it works

Use below snippets of code
var count = 0;
$('input[type="checkbox"]').on("change", function() {
count = 0;
if($(this).hasClass('check_all')){
$('input[type="checkbox"][class="checkbox1"]').prop('checked',true);
$('input[type="checkbox"][class="checkbox1"]').each(function(){
count += parseInt($(this).val());
});
}else{
$('input[type="checkbox"]:checked').each(function(){
count += parseInt($(this).val());
});
}
alert(count);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table id="div_table" >
<thead>
<tr>
<th><input type="checkbox" class="check_all" id="chk_all" /></th>
<th>Check All</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" class="checkbox1" id="candy" value="2" /></td>
<td>Candy</td>
</tr>
<tr>
<td><input type="checkbox" class="checkbox1" id="food" value="3" /></td>
<td>Food</td>
</tr>
<tr>
<td><input type="checkbox" class="checkbox1" id="water" value="0" /></td>
<td>Water</td>
</tr>
</tbody>
</table>

Your javascript code seems wrong. Try following
$(document).ready(function(){
$(".checkbox1").change(function() {
var count = 0;
var table_abc = document.getElementsByClassName("checkbox1");
for (var i = 0; table_abc[i]; ++i) {
if (table_abc[i].checked) {
count += parseInt(table_abc[i].value);
}
}
alert(count);
});
});

You can easily iterate over all your checkboxes using the jquery .each function like this:
(function($){
$("input[name='opt']").change(function() {
count = 0;
$("input[name='opt']").each(function(index, checkbox){
if(checkbox.checked)
count += parseInt(checkbox.value) // convert to integer
})
alert(count);
});
})(jQuery);
Few things to pay attention to:
$("input[name='opt']").change binds all the input checkboxes with name='opt' to the provided event handler.
The count variable is moved inside the change event handler, because it needs to be reset to 0 and re-calculated everytime a checkbox is changed.
$("input[name='opt']").each(function(index, checkbox) iterates through all the input checkboxes with name='opt'.
To correctly sum the values, you will need to use parseInt to convert your string value to integer.
Instead of using class="checkbox1", I use name='opt' in my codes to group all the checkboxes together.
Check out this fiddle for complete HTML and JS codes.

Related

Where do I implement the getElementById in my JavaScript function?

Background: For my website I have to count the number of checked checkboxes in a table. Depending on the result, there is then a different 'output'. As long as fewer than or equal to 2 checkboxes are checked --> output A. If more than 2 boxes are checked OR the first checkbox is checked --> output B.
Now to my problem: I specifically don't understand this line of code:
const checked = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
If I understand correctly, it checks all input fields in the form, adds and converts the results. But how can I implement an ID here that I only give to the first checkbox in order to solve the problem?
And another question: Can I then link the values ​​with a logical operator?
My code:
.hide {
display: none;
}
<form id="listForm">
<table>
<tbody>
<tr id="G">
<td><b>G</b></td>
<td></td>
<td><input type="checkbox" class="choice" id="cbg" name="choiceG" value="1"></td>
</tr>
<tr>
<td id="A"><b>A</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceA" value="1"></td>
</tr>
<tr>
<td id="B"><b>B</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceB" value="1"></td>
</tr>
<tr>
<td id="C"><b>C</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceC" value="1"></td>
</tr>
<tr>
<td colspan="2" ;="" style="text-align:right;"><b>Sum:</b></td>
<td><input disabled="" type="text" size="2" name="total" id="total" value="0"></td>
</tr>
</tbody>
</table>
</form>
<div id="showwhen2" class="hide">
<p>2 or less boxes checked; first box is unchecked</p>
</div>
<div id="showwhen3" class="hide">
<p>first box or more than two boxes are checked</p>
</div>
<script>
document.getElementById("listForm").addEventListener("input", function() {
let sum = 0;
let sumg = 0;
const checked = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
const checkedg = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
if (checked.length > 0) sum = checked.reduce((a, b) => a + b);
if (checkedg.length > 0) sumg = checkedg.reduce((a, b) => a + b);
console.log(sum);
console.log(sumg);
document.getElementById("total").value = sumg + sum;
document.getElementById("showwhen3").classList.toggle("hide", sum < 3 || sumg <1);
document.getElementById("showwhen2").classList.toggle("hide", sum > 2);
});
</script>
This seems really overcomplicated.
const checkedCount = this.querySelectorAll(".choice:checked").length
if (checkedCount > 2 || this.querySelector('input#cbg').checked) {
//output B
} else {
//output A
}
querySelectorAll returns a list of all elements that match the selector (i. e. all checked inputs) and querySelector just one element. # is selector syntax for element ids.

Return Value of JavaScript function

I'm pretty new to HTML and JavaScript. I have a table, where I can click on checkboxes. A JavaScript funtion is calculating the sum of the checked boxes and gives the result in a html text field. So far so good.
Now I want to hide code or not, whether the result is lower than 2 or higher, but I don't know which value I can use to check (in the script and the html).
Which value does the function hand over? How is it called?
How can I make sum a global variable without destroying the function?
My code:
function checkTotal() {
var sum = 0;
document.listForm.total.value = '';
for (i = 0; i < document.listForm.choice.length; i++) {
if (document.listForm.choice[i].checked) {
sum = sum + parseInt(document.listForm.choice[i].value);
}
}
document.listForm.total.value = sum;
}
//alert ("Summe: " + ???);
<table>
<form name="listForm">
<tr>
<td>A</td>
<td>Inhalt 1</td>
<td><input type="checkbox" name="choice" value="1" onchange="checkTotal()" /></td>
</tr>
<tr>
<td>B</td>
<td>Inhalt 2</td>
<td rowspan="2" ;> <input type="checkbox" name="choice" value="1" onchange="checkTotal()" /></td>
</tr>
<tr>
<td>Summe:</td>
<td><input disabled type="text" size="2" name="total" value="0" /></td>
</tr>
</form>
</table>
In your javascript file, if your make a variable called total and put it outside of your method, you can then update that value every time checkTotal is run.
So:
var total;
function checkTotal() {
var sum = 0;
for (i = 0; i < document.listForm.choice.length; i++) {
if (document.listForm.choice[i].checked) {
sum = sum + parseInt(document.listForm.choice[i].value);
}
}
total = sum;
}
function getTotal() {
return total;
}
Then in your html, you can call getTotal(), which will return whatever number total is set to.
Which value does the function hand over?
None, Your function is not returning any value so there is no handing over anything. If you, however, want to return any value you can do so by the return statement.
ie:
function checkTotal() {
var sum = 0;
document.listForm.total.value = '';
for (i = 0; i < document.listForm.choice.length; i++) {
if (document.listForm.choice[i].checked) {
sum = sum + parseInt(document.listForm.choice[i].value);
}
}
document.listForm.total.value = sum;
return sum;
}
So when you call the function you can save its return value
Like :
var total = checkTotal();
How is it called?
Currently its being called using event listener attribute. ie. onChange
its like doing this in javascript
document.querySelectorAll('input[type="checkbox"]')
.forEach(function(){
this.addEventListener("change", checkTotal)
})
How can I make sum a global variable without destroying the function?
You just have to declare the var sum = 0; outside the function in a global scope like this
var sum = 0;
function checkTotal() {
sum = 0;
document.listForm.total.value = '';
for (i = 0; i < document.listForm.choice.length; i++) {
if (document.listForm.choice[i].checked) {
sum = sum + parseInt(document.listForm.choice[i].value);
}
}
document.listForm.total.value = sum;
}
any function in javascript inherit the scope from its parents too so anything available before the function is declared, is also available inside the function (unlike php).
A note though: variables declared using let and const are block scoped. Meaning: they can’t be accessed from outside their immediate enclosing {...}
Putting everything together and correcting some errors
The final code looks like this.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form name="list-form">
<table>
<tr>
<td>A</td>
<td>Inhalt 1</td>
<td><input type="checkbox" name="Inhalt_1" value="1"></td>
</tr>
<tr>
<td>B</td>
<td>Inhalt 2</td>
<td><input type="checkbox" name="Inhalt_2" value="1"></td>
</tr>
<tr>
<td>Total:</td>
<td colspan="2"><input disabled type="text" id="total" name="total" value="0" /></td>
</tr>
</table>
</form>
<script src="path/to/your/js/file.js" type="text/javascript"></script>
</body>
</html>
JS
var checkboxes = document.forms[0].querySelectorAll('input[type="checkbox"]'),
inpTotal = document.getElementById('total'),
sum = 0;
// first we define the checkTotal
function checkTotal() {
sum = 0;
checkboxes.forEach(el => {
if (el.checked) sum += +el.value;
});
inpTotal.value = sum;
// alert(sum);
}
// then we add the event listeners
checkboxes.forEach(el => el.addEventListener("change", checkTotal));
PS: It is a good practice to put all your javascript in a seperate file from the html where possible.
Have a go at this.
I know it is a little complex but it is good practice
I fixed your illegal HTML and moved the inline event handlers to one eventListener
I gave the form an ID, using name is obsolete and not useful
If you plan to submit the form, you will need to rename one of the checkboxes or if you use PHP on the server, add [] to the name to make an array
Here I renamed them and gave them a class to use for the selector
document.getElementById("listForm").addEventListener("input", function() {
let sum = 0;
const checked = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value); // get all values from checked and convert to number
if (checked.length > 0) sum = checked.reduce((a, b) => a + b); // sum them
console.log(sum)
document.getElementById("total").value = sum; // show value
document.getElementById("showwhen2").classList.toggle("hide", sum < 2); // unhide when >= 2
});
.hide {
display: none;
}
<form id="listForm">
<table>
<tbody>
<tr id="A" +>
<td>A</td>
<td>Inhalt 1</td>
<td><input type="checkbox" class="choice" name="choiceA" value="1" /></td>
</tr>
<tr>
<td id="B">B</td>
<td>Inhalt 2</td>
<td><input type="checkbox" class="choice" name="choiceB" value="1" /></td>
</tr>
<tr>
<td>Summe:</td>
<td><input disabled type="text" size="2" name="total" id="total" value="0" /></td>
</tr>
</tbody>
</table>
</form>
<div id="showwhen2" class="hide">Equal 2</div>

Dragging a html table column value and increment the column value by 1 in java script

I need to increment an html table column value by 1.
For example, I have three columns in the table and the column value for the first row is 1, the second should be 2 etc.
So, If I have Roll No column with first column value is 1 then the next two rows Roll No value should be 2 and 3.
The following script does not work.
<!DOCTYPE html>
<html>
<head>
<script>
function myFunction() {
//document.getElementById('info').innerHTML = "";
var myTab = document.getElementById('sample_table');
var rollNo=document.getElementById('input2').value;
// LOOP THROUGH EACH ROW OF THE TABLE AFTER HEADER.
var count=0;
for (var i = 1; i < myTab.rows.length; i++) {
// GET THE CELLS COLLECTION OF THE CURRENT ROW.
var objCells = myTab.rows.item(i).cells;
// LOOP THROUGH EACH CELL OF THE CURENT ROW TO READ CELL VALUES.
for (var j = 0; j < objCells.length; j++) {
count++;
//alert('hi'+count);
if(count>1){
myTab.rows[i].cells[j+1].innerHTML=rollNo+1;
}
}
}
}
</script>
</head>
<body onload="myFunction()">
<table id='sample_table'>
<tr>
<th> Name</th>
<th> Roll No</th>
</tr>
<tr>
<td><input id='input1' value='abc' readonly></td>
<td><input id='input2' value='1' ></td>
</tr>
<tr>
<td><input id='input3' value='def' readonly></td>
<td><input id='input4' ></td>
</tr>
<tr>
<td><input id='input5' value='xyz' readonly></td>
<td><input id='input6' ></td>
</tr>
</table>
</body>
</html>
You can get all the inputs in a column using querySelectorAll, like this:
document.addEventListener('DOMContentLoaded', function() {
// Collects all the inputs from the 2nd column
const inputs = document.querySelectorAll('#sample_table td:nth-child(2) input');
// Get the value of the first input in the collection, and convert it to number
const first = +inputs[0].value;
// Iterate through the inputs in the collection excluding the first one
for (let n = 1, eN = inputs.length; n < eN; n++) {
inputs[n].value = first + n;
}
});
<table id="sample_table">
<tr>
<th> Name</th>
<th> Roll No</th>
</tr>
<tr>
<td><input id="input1" value="abc" readonly></td>
<td><input id="input2" value="5"></td>
</tr>
<tr>
<td><input id="input3" value="def" readonly></td>
<td><input id="input4"></td>
</tr>
<tr>
<td><input id="input5" value="xyz" readonly></td>
<td><input id="input6"></td>
</tr>
</table>
If the column of the inputs is changed, the number in nth-child() can be changed to point to the correct column. This indexing is 1-based.
I'm guessing something like
rowspan="2"
or
colspan="2"
but we need the code the image is good for reference but we need something to work with.

How can i wait until all table rows in the 1st column is 100 to display "done" in the 2nd column

I have a table which the number of row is dynamic depends on database record. So regardless of the no of table row, when all the rows in the first column is 100, all rows in the 2nd column will display "done".
Right now, when i input 100 in the 1st row, all rows in the 2nd column will display "done". How can i wait until all rows in the 1st column is 100 to display "done"
$(".test").on('keyup', function() {
var set = $('.test').val();
if (set == 100 ) {
$('.result').val("done");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<table>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
Here is one-of-the-ways to achieve it. Instead of keyup, you use input event.
On every event, you check if all input fields have values or not.
If all fields have values, check if all have values as 100 or not.
$(".test").on('input', function() {
checkAndUpdateSecondColumn();
});
function checkAndUpdateSecondColumn() {
var empty = $("input.test").filter(function() {
return this.value != "";
});
if ($("input.test").length == empty.length) {
var sum = $('.test').toArray().reduce(function(sum, element) {
return sum + Number(element.value);
}, 0);
$('.result').val('');
if (sum == $("input.test").length * 100) {
$('.result').val('done');
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<table>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
<tr>
<td><input type="number" class="test">
<td><input type="text" class="result">
</tr>
The problem with your code is that when you assign your variable set, you are attempting to read the .val() of a jQuery collection containing multiple DOM elements. The value of the first matching element is returned; the others are not evaluated.
It sounds like what you want to do is evaluate the entire set and make certain that all match your desired value before displaying a "done" message. One way to achieve this behavior is by filtering against the values of every element in the jQuery collection (every element of class "test").
var testInputs = $('.test');
var desiredValue = 100;
testInputs.on('keyup', function() {
var testInputsSetToDesiredValue = testInputs.filter(function() {
return parseInt(this.value, 10) === desiredValue;
});
if (testInputsSetToDesiredValue.length === testInputs.length) {
$('.result').val('done');
}
});

Select all checkboxes JS toggle issue

Hoping someone can help me overcome my Javascript ignorance.
I've got a form that includes checkboxes and I've got a piece of JS that toggles selecting/deselecting all the boxes. And so far, it all works as expected.
The wrench in the works is that I've got multiple groups of checkboxes in this form and I would like to select/deselect by group, not all the checkboxes in the form. This is a sample of the php and html. As you can see, the form is in a table and there is a checkbox in the header row that performs the action. 'resources_req' is the name of the checkbox element in the form
<form method="post" name="add_reservation">
<?php for($x=0; $x<count($groups); $x++) : // make seperate display for each group ?>
<div class="group_<?php echo $group_label; ?>">
<table class="res">
<tr>
<!-- form: checkbox all -->
<?php if($make_res == 'enter') : // adds checkbox to check all ?>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<?php endif; ?>
<!-- end form: checkbox all -->
</tr>
...
foreach($resources as $resource) { // for each resource/laptop
$form_start = '<td>';
$form_start .= '<input type="checkbox" name="resources_req[]" value="'.$resource['id'].'"';
$form_start .= ' />';
$form_start .= '</td>';
}
...
</table>
</div>
<?php endfor; // loop for each group ?>
<input type="submit" name="add_reservation" value="Make this reservation" />
</form>
Here is the JS being called:
function toggle(source, element) {
checkboxes = document.getElementsByName(element);
for(var i in checkboxes)
checkboxes[i].checked = source.checked;
}
Best I can put together, the 'this' in the script call is referring to the form. I thought if maybe I put each of these groups in to their own div class, I could then somehow refer to just that but now I'm just lost. Any help or suggestions appreciated!
EDIT: I asked for suggestions and it's been suggested I post only the html:
<form method="post" name="add_reservation">
<div class="group_A">
<table>
<tr>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<th>Name</th>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="1" /></td>
<td>John</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="2" /></td>
<td>Bill</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="3" /></td>
<td>Fred</td>
</tr>
</table>
</div>
<div class="group_b">
<table>
<tr>
<th><input type="checkbox" onClick="toggle(this, 'resources_req[]')" /></th>
<th>Name</th>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="4" /></td>
<td>George</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="5" /></td>
<td>Tom</td>
</tr>
<tr>
<td><input type="checkbox" name="resources_req[]" value="6" /></td>
<td>Raymons</td>
</tr>
</table>
</div>
<input type="submit" name="add_reservation" value="Make this reservation" />
</form>
I changed a few things:
First, instead of passing the value of name, I'm passing the tagName of 'input' instead.
<input type="checkbox" onClick="toggle(this, 'input')" />
Then in the toggle() function, I select the parentNode of the source element, and do a getElementsByTagName() so that I only get the input elements in the local div.
Also, I changed the for-in loop to a standard for loop, which is the proper type of loop to iterate over indexed elements. The for-in can actually give some problems.
function toggle(source, element) {
var checkboxes = source.parentNode.getElementsByTagName(element);
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Live Example: http://jsfiddle.net/37mT2/
Alternatives:
Instead of parentNode, select the ancestor <div> element by assigning it an ID, and passing it to your toggle() function.
<input type="checkbox" onClick="toggle(this, 'input', 'someUniqueId_1')" />
<input type="checkbox" onClick="toggle(this, 'input', 'someUniqueId_2')" />
function toggle(source, element, id) {
var checkboxes = document.getElementById( id ).getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Or you could traverse up the parent nodes until you reach your first <div> element:
<input type="checkbox" onClick="toggle(this, 'input')" />
function toggle(source, element) {
while( source && source = source.parentNode && source.nodeName.toLowerCase() === 'div' ) {
; // do nothing because the logic is all in the expression above
}
var checkboxes = source.getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
Or you could give the <div> elements at that level a common class name and traverse up the parent nodes until you reach that class. In the code below, your <div> elements class is "someClassName":
<input type="checkbox" onClick="toggle(this, 'input')" />
function toggle(source, element) {
while( source && source = source.parentNode && source.className === 'someClassName' ) {
; // do nothing because the logic is all in the expression above
}
var checkboxes = source.getElementsByTagName('input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = source.checked;
}
}
EDIT: Fixed a typo. I had getElementsById instead of getElementById.
Best I can put together, the 'this' in the script call is referring to the form. I thought if maybe I put each of these groups in to their own div class, I could then somehow refer to just that but now I'm just lost. Any help or suggestions appreciated!
http://jsfiddle.net/JG4uf/
JavaScript Loops: for...in vs for

Categories

Resources