Creating object property with array values from the DOM - javascript

I'm creating a new table from reading the DOM by having trouble with the object creation. Right now, I'm able to get it as {100: 4} varied for each row. I'm thinking the best way to get my desired result is to make an object that looks like such for each ID {ID: [loc, value, bax]} Should look like such based upon my current table. The location will be always be the same for each ID depending on the first location selected so for this instance, 100 will always be USA
Desired
ID | Location | Value | BAX
100 | USA | 4 | 55
My Current HTML and JS
<table>
<tr>
<th>ID</th>
<th>Location</th>
<th>Value</th>
<th>Bax</th>
</tr>
<tr>
<td><input name ="itinValue" value="100"></td>
<td><input name ="location" value="USA"></td>
<td><input name="initValue" value='1'></td>
<td><input name="bax" value='22'></td>
</tr>
<tr>
<td><input name ="itinValue" value="300"></td>
<td><input name ="location" value="CAN"></td>
<td><input name="initValue" value='2'></td>
<td><input name="bax" value='11'></td>
</tr>
<tr>
<td><input name ="itinValue" value="100"></td>
<td><input name ="location" value="USA"></td>
<td><input name="initValue" value='3'></td>
<td><input name="bax" value='33'></td>
</tr>
<tr>
<td><input name ="itinValue" value="200"></td>
<td><input name ="location" value="MEX"></td>
<td><input name="initValue" value='4'></td>
<td><input name="bax" value='44'></td>
</tr>
</table>
<table class="table-two">
<thead>
<tr>
<th>ID</th>
<th>Location</th>
<th>Value</th>
<th>Bax</th>
</tr>
</thead>
<tbody></tbody>
</table>
Javascript:
const itin = document.querySelectorAll('[name="itinValue"]');
var values = {};
var i = 1;
itin.forEach((item, i) => {
var idValue = item.value;
var next = document.getElementsByName('initValue')[i].value;
if (values.hasOwnProperty(idValue)) {
values[idValue] = values[idValue] += parseInt(next);
} else {
values[idValue] = parseInt(next);
}
i++;
});
var table_two = document.querySelector('.table-two tbody');
for (var prop in values) {
var val = values[prop];
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
td1.innerHTML = prop;
td2.innerHTML = val;
tr.appendChild(td1);
tr.appendChild(td2);
table_two.appendChild(tr);
}
and thats printing out the ID and Values correctly. I was thinking of along the lines of doing the same thing for BAX total by doing the same thing as value total and giving them array spots
var bax = document.getElementsByName('bax')[i].value;
if (values.hasOwnProperty(idValue)) {
values[idValue] = [values[idValue] += parseInt(next), values[idValue] += parseInt(bax)];
} else {
values[idValue] = [parseInt(next), parseInt(bax)];
}
I know thats sloppy by just to give an idea of what I was thinking/trying to do. Heres a link to a quick fiddle of where im at
https://jsfiddle.net/f4ha7xe6/52/

Was at this for awhile, finally got to a solution if anyone was interested
https://jsfiddle.net/f4ha7xe6/127/
code

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'type')

I have a table with two columns: values and checkboxes. I want to identify the smallest value with a checked checkbox. I adapted the setup from this question, but changed the way I identify checkboxes from
document.getElementsByTagName('input')
to
querySelectorAll(".myCheckbox"). The initial way became a problem when I added an additional input field (which is why I included it below)
However, the function throws Uncaught TypeError: Cannot read properties of undefined (reading 'type').
What's going wrong?
function smallestWeight() {
let values = [];
const ele = document.querySelectorAll(".myCheckbox");
let table = document.getElementById("myTable");
let trs = table.getElementsByTagName("tr");
for (i = 0, len = trs.length; i < len; i++) {
if (ele[i].type == 'checkbox' && ele[i].checked == true) {
values.push(parseFloat(trs[i].cells[0].innerHTML));
}
}
}
const btn = document.getElementById("click");
btn.addEventListener("click", function() {
smallestWeight();
})
<table id="myTable">
<thead>
<tr>
<th>value</th>
<th>include</th>
</tr>
</thead>
<tbody>
<tr>
<td>1.1</td>
<td><input type="checkbox" class="myCheckbox" id="include" value="include" checked></td>
</tr>
<tr>
<td>2.2</td>
<td><input type="checkbox" class="myCheckbox" id="include" value="include" checked></td>
</tr>
<tr>
<td>3.3</td>
<td><input type="checkbox" class="myCheckbox" id="include" value="include" checked></td>
</tr>
<tr>
<td>4.4</td>
<td><input type="checkbox" class="myCheckbox" id="include" value="include" checked></td>
</tr>
</tbody>
</table>
<button id="click">Click</button><br>
<input type="number">
Your code looks at all rows in the table. You do not take into account that the first row of the table is the thead. So your table rows is one more greater than the checkboxes.
const trs = table.querySelectorAll("tbody tr");

How to get all values inside HTML table using JQuery

I have a table which looks like below and i want to get all values inside the table including the value of text box and check box.
<div class="container-fluid">
<h1 class="h3 mb-4 text-gray-800"><?= $title; ?></h1>
<div class="container" style="text-align: left">
<table class="table table-sm" id="tbl">
<thead>
<tr>
<th>No</th>
<th>Checklist Item</th>
<th>Cheklist</th>
<th>Actual</th>
<th>Recomended</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">1</td>
<td>Check and clean rubber roller cage</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">2</td>
<td>Tension Rod all </td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
<tr>
<td scope="row">3</td>
<td>Delete all unnecessary file from system</td>
<td><input type="checkbox" name="chek" id="check"></td>
<td><input type="text"></td>
<td><input type="text"></td>
</tr>
</table>
save
</div>
when i grab all value using this script i cant get value inside the text box and checkbox
$(document).on('click', '#save', function() {
var myRows = [];
var headersText = [];
var $headers = $("th");
// Loop through grabbing everything
var $rows = $("tbody tr").each(function(index) {
$cells = $(this).find("td");
myRows[index] = {};
$cells.each(function(cellIndex) {
// Set the header text
if (headersText[cellIndex] === undefined) {
headersText[cellIndex] = $($headers[cellIndex]).text();
}
// Update the row object with the header/cell combo
myRows[index][headersText[cellIndex]] = $(this).text();
});
});
var myObj = {
"Array": myRows
};
alert(JSON.stringify(myObj));
});
I want to convert it to JSON but the value of text box and check box not shows inside table. Kindly help me to resolve this issue.
Thank you in advance.
You can find the input and use .val() to get its value if the table cell's text is empty. Checkboxes and text inputs will need to be handled separately.
const text = $(this).text();
if(text){
myRows[index][headersText[cellIndex]] = text;
} else {
const input = $(this).find('input');
if(input.is(":checkbox")){
myRows[index][headersText[cellIndex]] = +input.prop('checked');
} else {
myRows[index][headersText[cellIndex]] = input.val();
}
}

how to get the remaining qty per item using javascript

I have a problem here that when I click copy row and I want to get the remaining qty per item, the result is not accurate.
So let's just say the item mouse has 100 qty, and I inputted new qty for 50. So the remaining should be 50. And when I copied the item mouse and inputted 40, so the remaining now is 10. Same goes for other items. This should be the expected output.
Current Situation
JSFIDDLE
$('.qty').on("keyup", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
sum += parseFloat(value);
}
});
console.log(sum);
$('.remaining').val(sum);
});
Your overall logic is REALLY unclear. Here is an example that might help.
$(function() {
function refreshIndex($t) {
$('tbody tr', $t).each(function(i, el) {
var c = i + 1;
var select = $(this).find('td:eq(0)').text(c);
});
}
function copyRow(e) {
var self = $(e.target);
var row = self.closest("tr");
row.clone().appendTo(self.closest("tbody"));
refreshIndex($("#table_name"));
}
function updateItem(e) {
var self = $(e.target);
var row = self.closest("tr");
var p = parseInt(self.val());
var q = parseInt(row.find("td:eq(2) input").val());
$('.remaining', row).val(q - p);
}
$("#table_name tbody").on("keyup", '.price', updateItem);
$("#table_name tbody").on('click', '.copy', copyRow);
});
#table_name tr td input {
width: 4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Total</th>
<th>Qnty</th>
<th>Action</th>
<th>Remaing</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="price" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="price" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="price" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
When I enter 40 under Price, 60 appears as the difference between the Quantity and the Amount entered.
When Copy is clicked, a new row is appended, and functionality is binded to it already due to use of .on().
Hope that helps.
Basically you can use the data-id attribute to target the rows you actually want to update.
var clone_controll = function(num) {
//Needed to mod this so add rows have the event handler
$('#table_name').on("keyup", ".qty", function() {
var id = $(this).data('id');
var value = $(this).val();
var sum = 0;
//Filter is the wrong choice here - it is designed to filter objects
/*$("#table_name .qty").filter(function(){
if ($(this).data("id") == id){
//I think this logic is incorrect as well
//You are only getting the value from the
//field you are typing in
sum += parseFloat(value);
}
});*/
/*Use a better selector with each()*/
$("#table_name [data-id=" + id +"]").each(function(){
//In this context "this" is the item iterated in "each"
sum += parseFloat($(this).val());
console.log(sum);
});
console.log("Final: " + sum);
//Here is your problem, this updates All "remaining fields
//$('.remaining').val(sum);
//All rows contiaining this data id
var relevantRows = $("[data-id=" + id + "]").closest("tr");
//Update the "remaining fields in those rows
$(relevantRows).find(".remaining").val(sum);
});
}
clone_controll();
var $tableBody = $('#table_name').find("tbody");
clickEvent();
function clickEvent(){
$tableBody.find('.copy').off('click').on('click',function() {
$trLast = $(this).closest('tr'),
$trNew = $trLast.clone();
$trLast.after($trNew);
clickEvent();
clone_controll();
});
function refresh_index(){
$('#table_name > tbody > tr').each(function (i) {
i++;
var select = $(this).find('td').eq(0).text(i);
});
}
refresh_index();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table id="table_name">
<thead>
<tr>
<th>No</th>
<th>Item</th>
<th>Qty</th>
<th>Your Qty</th>
<th>Action</th>
<th>Remaing per item(not per row)</th>
</tr>
</thead>
<tbody>
<tr class="trs" id="tr-1">
<td>1</td>
<td>Mouse</td>
<td><input type="text" value="100" readonly></td>
<td><input type="text" class="qty" data-id="79"></td>
<td><button class="copy" id="copy-1">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-2">
<td>2</td>
<td>Keyboard</td>
<td><input type="text" value="20" readonly></td>
<td><input type="text" class="qty" data-id="80"></td>
<td><button class="copy" id="copy-2">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
<tr class="trs" id="tr-3">
<td>3</td>
<td>Monitor</td>
<td><input type="text" value="50" readonly></td>
<td><input type="text" class="qty" data-id="81"></td>
<td><button class="copy" id="copy-3">Copy</button></td>
<td><input type="text" class="remaining"></td>
</tr>
</tbody>
</table>
Your logic is still pretty unclear, but hopefully this gets you moving in the right direction.

detect duplicates on rows and remove class when value is changed HTML

Good day,
I have a table that can detect duplicated row on blur and I already implemented it, the code was from stack exchange and its jsfiddle, but Im confused on how to remove the class 'duplicate' when I change the value into a unique one.
heres my html
<table class="table" id="FS-table">
<thead>
<tr>
<th width="10%">Format Code</th>
<th width="60%">Account Title</th>
<th width="30%">Accound Number</th>
</tr>
</thead>
<tbody>
<tr>
<td><input id="rowId-1" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Cash on Hand</span></td>
<td><span class="account-number">11110</span></td>
</tr>
<tr>
<td><input id="rowId-2" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Petty Cash Fund</span></td>
<td><span class="account-number">11120</span></td>
</tr>
<tr>
<td><input id="rowId-3" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">CCash in Bank</span></td>
<td><span class="account-number">11110</span></td>
</tr>
<tr>
<td><input id="rowId-4" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Accounts Receivable - Trade</span></td>
<td><span class="account-number">11320</span></td>
</tr>
<tr>
<td><input id="rowId-5" type="text" class="fs-format-code form-control"></td>
<td><span class="accound-desc">Allowance for Bad Debts</span></td>
<td><span class="account-number">11110</span></td>
</tr>
</tbody>
</table>
and my js:
$('input.fs-format-code').on('blur', function(){
var tableRows = $("#FS-table tbody tr");
tableRows.each(function(n){
var FsInput = $(this).find('input.fs-format-code');
var id = FsInput.attr('id');
var row = $(this).find('input.fs-format-code').val();
tableRows.each(function(n){
var id2 = $(this).find('input.fs-format-code').attr('id');
// console.log("id2: "+id2 +", "+"id :"+id);
if(id2 != id){
var row2 = $(this).find('input.fs-format-code').val();
console.log("row2 :"+row2 + ", row :"+row);
if (row2 == row)
{
$(this).addClass('duplicate');
}
else{
// $(this).removeClass('duplicate');
}
}
});
});
});
if I add the else statement it will just remove again the added 'duplicate' class, How Am I gonna do it properly so that it can properly detect duplicate values or not ? thanks for your help. If you find my question hard to understand, please let me know so I can edit it right away. Have a Good day!
You could remove all of the duplicate classes at the start of the function, and then in your inner loop you could exclude all the ones marked duplicate:
$('input.fs-format-code').on('blur', function(){
var tableRows = $("#FS-table tbody tr");
/*-- Remove All Duplicate Classes --*/
tableRows.filter(".duplicate").removeClass("duplicate");
tableRows.each(function(n){
var FsInput = $(this).find('input.fs-format-code');
var id = FsInput.attr('id');
var row = $(this).find('input.fs-format-code').val();
/* -- Exclude Duplicates -- */
tableRows.not(".duplicate").each(function(n){
var id2 = $(this).find('input.fs-format-code').attr('id');
// console.log("id2: "+id2 +", "+"id :"+id);
if(id2 != id){
var row2 = $(this).find('input.fs-format-code').val();
console.log("row2 :"+row2 + ", row :"+row);
if (row2 == row)
{
$(this).addClass('duplicate');
}
}
});
});
});
It doubt it is the most efficient method, but it is probably one of the simplest modifications to your current code.
Update Fiddle here: http://jsfiddle.net/Kcas2/70/
In order to not change your code,
There is a trick to determine witch input is same as witch another, just change if/else of your code like this:
if (row2 == row && row2 != '' && row != '')
{
$(this).addClass('duplicate'+id);
}
else{
$(this).removeClass('duplicate'+id);
}
http://jsfiddle.net/yq72tr6b/

How can I populate a table's cell through JavaScript code?

I have a table as below. I have to populate the "Amount" field using the "Buy Quantity" and "Market Price" field. Amount = Buy Quantity*Market Price. I am doing something as -
<script>
function populate() {
var rows = document.getElementById("mytable").getElementsByTagName("tr");
for ( var i = 1; i <= rows.length; i++) {
cells = rows[i].getElementsByTagName("td");
for ( var j = 0; j <= cells.length; j++) {
if (j == 1) {
var num1 =parseFloat(cells[1].childNodes[0].value);
var num2 =parseFloat(cells[2].childNodes[0].data);
var num3=num1 * num2;
cells[3].childNodes[0].value = num3.toString();
}
}
}
}
</script>
I can get the values of column1 and column2, but the value in last column is not getting populated. The last line does not seem to work.
cells[3].childNodes[0].value = num3.toString();
What should I change?
The below html code is part of my .jsp file.
<form action="BuyServlet">
<table border="1" cellpadding="5" id="mytable">
<tr>
<th>Stock Name</th>
<th>Buy Quantity</th>
<th>Market Price</th>
<th>Amount</th>
</tr>
<tr>
<td>Stock Name</td>
<td><input type="text" name="quantity" onblur="populate()"></td>
<td>122</td>
<td><input type="text" name="amount">
</d>
</tr>
<tr>
<td>Stock Name</td>
<td><input type="text" name="quantity" onblur="populate()"></td>
<td>111</td>
<td><input type="text" name="amount"></td>
</tr>
</table>
</form>
Basically you are getting the value from the text box (best quantity) and you are using data to get the value of the Market price(better use innerText)
try this (Replace with your code inside loop)
var num1 =parseFloat(cells[1].childNodes[0].value);
var num2 =parseFloat(cells[2].innerText);
var num3=num1 * num2;
cells[3].innerText = num3.toString();
Your code is in need of improvement. In your table, you should have a thead and a tbody sections. This will make it more accessible and easier to ingore the heading row.
<table border="1" cellpadding="5" id="mytable">
<thead>
<tr>
<th>Stock Name</th>
<th>Buy Quantity</th>
<th>Market Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stock Name</td>
<td><input type="text" name="quantity"></td>
<td>122</td>
<td><input type="text" name="amount"></td>
</tr>
<tr>
<td>Stock Name</td>
<td><input type="text" name="quantity"></td>
<td>111</td>
<td><input type="text" name="amount"></td>
</tr>
</tbody>
</table>
</form>
Now with the code, you should be adding the onblur with code, not hardcoded. You are looping through the cells, there is no reason for that. Also there is no need to loop every row when the table is changed. Just calculate the one that changed! Using childNodes can be tricky because of whitespace differences in browsers. Run this code after the table has been rendered.
(function () {
var table = document.getElementById("mytable");
var tbody = table.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");​​​​​​​​​
function populateRow (index, addBlurEvent) {
var row = rows[index];
var cells = row.getElementsByTagName("td")
var textboxes = row.getElementsByTagName("input");
var amountTextbox = textboxes[0];
var totalTextbox = textboxes[1];
var costCell = cells[2];
var amount = amountTextbox.value.length>0 ? parseFloat(amountTextbox.value) : 0;
var cost = parseFloat(costCell.innerHTML);
var total = amount * cost;
totalTextbox.value = total;
if (addBlurEvent) {
amountTextbox.onblur = function () { populateRow(index, false); };
}
}
for (i=0;i<rows.length;i++) {
populateRow(i, true);
}
}());
The running fiddle of the above code
​
I think the error is due to spelling mistake - you have childnodes instead of childNodes on "cells[3].childnodes[0].value = num3.toString();"
Check this fiddle - http://jsfiddle.net/VwU7C/

Categories