I have a highchart in three languages with data filled from a database. Some of the translated titles will break and fill two lines. Without any precaution this will overflow the subtitles:
title: {
text: 'The quick brown fox jumps over the lazy dog and even more',
style: {
width: '320px'
}
},
subtitle: {
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr'
},
See this sample: http://jsfiddle.net/puhtu/
Is there a way to dynamically move the subtitles if the main title breaks in two lines?
It looks like a bug so I've reported it to our devs https://github.com/highslide-software/highcharts.com/issues/1704
Although a while ago, the following fixed it for me since this is still an issue:
title: {
text: "Hello very strange world where people tend to make long chart titles",
style: {
fontSize: '1.9vmin',
fontWeight: 'bold',
color: '#1381bc',
lineHeight: '15em' //This line did the trick
},
align: 'left',
x: 30,
y: 10
},
Related
I want to have a text s.calculatedQuantity and next to it an icon. But i want them to be always next to each other and not be separated. Sometimes when s.setDescription is long i have a bad result like in the image below. And i dont know why there is sometimes that space between the icon and the text s.calculatedQuantity. Can someone explain to me that ?
.
I Have my code like this :
function generateSetDescription(s, picto) {
return {
columns: [
{
text: `${s.setDescription} - `,
fillColor: '#000',
color: '#FFF'
},
{
text: `${s.calculatedQuantity}`,
fillColor: '#000',
color: '#FFF'
},
{
image: icon,
width: 10,
height: 10,
fillColor: '#000',
},
]
}
}
The problem you're having seems to be caused by too long words (not text) normal text seems to wrap correctly when a blank space is found.
My suggestion is to programmatically break your 'very long words' adding a - in between.
something like this should work in your case
const text = veryLongTextWithLongWords;
const wrappedText = text.split(' ').map(word => {
if(word.length > 80){
return `${word.substr(0, 40)}-${word.substr(41)}
}
return word;
})
const columns = [
{ text: wrappedText }
]
You can test it out here
http://pdfmake.org/playground.html
I am using react-typescript and I have successfully created a PDF file from an html page with the help of this ref
Generating a PDF file from React Components
But if we want to create a PDF with multiple pages then what to do?
with a4 size page with appropriate margins at all sides and in each new page that margin should be applied.
And here is my code.
private printDocument() {
const input = document.getElementById("pdf");
html2canvas(input)
.then((canvas) => {
const pdf = new jsPDF("p", "px", "a4");
pdf.addHTML(input, 0, 0, {
pagesplit: true,
background: "#ffffff",
}, () => {
pdf.save("download.pdf");
});
});
}
please help me its argent.
Thank you in advance
I tried to use jsPDF to workaround this problem, but i did not succeed. The way that jsPDF manage the content to split in paged are not clear to me.
So i decided to use pdfMake, another amazing js library.
I got these infos in this question: Generating PDF files with JavaScript
In the question that you metioned (Generating a PDF file from React Components), the best answer sugest a good way to handle the pagination. You make a div for each page. But in my case, my content can dinamically increase your vertical size, so i can't fix the div's vertical sizes.
So, i did like this:
printDocument() {
const divs = document.getElementsByClassName('example');
const newList = [].slice.call(inputs);
var contentArray = []
var docDefinition = {
pageSize: {width: 800, height: 1173},
content: [
{
text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.'
}
]
}
Promise.map(newList, async (element, index) => {
let canvas = await html2canvas(element);
const imgData = await canvas.toDataURL('image/png');
// console.log("imgData URL => ", imgData)
// margin horizontal -40 = removing white spaces
return contentArray[`${index}`] = [{ image: imgData, width: canvas.width, height: canvas.height, margin: [-40, 0] }, {
text: ` ${index} - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi.`
}];
}).then(
() => ( docDefinition.content.push(contentArray))
).then(
() => {
console.log("... starting download ...")
pdfMake.createPdf(docDefinition).download('examplePdf.pdf')
}
)
}
// In your react's component constructor ...
constructor(props) {
super(props);
this.printDocument = this.printDocument.bind(this)
}
// the imports below ...
import Promise from 'bluebird';
import html2canvas from 'html2canvas';
import pdfMake from 'pdfmake/build/pdfmake.js';
import pdfFonts from "pdfmake/build/vfs_fonts.js";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
// i'm using these middlewares
import promise from 'redux-promise'
import multi from 'redux-multi'
import thunk from 'redux-thunk'
<div>
The approach here is: a div it's not a page. Because if the image generated by the canvas element it's bigger than the page vertical size, we'll need to control the pagination by ourselves. So, we broke our content in small elements to the pdf generator handle the pagination to us. This way we garantee that the pagination will occurs without cuts.
<div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
// any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
</div>
<div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
// any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
</div>
<div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >
// any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.
</div>
</div>
<div>
<button onClick={this.printDocument}> print using PDFMake </button>
</div>
Using the Promise.map by bluebird with the async/await resources, we can ensure that we'll wait till the end of generation of all images from canvas. This process can take a while depending of your image's size.
http://bluebirdjs.com/docs/api/promise.map.html
Take a look at pdfMake's github:
https://github.com/bpampuch/pdfmake
And his playground with excelent examples and how tos:
http://pdfmake.org/playground.html
I'll still trying to upgrade this way to solve this problem with the pagination, but it was the quickest way that i solved the problem and i hope to be useful for somebody.
Are you try?
const printDocument= () => {
const input = document.getElementById('divToPrint');
const input2 = document.getElementById('divToPrint2');
const pdf = new jsPDF();
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
pdf.addImage(imgData, 'JPEG', 0, 0);
pdf.addPage();
html2canvas(input2)
.then((canvas2) => {
const imgData2 = canvas2.toDataURL('image/png');
pdf.addImage(imgData2, 'JPEG', 0, 0);
pdf.save("download.pdf");
})
;
})
;
}
This is in continuation to the question asked in github, Fit a wider table into PDF #261.
I'm reusing the same method(doc.autoTable) to create PDF out of different HTML inputs.
So, If I define the column style of 0th column as columnWidth: 'wrap', then the same style will be applied for all the HTML tables that invoke this particular method.
I'm not sure If I can follow long text example, as both the column names & table body are coming from HTML page directly. Whereas in the long text example, I'm seeing the column names being declared/defined as shown below
var columnsLong = getColumns().concat([
{title: "Title with\nlinebreak", dataKey: "text2"},
{title: "Long text column", dataKey: "text"},
]);
Now there are 2 questions.
1. I dont want to apply 'WRAP' for all the columns, as the table gets cut.
2. Need to apply 'wrap' for certain columns alone by mentioning the column name that comes from HTML/GSP page.
This is my code
var res = doc.autoTableHtmlToJson($(".printReportsCaveat")[0]);
doc.autoTable(res.columns, res.data, {
columnStyles : {'Plant':{columnWidth: 'wrap'},
'Mine':{columnWidth: 'wrap'},
0:{textColor: [0,105,170]}
},
margin: {top: 55, bottom : 110},
headerStyles: {
overflow: 'linebreak',
// columnWidth: 'auto',
halign: 'center'
},
styles : {
overflow: 'linebreak',
halign: 'center',
fontSize: 8
},
createdCell: function(cell, data) {
var group = $('#groupByValue').val();
addColorToCell(group, level3Flag, level2Flag, data, cell);
},
addPageContent : function(data) {
printHeadNFoot(doc, userDtl, data);
},
drawCell: function(cell, data) {
designCell(data,doc);
},
});
Kindly help!
If I understand your issue correctly you can try referencing a specific column by index instead of by key. I.e. columnWidth: {0: columnWidth: 'wrap'}.
I am using Highcharts to create some chart but I find it's not working for changing the background of a chart's title.
For instance:
// works, the color did get to red
title: {
text: title,
style: {"color":"#ff0000"}
},
// the color did get to white but the background is not set to red.
title: {
text: title,
style: {"backgroundcolor":"#ff0000", "color":"#ffffff"}
},
What should I do to fix this?
Thanks
Referencing this question, you can do this by setting useHTML: true and using background-color.
title: {
useHTML: true,
style: {
color: '#FF00FF',
'background-color': '#000000',
fontWeight: 'bold'
}
},
https://jsfiddle.net/nicholasduffy/a32vL38z/
Can someone please suggest if there is anyway we can rename the items in the export menu in highcharts. Currently it has entries like:
Download PNG image
Download JPEG image
...
I want to remove word "image". Moreover want to control the complete styling.
There are lots of options for this. Some can be done in Javascript, and I'm sure more can be done in CSS. Here is a JSFiddle example showing the desired text changes and some style changes.
You can read the details on this in the API under lang and navigation.
The text is changed with:
lang: {
printChart: 'Print chart',
downloadPNG: 'Download PNG',
downloadJPEG: 'Download JPEG',
downloadPDF: 'Download PDF',
downloadSVG: 'Download SVG',
contextButtonTitle: 'Context menu'
}
And the style of the button and menu with:
navigation: {
menuStyle: {
border: '1px solid #A0A0A0',
background: '#FFFFFF',
padding: '5px 0'
},
menuItemStyle: {
padding: '0 10px',
background: null,
color: '#303030',
fontSize: '11px'
},
menuItemHoverStyle: {
background: '#4572A5',
color: '#FFFFFF'
},
buttonOptions: {
symbolFill: '#E0E0E0',
symbolSize: 14,
symbolStroke: '#666',
symbolStrokeWidth: 3,
symbolX: 12.5,
symbolY: 10.5,
align: 'right',
buttonSpacing: 3,
height: 22,
// text: null,
theme: {
fill: 'white', // capture hover
stroke: 'none'
},
verticalAlign: 'top',
width: 24
}
}
You can get the default values from the source code, almost at the very top. Some of the defaults use variables that you won't have though, so you may need to change them. And as mentioned, CSS may get you the extra distance.