Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Add Header and footer on all PDF page In jsPDF with addHTML method

I'm convert html to pdf using jspdf. I'm using addHTML method to convert html page in to pdf

  var htmlSource = $('#body')[0];

 function crate (){
   var pdf = new jsPDF('p','px');

  pdf.addHTML(
    htmlSource,10, 10, {pagesplit: true, margin: {top: 10, right: 10,bottom: 10, left: 10, useFor: 'page'}},
    function(dispose){
       pdf.save('datapdf.pdf');
    }
  );

}

and I want add header and footer on all pages either leave blank space for header and footer. but using option I can only leave header space on first page of pdf.

like image 428
Vijay ijardar Avatar asked Apr 16 '18 09:04

Vijay ijardar


4 Answers

One approach could be to refill the html page rendering in the client browser so as to display it exactly as you want it to be printed in the pdf (then simply use the function you just created above), therefore in a format composed by a series of vertical elements like h, p1, f, h, p2, f, h, p3, f, etc (where h=header, p1 ... pn are the pages and f=footer) instead of a series containing just h, p1, p2, p3, ... , pn, f (as is now).

This means that you might have access to the source code of the html page (so it's not just a page taken from the internet), because if it's an external resource maybe the dimensions of the header and footer are programatically constructed as to also fill spaces in relation with other elements of the page (and I think here of flex / applied vertically / or grid technologies in rendering the webpage).

Another aspect, if going to do this method, is that maybe the split in content is not always possible (and I'm not thinking here about destroying tables or other multi-page elements visible only when using the scrolling), but also the rendering might take into consideration the vertical display of the page (opposite to landscape mode as in desktop) in order to redraw the elements from the page. That sometimes could make the footer and header maybe larger, so I'm not sure why you would want to spend parts of valuable estate of the final printed page by doing that. (The solution would be possibly to open a new window, thus re-rendering the page in the new format, maybe even behind the existing page, then launch the print confirmation / or download the file / before closing that respective page.)

The other way would be to change the function so to work with a virtual rendering of the page (no displayed page) - by making the changes into your function and not in the rendering itself.

However, that second approach present also a few challenges, too. Initially, at declaring the variable 'var pdf' this is created as a unique data storage container, then you assign to it the constructor ( var pdf = new jsPDF('p','px'); ). However on the next step you add to it a HTML content (pdf.addHTML) which is a single element, not a multiple entity. You should change the function in order to make it print an array where you first calculate the elements based on the dimensions of pages rendered.

Maybe the code would become something as :

var fullpage, onepage, headd, foott, edges, contentt, he, fo, c, pages;
fullpage = document.body.scrollHeight; // height of all html page (not just the visible content)
onepage = 1200; // height of each single page printed in pdf - in pixels
headd = document.getElementById("header");
he =  headd.offsetHeight;
foott = document.getElementById("footer"); 
fo = foott.offsetHeight;
edges = he + fo;
contentt = onepage - edges; // height of content of each page printed

pages = [0];  // start to work with first page which obviously is there
fullpage -= onepage; // remove height of first printed page (containg both header and footer)
    pdf.addHTML( // create first page of pdf file
    htmlSource, 10, 10, {pagesplit: true, margin: {top: 10, right:
      10, bottom: 10, left: 10, useFor: 'page'}},
    function(dispose){
       pdf.save('datapdf.pdf');
    });   // this is your code

var i = 0; // start the counter

 while(fullpage > 0) { // start adding header + footer to remaining pages
  fullpage += edges; // if there is still a page 2...n we add edges, etc.
  i++;
  pages[i] = content(onepage) { // here you must insert the code for harvesting the n-st page content from your source code
    return htmlSource;
  }
     function addPages(i) {
         var eachpdf = "datapdf" + i + ".pdf";
          // <= here goes again your code, with a small change
          // pagesplit: false - instead of true, in order to speed the process, and also
          // pdf.save(eachpdf); - instead of pdf.save('datapdf.pdf');              
     }
 }

What you try to achieve is to create a series he, p1, fo, he, p2, fo, he, p3, fo, etc (where he=header, p1 ... pn are the pages / named datapdfi above / and fo=footer) instead of a series containing just h, p1, p2, p3, ... , pn, f.

This means you must construct an array containing separate pdf pages as explained in code above.

I didn't yet create for you the code for separating the content of each page (which might return the htmlSource) however this is in strict dependence with the way in which your pages are rendered.

like image 195
1copyright Avatar answered Nov 08 '22 21:11

1copyright


There is a suggested method use HTML's elements <header> and <footer> for that purpose, for example:

<footer>
    <div style='text-align:center;'>Page <span class="pageCounter"></span>/<span class="totalPages"></span></div>
</footer>

See https://github.com/MrRio/jsPDF/pull/260

like image 32
Sajeetharan Avatar answered Nov 08 '22 22:11

Sajeetharan


If someone still looking for the short solution, you can try this,

For the footer as number of page,


html2pdf().from(element).set(opt).toPdf().get('pdf').then(function (pdf) {
  var totalPages = pdf.internal.getNumberOfPages();

  for (i = 1; i <= totalPages; i++) {
    pdf.setPage(i);
    pdf.setFontSize(10);
    pdf.setTextColor(150);
    pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 100, pdf.internal.pageSize.getHeight() - 30);
  } 
}).save();

For the header, you can write

pdfObject.text("my header text", 10, 10)

this will create the header text as my header text in each page position x=10, y=10.

like image 3
Tekson Avatar answered Nov 08 '22 21:11

Tekson


let doc = new JsPDF('p', 'pt', 'a4')
    doc.html(componentRef.current, {
        callback: function (pdf) {
            //pdf.setFontSize(10)
            let totalPages = pdf.internal.pages.length-1
            for (let i = 1; i <= totalPages; i++) {
                pdf.setPage(i);
                // pdf.setFontSize(10);
                // pdf.setTextColor(150);
                pdf.text('Page ' + i + ' of ' + totalPages, pdf.internal.pageSize.getWidth() - 100, pdf.internal.pageSize.getHeight() - 30);
            }
            pdf.save(
                `delivery-${deliveryDate}.pdf`
            )
        },
        margin: [10, 0, 55, 0],
        autoPaging: "text",
    })
like image 1
Arslan Avatar answered Nov 08 '22 22:11

Arslan