I have number inputs
number around 30
I need to sum them all to one field
what I have is below
View:
<table>
<tbody>
<tr>
<td><input class="days_tpu" type="number" id="sth_1"></td>
</tr>
<tr>
<td><input class="days_tpu" type="number" id="sth_2"></td>
</tr>
<tr>
<td><input class="days_tpu" type="number" id="sth_3"></td>
</tr>
</tbody>
// field in which it will add up
<tfoot>
<th><input id="id_days_tpu" type="time" type="text"></th>
</tfoot>
</table>
I tried:
I try to take all inputs.
and count by length
and sum them
but, it doesn't work
Javascript:
const days_tpu_s = [...document.getElementsByClassName("days_tpu")];
//or
const table = document.querySelector('table');
table.sumInputs = function () {
var inputs = document.getElementsByClassName('days_tpu'),
result = document.getElementById('sum_id_days_tpu'),
sum = 0;
for (var i = 0; i < inputs.length; i++) {
var ip = inputs[i];
if (ip.name && ip.name.indexOf("total") < 0) {
sum += parseInt(ip.value) || 0;
}
}
result.value = sum;
}
sumInputs();
anyone have a good idea?
You can use Array.prototype.map() to get all the input value the use Array.prototype.reduce() to sum them.
Demo:
const days_tpu_s = [...document.getElementsByClassName("days_tpu")];
function sumInputs() {
var sum = days_tpu_s.map(i => Number(i.value)).reduce((a, c) => a + c, 0);
document.getElementById('id_days_tpu').value = sum;
}
days_tpu_s.forEach(function(el){
el.addEventListener('input', sumInputs);
});
<table>
<tbody>
<tr><td><input class="days_tpu" type="number" id="sth_1"></td></tr>
<tr><td><input class="days_tpu" type="number" id="sth_2"></td></tr>
<tr><td><input class="days_tpu" type="number" id="sth_3"></td></tr>
</tbody>
// field in which it will add up
<tfoot>
<th><input id="id_days_tpu" type="text"></th>
</tfoot>
</table>
Related
I have a table with three columns: id, price and a checkbox. I want to parse the table to JSON but only include rows with a checked checkbox. However, my code throws Uncaught TypeError: Cannot read properties of undefined (reading 'type') in this line: if (ele[i].type == 'checkbox' && ele[i].checked == true). Where am I going wrong?
const btn = document.getElementById("click");
btn.addEventListener("click", function() {
tableToJson(table);
})
let table = document.getElementById("myTable");
function tableToJson(table) {
let data = [];
const ele = document.querySelectorAll(".myCheckbox");
// first row needs to be headers
let headers = [];
for (i = 0; i < table.rows[0].cells.length; i++) {
headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi, '');
}
// go through cells
for (i = 1; i < table.rows.length; i++) {
if (ele[i].type == 'checkbox' && ele[i].checked == true) {
let tableRow = table.rows[i];
let rowData = {};
for (j = 0; j < tableRow.cells.length; j++) {
rowData[headers[j]] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
}
console.log(data);
return data;
}
<body>
<button id="click">Click</button>
<table id="myTable">
<thead>
<tr>
<th>Id</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>12.81</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>BBB</td>
<td>1.06</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>CCC</td>
<td>1.89</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>DDD</td>
<td>1.94</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>EEE</td>
<td>3.61</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
</tbody>
</table>
</body>
As you're iterating on ele.length you should use ele[i].type == 'checkbox'.
Other than that, since you have 5 checkboxes and 6 rows, when you read tableRow you need to add a + 1 otherwise you'll select the wrong row.
In your current code, if you select the first element (index 0) you get the header row (index 0) while you should take index 1 instead.
let tableRow = table.rows[i+1];
const btn = document.getElementById("click");
btn.addEventListener("click", function() {
tableToJson(table);
})
let table = document.getElementById("myTable");
function tableToJson(table) {
let data = [];
const ele = document.querySelectorAll(".myCheckbox");
// first row needs to be headers
let headers = [];
for (i = 0; i < table.rows[0].cells.length; i++) {
headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi, '');
}
// go through cells
for (i = 0; i < ele.length; i++) {
if (ele[i].type == 'checkbox' && ele[i].checked == true) {
let tableRow = table.rows[i+1];
let rowData = {};
for (j = 0; j < tableRow.cells.length; j++) {
rowData[headers[j]] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
}
console.log(data);
return data;
}
<body>
<button id="click">Click</button>
<table id="myTable">
<thead>
<tr>
<th>Id</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>12.81</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>BBB</td>
<td>1.06</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>CCC</td>
<td>1.89</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>DDD</td>
<td>1.94</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
<tr>
<td>EEE</td>
<td>3.61</td>
<td><input type="checkbox" class="myCheckbox" checked></td>
</tr>
</tbody>
</table>
</body>
first I do not know where you aré importing your js.
Second javascript Is faster than the dom so by the time you r js gets into if (ele[i].type == 'checkbox' && ele[i].checked == true) your dom Is not rendered yet. Thats y it breaks you need to wait for your dom to be rendered.
document.addEventLidtener("DOMContentLoaded", e=>{
// Add your code here
});
I'm very new to JS and I'm trying to learn for loops and in this case, I want to turn this into a for loop if possible. I want to calculate a static number string in cell 3, times the input number in cell 4, and output the result to a new cell 5 that has been created in the loop. Any help is much appreciated
var table = document.getElementById("table");
var Row1 = table.rows[1],
cell1 = Row1.insertCell(5);
var Row2 = table.rows[2],
cell2 = Row2.insertCell(5);
var Row3 = table.rows[3],
cell3 = Row3.insertCell(5);
var Row4 = table.rows[4],
cell4 = Row4.insertCell(5);
var Row5 = table.rows[5],
cell5 = Row5.insertCell(5);
var Row6 = table.rows[6],
cell6 = Row6.insertCell(5);
var x1 = table.rows[1].cells[4].getElementsByTagName('input')[0].value;
var y1 = table.rows[1].cells[3].innerHTML;
cell1.innerHTML = y1 * x1;
var x2 = table.rows[2].cells[4].getElementsByTagName('input')[0].value;
var y2 = table.rows[2].cells[3].innerHTML;
cell2.innerHTML = y2 * x2;
var x3 = table.rows[3].cells[4].getElementsByTagName('input')[0].value;
var y3 = table.rows[3].cells[3].innerHTML;
cell3.innerHTML = y3 * x3;
var x4 = table.rows[4].cells[4].getElementsByTagName('input')[0].value;
var y4 = table.rows[4].cells[3].innerHTML;
cell4.innerHTML = y4 * x4;
var x5 = table.rows[5].cells[4].getElementsByTagName('input')[0].value;
var y5 = table.rows[5].cells[3].innerHTML;
cell5.innerHTML = y5 * x5;
var x6 = table.rows[6].cells[4].getElementsByTagName('input')[0].value;
var y6 = table.rows[6].cells[3].innerHTML;
cell6.innerHTML = y6 * x6;
These don't need to be in functions but just to make it easier to read
function createCells() {
cells = []
for (let i = 1; i < 7; i++) {
var cells[i] = table.rows[i].insertCell(5)
}
}
function calculate() {
for
let (i = 1; i < 7; i++) {
var x = table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y = table.rows[i].cells[3].innerHTML;
cells[i].innerHTML = (y * x);
}
}
A short answer using a simple for-loop is this:
Loop through every row
For each row, multiply quantity with price
Output total in same row
Since we basically always want to have a "total"-field in every row, we can add it in the HTML directly.
And since we know the position of the price-element and quantity-element, we can access them using fixed values as indices.
var rows = document.querySelectorAll("#pricetable tbody tr");
for (var i = 0; i < rows.length; ++i) {
var price = rows[i].children[3].innerHTML;
var quantity = rows[i].children[4].children[0].value;
var total = price * quantity; // Implicit type-casting to numbers
rows[i].children[5].innerHTML = total;
}
<table id="pricetable">
<thead>
<tr>
<th>Number</th>
<th>Product</th>
<th>Brand</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>23456789</td>
<td>Phone</td>
<td>Apple</td>
<td>6500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>22256289</td>
<td>Phone</td>
<td>Samsung</td>
<td>6200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>24444343</td>
<td>Phone</td>
<td>Huawei</td>
<td>4200</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>19856639</td>
<td>Tablet</td>
<td>Apple</td>
<td>4000</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>39856639</td>
<td>Tablet</td>
<td>Samsung</td>
<td>2800</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
<tr>
<td>12349862</td>
<td>Tablet</td>
<td>Huawei</td>
<td>3500</td>
<td>
<input type="text" size="3" value="1" />
</td>
<td></td>
</tr>
</tbody>
</table>
Note: When changing the position of those elements (e.g. by add a new column infront of them), their index would shift. That would make you have to update the indices in the JS-file manually.
You can make this easier for yourself by using this simple "trick":
Add specific classes to the elements (e.g. .price, .quantity, .total), allowing you to easily find them using Element.querySelector().
Note: The script only runs once, the first time the page is loaded. That means, inputting a different quantity won't update the "total"-field. For that, we need an EventListener.
Another approach
By observing the for-loop, we can see:
We access only one row for each iteration
The order in which we access each row is irrelevant
Since both these points are checked, we can use a for...of-loop (also called foreach-loop or enhanced for-loop). A for...of-loop is (in my opinion) easier to read, and tells what we checked using the list above by itself.
Note: Be wary of the difference of the for...of-loop and the for...in-loop.
Now, we could calculate the total right then and there in the loop, but thinking ahead, we want to perform the same calculation again when inputting a new quantity-value. We can reduce the duplicate code by making the calculation a Function updateRowTotal(), making the code easier to debug and understand.
To actually update the total when entering a new quantity-value, we can use an EventListener that calls a function automatically when a new value is entered into the <input>-field (by calling updateRowTotal(evt.target.closest("tr"))).
function clamp(min, value, max) {
return Math.max(min, Math.min(value, max));
}
for (let row of document.querySelectorAll("#pricetable tbody tr")) {
updateRowTotal(row);
row.querySelector("input.quantity").addEventListener("input", evt => {
// Add '/*' before this comment to "remove" this extra part
// The 5 lines below are to clamp 'value' between 'min' and 'max'
let min = parseInt(evt.target.getAttribute("min"));
let max = parseInt(evt.target.getAttribute("max"));
if (isNaN(min)) min = Number.MIN_SAFE_INTEGER;
if (isNaN(max)) max = Number.MAX_SAFE_INTEGER;
evt.target.value = clamp(min, evt.target.value, max);
// */
updateRowTotal(evt.target.closest("tr"));
});
}
function updateRowTotal(row) {
row.querySelector(".total").innerHTML = row.querySelector(".price").innerHTML * row.querySelector(".quantity").value;
}
<table id="pricetable">
<thead>
<tr>
<th>Price</th>
<th>Quantity</th>
<th>Row-Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="price">6500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">6200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4200</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">4000</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">2800</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
<tr>
<td class="price">3500</td>
<td>
<input class="quantity" type="number" min="0" max="999" value="1" />
</td>
<td class="total"></td>
</tr>
</tbody>
</table>
Sidenote
Making the <input>-field of type="number" prevents any non-numeric character to be entered.
And since the min- and max-attributes only prevent form-submission, we have to code the value-clamping ourselves. This is easily done by reading the values of the attributes and clamping the value to their defined range. Note that we have added default values for both min and max, being the lower-most and upper-most safe integer-value.
You can use for-loops like the one given below. Looks like you are operating on numbers, so I have added a + in front of x1's and y1's assignment to implicitly type-cast them to numbers.
for(var i = 1; i <= 6; i++) {
var firstRow = table.rows[i], cell = firstRow.insertCell(5);
var x1 = +table.rows[i].cells[4].getElementsByTagName('input')[0].value;
var y1 = +table.rows[i].cells[3].innerHTML;
cell.innerHTML = y1 * x1;
}
HTML:
<table id="tbl" border="1">
<tr>
<th>Name</th>
<th>Mark1</th>
<th>Mark2</th>
<th>Total</th>
</tr>
<tr>
<td><input type="text"></td>
<td><input type="text" class="cell"></td>
<td><input type="text" class="cell"></td>
<td><b><span id="total_sum_value"></span></b></td>
<td><b><span id="total_sum_value1"></span></b></td>
<th><input class="add-row" data-id="1" type="button" value="+"></th>
</tr>
</table>
JavaScript:
$(document).ready(function(){
var i = $(".add-row").data("id");
$(".add-row").click(function(){
$('#tbl').append('<tr><td><input type="text"></td><td><input type="text"></td><td><input type="text"></td></tr>');
var two = $("input").addClass("cell"+i);
$("#tbl").on('input','.cell'+i,function(){
var sum1 = 0;
$(".cell"+i).each(function() {
var get_val = $(this).val();
sum1 += parseFloat(get_val);
});
$("#total_sum_value1").html(sum1);
});
i++;
});
$("#tbl").on('input','.cell',function(){
var sum = 0;
$('.cell').each(function(){
var get_val = $(this).val();
sum += parseFloat(get_val);
});
$("#total_sum_value").html(sum);
});
});
When you click on the plus sign button, it generates three textboxes. I want to calculate the sum of those textboxes and print it in a span.
Here is a CodePen of my code: https://codepen.io/anon/pen/XBqKVZ?editors=1010
can you try like this:
$('.cell').on('change', function(){
var sum = 0;
var data ={
}
$('.cell').each(function(index, item){
var val = $(item).val();
var get_val = $(this).val();
sum += Number(get_val);
console.log(sum);
});
$("#total_sum_value").html(sum);
});
URL: Jsfiddle
I want to copy and paste excel columns or any similar lists into HTML table. I have found this code, but there is an issue. It pastes data like a row. So how can I change It to paste like a column? Thanks in advance.
$(document).ready(function() {
$('td input').bind('paste', null, function (e) {
$this = $(this);
setTimeout(function () {
var columns = $this.val().split(/\s+/);
var i;
var input = $this;
for (i = 0; i < columns.length; i++) {
input.val(columns[i]);
if( i % 3 !== 2){
input = input.parent().next().find('input');
} else{
input = input.parent().parent().next().find('input');
}
}
}, 0);
});
} );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
</thead>
<tbody>
<tr>
<td><input type="text"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td><input type="text"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td><input type="text"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
</tbody>
</table>
Here is solution for you:
$(document).ready(function() {
$('td input').bind('paste', null, function(e) {
$input = $(this);
setTimeout(function() {
var values = $input.val().split(/\s+/),
row = $input.closest('tr'),
col = $input.closest('td').index();
console.log(col);
for (var i = 0; i < values.length; i++) {
row.find('input').eq(col).val(values[i]);
row = row.next();
}
}, 0);
});
});
My function will succesfully load the dropdown values but fails to load any of the input text values. I just get an output showing blank input boxes so it's not picking up what type of input it is.
$(document).ready(function () {
$('#clicker').on('click', function (e) {
var tableToObj = function (table) {
var trs = table.rows, //replacing , with ; at end of each line
trl = trs.length,
i = 0,
j = 0,
keys = [],
obj, ret = [];
for (; i < trl; i++) {
if (i === 0) {
// var sel = $(trs[i].children[j]).find('select');
//changed from input
for (; j < trs[i].children.length; j++) { //removed ; from (;
var sel = $(trs[i].children[j]).find('select'); //same as below
if (sel.length === 0) {
keys.push(trs[i].children[j].innerHTML);
} else {
keys.push(sel.find('option:selected').val());
}
var input = trs[i].children[j].value;
}
} else {
obj = {};
for (j = 0; j < trs[i].children.length; j++) { //this works j = 0;
var sel = $(trs[i].children[j]).find('select'); //replaced " with ' around select
if (sel.length === 0) {
obj[keys[j]] = trs[i].children[j].innerHTML;
} else {
obj[keys[j]] = sel.find('option:selected').val();
}
var input = trs[i].children[j].value;
}
ret.push(obj);
}
}
return ret;
};
document.getElementById('r').innerHTML = JSON.stringify(tableToObj(document.getElementById('myTable')));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<thead>
<tr>
<th>FirstColumn</th>
<th>SecondColumn</th>
<th>ThirdColumn</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select><option value="tr1">tr1</option><option value="tr2">tr2</option><option value="tr3">tr3</option><option value="tr4">tr4</option></select></td>
<td>1</td>
<td>
<select><option value="tr1">tr1</option><option value="tr2">tr2</option><option value="tr3">tr3</option></select></td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>
<select><option value="tr1">tr1</option><option value="tr2">tr2</option><option value="tr3">tr3</option><option value="tr4">tr4</option></select></td>
</tr>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td>
<select><option value="tr1">tr1</option><option value="tr2">tr2</option><option value="tr3">tr3</option></select></td>
</tr>
<tr>
<td>
<input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td>
<select><option value="tr1">tr1</option><option value="tr2">tr2</option><option value="tr3">tr3</option></select></td>
</tr>
</tbody>
</table><input type="button" id="clicker" value="Click Me"/>
<br/> Result:
<fieldset id="r">
</fieldset>
<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false" unselectable="on">
<div class="ms-rtestate-notify ms-rtestate-read 9622406d-82bb-4b09-8e13-8fb81e9da538" id="div_9622406d-82bb-4b09-8e13-8fb81e9da538" unselectable="on">
</div>
<div id="vid_9622406d-82bb-4b09-8e13-8fb81e9da538" unselectable="on" style="display: none;">
</div>
</div><br/>
My current OBJ output is:
[{"FirstColumn":"tr1","SecondColumn":"1","ThirdColumn":"tr1"},{"FirstColumn":"1","SecondColumn":"2","ThirdColumn":"tr1"},{"FirstColumn":"","SecondColumn":"","ThirdColumn":"tr1"},{"FirstColumn":"\n ","SecondColumn":"","ThirdColumn":""},{"FirstColumn":"","SecondColumn":"","ThirdColumn":"tr1"}]