Looping through html tables - javascript

I have a page that has a table and a small form. The table has some data on questionnaires. I am trying to use jquery to loop through the table, checking if a condition is met, then adding it to the correct field of the form. The problem I have is that the forms are not created by me so I cant match them to set id's. So i need to get the field_id from relate, and the answer inserting into that location. Im new to Jquery and js. This is what I came up with.
html
<div align="left">
<table class="table table-striped">
<thead>
<td>Question</td>
<td>Answer</td>
<td>Relates to</td>
</thead>
<tbody>
<tr>
<td>Random question 1</td>
<td>Random answer 1</td>
<td>add to variable form field</td>
</tr>
<tr>
<td>Random question 2</td>
<td>Random answer 2</td>
<td>add to a different form field</td>
</tr>
</tbody>
</table>
</div>
<input type="text" id="variable id that could be matched with element of table">
main.js
table.find('tr').each(function (i, el) {
var $mylists = $('#' + relate)
$mylists.html('');
var $tds = $(this).find('td'),
label = $tds.eq(0).text(),
relate = $tds.eq(1).text(),
answer = $tds.eq(2).text();
$('<span></span>').text(answer).appendTo($mylists);
});

Since you have a single input that you want to append values you, you need to set the val of the input. And since you want to create that single input value from multiple other values (answers), you need to loop through, get all your answers, then combine them into a single value. Something like this:
var $mylists = $('#' + relate);
$mylists.val('');
var answers = [];
table.find('tr').each(function (i, el) {
var $tds = $(this).find('td'),
label = $tds.eq(0).text(),
relate = $tds.eq(1).text(),
answer = $tds.eq(2).text();
answers.push(answer);
});
// at this point, answers contains an array of all your individual answer values.
// decision time: what do you want to do with them?
// in this example, I join them together in a comma-delimited list.
$mylists.val( answers.join(', ') );

Related

Create post request with data from html table rows and save each row separately Order-Products

can someone give me tip how to slove problem. Am building Order Managment System app using PHP, MYSQL, HTML and JS.
Order information is stored in one db table and
Order Products is sotred in second db table which cointains two foreign key (order_id and product_id). Order can have many products!
What is problem
The problem is that I don't know how to get html table rows and put that rows in array, and that array i need to send via ajax to php where i will process.
I was thinking the following:
When the user selects a product from the drop-down list, enters the quantity and presses the "ADD PRODUCT" button.
In javascript, I create an event for a button ('click') where after event is triggered I will dynamically create a new row in the table using js insertRow().
In the columns of the rows I saved the values ​​in the form fields. Maybe I was wrong there.
`id.innerHTML = '<input type="text" value="'+data[0]['id']+'" id="id-'+data[0]['id']+'";
Products is successfully added as rows with values ​​to the table.
I'm not asking you to do my job. I just want you to advise me how it should be done in the right way.
HTML
<table id="document_items_table">
<thead class="table-light">
<tr>
<th width="10%">#</th>
<th>Šifra</th>
<th>Naziv</th>
<th>Količina</th>
<th>JM</th>
</tr>
</thead>
<tbody></tbody>
</table>
JavaScript
// add item to document
$("#btn_add_document_item").on('click', function(e) {
var data = $('#select2-proizvodi').select2('data');
// add table row
var table = document.getElementById('document_items_table');
var row = table.insertRow(-1);
var id = row.insertCell(0);
var code = row.insertCell(1);
var name = row.insertCell(2);
var qty = row.insertCell(3);
row.setAttribute('id', 'row-'+table.rows.length);
id.innerHTML = '<input type="text" value="'+data[0]['id']+'" id="id-'+data[0]['id']+'" name="item[]["id"]" ;
code.innerHTML = '<input type="text" value="'+data[0]['code']+'" name="item[]["code"]";
name.innerHTML = '<input type="text" value="'+data[0]['text']+'" name="item[]["name]";
qty.innerHTML = '<input type="text" class="form-input" value="'+$("#kolicina_input").val()+'" name="kolicina[]["kolicina"]" ;
});
PHP is not a problem.
Check image
This is how I would have done it personally :
What I understand : You want to be able to save mutiple lines in the same time (because each line is a diffrent product of the same order for exemple)
You create a table where each line is a product and each cell of this line is the product info (name, qty, price, etc...)
When you click "save" button it has to trigger an ajax request that will call a php page, this page will cretate a new order and return the id as a response to the request.
Now you can loop throw your table rows, for each row you send an ajax request to a php page (data of this request is row cells + order_id you got previously)
Your php will recieved data from the ajax request and store it in your db table (order product)
I hope it answer your question, if you need help to write a part of this code feel free to ask me ;)
Maxime
How to get data froms table rows :
HTML :
<table id="table-products">
<thead>
<tr>
<th>Label</th>
<th>Qty</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Product 1</td>
<td>4</td>
<td>35</td>
</tr>
<tr>
<td>Product 2</td>
<td>8</td>
<td>12</td>
</tr>
<tr>
<td>Product 3</td>
<td>2</td>
<td>99</td>
</tr>
</tbody>
JS :
let table = document.querySelector('#table-products');
let headers = [...table.rows[0].cells].map(th => th.innerText);
for(let row of [...table.rows].slice(1, table.rows.length)) {
let product = Object.fromEntries(new Map([...row.cells].map((cell, i) => [headers.at(i), cell.innerText])));
console.log(product);
}

Use javascript to Transfer Text

I have got 3 tables in html that at a certain time, i want to move text from 1 table will move to another. Can someone show me a javascript function ( just a few lines long - don't spend too long) that can transfer text from one td to another.
Transferring ONE td value to another:
Well if you assign a td an ID (ex. "firstTD", "secondTD"), you could store it's value in a variable (ex. "tdToMove"):
var tdToMove = document.getElementById("firstTD").innerHTML;
document.getElementById("secondTD").innerHTML = tdToMove;
Note: This will only copy the innerHTML of a single td, and duplicate it on the other. If you wish to clear the first entry, run:
document.getElementById("firstTD").innerHTML = "";
to render the first td 'blank'.
You will have to experiment to find a way to move ALL values to the other table, this was just a pointer.
Also, If the text is moving from table to table, and the tables remain identical, why not just place the input in both to begin with, OR, simply run a code to duplicate the table when you would like to move the data?
You can use Node.textContent property to get and set the text of a Node.
Here is a link about it:https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
I have made a fiddle to show you that in action: https://jsfiddle.net/3dep0msg/
In this fiddle i transfer the text of cell1 to cell2 and add it to the text of cell2.
I use textContent and not innerHTML property, because you wanted to transfer ONLY text!
function copyTextFromCell(id1,id2){
var cell1= document.getElementById(id1);
var cell2= document.getElementById(id2);
cell2.textContent = cell2.textContent+cell1.textContent;
}
copyTextFromCell("cell1","cell2");
if you want to do this using jquery.
<table id="table1">
<tr>
<td>1,1</td>
<td>1,2</td>
</tr>
<tr>
<td>2,1</td>
<td>2,2</td>
</tr>
</table>
<table id="table2">
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
$('#table1 tr').each(function (indexR, element) {
$(this).find('td').each(function (index, element) {
var table2Rows = $('#table2 tr');
var table2Row = table2Rows.eq(indexR);
var table2Column = table2Row.find('td');
var table2cell = table2Column.eq(index);
table2cell.html( $(this).html());
});
});
working fiddle.

Grab table by ID and iterate over rows one at a time

I would like to use
var merch = document.getElementById('merch');
to retrieve a table on my webpage, which is dynamically populated. Then I would like to iterate over the table, one row at a time, grabbing the
<td>
elements and storing each of them as a string in an array. Each row will have its own array.
Can someone give me a clue as to how to accomplish this? I feel certain there is a simple method I just haven't found in my searches.
Thank you in advance for your consideration.
The working demo.
var merch = document.getElementById('merch');
// this will give you a HTMLCollection
var rows = merch.rows;
// this will change the HTMLCollection to an Array
var rows = [].slice.call(merch.rows);
// if you want the elements in the array be string.
// map the array, get the innerHTML propery.
var rows = [].slice.call(merch.rows).map(function(el) {
return el.innerHTML;
});
map
You will want to use jQuery for this, it'll make it much easier. Then you can do something like this.
HTML Table
<table id="iterateOverThisTable">
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
</table>
JS File (with jQuery already included)
$(function() {
var rows = [];
$("#tableToIterateOver tr").each(function() {
var = cells = [];
$(this).find('td').each(function() {
cells.push($(this).text());
});
rows.push(cells);
});
})

Getting inner tag element inside an "each"

I've been messing around with different forms and tables, now I need something that takes data from table tr and td field, runs a if statement on each fetched item, and outputs text inside the form, depending what was found in td fields.
So right now I have something like this, which doesn't do anything useful at all, for now, just outputs td-01 class values into the form:
var test;
$('tbody tr').each(function(index) {
test = $(this+'.td.td-0');
$('fieldset.csc-mailform').after($('td.td-0'));
});
and my table structure looks something like this:
<table class="contenttable contenttable-3 tabel">
<tr class="tr-even tr-0">
<td class="td-0">01</td>
<td class="td-1">Valik 1</td>
<td class="td-last td-2">150€</td>
</tr>
<tr class="tr-odd tr-1">
<td class="td-0">01</td>
<td class="td-1">Valik 2</td>
<td class="td-last td-2">50€</td>
</tr>
<tr class="tr-even tr-2">
<td class="td-0">01</td>
<td class="td-1">Valik 3</td>
<td class="td-last td-2">170€</td>
</tr>
<tr class="tr-odd tr-3">
<td class="td-0">01</td>
<td class="td-1">Valik 4</td>
<td class="td-last td-2">88€</td>
</tr>
</table>
Right now it only find tr tags and outputs all of them. I need it to split the tr tag up, run if condition on td-0 to determine if it needs to be radio button/text input/checkbox etc, then see what td-1 contains and make that field name, then td-2 is for example a price. all of this should end up in a form.
So as you can see, I am stuck with jQuery, but I think it should be doable.
edit:
I got something like this after messing around a little, but my if statements don't seem to work on jQuery objects, any way to get around this?
var check1;
$('tbody tr').each(function(index) {
//test = $(this+'.td.td-0');
check1 = $('td.td-0');
alert(check1);
if(check1=='01'){
content_type="checkbox";
}else if(check1=='02'){
content_type="text";
}else{
content_type="none";
}
$('fieldset.csc-mailform').after(content_type);
//$('fieldset.csc-mailform').after($('td.td-0'));
});
//edit2
Ugh, I was running if statement against jQuery object, of course it didn't work.
I got it working with this, looks quite nasty, but it seems to work:
$('tr').each(function () { var val = $(this).children('td:first').text();
//$check1 = $('td.td-0');
if(val=='01'){
content_type="checkbox";
}else if(val=='02'){
content_type="text";
}else{
content_type="none";
}
$('fieldset.csc-mailform').after(content_type + '<br/>');
}
);
Now, I need to figure out how to create input fields from these.
You could possibly make it a bit cleaner by using the jQuery selector context, e.g.:
$('tr').each(function () {
var val = $('td:first', this).text();
..
}
Something like this will do:
$('table tr').each(function() {
$tds = $(this).children();
for(var i=0;i<$tds.length;i++){
$td = $tds[i];
if($td.hasClass('td-0'){
//do your thing by getting next TD or something else
break;
}
}
});

Optimizing Jquery iteration through table columns comparing with existing row

I'm trying to write a function to add color to a table based on a reference which is one of the top rows of the table. There are several questions in SO mentioning row based iteration but not so much about column.
The structure of the table is something like:
<table id="data">
<tr>
<th rowspan="2">Name</th>
<th rowspan="2">Selection</th>
<th rowspan="2">Title</th>
<th rowspan="2">Info1</th>
<th rowspan="2">Info2</th>
<th colspan="10">Data</th>
</tr>
<tr>
<th>001</th>
<th>002</th>
<th>003</th>
<th>004</th>
<th>005</th>
<th>006</th>
<th>007</th>
<th>008</th>
<th>009</th>
<th>010</th>
</tr>
<tr id="ref_control">
<td></td>
<td>RefName</td>
<td></td>
<td></td>
<td></td>
<td>A</td>
<td>B</td>
<td>J</td>
<td>L</td>
<td>Z</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td><input type="checkbox" name="checkbox"/></td>
<td>Entity 1</td>
<td>Info...</td>
<td>More info...</td>
<td>Even more...</td>
<td>A</td>
<td>T</td>
<td>M</td>
<td>L</td>
<td>Z</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
<td>5</td>
</tr>
(...)
</table>
In addition I'm using JQuery and the JQuery column cell select plugin to perform the mentioned task.
The Javascript code looks like this:
$(document).ready(function() {
// Colorize table based on matches
// Number of Data entries - Count on the reference (2nd row)
// and only 5th column onwards (index starts at 0)
var datasize = $("#data tr:eq(2) td:gt(4)").length;
// Start with column 6 (index starts at 1)
var begin = 6;
for (var i = begin; i < begin + datasize; ++i) {
var curCol = $("#data td").nthCol(i);
var ref = curCol.eq(0).text();
curCol.not(curCol.eq(0)).each(function() {
var data = $(this);
if (data.text() == '') {
data.addClass("black");
} else if (data.text() != ref) {
data.addClass("color");
}
});
}
});
A working example can be visualized here. In the example the table has only 9 rows and 10 data columns. The actual page I'm trying to optimize has 20 rows and 90 data columns.
Using the mentioned Javascript extensions/plugins the big sized table poses no threat to the Google Chrome browser taking a few seconds to load, however Opera, Firefox and Internet Explorer have a hard time running the function or end up asking for user interaction to stop the script from running.
So my question is aimed at both alternatives to the column select plugin or ways to optimize the code such that I don't kill almost all browsers except Google Chrome.
Edit: Changes according the the two comments from #Pointy
You can easily get 10x faster code if you want. Just save references once and go row by row instead of column by column. It doesn't become more complicated yet it performs much better. The reason is that your plug-in hides the abstraction that your table is made of rows that are made of columns. And not the other way around. Emulating the second version can be costy as you noticed in this example.
You may also use DOM properties instead of jQuery methods. They are really straightforward.
// get text (modern browsers || IE <= 8)
var text = elem.textContent || elem.innerText;
// set class
elem.className = "black";
your final code will be something like:
var refcells = $("#data tr:eq(2) td:gt(4)");
var datasize = refcells.length;
// Start with column 5
var begin = 5;
var refs = [];
var i = begin;
refcells.each(function () {
refs[i++] = $(this).text();
});
$("#data tr:gt(2)").each(function () {
var cells = $("td", this);
for (var i = begin; i < begin + datasize; i++) {
var elem = cells[i];
var text = elem.textContent || elem.innerText;
if (!text) {
elem.className = "black";
} else if (text != refs[i]) {
elem.className = "color";
}
}
});
Doing what you're doing is going to be very computationally intensive. Since your table layout seems pretty regular, I'd just completely ditch that nthCol() thing (for this page anyway) and do your work by iterating over the table once:
Grab the "key" row first, and save it
Loop through each relevant <tr>, and for each one get the <td> elements and iterate over them as a raw node list, or as a jQuery list. Either way it should be a lot faster.
In the second loop, you'll do the same logic you've got (although I'd use addClass() and removeClass()), referring back to the saved "key" row for each cell.
In your current loop, you're re-building the jQuery object of every <td> in the table for each column, and then you're doing that nthCol() work! That's a lot of work to do if you do it once, so repeating that for every single column is going to really drag that CPU down. (On IE6 - especially with all those "class" changes - I bet it's almost unbearably slow.)
edit — I looked over that code (for the plugin), and while it looks like it was competently implemented it doesn't have any "magic tricks". All it does is iterate through all the table cells you give it and checks whether or not each cell is in fact in the "nth" column. Thus, your iteration will perform that test on every cell in the table for every column you care about. In your 90x20 table, that'd be about 85 iterations through all 1800 cells. And that's before you do your work!

Categories

Resources