Merging javascript objects into HTML table - javascript

I have two javascript objects, the contents of which came from these two HTML tables.
Each pre-merge table now has it's own object. The object is structured as follows:
The first array element within the object contains the column headers from the pre-merge tables, and the array elements following that contain the <tr> data from each table.
Is it possible to merge these two objects together to produce one HTML table? As you can see the in the pre-merge tables the x-value is shared between both, meaning it is common between the two objects too. I thought there may be a way of comparing these values, and then populating the table, but I'm not sure how.
I would like the merged table to look like the following:
x-value: common dates shared between objects
columns: data from each of the pre-merge tables with their headers
Here is my code (you can also see it on this CodePenHere):
$(document).ready(function(){
gatherData();
results();
});
function gatherData(){
data = [];
tables = $('.before').find('table');
$(tables).each(function(index){
table = [];
var headers = $(this).find('tr:first');
var headerText = [];
headerText.push($(headers).find('td:nth-child(1)').text());
headerText.push($(headers).find('td:nth-child(2)').text());
table.push(headerText)
$(this).find('tr').each(function(index){
var rowContent = [];
if (index != 0){
$(this).find('td').each(function(index){
rowContent.push($(this).text());
})
}
table.push(rowContent)
})
data.push({table: table})
});
console.log(data)
}
function results(){
var results = $('.after1').find('thead');
$(results).append("<th>" + data[0].table[0][0] + "</th>");
for (i in data){
$(results).append("<th>" + data[i].table[0][1] + "</th>");
var b = data[i].table.length;
for (a = 2; a < b; a++){
console.log(data[i].table[a][0] + " || " + data[i].table[a][1])
}
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div class="container">
<h1 class="page-header">Formatter.js</h1>
</div>
<div class="container before">
<h3>Before</h3>
<table border=1 cellspacing=0 cellpadding=0 alignment="" class="a" id="3">
<tbody>
<tr>
<td>x-value</td>
<td>Operational Planned</td>
</tr>
<tr>
<td>09/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>10/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>11/11/2015</td>
<td>66358</td>
</tr>
<tr>
<td>12/11/2015</td>
<td>65990</td>
</tr>
<tr>
<td>13/11/2015</td>
<td>55993</td>
</tr>
<tr>
<td>14/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>15/11/2015</td>
<td>0</td>
</tr>
</tbody>
</table>
<table border=1 cellspacing=0 cellpadding=0 alignment="" class="a" id="3">
<tbody>
<tr>
<td>x-value</td>
<td>Something Else</td>
</tr>
<tr>
<td>09/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>10/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>11/11/2015</td>
<td>2552</td>
</tr>
<tr>
<td>12/11/2015</td>
<td>86234</td>
</tr>
<tr>
<td>13/11/2015</td>
<td>33623</td>
</tr>
<tr>
<td>14/11/2015</td>
<td>0</td>
</tr>
<tr>
<td>15/11/2015</td>
<td>0</td>
</tr>
</tbody>
</table>
<hr>
</div>
<div class="container after">
<h3>After</h3>
<table class="table after1">
<thead>
</thead>
<tbody>
</tbody>
</table>
</div>

As I understand your issue, you want to merge the tables by the key values in coloumn x-value.
Here is how I would do it:
Collect data from each table into a dictionary with coloumn x-value as key
Save values for each key as array.
The main part is collecting the data in the dictionary. Here is the part:
var table = {
header: [],
data: {}
};
$(this).find('tr').each(function(index) {
// ignore first row
if (index === 0) return true;
// read all data for row
var rowData = [];
$(this).find('td').each(function() {
var value = $(this).text();
rowData.push(value);
});
// key value for dictionery
var key = rowData[0];
// add value to array in dictionary if existing or create array
if(table.data[key]) {
table.data[key].push(rowData[1]);
} else {
table.data[key] = [rowData[1]];
}
});
By using a simple javascript object as a dictionary we create properties on the fly, just like a dictionary.
See the plunker for the full script. I've written comments on the different parts to make the functionality clear. Let me know if anything is unclear.
As a note on your code. You can use multiple arguments in the jQuery selector to make your selections simpler, so this (see note below)
tables = $('.before').find('table');
can become this:
tables = $('.before table');
Edit
As noted by Mark Schultheiss in the comments, the later, but shorter syntax for jQuery selectors can be slower than the first one on large DOMs. So use the extended syntax on large DOMs. I've updated the plunker to use the better performing syntax.

Related

How to get the cells header name of cells to whom am passing a different class name in table

What I am trying to get the cell header name of those cells who has a specific class assigned like suppose I have 10 cells in each row and some of them has class by name like test, then I want to store the names of all those cells in array who has this class name.
My HTML as like below:
<table>
<tr>
<th>Header1</th>
<th>Header2</th>
<th>Header3</th>
</tr>
<tr>
<td class="test">gggg</td>
<td>hhhh</td>
<td class="test">iiiiiii</td>
</tr>
<tr>
<td>ddddd</td>
<td>eeee</td>
<td>ffffff</td>
</tr>
</table>
As per above HTML these should be a Header1 and Header3 in array, here I want to get this data without click event, means am adding the class name to these cells using Javascript means that is dynamic so I want to store the name of the header cells in array whenever cells under that header cell will have this class and this class assignment is happening for single row only in entire table.
Since your table is regular (no colspans), it's quite straightforward:
Find the index of the cells with the class test using index.
Find the matching header cells using the :eq pseudo-selector (.e.g, $("selector-for-the-table th:eq(" + index + ")") where index is the index of the header cell you want). (Or the .eq function could be used in a similar way.)
Get the th's text using text.
Example:
var indexes = $(".test").map(function() {
return $(this).index();
}).get();
var headers = indexes.map(function(index) {
return $("th:eq(" + index + ")").text();
});
console.log(headers);
var indexes = $(".test").map(function() {
return $(this).index();
}).get();
var headers = indexes.map(function(index) {
return $("th:eq(" + index + ")").text();
});
console.log(headers);
<table>
<tr>
<th>Header1</th>
<th>Header2</th>
<th>Header3</th>
</tr>
<tr>
<td class="test">gggg</td>
<td>hhhh</td>
<td class="test">iiiiiii</td>
</tr>
<tr>
<td>ddddd</td>
<td>eeee</td>
<td>ffffff</td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Or more compactly:
var headers = $(".test").map(function() {
return $("th:eq(" + $(this).index() + ")").text();
}).get();
console.log(headers);
var headers = $(".test").map(function() {
return $("th:eq(" + $(this).index() + ")").text();
}).get();
console.log(headers);
<table>
<tr>
<th>Header1</th>
<th>Header2</th>
<th>Header3</th>
</tr>
<tr>
<td class="test">gggg</td>
<td>hhhh</td>
<td class="test">iiiiiii</td>
</tr>
<tr>
<td>ddddd</td>
<td>eeee</td>
<td>ffffff</td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

2D loops for building a table

I want to loop through a two-dimensional structure in angularjs to display it in a table. The data looks as follows:
data = {
"keyA": ["valueA", "valueB"],
"keyB": ["valueC", "valueD"]
}
the output should look like this:
<table>
<tr>
<th>keyA</th>
<td>valueA</td>
</tr>
<tr>
<th>keyA</th>
<td>valueB</td>
</tr>
<tr>
<th>keyB</th>
<td>valueC</td>
</tr>
<tr>
<th>keyB</th>
<td>valueD</td>
</tr>
</table>
at the moment my angular enriched html doesn't work and looks as follows:
<table>
<div ng:repeat="(key, values) in data">
<div ng:repeat="value in values">
<tr>
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</div>
</div>
</table>
In this case I'm using the <div> element, but it doesn't work because obviously a <div> doesn't belong into a <table> like that. Is there some find of a No-Op-Element, which I have to use for loops like this?
I'm not sure if that's possible. Maybe someone can be a little more creative then I. You could try something like this though:
Controller-
var data = {
"keyA": ["valueA", "valueB"],
"keyB": ["valueC", "valueD"]
};
$scope.getPairs = function() {
var ret = [];
for(var key in data) {
for(var i = 0; i < data[key].length; i++) {
ret.push(key, data[key][i]);
}
}
return ret;
}
HTML -
<table>
<tr ng-repeat="pair in getPairs() track by $index">
<td>{{pair[0]}}</td>
<td>{{pair[1]}}</td>
</tr>
</table>
You could add ngRepeat on <tr> and <tbody> element:
<table>
<tbody ng-repeat="(key, values) in data">
<tr ng-repeat="value in values">
<th>{{key}}</th>
<td>{{value}}</td>
</tr>
</tbody>
</table>
Plunker

an easy way to get all the table rows from a table without using a loop

Is there an easy way to get all the table rows from a table without using a loop.
I thought that this would work but it only alerts the first row.
http://jsfiddle.net/THPWy/
$(document).ready(function () {
var O = $('#mainTable').find('tr');
//var O = $('#mainTable tr');
alert(O.html());
//alerts <th>Month</th><th>Savings</th>
});
<table id ="mainTable" border="1">
<caption>Monthly savings</caption>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$50</td>
</tr>
<tr>
<td>March</td>
<td>$50</td>
</tr>
<tr>
<td>a</td>
<td>$50</td>
</tr>
<tr>
<td>m</td>
<td>$50</td>
</tr>
<tr>
<td>j</td>
<td>$50</td>
</tr>
<tr>
<td>july</td>
<td>$50</td>
</tr>
<tr>
<td>aug</td>
<td>$50</td>
</tr>
<tr>
<td>sep</td>
<td>$50</td>
</tr>
</table>
Whatever you use will be iterating through each row to get the inner HTML out of it. So no, you cannot do it without a loop.
Here is an alternate method that gets the message in one line if that's what you're after, it's slightly less efficient than going with a loop though as it needs to make a new array.
jsFiddle
$(document).ready(function () {
var rows = $('#mainTable tr');
var message = $.map(rows, function (v) {
return v.innerHTML;
}).join('\n');
alert(message);
});
I would recommend just doing it in a regular loop.
FYI .html() only alerts the first row because that's what it was designed to do as that is what would be most useful.
Description: Get the HTML contents of the first element in the set of matched elements.
What about:
// get all tr (excluding the caption)
var O = $('table#mainTable').children().slice(1);
http://jsfiddle.net/THPWy/7/
What you have in your code already retrieves all table rows as an array of jQuery elements:
var trs = $('#mainTable').find('tr');
If you want to print the html contents of each row then you would have to use a loop:
trs.each(function (index, element) {
alert($(this).html());
});
You can get by using
gt(), lt(),eq()
.gt(index) // will get all the rows greater than specified index
.lt(index) // will get all the rows less than specified index
.eq(index) // will get all the rows equal to specified index
For Example
$('#mainTable tr').eq(1) will give second row
But when you want to know all the table rows data then go with Konstantin D - Infragistics solution

Remove tables from HTML using jQuery

I've got many chunks of HTML coming into my app which I have no control over. They contain tables for layout, which I want to get rid of. They can be complex and nested.
What I want is to basically extract the HTML content from the tables, so that I can inject that into other templates in the app.
I can use jQuery or plain JS only, no server side trickery.
Does anyone know of a jQuery plugin of good tip that will do the job?
Littm - I mean to extract content from the td tags essentially. I want no trace of table left in the code when it's done. Thanks!
Here's an example of the type of HTML in question. It all comes in via XHR from some ancient application so I have no control over the markup. What I want is to get rid of the tables completely, leaving just the rest of the HTML or other text content.
<table>
<tr><td colspan="4"></td></tr>
<tr>
<td width="1%"></td>
<td width="40%" style="padding-left: 15px">
<p>Your access level: <span>Total</span></p>
</td>
<td width="5%">
<table><tr><td><b>Please note</b></td></tr></table>
</td>
<td width="45%" style="padding-left: 6px" valign="top"><p>your account</p></td>
</tr>
<tr><td colspan="4"> </td></tr>
<tr>
<td width="1%"></td>
<td width="40%" style="padding-left: 15px">
<table>
<tr>
<td align="right">Sort Code: </td>
<td align="center"><strong>22-98-21</strong></td>
</tr>
<tr>
<td align="right">Account Number: </td>
<td><strong>1234959</strong></td>
</tr>
</table>
</td>
<td width="5%"></td>
<td width="45%" style="padding-left: 6px">Your account details for</td>
</tr>
</table>
I've tried;
var data = ""
$("td").each(function(){
data += $(this).html()
});
$("article").append(data);
$("table").remove();
But var data still contains nested td tags. I'm no JS expert so I'm not sure what else to try....
Let's suppose that you have X number of tables.
In order to extract all the content information from these, you could try something like this:
// Array containing all the tables' contents
var content = [];
// For each table...
$("table").each(function() {
// Variable for a table
var tb = [];
$(this).find('tr').each(function() {
// Variable for a row
var tr = [];
$(this).find('td').each(function() {
// We push <td> 's content
tr.push($(this).html());
});
// We push the row's content
tb.push(tr);
});
// We push the table's content
content.push(tb);
});
So for instance, if we have the following 2 tables:
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>A</td>
</tr>
</table>
<table>
<tr>
<td>r1</td>
<td>r2</td>
<td>r3</td>
</tr>
<tr>
<td>rA</td>
<td>rB</td>
</tr>
<tr>
<td>rP</td>
</tr>
</table>
The array content will be something like this:
content = [ [ [1, 2], [A] ] ] , [ [r1, r2, r3], [rA, rB], [rP] ] ]
\_______________/ \______________________________/
1st table 2nd table
and if you want to access the first table, you'll just have to access content[0] for instance.
Now, let's suppose that you have a DIV, with and id my_div, and that you want to output some table content in it.
For example, let's suppose that you only want to have the 1st table only. Then, you would do something like this:
// Note: content[0] = [[1, 2], [A]]
var to_print = "<table>";
for(var i=0; i<content[0].length; i++) {
to_print += "<tr>";
for(var j=0; j<content[0][i].length; j++)
to_print += "<td>"+ content[0][i][j] +"</td>";
to_print += "</tr>";
}
to_print += "</table>";
$("#my_div").html(to_print);
which will give you something like this:
<div id="my_div">
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>A</td>
</tr>
</table>
</div>
Hope this helps.
Edit: You should create a recursive function to do that.
Simply create you function that gets "td"'s as a value:
function searchTexts(td) {
if (td.find("td")) {
searchTexts(td.find("td"));
}
td.each(function(){
data += $(this).html()
$(this).remove(); // remove it for avoiding duplicates
});
}
Then call it passing a jQuery object to the function.

HTML and JavaScript auto increment number

I am new to HTML and JavaScript. I got a problem like this in HTML (This code below only visualize the problem for you to easy to reference.)
<tr>
<td>1</td>
<td>Harry</td>
</tr>
<tr>
<td>2</td>
<td>Simon</td>
</tr>
<td>3</td>
<td>Maria</td>
</tr>
</tr>
<td>4</td>
<td>Victory</td>
</tr>
This is a name list, however the problem is that sometime i need to add more name into this table and I HAVE TO ADD in front of Number 1, so meaning i have to re-write the number list, (EX: 1 1 2 3 4 --> 1 2 3 4 5). I feel that is not a good way.
NOTE: I don't want to change the list number decrease from top to bottom. And this is a HTML file so can't apply PHP
Anyone can help me to make the number to a variable like "i" and a function can help me to fill variable i increment from top to bottom automatically like
<tr>
<td>i</td>
<td>Harry</td>
</tr>
<tr>
<td>i</td>
<td>Simon</td>
</tr>
<td>i</td>
<td>Maria</td>
</tr>
</tr>
<td>i</td>
<td>Victory</td>
</tr>
Function Fill_i for example:
I think that JavaScript should be used in this case. Thanks for your help and suggestion on this problem.
Again: I am not allowed to use PHP or ASP and when I add a new name, I add it manually by HTML.
You can use a css counter - MDN
table {
counter-reset: section;
}
.count:before {
counter-increment: section;
content: counter(section);
}
<table>
<tr>
<td class="count"></td>
<td>Harry</td>
</tr>
<tr>
<td class="count"></td>
<td>Simon</td>
</tr>
<tr>
<td class="count"></td>
<td>Maria</td>
</tr>
<tr>
<td class="count"></td>
<td>Victory</td>
</tr>
</table>
FIDDLE
This should work for you:
<table>
<tr>
<td>Harry</td>
</tr>
<tr>
<td>Simon</td>
</tr>
<tr>
<td>Maria</td>
</tr>
<tr>
<td>Victory</td>
</tr>
</table>
<script>
var tables = document.getElementsByTagName('table');
var table = tables[tables.length - 1];
var rows = table.rows;
for(var i = 0, td; i < rows.length; i++){
td = document.createElement('td');
td.appendChild(document.createTextNode(i + 1));
rows[i].insertBefore(td, rows[i].firstChild);
}
</script>
The script should be placed immediately after your table. It goes through each row of your table and adds an extra cell to the beginning with the incrementing number inside that cell.
JSFiddle Demo
Edit: seems like the other solution posted would work do (was added while I typed this up).
You really should be using PHP to do something dynamic like this, which would become trivial with a single for loop.
However, if you insist on using HTML/Javascript (or perhaps this is a 'static page'...) then what you are asking should be possible.
You could add a class to each of the <td> elements you want to use, so:
<tr>
<td class='personid'>i</td>
<td>Harry</td>
</tr>
<tr>
<td class='personid'>i</td>
<td>Simon</td>
</tr>
<td class='personid'>i</td>
<td>Maria</td>
</tr>
</tr>
<td class='personid'>i</td>
<td>Victory</td>
</tr>
Then you would have a javascript function that does something like this:
var list = document.getElementsByClassName("personid");
for (var i = 1; i <= list.length; i++) {
list[i].innerHTML = i;
}
Are you sure you don't want an ordered list?
<ol>
<li>Fred</li>
<li>Barry</li>
</ol>
<script>
function addRow(index, name){
var tbody = document.getElementById("nameList");
var row = document.createElement("tr");
var data1 = document.createElement("td");
data1.appendChild(document.createTextNode(index));
var data2 = document.createElement("td");
data2.appendChild(document.createTextNode(name));
row.appendChild(data1);
row.appendChild(data2);
tbody.appendChild(row);
}
var name=new Array();
name[0]="Harry";
name[1]="Simon";
name[2]="Maria";
name[3]="Victory";
for(var i=0; i < name.length; i++) {
addRow(i,name[i]);
}
</script>
<html>
<body>
<table id="nameList">
</table>
</body>
</html>
I would say do this (im going to assume you are not going to load in jquery or anything fancy):
<html>
<head>
<script type="text/javascript>
function writeTable(){
// list of names
var myList = [ "name1", "name2", "etc", "etc"];
// your variable to write your output
var outputTable = "<table>";
//the div to write the output to
var outputDiv = document.getElementById("output");
//the loop that writes the table
for (var i=0; i<myList.length; i++){
outputTable += "</tr><td>"+i+"</td><td>"+myList[i]+"</td></tr>";
}
//close the table
outputTable += "</table>";
//write the table
outputDiv.innerHTML = outputTable;
}
</script>
</head>
<body onload=writeTable()>
<div id='output'></div>
</body>
</html>
hope this helps :)
Try this
$(document).ready(function() {
var addSerialNumber = function () {
$('table tr').each(function(index) {
$(this).find('td:nth-child(1)').html(index);
});
};
addSerialNumber();
});

Categories

Resources