66

what I'm doing is using jsPDF to create a PDF of the graph I generated. However, I am not sure how to wrap the title (added by using the text() function). The length of the title will vary from graph to graph. Currently, my titles are running off the page. Any help would be appreciated!

This is the code i have so far:

var doc = new jsPDF();
doc.setFontSize(18);
doc.text(15, 15, reportTitle);
doc.addImage(outputURL, 'JPEG', 15, 40, 180, 100);
doc.save(reportTitle);

Nothing to keep the reportTitle from running off the page

user3749946
  • 1,997
  • 2
  • 12
  • 9
  • Welcome to SO! You should expand your question a bit - show us what you've tried, what your expected result is, and what you're actually getting. – Kryten Jun 17 '14 at 20:00
  • I've added the bit of code I'm using to create the document. And as I've stated, sometimes the reportTitle is too long and runs off the right side of the PDF. Instead, I want to make it wrap somehow. – user3749946 Jun 17 '14 at 20:19

7 Answers7

132

Okay I've solved this. I used the jsPDF function, splitTextToSize(text, maxlen, options). This function returns an array of strings. Fortunately, the jsPDF text() function, which is used to write to the document, accepts both strings and arrays of strings.

var splitTitle = doc.splitTextToSize(reportTitle, 180);
doc.text(15, 20, splitTitle);
user3749946
  • 1,997
  • 2
  • 12
  • 9
  • 1
    Thanks, it helped me. Just one comment, in the text method of jsPDF, splitTitle should be the first parameter. – Guy Jul 10 '16 at 07:51
  • reportTitle: what should i replace for this.... Got this error Uncaught ReferenceError: reportTitleis not defined – Monicka Akilan Aug 10 '16 at 11:48
  • @MonickaAkilan reportTitle is a variable I had used. It's probably just a string. You probably have to set the variable first – user3749946 Aug 12 '16 at 04:35
  • 2
    I am using jsPDF version 1.2.60 and doc.splitTextToSize(reportTitle, 180); is no more available in the api. I am facing the same word wrapping issue. What should I do? – Hamza Ahmed Aug 31 '16 at 13:06
  • 1
    I had no idea this feature existed. Thank you very much for saving me a couple of hours and a bad headache. – Hankrecords Mar 08 '17 at 14:29
  • 1
    @HamzaAhmedZia Looks like that stuff is now considered a "plugin" and not part of the core: http://rawgit.com/MrRio/jsPDF/master/docs/plugins_split_text_to_size.js.html – Glen Selle Apr 08 '17 at 20:51
  • 2
    @GlenSelle I was able to use it without importing anything other than jsPDF's minified version, just `doc.splitTextToSize` worked out-of-the-box – SidOfc Jun 05 '20 at 19:08
  • Need to be careful with the unit size. I had set it to inch and the value was 400. so it never worked. I change it to 10 and now its working fine. – Santosh Aug 09 '23 at 10:05
  • @GlenSelle how to use the "plugin" function in JsPDF? – john_smith Aug 10 '23 at 06:21
20

You can just use the optional argument maxWidth from the text function.

doc.text(15, 15, reportTitle, { maxWidth: 40 });

That will split the text once it reaches the maxWidth and start on the next line.

Paul
  • 500
  • 3
  • 8
11

Auto-paging and text wrap issue in JSPDF can achieve with following code

 var splitTitle = doc.splitTextToSize($('#textarea').val(), 270);
    var pageHeight = doc.internal.pageSize.height;
    doc.setFontType("normal");
    doc.setFontSize("11");
    var y = 7;
    for (var i = 0; i < splitTitle.length; i++) {                
        if (y > 280) {
            y = 10;
            doc.addPage();
        }
        doc.text(15, y, splitTitle[i]);
        y = y + 7;
    }
    doc.save('my.pdf');
KB1788
  • 184
  • 1
  • 9
  • Thanks @KB1788, this did the trick for me. Had a XML file in a textarea that was to long for one page. This solution breaks the XML when it gets to long for one page and creats a new one. – K.Oleksiak Feb 06 '20 at 07:09
5

To wrap long string of text to page use this code:

var line = 25 // Line height to start text at
var lineHeight = 5
var leftMargin = 20
var wrapWidth = 180
var longString = 'Long text string goes here'

var splitText = doc.splitTextToSize(longString, wrapWidth)
for (var i = 0, length = splitText.length; i < length; i++) {
  // loop thru each line and increase
  doc.text(splitText[i], leftMargin, line)
  line = lineHeight + line
}
gaskills
  • 51
  • 1
  • 1
2

If you need to dynamically add new lines you want to access the array returned by doc.splitTextToSize and then add more vertical space as you go through each line:

var y = 0, lengthOfPage = 500, text = [a bunch of text elements];

//looping thru each text item
for(var i = 0, textlength = text.length ; i < textlength ; i++) {

    var splitTitle = doc.splitTextToSize(text[i], lengthOfPage);

    //loop thru each line and output while increasing the vertical space
    for(var c = 0, stlength = splitTitle.length ; c < stlength ; c++){

        doc.text(y, 20, splitTitle[c]);
        y = y + 10;

    }

}
1

Working Helper function

Here's a complete helper function based on the answers by @KB1788 and @user3749946:

It includes line wrap, page wrap, and some styling control:

(Gist available here)

function addWrappedText({text, textWidth, doc, fontSize = 10, fontType = 'normal', lineSpacing = 7, xPosition = 10, initialYPosition = 10, pageWrapInitialYPosition = 10}) {
  var textLines = doc.splitTextToSize(text, textWidth); // Split the text into lines
  var pageHeight = doc.internal.pageSize.height;        // Get page height, well use this for auto-paging
  doc.setFontType(fontType);
  doc.setFontSize(fontSize);

  var cursorY = initialYPosition;

  textLines.forEach(lineText => {
    if (cursorY > pageHeight) { // Auto-paging
      doc.addPage();
      cursorY = pageWrapInitialYPosition;
    }
    doc.text(xPosition, cursorY, lineText);
    cursorY += lineSpacing;
  })
}

Usage

// All values are jsPDF global units (default unit type is `px`)
const doc = new jsPDF();

addWrappedText({
  text: "'Twas brillig, and the slithy toves...", // Put a really long string here
  textWidth: 220,
  doc,

  // Optional
  fontSize: '12',
  fontType: 'normal',
  lineSpacing: 7,               // Space between lines
  xPosition: 10,                // Text offset from left of document
  initialYPosition: 30,         // Initial offset from top of document; set based on prior objects in document
  pageWrapInitialYPosition: 10  // Initial offset from top of document when page-wrapping
});  
Master of Ducks
  • 559
  • 6
  • 11
  • cursorY = pageWrap; doesn't work. I believe it's supposed to be pageWrapInitialYPosition – Dave ت Maher Dec 13 '19 at 20:09
  • This is useful. A correction: `splitToSize` uses font settings to determine the width of the line, so you need to move `setFontSize` and other font settings BEFORE `splitToSize`. Instead of passing in `lineSpacing`, you can easily calculate it from `fontSize`: `const lineSpacing = fontSize * doc.getLineHeightFactor() * .35;` (Multiply by .35 to convert points to mm, adjust if you're not using mm.) – Dana Nov 15 '21 at 16:42
-1

When we use linebreak in jsPDF we get an error stating b.match is not defined, to solve this error just unminify the js and replace b.match with String(b).match and u will get this error twice just replace both and then we get c.split is not defined just do the same in this case replace it with String(c).match and we are done. Now you can see line breaks in you pdf. Thank you

Prasad Shetty
  • 115
  • 1
  • 5