Flot Chart from Data Table - javascript

I want to build a flot chart from a table. The table is built using the jquery datatables plugin. The table can be edited inline.
I was wondering if anyone had any tips to display the data in flot. Would you pull the data from json or directly from the chart to build the flot chart?
The data is populated in dynamically using the datatables jquery plugin.
The table looks like this..
<div id="plotarea">
<table>
<caption>GDP, based on exchange rates, over time. Values in billion USDs.</caption>
<tr>
<td></td>
<th scope="col">2003</th>
<th scope="col">2002</th>
<th scope="col">2001</th>
<th scope="col">2000</th>
<th scope="col">1999</th>
<th scope="col">1998</th>
</tr>
<tr>
<th scope="row">USA</th>
<td>10,882</td>
<td>10,383</td>
<td>10,020</td>
<td>9,762</td>
<td>9,213</td>
<td>8,720</td>
</tr>
<tr>
<th scope="row">EU</th>
<td>10,970</td>
<td>9,040</td>
<td>8,303</td>
<td>8,234</td>
<td>8,901</td>
<td>8,889</td>
</tr>
</table>
</div>
Thanks!

You can use loops to go through your table and build the data array for flot. Something like this:
var headerTr = $('table tr:first()');
var rowCount = $('table tr').length - 1;
var data = [];
for (var row = 0; row < rowCount; row++) {
var tr = $('table tr').eq(row + 1);
var dataseries = {
label: tr.find('th').text(),
data: []
};
for (var col = 0; col < tr.find('td').length; col++) {
var xval = headerTr.find('th').eq(col).text();
var yval = tr.find('td').eq(col).text().replace(',', '');
dataseries.data.push([xval, yval]);
}
data.push(dataseries);
};
Here is a fiddle with a working example. The drawing is started by button click. For your datatables you could change that to an onchange event or something similar.

Related

How to Loop through a Table of values in AngularJS

I have a table that is being populated from database through an angularJS array.
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Code</th>
<th>Description</th>
<th>Budget Amount</th>
<th>Actual Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="lineItem in vm.budget.budgetLines">
<td>
{{lineItem.code}}
</td>
<td>#{{lineItem.description}}</td>
<td>{{lineItem.budgetAmount | currency}}</td>
<td><input type="number" class="form-control" ng-model="lineItem.actualAmount" required /></td>
</tr>
</tbody>
</table>
The data population works fine. But if you look at the table, you would notice an input field in the last column. I need to be able to perform an update with changes made to the input for which I need just the 1st and last column for the operation. I used the following approach but it didn't work because it just used the original values with which the table was first populated.
$scope.lineItems = [];
for (var i = 0; i < vm.budget.budgetLines.length; i++) {
var lineItem = vm.budget.budgetLines[i];
$scope.lineItems.push({
'code': lineItem.code,
'actualAmount': lineItem.actualAmount
});
}
So I thought of using pure javascript inside my angular controller to loop through the table rows and push the columns I need in the array like so;
var myTable = document.getElementById("tblValues");
var current, cell;
for (var i = 0; i < myTable.rows.length ; i++) {
var rowItem = myTable.rows[i];
$scope.lineItems.push({
'code': rowItem.cells[1],
'actualAmount': rowItem.cells[4].children[0].value
});
}
But an error is thrown in the console: rowItem.cells[4].children[0] is undefined
Please how can I get this to work just the way I want it?
I got it to work just the way I desired it to.
var myTable = document.getElementById("tblValues");
var current, cell;
$scope.lineItems.length = 0;
for (var i = 0; i < myTable.rows.length ; i++) {
var rowItem = myTable.rows[i + 1];
$scope.lineItems.push({
'code': rowItem.cells[1].innerText,
'actualAmount': rowItem.cells[4].firstChild.value
});
}

jQuery sort custom table

I'm working on a small userscript to sort a table, the structure of the table is really weird however. What i'm trying to do is to add an extra sort feature so I can sort on the ranking (#) of the persons.
Table data looks like this:
<table id="outer">
<tr>
<td><div id="bgn"></div></td>
<td>User 1</td>
<td>
<table id="inner">
<tbody>
<tr>
<td>Rank</td>
<td id="tdp">#28</td>
</tr>
</tbody>
</table>
</td>
</tr>
<!-- more rows -->
</table>
There are some additional <td>'s but they are not important right now. There are about 52 rows, but these could vary, of course.
Current jQuery code I have:
jQuery( document ).ready(function() {
var rankings = [];
$(document).on('click', '#tdr', function() {
// skipping first line because it's the header
$('tr:not(:first-child').each(function () {
var rank = $(this).find('#tdp').text();
var rank2 = rank.substring(1, rank.length)
rankings.push(rank2);
});
console.log(rankings.sort(sortNumber));
});
function sortNumber(num1, num2) {
return num1 - num2;
}
});
JS Bin Example
The output in the console is a correctly sorted array with all the rankings, I just don't have any idea how to also swap the corresponding <tr>'s so that the table get's rebuild the right way. Looking for any tips or pointers!
This suggestion is not really into "sorting" the rows, but re-constructing the table with the sorted rows. But this should do the job:
rankings = rankings.sort(sortNumber);
var table = $('<table></table>');
for (var i = 0; i < rankings.length; i++) {
var row = $('tr').filter(function() {
var rank = $(this).find('#tdp').text();
return rank.substring(1, rank.length) == i;
});
table.append(row);
}
$('#originalTable').html(table.html());

Limit dynamically added columns to table

Please take a look at this fiddle example. I'm adding new columns using AJAX on click. Is there a way to count the columns of the table and limit the number of new columns to 6? Could anyone give me suggestions?
jQuery:
$(function () {
var ajaxfunction = function(){
$('.area').on("click","button", function(){
var source = $(this).data('feed');
$.ajax({
url: source,
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
year = item.year,
job = item.Job,
education = item.Education,
background = item.Background,
ingredient = item.Ingredient;
$('#header').after('<th>'+title+'</th>')
$('#ingredient').after('<td>'+ingredient+'</td>')
$('#year').after('<td>'+year+'</td>')
$('#background').after('<td>'+background+'</td>')
$('#education').after('<td>'+education+'</td>')
$('#job').after('<td>'+job+'</td>')
});
$('#toptable').stickyTableHeaders(); //Fixed Header Plugin
},
});
});
}
ajaxfunction();
});
HTML
<div class="area">
<button>Class B</button>
<button>Class C</button>
<button>Class D</button>
</div>
<table id="toptable">
<thead>
<tr>
<th id="header" style="visibility:hidden">-</th>
</tr>
</thead>
<tbody>
<tr>
<td id="ingredient">Ingredient</td>
</tr>
<tr>
<td id="year">Year</td>
</tr>
<tr>
<td id="background">Background</td>
</tr>
<tr>
<td id="education">Education</td>
</tr>
<tr>
<td id="job">Job</td>
</tr>
</tbody>
</table>
Get Column Count (If you start using colspans this will need to change to reflect that):
var colcount = $("#toptable").find("tr:first th").length; or
var colcount = $("tr:first th", "#toptable").length; or
var colcount = $("#toptable tr:first th").length;
Limit the number of columns (tested and working):
$('.area').on("click","button", function(){
var colspan = $("#toptable tr:first th").length;
alert("Current number of Columns = " + colspan);
if(colspan > 6)
{
alert("Too Many Columns");
return false;
}
var source = $(this).data('feed');
//the rest of your code
});
See this working Fiddle
NOTE: Because you are adding columns on an Ajax Success result, the column count is only true at the time of the click event. This means that the column count could be more once the Ajax Response arrives. You need to either cancel the request if there is an Ajax call in progress, or redesign so that you're not making so many HTTP calls (which is bad practice anyway, something like 68% of all performance improvements on the web are found in reducing HTTP calls.)

table mapping by th and first td in row to populate from json object

using php to echo json array inline i want js/jquery to populate table according to these data.
HTML table
<table>
<thead>
<tr>
<th>Time</th>
<th data-day='2013-03-15'>15-3</th>
<th data-day='2013-03-16'>16-3</th>
<th data-day='2013-03-17'>17-3</th>
</tr>
</thead>
<tbody>
<tr data-time='09'>
<td>9am</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<script>
var arr=[
{"date":"2013-03-15","id":"4","time_booked":"09:00:00"},
{"date":"2013-03-15","id":"1","time_booked":"09:10:00"},
{"date":"2013-03-17","id":"5","time_booked":"09:30:00"}
];
$.each(arr,function(){
console.log('id:'+this.id+'inside:'+this.date+'|'+this.time_booked);
});
</script>
i want to loop thro arr and according to its date and time_booked write id inside td.
for example first row will go to td with date-day='2013-03-15' and data-time='09'
so how can i do this using javascript ?
im thinking should i include data-day,data-time inside each td in tbody ? or is there a better way to do it ?
current approach:
include data-day inside each tr so html of tbody is
<tr data-time='09'>
<td data-day='2013-03-15'></td>
<td data-day='2013-03-16'></td>
etc..
</tr>
then use js
$.each(arr,function(){
var rday=this.date;
var rtime=this.time_booked;
var sel='tr[data-hr="'+rtime.substr(0,2)+'"]';
var dom=$(sel).find('td[data-day="'+rday+'"]').first();
if(dom.length)dom.append(this.id);
});
but i have a feeling its stupid ! there must be a way to map table using x,y (table head,row head) or there is none ?
I think the jQuery index function is what you're looking for. In the code sample below, I've used it to fetch the colIndex for the date. In this case, it fetches all of the th cells within the table, and uses .index(..) with a selector seeking the required date. This gives the column index of the date you're seeking, and from there it's all pretty straight-forward.
var arr=[
{"date":"2013-03-15","id":"4","time_booked":"0900"},
{"date":"2013-03-15","id":"1","time_booked":"0910"},
{"date":"2013-03-17","id":"5","time_booked":"0930"}
];
$.each(arr,function(){
var cell = GetCellByDateAndTime(this.date, this.time_booked);
$(cell).text(this.id);
});
function GetCellByDateAndTime(date, time) {
var colIndex = $("#BookingsTable th").index($("[data-day='" + date + "']"));
var row = $("#BookingsTable tr[data-time='" + time + "']")
var cell = $(row).children($("td"))[colIndex];
return cell;
}
And a Fiddle.

Delete all rows in an HTML table

How can I delete all rows of an HTML table except the <th>'s using Javascript, and without looping through all the rows in the table? I have a very huge table and I don't want to freeze the UI while I'm looping through the rows to delete them
this will remove all the rows:
$("#table_of_items tr").remove();
Keep the <th> row in a <thead> and the other rows in a <tbody> then replace the <tbody> with a new, empty one.
i.e.
var new_tbody = document.createElement('tbody');
populate_with_new_rows(new_tbody);
old_tbody.parentNode.replaceChild(new_tbody, old_tbody)
Very crude, but this also works:
var Table = document.getElementById("mytable");
Table.innerHTML = "";
Points to note, on the Watch out for common mistakes:
If your start index is 0 (or some index from begin), then, the correct code is:
var tableHeaderRowCount = 1;
var table = document.getElementById('WRITE_YOUR_HTML_TABLE_NAME_HERE');
var rowCount = table.rows.length;
for (var i = tableHeaderRowCount; i < rowCount; i++) {
table.deleteRow(tableHeaderRowCount);
}
NOTES
1. the argument for deleteRow is fixed
this is required since as we delete a row, the number of rows decrease.
i.e; by the time i reaches (rows.length - 1), or even before that row is already deleted, so you will have some error/exception (or a silent one).
2. the rowCount is taken before the for loop starts
since as we delete the "table.rows.length" will keep on changing, so again you have some issue, that only odd or even rows only gets deleted.
Hope that helps.
This is an old question, however I recently had a similar issue.
I wrote this code to solve it:
var elmtTable = document.getElementById('TABLE_ID_HERE');
var tableRows = elmtTable.getElementsByTagName('tr');
var rowCount = tableRows.length;
for (var x=rowCount-1; x>0; x--) {
elmtTable.removeChild(tableRows[x]);
}
That will remove all rows, except the first.
Cheers!
If you can declare an ID for tbody you can simply run this function:
var node = document.getElementById("tablebody");
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
Assuming you have just one table so you can reference it with just the type.
If you don't want to delete the headers:
$("tbody").children().remove()
otherwise:
$("table").children().remove()
hope it helps!
I needed to delete all rows except the first and solution posted by #strat but that resulted in uncaught exception (referencing Node in context where it does not exist). The following worked for me.
var myTable = document.getElementById("myTable");
var rowCount = myTable.rows.length;
for (var x=rowCount-1; x>0; x--) {
myTable.deleteRow(x);
}
the give below code works great.
It removes all rows except header row. So this code really t
$("#Your_Table tr>td").remove();
this would work iteration deletetion in HTML table in native
document.querySelectorAll("table tbody tr").forEach(function(e){e.remove()})
Assing some id to tbody tag. i.e. . After this, the following line should retain the table header/footer and remove all the rows.
document.getElementById("yourID").innerHTML="";
And, if you want the entire table (header/rows/footer) to wipe out, then set the id at table level i.e.
How about this:
When the page first loads, do this:
var myTable = document.getElementById("myTable");
myTable.oldHTML=myTable.innerHTML;
Then when you want to clear the table:
myTable.innerHTML=myTable.oldHTML;
The result will be your header row(s) if that's all you started with, the performance is dramatically faster than looping.
If you do not want to remove th and just want to remove the rows inside, this is working perfectly.
var tb = document.getElementById('tableId');
while(tb.rows.length > 1) {
tb.deleteRow(1);
}
Pure javascript, no loops and preserving headers:
function restartTable(){
const tbody = document.getElementById("tblDetail").getElementsByTagName('tbody')[0];
tbody.innerHTML = "";
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<table id="tblDetail" class="table table-bordered table-hover table-ligth table-sm table-striped">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 2</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
a
</td>
<td>
b
</td>
<td>
c
</td>
<td>
d
</td>
</tr>
<tr>
<td>
1
</td>
<td>
2
</td>
<td>
3
</td>
<td>
4
</td>
<tr>
<td>
e
</td>
<td>
f
</td>
<td>
g
</td>
<td>
h
</td>
</tr>
</tr>
</tbody>
</table>
<button type="button" onclick="restartTable()">restart table</button>
If you have far fewer <th> rows than non-<th> rows, you could collect all the <th> rows into a string, remove the entire table, and then write <table>thstring</table> where the table used to be.
EDIT: Where, obviously, "thstring" is the html for all of the rows of <th>s.
This works in IE without even having to declare a var for the table and will delete all rows:
for(var i = 0; i < resultsTable.rows.length;)
{
resultsTable.deleteRow(i);
}
this is a simple code I just wrote to solve this, without removing the header row (first one).
var Tbl = document.getElementById('tblId');
while(Tbl.childNodes.length>2){Tbl.removeChild(Tbl.lastChild);}
Hope it works for you!!.
Assign an id or a class for your tbody.
document.querySelector("#tbodyId").remove();
document.querySelectorAll(".tbodyClass").remove();
You can name your id or class how you want, not necessarily #tbodyId or .tbodyClass.
#lkan's answer worked for me, however to leave the first row, change
from
for (var x=rowCount-1; x>0; x--)
to
for (var x=rowCount-1; x>1; x--)
Full code:
var myTable = document.getElementById("myTable");
var rowCount = myTable.rows.length;
for (var x=rowCount-1; x>1; x--) {
myTable.deleteRow(x);
}
This will remove all of the rows except the <th>:
document.querySelectorAll("td").forEach(function (data) {
data.parentNode.remove();
});
Same thing I faced. So I come up with the solution by which you don't have to Unset the heading of table only remove the data..
<script>
var tablebody =document.getElementById('myTableBody');
tablebody.innerHTML = "";
</script>
<table>
<thead>
</thead>
<tbody id='myTableBody'>
</tbody>
</table>
Try this out will work properly...
Assuming the <table> element is accessible (e.g. by id), you can select the table body child node and then remove each child until no more remain. If you have structured your HTML table properly, namely with table headers in the <thead> element, this will only remove the table rows.
We use lastElementChild to preserve all non-element (namely #text nodes and ) children of the parent (but not their descendants). See this SO answer for a more general example, as well as an analysis of various methods to remove all of an element's children.
const tableEl = document.getElementById('my-table');
const tableBodyEl = tableEl.querySelector('tbody');
// or, directly get the <tbody> element if its id is known
// const tableBodyEl = document.getElementById('table-rows');
while (tableBodyEl.lastElementChild) {
tableBodyEl.removeChild(tableBodyEl.lastElementChild);
}
<table id="my-table">
<thead>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
</thead>
<tbody id="table-rows">
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<!-- comment child preserved -->
text child preserved
<tr>
<td>Banana</td>
<td>Yellow</td>
</tr>
<tr>
<td>Plum</td>
<td>Purple</td>
</tr>
</tbody>
</table>
Just Clear the table body.
$("#tblbody").html("");
const table = document.querySelector('table');
table.innerHTML === ' ' ? null : table.innerHTML = ' ';
The above code worked fine for me. It checks to see if the table contains any data and then clears everything including the header.

Categories