HTML Table export with jsPDF not responsive - javascript

why my table in pdf file like this ? i really confused about this.
table in pdf
table in html
package used: jsPDF
function for generate pdf
function generatePdf() {
var doc = new jsPDF("p", "pt", "a4");
var pdfjs = document.querySelector("#toPDF");
doc.html(pdfjs, {
callback: function (doc) {
doc.save("output.pdf");
},
});
}
table code
<table class="w-full mt-1">
<thead>
<tr>
<th>No</th>
<th>Jenis Saham</th>
<th>Pemilik</th>
<th>Jumlah Saham</th>
<th>Persentase Saham (%)</th>
<th>Nilai (dalam Rupiah)</th>
</tr>
</thead>
<tbody>
<tr class="w-full text-center">
<td>1</td>
<td>asd</td>
<td>10</td>
<td>10</td>
<td>10</td>
<td>Rp. 100</td>
</tr>
</tbody>
</table>
i expect normal table
expect result

Related

Programmatically create HTML table from D3 nested JSON object

I'm trying to make tables for a dashboard using React/D3. One of them is similar to this HTML hard-coded table which I'm trying to make:
table, td{
border: 1px solid black;
}
<table>
<thead>
<td>Location</td>
<td>State</td>
<td># Jobs</td>
</thead>
<tbody>
<tr>
<td rowspan="2">Cell 1 spanning if we have multiple values for this key</td>
<td>SUCCESSFUL</td>
<td>75</td>
</tr>
<tr>
<td>FAILED</td>
<td>22</td>
</tr>
</tbody>
</table>
<br />
Data
The data is retrieved from a SQL-Server database through node-mssql and express and then stored in react state, I pull 7 days worth of data and filter this down to 1 day per component in my react app as i need it.
It returns as normal and has NO nesting in it e.g.
{
"location": "Ireland",
"state": "Finished",
"finish_time": "2018-10-18T12:00:00",
"seconds_passed": 30
}
D3
With D3 I aggregated this data so that, it would be aggregated by location, then by state and then a count of the rows in that aggregation. I achieved this with nest and rollup:
dailyJobStatusCounts = () => {
return (
nest()
.key( row => row.location)
.key( row => row.state)
.rollup(function(values) { return values.length; })
.entries(this._filterTwentyFourHours())
);
}
This returns an object that looks like this:
[{"key":"Ireland","values":[{"key":"SUCCEEDED","value":14},{"key":"FAILED","value":7}]}]
Rendering to HTML in React
My issue occurs around my lack of understanding of how to render this nested JSON object as a HTML table. When attempting to render, I have tried two variations:
React
<table>
<thead>
<tr>
<th>Location</th>
<th>State</th>
<th># Jobs</th>
</tr>
</thead>
<tbody>
{data.map(row => {
return <tr>
<td>{row.key}</td>
{ row.values.map( v => {
return <React.Fragment>
<td>{v.key}</td>
<td>{v.value}</td>
</React.Fragment>
})}
</tr>
})}
</tbody>
</table>
Which renders the table like this:
HTML Output
table, td {
border: 1px solid black;
}
<table>
<thead>
<tr>
<th>Location</th>
<th>State</th>
<th>Jobs</th>
</tr>
</thead>
<tbody>
<tr>
<td>ie11</td>
<td>SUCCEEDED</td>
<td>14</td>
<td>FAILED</td>
<td>7</td>
</tr>
</tbody>
</table>
Or the other variation:
React
<table>
<thead>
<tr>
<th>Location</th>
<th>State</th>
<th># Jobs</th>
</tr>
</thead>
<tbody>
{data.map(row => {
return <tr>
<td>{row.key}</td>
{ row.values.map( v => {
return <tr>
<td>{v.key}</td>
<td>{v.value}</td>
</tr>
})}
</tr>
})}
</tbody>
</table>
HTML Output
table, td {
border: 1px solid black;
}
<table>
<thead>
<tr>
<th>Location</th>
<th>State</th>
<th># Jobs</th>
</tr>
</thead>
<tbody>
<tr>
<td>ie11</td>
<tr>
<td>SUCCEEDED</td>
<td>13</td>
</tr>
<tr>
<td>FAILED</td>
<td>7</td>
</tr>
</tr>
</tbody>
</table>
I see that some of the HTML being output for table is not valid as I have nested values, however I am struggling to get my head around how I can map this JSON object to display the HTML table with the rowspan mentioned at the beginning of this question. Thanks in advance for any answers.
Looked at a somewhat similar SO question which is close, but I'm not sure it answers my use-case here

How to make footable work in a table that's being populated with JS from JSON?

I have something like this:
<table id="thatTable" class="table toggle-circle">
<thead>
<tr>
<th>ID</th>
<th>FieldA</th>
<th data-hide="all">FieldB</th>
<th data-hide="all">FieldC</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="text-right">
<ul class="pagination"></ul>
</div>
</td>
</tr>
</tfoot>
</table>
Then a JS like this:
var fillThatTable = function (list) {
$.each(list, function (index, item) {
$('#thatTable tbody').append($('<tr>')
.append($('<td>').text(item.ID))
.append($('<td>').text(item.FieldA))
.append($('<td>').text(item.FieldB))
.append($('<td>').text(item.FieldC))
)
);
});
};
Everything works fine, the table gets the data and shows it all. Problem comes when I want to set footable() to that table, like so:
$(document).ready(function () {
fillThatTable();
$('#thatTable').footable();
});
And instead of getting something beautiful, I just receive an average filtered table, almost like I didn't put that $('#thatTable').footable(). I checked the JS are imported, they are. Is it maybe because the table doesn't have anything in the tbody? What am I missing?
Dream:
Reality:
I've updated PM's fiddle to make an easier use of FooTable: http://jsfiddle.net/0pb4x7h6/1
If your html changes to this:
<table id="thatTable" class="table toggle-circle">
<thead>
<tr>
<th data-name="ID">ID</th>
<th data-name="FieldA">FieldA</th>
<th data-name="FieldB" data-breakpoints="all">FieldB</th>
<th data-name="FieldC" data-breakpoints="all">FieldC</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="text-right">
<ul class="pagination"></ul>
</div>
</td>
</tr>
</tfoot>
</table>
Then you can simplify your script to this:
$(document).ready(function () {
var list = [
{"ID":"1","FieldA":"A1","FieldB":"B1","FieldC":"C1"},
{"ID":"2","FieldA":"A2","FieldB":"B2","FieldC":"C2"},
{"ID":"3","FieldA":"A3","FieldB":"B3","FieldC":"C3"}
];
// No need for this
//fillThatTable();
$('#thatTable').footable({
rows: list
});
});

Access each individual custom cell with Angular bootstrap calendar

I'm working on an app where I need a calendar skeleton (without the standard events) so I can put tables inside each cell, so I'm using the Angular Bootstrap Calendar with custom cell templates. I have everything working fine in terms of displaying the custom template in each cell and being able to navigate between months, but I need to be able to access each individual day and make data available in each one.
Here's my controller:
(function() {
angular.module('myApp')
.controller('calendarController', function($scope, $state, moment, calendarConfig) {
var vm = this;
calendarConfig.templates.calendarMonthCell = 'views/calendar/dayTemplate.html';
calendarConfig.dateFormatter = 'moment';
vm.events = [];
vm.calendarView = 'month';
vm.viewDate = moment().startOf('month').toDate();
$scope.$on('$destroy', function() {
calendarConfig.templates.calendarMonthCell = 'mwl/calendarMonthCell.html';
});
});
})();
and the corresponding dayTemplate.html:
<div class="cal-month-day">
<span
class="pull-right"
data-cal-date
ng-click="calendarCtrl.dateClicked(day.date)"
ng-bind="day.label">
</span>
<!--
<small style="position: absolute; bottom: 10px; left: 5px">
There are {{ day.events.length }} events on this day
</small> -->
<!-- <table class="table table-bordered table-condensed"> -->
<table class="table table-bordered table-condensed">
<thead>
<tr>
<td>Station</td>
<td>Position</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3" align="top">1</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
<table class="table table-bordered table-condensed">
<tbody>
<tr>
<td rowspan="3" align="top">2</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
<table class="table table-bordered table-condensed">
<tbody>
<tr>
<td rowspan="3" align="top">3</td>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
<tr>
<td>Position</td>
<td>Name</td>
</tr>
</tbody>
</table>
</div>
When using the calendar as it normally is used, you can see that the days.events object has the data, but I need to access that object, or create my own so I can fill my tables. Is there a simple (or even not so simple) way to do that?
Thanks.
UPDATE: I just went back and read the docs and noticed this
An optional expression that is evaluated on each cell generated for
the year and month views. calendarCell can be used in the expression
and is an object containing the current cell data which you can modify
(see the calendarHelper service source code or just console.log it to
see what data is available). If you add the cssClass property it will
be applied to the cell.
Due to my lack of knowledge, I'm not understanding how to use this to override. If I console.log calendarCell in my calendarController it chokes because that object doesn't exist. If I'm reading this correctly, I can intercept the cell data and modify, but I'm not understanding how.
In this case, RTFM turned out to be the correct answer. Per the docs:
<div ng-controller="CellModifierCtrl as vm">
<ng-include src="'calendarControls.html'"></ng-include>
<mwl-calendar
events="vm.events"
view="vm.calendarView"
view-date="vm.viewDate"
cell-modifier="vm.cellModifier(calendarCell)">
</mwl-calendar>
</div>
goes with this in the controller:
vm.cellModifier = function(cell) {
console.log(cell);
if (cell.label % 2 === 1 && cell.inMonth) {
cell.cssClass = 'odd-cell';
}
cell.label = '-' + cell.label + '-';
};
and voila!, you have access to the data. I'm still trying to figure out how to pass additional data into the function, but I'll open a separate question for that.

Getting all data in table base on some highlighted row

This is the scenario. I have a <table> like this:
<table>
<tr>
<th>No.</th>
<th>Name</th>
<th>Price</th>
</tr>
<tr>
<td>1</td>
<td>Coca cola</td>
<td>5</td>
</tr>
<tr>
<td>2</td>
<td>Pepsi</td>
<td>5</td>
</tr>
<tr>
<td>3</td>
<td>Water</td>
<td>3</td>
</tr>
</table>
Now, user will highlight 2 first rows, for example. My task is to extract the appropriate 3 XPaths to get data in each column.
Does anyone have any idea about this? I have thought about it a lot but haven't found any good solution yet. Please help me. Thanks a lot.
EDIT!!!
You can try using Scraper from Google Chrome extension for more detail. What I want is just a little bit like it. Thanks.
Let's say you add a class to the highlighted rows, and after highlighting your html DOM is like this:
<table id="highlights">
<tr>
<th>No.</th>
<th>Name</th>
<th>Price</th>
</tr>
<tr class="highlighted">
<td>1</td>
<td>Coca cola</td>
<td>5</td>
</tr>
<tr class="highlighted">
<td>2</td>
<td>Pepsi</td>
<td>5</td>
</tr>
<tr>
<td>3</td>
<td>Water</td>
<td>3</td>
</tr>
</table>
I added id="highlights" just to make it distingushable, if you have other tables in the page. then this is what you have to do:
var noXpath = "//table[#id='highlights']/tbody/tr[#class='highlighted']/td[1]/text()";
var nameXpath = "//table[#id='highlights']/tbody/tr[#class='highlighted']/td[2]/text()";
var priceXpath = "//table[#id='highlights']/tbody/tr[#class='highlighted']/td[3]/text()";
function getData(xpathQuery) {
var iterator = document.evaluate(xpathQuery, document.body, null, XPathResult.ANY_TYPE, null);
var nodes = [];
var node;
while (node = iterator.iterateNext()) {
nodes.push(node.nodeValue);
}
return nodes;
}
var noData=getData(noXpath);
var namesData=getData(nameXpath);
var priceData=getData(priceXpath);
and this is the working DEMO.

Javascript <tbody> swapping not working

I've got a couple tables whose content should change based on clicking certain buttons (in this case, links). I've used this Javascript code elsewhere successfully, though with only one parameter in the switchid() function (there was only one table to mess around with). I keep researching examples of this and I seem to be passing the variables correctly, so what am I doing wrong? This code doesn't work on Chrome or IE:
Edit: Per the comments, I was able to whittle my javascript section down to a single, smaller function, that should do the same thing. I have made the change below. It still doesn't work, though.
I also changed my "array" and "x" variables to "JonArray" and "JonX" to avoid any chances of one of those being a reserved word.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
var topTable = new Array('English','Spanish');
var bottomTable = new Array('Japanese','Italian');
function switchid(JonArray,JonX) {
for(var i=0;i<JonArray.length();i++) {
document.getElementById(JonX).style.display='none';
}
document.getElementById(JonX).style.display='table-row-group';
}
</script>
<table border='1'>
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td>English</td><td>Spanish</td></tr>
</tfoot>
<tbody id='English'>
<tr><td>One</td><td>Two</td></tr>
<tr><td>Three</td><td>Four</td></tr>
</tbody>
<tbody id='Spanish' style="display:none;">
<tr><td>Uno</td><td>Dos</td></tr>
<tr><td>Tres</td><td>Quatro</td></tr>
</tbody>
</table>
<br />
<table border='1'>
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td>Japanese</td><td>Italian</td></tr>
</tfoot>
<tbody id='Japanese'>
<tr><td>Ichi</td><td>Ni</td></tr>
<tr><td>San</td><td>Shi</td></tr>
</tbody>
<tbody id='Italian' style="display:none;">
<tr><td>Un</td><td>Due</td></tr>
<tr><td>Tre</td><td>Quattro</td></tr>
</tbody>
</table>
</body>
</html>
http://jsfiddle.net/92ZPM/1/
I made sure the function and variables were available regardless of when they are created.
I also gave your variables descriptive names, cleaned up and stored the table data in a single object.
JavaScript
window.switchid = function (table, language) {
var tables = {
'top': ['English', 'Spanish'],
'bottom': ['Japanese', 'Italian']
};
for (var i = 0; i < tables[table].length; i++) {
document.getElementById(tables[table][i]).style.display = 'none';
}
document.getElementById(language).style.display =
'table-row-group';
}
HTML
<table border='1'>
<thead>
<tr>
<td>Odds</td>
<td>Evens</td>
</tr>
</thead>
<tfoot>
<tr>
<td>English
</td>
<td>Spanish
</td>
</tr>
</tfoot>
<tbody id='English'>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
<tbody id='Spanish' style="display:none;">
<tr>
<td>Uno</td>
<td>Dos</td>
</tr>
<tr>
<td>Tres</td>
<td>Quatro</td>
</tr>
</tbody>
</table>
<br />
<table border='1'>
<thead>
<tr>
<td>Odds</td>
<td>Evens</td>
</tr>
</thead>
<tfoot>
<tr>
<td>Japanese
</td>
<td>Italian
</td>
</tr>
</tfoot>
<tbody id='Japanese'>
<tr>
<td>Ichi</td>
<td>Ni</td>
</tr>
<tr>
<td>San</td>
<td>Shi</td>
</tr>
</tbody>
<tbody id='Italian' style="display:none;">
<tr>
<td>Un</td>
<td>Due</td>
</tr>
<tr>
<td>Tre</td>
<td>Quattro</td>
</tr>
</tbody>
</table>
you have to change your javascript a little:
var tables=new Array();
tables['topTable'] = new Array('English','Spanish');
tables['bottomTable'] = new Array('Japanese','Italian');
function switchid(JonArray,JonX) {
//alert(JonArray);
var tmptable=tables[JonArray];
for(var i=0;i < tmptable.length;i++) {
document.getElementById(tmptable[i]).style.display='none';
}
document.getElementById(JonX).style.display='';
}
Some of these answers work, but I just caught the REAL answer via Chrome DevTools! In my 'for' loop I was using 'length()' instead of 'length'!!!
Why not to use CSS instead of looping through IDs?
JSFiddle
HTML
<table border='1' class="English">
<thead>
<tr><td>Odds</td><td>Evens</td></tr>
</thead>
<tfoot>
<tr><td onclick="changeLang(this,'English')">English</td><td onclick="changeLang(this,'Spanish')">Spanish</td></tr>
</tfoot>
<tbody id='English'>
<tr><td>One</td><td>Two</td></tr>
<tr><td>Three</td><td>Four</td></tr>
</tbody>
<tbody id='Spanish'>
<tr><td>Uno</td><td>Dos</td></tr>
<tr><td>Tres</td><td>Quatro</td></tr>
</tbody>
</table>
CSS
tbody {
display: none;
}
.English #English, .Spanish #Spanish, .Japanese #Japanese, .Italian #Italian {
display: table-row-group;
}
JS
function changeLang(cell, lang) {
cell.parentNode.parentNode.parentNode.className = lang;
}

Categories