To my understanding after going through GitHub, documentation and stack overflow:
doc.html() is supposed to be able to take in a string with html formatting (AKA rich text)
There has been work done to ensure that doc.html() is able to produce multiple html snippets within the same pdf document
To produce more than one html in the same document, one is supposed to utilize the callback function and nest any further edits to the pdf.
doc.html() does not behave in the same sense as the other functions (text, rect, etc.) where you can add as many as you want.
var pageWidth = 1000,
lineHeight = 1,
margin = 20,
maxLineWidth = pageWidth - margin * 2,
fontSize = 11,
ptsPerMM = 72 / 25.6,
oneLineHeight = (fontSize * lineHeight) / ptsPerMM;
var doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'letter',
lineHeight: lineHeight
});
var field1 = "<b>this is field 1 </b>";
var field2 = "<b>this is field 2 </b>";
//add first html
doc.html("<body>" + field1 + "</body>", {
callback: function (doc) {
//do nothing
},
width: maxLineWidth ,
windowWidth: maxLineWidth ,
html2canvas: {
backgroundColor: 'lightyellow',
width: maxLineWidth ,
height: 150
},
backgroundColor: 'lightblue',
x: 10,
y: 10,
autoPaging: 'text'
});
//add second html
doc.html("<body>" + field2 + "</body>", {
callback: function (doc) {
//do nothing
},
width: maxLineWidth ,
windowWidth: maxLineWidth ,
html2canvas: {
backgroundColor: 'lightyellow',
width: maxLineWidth ,
height: 150
},
backgroundColor: 'lightblue',
x: 10,
y: 10,
autoPaging: 'text'
});
//export pdf
window.open(doc.output('bloburl'));
The code above does not work. how can I fix this issue where I cannot export multiple html snippets in the same pdf document?
I went over GitHub, documentation and stack overflow and for the first time ever, whenever someone asks a question related to this topic, they don't seem to get an answer.
I would really appreciate it if someone could help me figure this out.
I've tried returning doc within the callback and reusing that but that didn't seem to work
Found it!
just use await and make sure to return doc inside the callback
something like this
var doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'letter'
});
var field = "<b>html test </b>";
doc.text(10, 10, "test");
//add first html
await doc.html(field, {
callback: function (doc) {
return doc;
},
width: 210,
windowWidth: 210,
html2canvas: {
backgroundColor: 'lightyellow',
width: 210,
height: 150
},
backgroundColor: 'lightblue',
x: 10,
y: 50,
autoPaging: 'text'
});
window.open(doc.output('bloburl'));
Related
Ok, here's my problem, I'm actually reading a json file in my local html file to make an animation.
The animation works pretty well on chrome, mozilla and safari (even if it's lagging a bit on safari but i think it's because my mac is old but nvm).
So here it's what i want, I created an ios app, the app is what i'm using to create the json and i wanted to be able to see the animation from the json in the app.
So i created an WKWebView that allows me to see my web page and here's the problem.
During the animation on my ipad, if i press the plotly animation, points that was here at the moment stay till i reload the web page. Moreover, this is also happening when i enter a number in the field i created that allows me to change the speed animation (a litlle thing that just increase my index by the number entered)
So Here's my webView code (even if i don't think the problem comes from there):
import UIKit
import WebKit
class WebViewVC: UIViewController {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "test", withExtension: "html")
let myRequest = NSURLRequest(url: url!)
webView.load(myRequest as URLRequest)
}
#IBAction func leaveButtonPressed(){
let menuVC = self.storyboard?.instantiateViewController(withIdentifier: "MenuVC") as! MenuVC
menuVC.modalPresentationStyle = .fullScreen
self.present(menuVC, animated: true, completion: nil)
}
}
and here a part of my plotly js code:
function createDico(i) {
return {
x: [i],
y: [i],
z: [i],
mode: 'markers',
marker: {
size: 12,
line: {
color: 'rgba(217, 217, 217, 0.14)',
width: 0.5
},
opacity: 0.8
},
type: 'scatter3d'
};
}
function setDatas() {
for (const [key] of datas[0]) {
if (key != 'bodyOrientation') {
joints[key] = createDico(0)
}
}
var data = getDataStep(0)
console.log(data)
var layout = {
margin: {
l: 0,
r: 0,
b: 0,
t: 100,
},
scene: {
xaxis: {
range: [xMin - 3, xMax + 3],
},
yaxis: {
range: [yMin - 3, yMax + 3],
},
zaxis: {
range: [zMin - 0.5, zMax + 0.5],
},
aspectratio: {
x: 1,
y: 1,
z: 1
},
width: 1000,
},
autoexpand: false,
title: {
text: "jsonPlot",
xanchor: "center"
},
width: 700,
height: 500,
autosize: false
};
Plotly.newPlot('myDiv', data, layout);
}
And i don't even know where the problem comes from so i'm not able to solve anything :/
I am trying to convert my html page to pdf using jsPDF. Essentially i am using the html method of jsPDF, giving it a source, and options and then in the callback function i would save the document.
But i am having a problem when it comes to dividing the single html document into mulitple divs and saving each div in a page. I am trying the below code and it renders all the pages blank.
My html looks like
<div class = "resultpage" >
<div class = "print-section-1">
//some content
</div>
<div class = "print-section-2">
//some content again
</div>
<div class = "print-section-3">
//content...
</div>
</div>
My js looks like :
window.jsPDF = window.jspdf.jsPDF;
let doc = new jsPDF({
orientation : "portrait",
unit : 'px',
format : 'a4',
hotfixes : ["px_scaling"],
putOnlyUsedFonts : true
})
doc.html($(".prints-section-1")[0], {
x: 10,
y : 10,
margin : [50, 200, 50, 200],
autoPaging : "text"
})
doc.addPage()
doc.html($(".print-section-2")[0], {
x: 10,
y : 10,
margin : [50, 200, 50, 200],
autoPaging : "text"
})
doc.addPage()
doc.html($(".print-section-3")[0], {
x: 10,
y : 10,
margin : [50, 200, 50, 200],
autoPaging : "text"
})
doc.save("test")
This renders all the pages empty.
If i modify the js, to have a chaining of callbacks like below, i am able to get the last div (print-side-2 in this case) printed but the pages previous to it are blank.
doc.html($(".print-section-1")[0], {
callback : function(doc) {
doc.addPage();
doc.html($(".print-section-2")[0], {
callback : function(doc) {
doc.save("test.pdf")
}
x: 10,
y : 10,
margin : [50, 200, 50, 200],
autoPaging : "text"
})
}
x: 10,
y : 10,
margin : [50, 200, 50, 200],
autoPaging : "text"
})
Can anyone point out what i am doing wrong ? I searched for solutions but many use deprecated methods like addFromHTtml, and some suggested using line breaks like "<!--ADD_PAGE>" _ and
style = "page-break-before : always" but both don't work. I looked into the documentation and it hasn't been great support. Please help me.
Referencing this answer (refrencing)
Just use await and make sure to return doc inside the callback
something like this
var doc = new jspdf.jsPDF({
orientation: 'p',
unit: 'pt',
format: 'letter'
});
var field = "<b>html test </b>";
doc.text(10, 10, "test");
//add first html
await doc.html(field, {
callback: function (doc) {
return doc;
},
width: 210,
windowWidth: 210,
html2canvas: {
backgroundColor: 'lightyellow',
width: 210,
height: 150
},
backgroundColor: 'lightblue',
x: 10,
y: 50,
autoPaging: 'text'
});
window.open(doc.output('bloburl'));
now you can call doc.html as many times as you want for that same document
Originally posted by #bakuur in https://github.com/parallax/jsPDF/issues/3074#issuecomment-1328427528
I have this code :
const createBrandedPresentation = () => {
let pptx = new pptxgen();
let slide = pptx.addSlide({ sectionTitle: 'ZG test' });
slide.background = { color: '#1c1c21' };
slide.addText('Title', {
y: 1.67,
fontSize: 88,
bold: true,
color: '#eb34a8',
isTextBox: true,
align: 'center',
});
slide.addImage ({
path: "./Logosvg.svg",
w: 1.5,
h: 1.5,
x: 7.5,
y: 2
})
return pptx;
};
but every time I generate a new presentation, the photo is empty. I'm calling this function from a react component, (dev server) and I can't understand why it can't add images even tho thse images are served statically with my app. This question goes double for PNG (which don't work either)
I am struggling to insert a comma into my JustGauge Chart.
So far I have the following code. most of it is working as expected;
window.onload = function() {
var g1 = new JustGage({
id: "g1",
value: 24692,
min: 0,
max: 30009,
title: 'Document Countdown',
titlePosition: 'above',
width: 800,
height: 800,
pointer: true,
textRenderer: function(val) {
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
gaugeWidthScale: 1.2,
noGradient: true,
customSectors: [{
color: '#32CD32',
lo: 0,
hi: 30009
}]
});
}
Fiddle https://jsfiddle.net/johnny_s/xsgpp4ng/1/
The 'textRenderer' part of the above code adds a comma to the 'value', I'm not sure how to do the same with 'max'.
I need to add a comma to the 'max' value - so it's '30,009'. When I try to add it manually the chart won't load.
Any help is appreciated.
This has been a feature request posted as request 193 and has been implemented as an extra property maxTxt in the update of February 3, 2016 and is part of release 1.2.7. Current version is 1.2.9.
Note that several features changed in version 1.2.9 compared to the version you used (1.2.2):
the structure of the customSectors: it is no longer an array. The array part is now moved into a subproperty ranges
Support for title has been removed, as this really does not belong to the "core business" of the widget; one can better control the position and style of such a title in the surrounding HTML/CSS.
There is a bug related to the noGradient setting: issue 270. The suggested fix has not been included in the latest release. Instead of tampering with the library yourself, I would suggest working around that issue by adding a customSectors.length property with a positive value.
I have included these changes also in the updated fiddle which uses version 1.2.9:
var g1 = new JustGage({
id: "g1",
value: 24692,
min: 0,
max: 30009,
maxTxt: "30,009", // <------ add this
// remove title attributes -- no longer supported
//title: 'Document Countdown',
//titlePosition: 'above',
width: 800,
height: 400, // <--- reduced to allow title to be closer to gauge
pointer: true,
textRenderer: function(val) {
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
gaugeWidthScale: 1.2,
pointerOptions: {
toplength: -15,
bottomlength: 10,
bottomwidth: 12,
color: '#8e8e93',
stroke: '#ffffff',
stroke_width: 3,
stroke_linecap: 'round'
},
noGradient: true,
customSectors: { // <--- no longer an array...
ranges: [{ // <--- ... which has moved to this property
color: '#32CD32',
lo : 0,
hi : 30009
}],
length: 1 // fixes a bug
}
});
The HTML should contain the title. Something like this:
<div style="display: inline-block">
<h2 style="text-align:center;">Document Countdown</h2>
<div id="g1"></div>
</div>
Another way of doing it is add formatNumber: true when you initialize. It will format min max and value. You can also get rid of the textRenderer field.
I updated your fiddle
window.onload = function(){
var g1 = new JustGage({
id: "g1",
value: 24692, /* <-- just change this to your current value */
min: 0,
max: 30009, /* start amount */
title: 'Document Countdown',
titlePosition: 'above',
width: 800,
height: 800,
pointer: true,
formatNumber: true,
gaugeWidthScale: 1.2,
pointerOptions: {
toplength: -15,
bottomlength: 10,
bottomwidth: 12,
color: '#8e8e93',
stroke: '#ffffff',
stroke_width: 3,
stroke_linecap: 'round'
},
noGradient: true,
customSectors: [{
color: '#32CD32',
lo: 0,
hi: 30009
}]
});
}
Updated & Resolved, see below.
I have been working on this for several days, searching and reading many tutorials and I am still stuck. Ultimately I am working on a page that will contain multiple solid gauge charts with data supplied by JSON from an SQLITE3 database. The database is updated every minute and I would like to have the chart data update dynamically, not by refreshing the browser page.
For the purpose of my learning, I have reduced this down to one chart.
All current and future data will be arranged as such:
PHP
[{"name":"s1_id","data":[684172]},
{"name":"s1_time","data":[1483097398000]},
{"name":"s1_probe_id","data":["28-0000071cba01"]},
{"name":"s1_temp_c","data":[22.125]},
{"name":"s1_temp_f","data":[71.825]},
{"name":"s2_id","data":[684171]},
{"name":"s2_time","data":[1483097397000]},
{"name":"s2_probe_id","data":["28-0000071d7153"]},
{"name":"s2_temp_c","data":[22.062]},
{"name":"s2_temp_f","data":[71.7116]}]
This is the current layout of my java:
JS
$(function() {
var options = {
chart: {
type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '90%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.10, '#2b908f'],//Blue
[0.35, '#55BF3B'],//Green
[0.65, '#DDDF0D'],//Yellow
[0.90, '#DF5353']//Red
],
lineWidth: 0,
minorTickInterval: null,
tickPixelInterval: 1000,
tickWidth: 0,
title: {
y: -70
},
labels: {
y: 16
},
min: 0,
max: 1000000,
title: {
text: 'Degree C'
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: -10,
borderWidth: 0,
useHTML: true
}
}
},
series: []
};
var gauge1;
$.getJSON('sgt3.php', function(json){
options.chart.renderTo = 'chart1';
options.series.push(json[0]);
gauge1 = new Highcharts.Chart(options);
});
});
I was using information from this post but it leaves off the dynamic update aspect. As I mentioned before, I will have more charts rendering to div ids, all coming from the one JSON array, which is why I have referenced the following link:
Multiple dynamic Highcharts on one page with json
If anyone has an idea how to dynamically update this please let me know. I have tried several setInterval methods but all they seem to do is redraw the chart but no data is updated.
Update:
I spent a while doing some more iterations and resolved before coming back here. I changed each gauge to have their own function such as:
$('#gauge0').highcharts(Highcharts.merge(options, {
yAxis: {
min: 15,
max: 30,
tickPositions: [15, 20, 25, 30],
title: {
text: 'Table'
}
},
credits: {
enabled: false
},
series: [{
data: [30],
dataLabels: {
y: 20,
format: '<div style="text-align:center"><span style="font-size:48px;color:' +
((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">{y:.3f}</span><br/>' +
'<span style="font-size:12px;color:silver">Degree C</span></div>'
},
tooltip: {
valueSuffix: 'Tooltip 1'
}
}]
}));
Then got the setInterval to work by assigning to each gauge respectively. I have added a lot more info than just the two I referenced but each var and setData can be added respectively.
// Bring life to the dials
setInterval(function() {
$.ajax({
url: 'data_temps.php',
success: function(json) {
var chart0 = $('#gauge0').highcharts();
var chart1 = $('#gauge1').highcharts();
// add the point
chart0.series[0].setData(json[3]['data'],true);
chart1.series[0].setData(json[8]['data'],true);
},
cache: false
})
}, 1000)
Hopefully this can help someone in the future. This may not be the most efficient way but its working great right now. Thanks again everyone for your suggestions.
You may try something like this:
change:
var gauge1;
$.getJSON('sgt3.php', function(json){
options.chart.renderTo = 'chart1';
options.series.push(json[0]);
gauge1 = new Highcharts.Chart(options);
});
to:
options.chart.renderTo = 'chart1';
var gauge1 = new Highcharts.Chart(options);
$.getJSON('sgt3.php', function(json){
gauge1.series[0].points.length = 0;
gauge1.series[0].points.push(json[0]);
});
That is, updating the existing series on a chart instead of re-creating it.
As I've mentioned in the comment before, highcharts provide an example of dynamically updated gauge:
http://jsfiddle.net/gh/get/jquery/3.1.1/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/gauge-solid/