jspdf parent and child table overlaping probem - javascript

I have a object and that object has a list. that means i have a table and that table has multiple child table. Now i want my parent table print a single page and other child table print another page, but it prevent overlaping when table go to the next page.
Here is my code
function generatePDF() {
debugger;
var pdf = new jsPDF('p', 'pt', 'letter');
pdf.setFont("sans serif", "bold");
pdf.text('Disciplinary Actions And Criminal Prosecution & History', 105, 50);
source = $('#table')[0];
var childTables = $(source).find('table');
var tableCount = childTables.length;
specialElementHandlers = {
'#bypassme': function (element, renderer) {
return true
}
};
margins = {
top: 80,
bottom: 10,
left: 78,
width: 522
};
$('#table tr').each(function () {
var row = $(this);
if (row.find('td:contains("Document")').length) {
row.remove();
}
});
pdf.fromHTML(
source,
margins.left,
margins.top, {
'width': margins.width,
'elementHandlers': specialElementHandlers
},
function (dispose) {
pdf.save('DisciplinaryAction&History.pdf');
}, margins
);
}
this is my pdf problem
i do not want this over laping. and do not table split bottom the page, if have not enough space for table print then it go to the next page

Related

Adding Images with JSPDF

Am using JSPDF to generate PDF in javascript, when I add Images and I generate the PDF file, the PDF file does not display the image until I generate the PDF a second time. Here is my code below
var doc = new jsPDF('p', 'pt', 'a4');
var res = doc.autoTableHtmlToJson(document.getElementById("data-table-committee"));
var header = function (data) {
doc.setFontSize(18);
doc.setTextColor(40);
doc.setFontStyle('normal');
doc.text("Committee Count List", data.settings.margin.left, 80);
console.log('adding image');
doc.addImage(headerImgData, 'PNG', data.settings.margin.left, 20, 150, 30);
console.log('adding image done');
};
var options = {
beforePageContent: header,
margin: {
top: 50
},
startY: doc.autoTableEndPosY() + 20
};
doc.autoTable(res.columns, res.data, options);
doc.save("Committee Count List.pdf");
What am I doing wrong and How can I get my image to be displayed the first time I generate the PDF
You can also create pdf using pdfkit. Here is the code that generates pdf with an image.
var PDFDocument = require ('pdfkit');
var fs = require('fs');
doc = new PDFDocument
doc.pipe(fs.createWriteStream('output.pdf'))
doc.image('E:/sii/nodejs/uploads/public/uploads/test.jpg', {
fit: [250, 300],
align: 'center',
valign: 'center'
});
doc.end()

jsPDF set table style

How i can set height of table cell, i now using this code:
function createNew()
{
//GenPDF();
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 500,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
}
On page i have two words on header and more then 30 tables, but in pdf tables cell height is so big and use much space, can some one help me for add cell height in this code, or maybe have a some way for this in my html tables?
i found a solution:
function createNew() {
var pdf = new jsPDF('p', 'pt', 'letter')
, source = window.document.getElementsByTagName("body")[0]
, specialElementHandlers = {
'#CreateReport' : function(element, renderer){
// true = "handled elsewhere, bypass text extraction"
return true;
},
'#PrintReport': function(element, renderer){
// true = "handled elsewhere, bypass text extraction"
return true;
},
'#ignorePDF': function(element, renderer){
// true = "handled elsewhere, bypass text extraction"
return true;
}
}
margins = {
top: 60,
bottom: 60,
left: 40,
width: 1000
};
pdf.fromHTML(
source
, margins.left
, margins.top
, {
'width': margins.width
, 'elementHandlers': specialElementHandlers
},
function (dispose) {
pdf.output("dataurlnewwindow");
},
margins
)
}
i put this code and now working fine

Html2canvas for each div export to pdf separately

I have Page, It has 6 div with same class name "exportpdf", I am converting those div into pdf using jspdf and html2canvas
var elementTobePrinted = angular.element(attrs.selector),
iframeBody = elementTobePrinted.contents().find('div.exportpdf');
In html2canvas.....
html2canvas(elementTobePrinted, {
onrendered: function (canvas) {
var doc = new jsPDF();
for(var i=1;i<elementTobePrinted.length;i++){
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
}
doc.save(attrs.fileName);
}
I converted page to canvas.its create same div contents for whole pdf. I need each div contents into same pdf with different pages.
Can anyone help me?
The problem is with html2canvas:
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40,180, 160);
Here I need to pass elementTobePrinted list to addImage.
On angular 2(now 6) framework.
u can use the logic as below,
On click execute generateAllPdf() function,
gather all 6 id's from my html collection,
iterate through each id and call html2canvas function,
as html2canvas runs in background to process images, i m using
await on function,
after the html2canvas completes its process, i ll save the
document,
If suppose i wont use await i ll end-up in downloading an empty
page.
below is my code logic,
// As All Functions in js are asynchronus, to use await i am using async here
async generateAllPdf() {
const doc = new jsPDF('p', 'mm', 'a4');
const options = {
pagesplit: true
};
const ids = document.querySelectorAll('[id]');
const length = ids.length;
for (let i = 0; i < length; i++) {
const chart = document.getElementById(ids[i].id);
// excute this function then exit loop
await html2canvas(chart, { scale: 1 }).then(function (canvas) {
doc.addImage(canvas.toDataURL('image/png'), 'JPEG', 10, 50, 200, 150);
if (i < (length - 1)) {
doc.addPage();
}
});
}
// download the pdf with all charts
doc.save('All_charts_' + Date.now() + '.pdf');
}
I think the issue here is that elementTobePrintedis not what you think it is.
When you run the code:
var elementTobePrinted = angular.element(attrs.selector)
This will return you a list of every element that matches the conditions, so you said you have 6 of these elements ("It has 6 divs").
Have you tried replacing:
html2canvas(elementTobePrinted, {
onrendered: function (canvas) {
var doc = new jsPDF();
for(var i=1;i<elementTobePrinted.length;i++) {
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
}
doc.save(attrs.fileName);
}
With...
for(var i=0; i<elementTobePrinted.length; i++){
html2canvas(elementTobePrinted[i], {
onrendered: function (canvas) {
var doc = new jsPDF();
doc.addImage(canvas.toDataURL("image/jpeg"), 'jpeg', 15, 40, 180, 160);
doc.addImage(canvas.toDataURL("image/jpeg"),'JPEG', 0, 0, 215, 40)
doc.addPage();
doc.save(attrs.fileName);
}
}
The reason I suggest this is that html2Canvas wants a SINGLE element as its first parameter and your example above passes a list of elements (I think, assuming angular.element(attrs.selector) finds all 6 divs you are trying to print).

Adding dgrids with variable widths to TabContainer

I'm populating a TabContainer with grids (Dojo 1.8, dgrid) that are showing the results of a query for different datasets. Each tab is the result of a single dataset. The different datasets will have a varying number of fields, so I'm dynamically building each grid and adding it to a ContentPane, which gets added to the TabContainer.
My current problem is seting the width of the grids when they are built. The datasets could have from two fields to upwards of 100 fields to be shown in the grid. I've set a default width in CSS for the grid of 600px, but the grid will only show the first six fields of the dataset. If I set the width to "auto", it is only as wide as the TabContainer, removing the scroll bar and cutting off the data. Is it possible to set a width for each grid separately?
This is what the result looks like
This is the code for populating the TabContainer
function buildColumns(feature) {
var attributes = feature.attributes;
var columns = [];
for (attribute in attributes) {
if (attribute != "Shape") {
var objects = {};
objects.label = attribute;
objects.field = attribute;
columns.push(objects);
}
}
return columns;
}
function populateTC(results, evt) {
try {
if (dijit.byId('tabs').hasChildren) {
dijit.byId('tabs').destroyDescendants();
}
if (results.length == 0) {
console.log('Nothing found.');
return;
}
var combineResults = {};
for (var i = 0, len = results.length; i < len; i++) {
var result = results[i];
var feature = result.feature;
var lyrName = result.layerName.replace(' ', '');
if (combineResults.hasOwnProperty(lyrName)) {
combineResults[lyrName].push(result);
}
else {
combineResults[lyrName] = [result];
}
}
for (result in combineResults) {
var columns = buildColumns(combineResults[result][0].feature);
var features = [];
for (i = 0, len = combineResults[result].length; i < len; i++) {
features.push(combineResults[result][i].feature);
}
var data = array.map(features, function (feature) {
return lang.clone(feature.attributes);
});
var dataGrid = new (declare([Grid, Selection]))({
id: "dgrid_" + combineResults[result][0].layerId,
bufferRows: Infinity,
columns: columns,
"class": "resultsGrid"
});
dataGrid.renderArray(data);
dataGrid.resize();
dataGrid.on(".dgrid-row:click", gridSelect);
var cp = new ContentPane({
id: result,
content: "<b>" + combineResults[result][0].layerName + "\b",
//content: dataGrid,
title: combineResults[result][0].layerId
}).placeAt(dijit.byId('tabs'));
cp.addChild(dataGrid);
cp.startup();
cp.resize();
}
tc.startup();
tc.resize();
map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
}
catch (e) { console.log(e.message); }
}
The problem is not with the grid width, it's the column widths. They fit the container.
If you give a column a fixed width, you will get the desired effect.
You should be able to style .dgrid-cell or .dgrid-column-[index]
I've also had a need for more control depending on the column data. You can control the style by providing a column with its own renderHeaderCell and renderCell method as well. (style refers to dom-style)
renderHeaderCell: function(node) {
style.set(node, 'width', '50px');
}
renderCell: function(object, value, node) {
style.set(node, 'width', '50px');
}
I was able to use the AddCssRule to dynamically change the size of the grids
var dataGrid = new (declare([Grid, Selection]))({
id: "dgrid_" + combineResults[result][0].layerId,
bufferRows: Infinity,
columns: columns,
"class": "resultsGrid"
});
dataGrid.renderArray(data);
var gridWidth = "width: " + String(columns.length * 100) + "px";
dataGrid.addCssRule("#" + dataGrid.id, gridWidth);
dataGrid.resize();
dataGrid.refresh();
Here is a Fiddle that shows the result. Click on a colored polygon to show the different grids (although the content is sometimes being shoved into the header of the grid). Also, the tabs aren't being rendered correctly, but there should be 0, 224, and 227 (if you also clicked on a point).

Multiple Instances of Google Visualizations Chart Inside Separate Divs

I'm trying to show several Google Gauge charts in separate divs on the same screen. I also need to handle the click event on those divs (consequently the charts). I tried to do that dynamically but I had some issues. But anyway, even when I tried do this statically (which worked), I still couldn't get the chart area to be clickable. What happened is that the whole div is clickable except for the chart area.
Anyway, here's my (messy - test) code:
<div id="gaugePlaceHolder" class="gaugeWrapper"></div>
<div id="gaugePlaceHolder2" class="gaugeWrapper"></div>
document.getElementsByClassName = function (cl) {
var retnode = [];
var myclass = new RegExp('\\b' + cl + '\\b');
var elem = this.getElementsByTagName('*');
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) retnode.push(elem[i]);
}
return retnode;
};
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(function () {
drawChart1();
drawChart2();
});
function drawChart1() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Memory', 80]
]);
var options = {
width: 400, height: 120,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('gaugePlaceHolder'));
chart.draw(data, options);
}
function drawChart2() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Another', 30]
]);
var options = {
width: 400, height: 120,
redFrom: 90, redTo: 100,
yellowFrom: 75, yellowTo: 90,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('gaugePlaceHolder2'));
chart.draw(data, options);
}
window.onload = function () {
var elements = $('.gaugeWrapper');
console.log(elements);
elements.click(function () {
alert("clicked");
});
}
Any explanations/suggestions?
The right way to add a listener to a Gauge is using google.visualization.events.addListener method, as shown in this example.
You could also try your code on Google Playground.

Categories

Resources