Can plotly use a dynamic html table as source data? - javascript

If I have an html table that contains values that are calculated based on filters within my file, can I get plotly to read and produce a plot based on those values?
I'm not sure that it matters to answering this question, but I use R primarily, and use the r code chunks calculate sums from a sharedData object names shared_ert that I created with the crosstalk package for R.
<table id="example" class="cell-border" style="width:100%">
<tr>
<th>Enrolled</th>
<th>Not Enrolled</th>
</tr>
<tr>
<td>
```{r, echo=FALSE, collapse=TRUE, warning=FALSE, message=FALSE}
summarywidget::summarywidget(shared_ert,statistic = 'sum',column = 'Enrolled')
```
</td>
<td>
```{r, echo=FALSE, collapse=TRUE, warning=FALSE, message=FALSE}
summarywidget::summarywidget(shared_ert,statistic = 'sum',column = 'Not Enrolled')
```
</td>
</tr>
</table>
Note that summary widget ends up producing a span tag within each td.
The spans look like <span id ="waffle" class="summarywidget html-widget html-widge-static-bound">1293</span>
So the table ends up looking like:
<table id="example" class="cell-border" style="width:100%">
<tr>
<th>Enrolled</th>
<th>Not Enrolled</th>
</tr>
<tr>
<td>
<span id ="waffle" class="summarywidget html-widget html-widge-static-bound">1293</span>
<script type="application/json" data-for="waffle">
### a bunch of data appears here, from which the 1293 value is derived
</script>
</td>
<td>
<span id ="iron" class="summarywidget html-widget html-widge-static-bound">948</span>
<script type="application/json" data-for="iron">
### a bunch of data appears here, from which the 948 value is derived
</script>
</td>
</tr>
</table>
From my limited understanding of the world of javascript, I need my data to look something like
var data = [
{
x: ['giraffes', 'orangutans', 'monkeys'],
y: [20, 14, 23],
type: 'bar'
}
];
So that I can get a plot produced with something like:
Plotly.newPlot('myDiv', data);
(directly from https://plotly.com/javascript/bar-charts/)
If I understand the problem correctly, I need to read the html table example and create a var that holds the table. After much searching around SO and the web in general, my guess is that the solution here: HTML Table to JSON pulls the table into the correct format. I'm trying
```{js}
function tableToJson(table) {
var data = [];
// first row needs to be headers
var headers = [];
for (var i=0; i<table.rows[0].cells.length; i++) {
headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
}
// go through cells
for (var i=1; i<table.rows.length; i++) {
var tableRow = table.rows[i];
var rowData = {};
for (var j=0; j<tableRow.cells.length; j++) {
rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
return data;
}
var tabdata = $document.getElementById('#example').tableToJSON();
```
I think from here, I need plotly to read the data from the table in it's current state, so I produce the plot using a button and onclick, as follows:
<button type="button" onclick="Plotly.newPlot('myDiv',tabdata);">Make Plot</button>
Upon clicking, the plotly plot appears, but doesn't have a data point anywhere.
I might be way off track in my methodology, so I defer to the original question: can I get plotly to read and produce a plot based on a dynamic html table?
Any help establishing a means to this end would be very much appreciated.

You need generate your json with keys x & y .So , here x value will be your header i.e : th tags and y values will be tdvalues . Now , if you have only one row in your table you can simply create JSON Object and then push value inside this using key i.e : data["x"] , data["y"]..etc .
Demo Code :
function tableToJSON(table) {
var data = {}; //create obj
data["x"] = [] //for x & y
data["y"] = []
data["type"] = "bar"
for (var i = 0; i < table.rows[0].cells.length; i++) {
data["x"].push(table.rows[0].cells[i].innerHTML.toLowerCase().trim()); //push x values
}
for (var i = 1; i < table.rows.length; i++) {
var tableRow = table.rows[i];
for (var j = 0; j < tableRow.cells.length; j++) {
data["y"].push(parseInt(tableRow.cells[j].querySelector(".summarywidget").textContent.trim()));
//push y values
console.log(tableRow.cells[j].querySelector(".summarywidget").textContent.trim())
}
}
return data;
}
function draw() {
var tabdata = tableToJSON(document.getElementById('example'));
tester = document.getElementById('tester');
Plotly.newPlot(tester, [tabdata])
}
<script src="https://cdn.plot.ly/plotly-2.1.0.min.js"></script>
<table id="example" class="cell-border" style="width:100%">
<tr>
<th>Enrolled</th>
<th>Not Enrolled</th>
</tr>
<tr>
<td>
<span id="waffle" class="summarywidget html-widget html-widge-static-bound">1293</span>
<script type="application/json" data-for="waffle">
###
a bunch of data appears here, from which the 1293 value is derived
</script>
</td>
<td>
<span id="iron" class="summarywidget html-widget html-widge-static-bound">948</span>
<script type="application/json" data-for="iron">
###
a bunch of data appears here, from which the 948 value is derived
</script>
</td>
</tr>
</table>
<button type="button" onclick="draw()">Make Plot</button>
<div id="tester" style="width:600px;height:250px;"></div>
Now , if you have mutliple rows in your table you need to generate JSON Array of that values .For that you need to keep main_array and then push values inside this main_array on each iterations.
Demo Code :
function tableToJSON(table) {
var main_array = [] //for main array
var for_x = [] //for x values
for (var i = 0; i < table.rows[0].cells.length; i++) {
for_x.push(table.rows[0].cells[i].innerHTML.toLowerCase().trim()); //push value
}
for (var i = 1; i < table.rows.length; i++) {
var tableRow = table.rows[i];
var data = {}; //create obj..
data["y"] = [] //for y values
for (var j = 0; j < tableRow.cells.length; j++) {
data["y"].push(parseInt(tableRow.cells[j].innerHTML.trim())); //push y values
}
//save other values..
data["x"] = for_x
data["type"] = "bar"
data["name"] = "Rows" + i
main_array.push(data) //push values in main array
}
//console..[{},{}..]
return main_array;
}
function draw() {
var tabdata = tableToJSON(document.getElementById('example'));
tester = document.getElementById('tester');
//pass it here
Plotly.newPlot(tester, tabdata, {
barmode: 'stack'
})
}
<script src="https://cdn.plot.ly/plotly-2.1.0.min.js"></script>
<table id="example" class="cell-border" style="width:100%">
<tr>
<th>Enrolled</th>
<th>Not Enrolled</th>
</tr>
<tr>
<td>
123
</td>
<td>
125
</td>
</tr>
<tr>
<td>
121
</td>
<td>
127
</td>
</tr>
</table>
<button type="button" onclick="draw()">Make Plot</button>
<div id="tester" style="width:600px;height:250px;"></div>

Related

Getting a checkbox from a table field

Good afternoon, below is the code in it I am getting fields from my table. The 0 field contains a checkbox, how can I find out if it is checked or not(true or false)? You need to change this line: console.log (td.item (f));
var table = document.getElementsByClassName("table-sm");
for (var i = 0; i < table.length; i++) {
var tr = table.item(i).getElementsByTagName("tr");
for (var j = 0; j < tr.length; j++) {
var trr = tr.item(j);
var td = tr.item(j).getElementsByTagName("td");
for (var f = 0; f < td.length; f++) {
if (f === 0) console.log(td.item(f));
console.log(td.item(f).innerText);
}
}
}
Firstly, please learn about JavaScript Table API is much better than just making complex for-loops.
Next time please add full code (HTML/JavaScript) so people can help you.
Now let's fix your code.
Suppose we have this table
<table class="table-sm" id="myTable">
<thead>
<tr>
<th>Checkbox</th>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="selected[]" checked /></td>
<td>1</td>
<td>Mohammed</td>
</tr>
<tr>
<td><input type="checkbox" name="selected[]" /></td>
<td>2</td>
<td>Ali</td>
</tr>
</tbody>
</table>
and we want to get the first item of each rows, and check whether the checkbox is checked or not.
We can do it easly using JS Table APIs.
Get the table by it's ID.
var table = document.getElementById("myTable");
Get the table rows
I use Array.from() to convert HTMLCollection to normal array, so I can use Array APIs (Like .forEach).
var rows = Array.from(table.rows);
Loop into table rows, and get cells of each row.
rows.map((row) => {
var cells = Array.from(row.cells);
// TODO add logic here.
});
Get the firstChild of first cell.
rows.map((row) => {
var cells = Array.from(row.cells);
if (Array.isArray(cells) && cells.length > 0) {
var firstChild = cells[0].firstChild;
console.log(firstChild.checked);
}
});
Live Example

How to find the last table cell which doesn't have text value and put a message?

I want to detect the last table row cell of a table which doesn't have any value (text).
var all_product_cell = document.getElementsByClassName("product-cell");
for (var i = 0; i < all_product_cell.length; i++) {
var td = all_product_cell[i];
alert(all_product_cell.length);
}
This code returns the table rows length... but I don't know how to check the last row which is clean and put there a message "hello!"...
UPDATE :
With this code system find last cell and put HELLO, but how I check the last cells who haven't text value and put the Hello there?
var all_local_cell = document.getElementsByClassName("product-cell");
for (var i = 0; i < all_local_cell.length; i++) {
var td = all_local_cell[i];
total_rows = all_local_cell.length-1;
all_product_cell[total_rows].value = "HELLO";
const productTable = document.querySelector(".your-product-table"); // get the table
const textOnLastCell = productTable
.rows[productTable.rows.lenght -1] // get last row
.cells[productTable.rows[productTable.rows.lenght -1].cells.lenght -1] // get last cell of last row
.innerText // get inner text
You can get last row of table by using below line :
var product_table = document.getElementsByClassName("product-cell");
console.log(product_table);
for (var i = 0; i < product_table.length; i++) {
total_rows = product_table[i].rows.length;
last_row = product_table[i].rows[total_rows-1];
last_row_length = last_row.cells.length;
last_column = last_row.cells[last_row_length-1]; // directly get last cell
If(last_column.innerHTML() == “”){
last_column.innerHTML = “Hello friend”;
}
console.log(last_column.innerHTML);
for(var j =0;j<last_row.cells.length;j++){ // you can find through loop using which cells is empty
console.log(last_row.cells[j]);
}
// console.log(last_row);
}
If you give html code will help better way.
https://codepen.io/aviboy2006/pen/ZEYBWWE
Here's a table with two empty TD'S.
The function will get an array of all TD's with the class product-cell and loop through each cell and check if innerHTML is empty, and then it will set lastTD to the last empty TD and set its innerHTML to "Hallo"
setTextLastEmptyCell()
function setTextLastEmptyCell(){
let tds = document.getElementsByClassName('product-cell')
for(let td of tds){
if(td.innerHTML === '') lastTD = td
}
lastTD.innerHTML = 'HALLO'
}
<table>
<tr>
<td class="product-cell">ABC</td>
<td class="product-cell">DEF</td>
<td class="product-cell">CBA</td>
</tr>
<tr>
<td class="product-cell"></td>
<td class="product-cell">CDA</td>
<td class="product-cell">ACB</td>
</tr>
<tr>
<td class="product-cell">ABC</td>
<td class="product-cell"></td>
<td class="product-cell">DEF</td>
</tr>
</table>

Dynamically delete multiple columns in html table

I am trying to delete multiple columns from html table using javascript.
The logic it is using is that it searches in top row for tag "" and then deletes that column.
The problem is if only one cell in top row is having '', then it deletes that columns fine, but if there are multiple columns it throws error.
Here is my code
<!DOCTYPE html>
<html>
<body>
<table style="width:100%" border='1' id='Just_for_california'>
<tr>
<td><span></span></td>
<td>S</td>
<td><span></span></td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
<script>
var dataTable_length = document.getElementById('Just_for_california').rows[0].cells.length;
var count_rows = document.getElementById('Just_for_california').rows.length;
var column_array = [];
for(var i=0; i<dataTable_length; i++)
{
var str = document.getElementById("Just_for_california").rows[0].cells[i].innerHTML;
if(str.search("<span></span>") != -1)
{
column_array.push(i);
}
}
var len = column_array.length;
for(var i=count_rows-1 ; i>=0;i--)
{
rows_number = document.getElementById('Just_for_california').rows[i];
console.log("row_number:"+i);
for(var j=0; j<len;j++)
{
rows_number.deleteCell(column_array[j]);
}
}
</script>
</html>
It happens because you calculate indexes incorrectly when you delete cells. I refactored you code (making it clearer) and it seems to work now:
var table = document.getElementById('Just_for_california'),
rows = table.rows;
for (var i = 0; i < rows[0].cells.length; i++) {
var str = rows[0].cells[i].innerHTML;
if (str.search("<span></span>") != -1) {
for (var j = 0; j < rows.length; j++) {
rows[j].deleteCell(i);
}
}
}
The problem is that you are trying to remove cells "horizontally" in the row. So say you want to delete cells at indexes 1 and 3 and there are 4 columns in the table. When you delete the first cell 1 it works fine. However then you move to the right and try to remove cell at index 3. This fails because since you have already removed cell 1, there is no cell with index 3 anymore. The maximum index now is 2. Hence the error.
In my improved code I'm removing columns "vertically", so such an issue can't happen.
Demo: http://jsfiddle.net/t2q60aag/

Sorting function in javascript

Hi I have html structure with table. I want to sort td according to their value. I trying it but cant find the logic to make it happen. My function is
<head>
<script type="text/javascript">
function sorting(){
var sortvalue= document.getElementsByTagName('td');
for(i=0; i<sortvalue.length;i++){
var val= sortvalue[i].value
}
}
</script>
</head>
<body>
<table width="500" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>5</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
</table>
click to sort
</body>
If you plan to do more than just organize those numbers: those saying you should use a plugin are correct. It'd take more effort than it's worth to try to make your own table sorter.
If all you want to do is sort those numbers (small to large):
function sorting() {
td = document.getElementsByTagName("td");
sorted = [];
for (x = 0; x < td.length; x++)
sorted[x] = Number(td[x].innerHTML);
sorted.sort();
for (x = 0; x < sorted.length; x++)
td[x].innerHTML = sorted[x];
}
Largest to smallest:
function sorting() {
td = document.getElementsByTagName("td");
sorted = [];
for (x = 0; x < td.length; x++)
sorted[x] = Number(td[x].innerHTML);
sorted.sort().reverse();
for (x = 0; x < sorted.length; x++)
td[x].innerHTML = sorted[x];
}
Assuming that you're putting the script under your link, or adding it on domready:
function sorting(){
var tbl = document.getElementsByTagName('table')[0];
var store = [];
for(var i=0, len=tbl.rows.length;i<len; i++){
var row = tbl.rows[i];
var sortnr = parseFloat(row.cells[0].textContent || row.cells[0].innerText);
if(!isNaN(sortnr)) store.push([sortnr, row]);
}
store.sort(function(x,y){
return x[0] - y[0];
});
for(var i=0, len=store.length; i<len; i++){
tbl.appendChild(store[i][1]);
}
store = null;
}
link here: http://jsfiddle.net/UMjDb/
For your example you can make an array of the cell data from the node list and sort that array, and then replace the cells data with the sorted data. Simpler than moving elements.
<head>
<script type= "text/javascript">
function sorting(){
var T= [], tds= document.getElementsByTagName('td');
for(var i= 0;i<tds.length;i++){
T.push(tds[i].firstChild.data);
}
T.sort(function(a, b){
return a-b
});
for(var i= 0;i<tds.length;i++){
tds[i].replaceChild(document.createTextNode(T[i]), tds[i].firstChild);
}
}
</script>
</head>
<body>
<table width= "500" border= "0" cellspacing= "0" cellpadding= "0">
<tr>
<td>5</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
</table>
click to sort
</body>
i giving a jquery solution, hope this post helps you.
var tdData = Array();
$(document).ready(function(){
$('td').each(function(i){
tdData [i] = $(this).text();
});
});
function sorting(){
var sortedData = tdData.sort();
$('td').each(function(i){
$(this).text(sortedData[i]);
} );
}
complete solution: link
step 1: find all td's
step 2: fetch their values
step 3: sort them on their values
step 4: put them back into their parent in the correct order. This can simply be done with an $(parent).html("").append(sortedNodes) (if you use jQuery that is).
As #FelixKling points out below, the .html("") is not strictly necessary other than for code clarity since "If you have nodes that already exist in the tree, then .append will remove them first from their current location and add them to the new parent"
You need to re-organise the table.
The simplest approach would be to use a plugin like this one for jQuery
You need to modify the DOM, they would be different way to do that, like grabbing all the data, removing all the rows and adding them back in the right order.
It could be improved better using detach and reattaching.

Get a particular cell value from HTML table using JavaScript

I want to get each cell value from an HTML table using JavaScript when pressing submit button.
How to get HTML table cell values?
To get the text from this cell-
<table>
<tr id="somerow">
<td>some text</td>
</tr>
</table>
You can use this -
var Row = document.getElementById("somerow");
var Cells = Row.getElementsByTagName("td");
alert(Cells[0].innerText);
function Vcount() {
var modify = document.getElementById("C_name1").value;
var oTable = document.getElementById('dataTable');
var i;
var rowLength = oTable.rows.length;
for (i = 1; i < rowLength; i++) {
var oCells = oTable.rows.item(i).cells;
if (modify == oCells[0].firstChild.data) {
document.getElementById("Error").innerHTML = " * duplicate value";
return false;
break;
}
}
var table = document.getElementById("someTableID");
var totalRows = document.getElementById("someTableID").rows.length;
var totalCol = 3; // enter the number of columns in the table minus 1 (first column is 0 not 1)
//To display all values
for (var x = 0; x <= totalRows; x++)
{
for (var y = 0; y <= totalCol; y++)
{
alert(table.rows[x].cells[y].innerHTML;
}
}
//To display a single cell value enter in the row number and column number under rows and cells below:
var firstCell = table.rows[0].cells[0].innerHTML;
alert(firstCell);
//Note: if you use <th> this will be row 0, so your data will start at row 1 col 0
You can also use the DOM way to obtain the cell value:
Cells[0].firstChild.data
Read more on that in my post at http://js-code.blogspot.com/2009/03/how-to-change-html-table-cell-value.html
You can get cell value with JS even when click on the cell:
.......................
<head>
<title>Search students by courses/professors</title>
<script type="text/javascript">
function ChangeColor(tableRow, highLight)
{
if (highLight){
tableRow.style.backgroundColor = '00CCCC';
}
else{
tableRow.style.backgroundColor = 'white';
}
}
function DoNav(theUrl)
{
document.location.href = theUrl;
}
</script>
</head>
<body>
<table id = "c" width="180" border="1" cellpadding="0" cellspacing="0">
<% for (Course cs : courses){ %>
<tr onmouseover="ChangeColor(this, true);"
onmouseout="ChangeColor(this, false);"
onclick="DoNav('http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp?courseId=<%=cs.getCourseId()%>');">
<td name = "title" align = "center"><%= cs.getTitle() %></td>
</tr>
<%}%>
........................
</body>
I wrote the HTML table in JSP.
Course is is a type. For example Course cs, cs= object of type Course which had 2 attributes: id, title.
courses is an ArrayList of Course objects.
The HTML table displays all the courses titles in each cell. So the table has 1 column only:
Course1
Course2
Course3
......
Taking aside:
onclick="DoNav('http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp?courseId=<%=cs.getCourseId()%>');"
This means that after user selects a table cell, for example "Course2", the title of the course- "Course2" will travel to the page where the URL is directing the user: http://localhost:8080/Mydata/ComplexSearch/FoundS.jsp . "Course2" will arrive in FoundS.jsp page. The identifier of "Course2" is courseId. To declare the variable courseId, in which CourseX will be kept, you put a "?" after the URL and next to it the identifier.
I told you just in case you'll want to use it because I searched a lot for it and I found questions like mine. But now I found out from teacher so I post where people asked.
The example is working.I've seen.
Just simply.. #sometime when larger table we can't add the id to each tr
<table>
<tr>
<td>some text</td>
<td>something</td>
</tr>
<tr>
<td>Hello</td>
<td>Hel</td>
</tr>
</table>
<script>
var cell = document.getElementsByTagName("td");
var i = 0;
while(cell[i] != undefined){
alert(cell[i].innerHTML); //do some alert for test
i++;
}//end while
</script>
<td class="virtualTd" onclick="putThis(this)">my td value </td>
function putThis(control) {
alert(control.innerText);
}
I found this as an easiest way to add row . The awesome thing about this is that it doesn't change the already present table contents even if it contains input elements .
row = `<tr><td><input type="text"></td></tr>`
$("#table_body tr:last").after(row) ;
Here #table_body is the id of the table body tag .
Here is perhaps the simplest way to obtain the value of a single cell.
document.querySelector("#table").children[0].children[r].children[c].innerText
where r is the row index and c is the column index
Therefore, to obtain all cell data and put it in a multi-dimensional array:
var tableData = [];
Array.from(document.querySelector("#table").children[0].children).forEach(function(tr){tableData.push(Array.from(tr.children).map(cell => cell.innerText))});
var cell = tableData[1][2];//2nd row, 3rd column
To access a specific cell's data in this multi-dimensional array, use the standard syntax: array[rowIndex][columnIndex].
Make a javascript function
function addSampleTextInInputBox(message) {
//set value in input box
document.getElementById('textInput').value = message + "";
//or show an alert
//window.alert(message);
}
Then simply call in your table row button click
<td class="center">
<a class="btn btn-success" onclick="addSampleTextInInputBox('<?php echo $row->message; ?>')" title="Add" data-toggle="tooltip" title="Add">
<span class="fa fa-plus"></span>
</a>
</td>

Categories

Resources