altgov3en
altgov3en

Reputation: 1206

Print whole HTML page including pdf file inside iframe

I've got an assignment to embed relatively small pdf file inside html page and print the entire html pade including the pdf file inside the iframe. Here is the structure of my html page: enter image description here

Here is my code:

@media print{
	body * {display:block;}
    .toPrint{display:block; border:0; width:100%; min-height:500px}
<body>
    <button onclick="window.print()">Print</button>

	<h3>MUST BE PRINTED</h3>
    <p> MUST BE PRINTED</p>
    <iframe class="toPrint" src="https://nett.umich.edu/sites/default/files/docs/pdf_files_scan_create_reducefilesize.pdf" style="width:100%; height:97vh;"></iframe>
	<h3>MUST BE PRINTED</h3>
    <p> MUST BE PRINTED</p>
</body>

Currently I'm printing the page using css @media query. But unfortunately this media query prints the pdf's first page only.

What can I do print the entire pdf file?

Upvotes: 16

Views: 5219

Answers (6)

user28862421
user28862421

Reputation: 1

@media print{
    body * {display:block;}
    .toPrint{display:block; border:0; width:100%; min-height:500px}
<body>
    <button onclick="window.print()">Print</button>

    <h3>MUST BE PRINTED</h3>
    <p> MUST BE PRINTED</p>
    <iframe class="toPrint" src="https://nett.umich.edu/sites/default/files/docs/pdf_files_scan_create_reducefilesize.pdf" style="width:100%; height:97vh;"></iframe>
    <h3>MUST BE PRINTED</h3>
    <p> MUST BE PRINTED</p>
</body>

Upvotes: -1

Here is a simpler solution using javascript.

<body>
        <h3 id='first_h3'>MUST BE PRINTED</h3>
        <p id ='first_paragraph'> MUST BE PRINTED</p>
        <div id="pdfRenderer"></div>
        <h3 id='second_h3'>MUST BE PRINTED</h3>
        <p id='second_paragraph'> MUST BE PRINTED</p>

<input type="submit" value="Print All"
  onclick="javascript:printPage()"
 />

</body>

<script>

 pages =[] // initiate an empty list here

function printPage() {

var first_h3 = document.getElementById('first_h3');
// get the first h3 tag and
// then push its innerHTML into the list
   pages.push(first_h3.innerHTML); 

var first_paragraph = document.getElementById('first_paragraph');
// get the first paragraph and
// then push its innerHTML into the list
   pages.push(first_paragraph.innerHTML); 

var pdfRenderer = document.getElementById('pdfRenderer');
// get the pdfRenderer and
// then push its innerHTML into the list
   pages.push(pdfRenderer.contentWindow.document.body.innerHTML); 

var second_h3 = document.getElementById('second_h3');
// get the second h3 tag and
// then push its innerHTML into the list
   pages.push(second_h3.innerHTML); 

var second_paragraph = document.getElementById('second_paragraph');
// get the second paragraph and
// then push its innerHTML into the list
   pages.push(second_paragraph.innerHTML); 

if (pages && pages.length) {

// this if statement, just checks to ensure our list is not empty before running the code.

// here is the magic, we now set the parent window to be equal to all the concatenated innerHTML
window.content.document.body.innerHTML = pages;
// then we print this new window that contains all the different parts in the exact order we pushed them into the list.
window.print();
} 
else {
// do nothing
}


}
</script>

With this solution avoid the problem of the iframe being cut off if it exceeds one page. Secondly, you get only one print dialogue box even if you have multiple iframes.

Upvotes: -1

altgov3en
altgov3en

Reputation: 1206

I used Mozilla's pdf.js to solve my problem. It renders the pdf file on html5 canvas thus it allows to print the whole html page as required.

Here is the code (credit):

<html>
<body>

<script type="text/javascript" src="https://raw.github.com/mozilla/pdf.js/gh-pages/build/pdf.js"></script>
<script type="text/javascript">
function renderPDF(url, canvasContainer, options) {
    var options = options || { scale: 1 };
        
    function renderPage(page) {
        var viewport = page.getViewport(options.scale);
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var renderContext = {
          canvasContext: ctx,
          viewport: viewport
        };
        
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        canvasContainer.appendChild(canvas);
        
        page.render(renderContext);
    }
    
    function renderPages(pdfDoc) {
        for(var num = 1; num <= pdfDoc.numPages; num++)
            pdfDoc.getPage(num).then(renderPage);
    }
    PDFJS.disableWorker = true;
    PDFJS.getDocument(url).then(renderPages);
}   
</script> 
        <h3>MUST BE PRINTED</h3>
        <p> MUST BE PRINTED</p>
		<div id="holder"></div>
        <h3>MUST BE PRINTED</h3>
        <p> MUST BE PRINTED</p>

<script type="text/javascript">
renderPDF('yourFile.pdf', document.getElementById('holder'));
</script>  

</body>
</html>

Upvotes: 0

Ronak Bhavsar
Ronak Bhavsar

Reputation: 19

Use https://github.com/itext/itextsharp itextsharp or https://github.com/MrRio/jsPDF jsPDF. It is easy to use by plugin

Upvotes: 0

avladov
avladov

Reputation: 851

The reason it's not printing the whole PDF is because it's in an iframe and the height is fixed. In order to print the whole PDF you'll need the iframe height to match its content height (there should be no scrollbar on the iframe).

Another option is to print only the iframe. Add id to your iFrame:

<iframe id="toPrint" class="toPrint"></iframe>

Focus the iframe and print its content:

var pdfFrame = document.getElementById("toPrint").contentWindow;

pdfFrame.focus();
pdfFrame.print();

Upvotes: 11

Rik
Rik

Reputation: 519

Try this, it includes some JS but thats always good. HTML:

<body>
        <h3>MUST BE PRINTED</h3>
        <p> MUST BE PRINTED</p>
        <div id="pdfRenderer"></div>
        <h3>MUST BE PRINTED</h3>
        <p> MUST BE PRINTED</p>
    </body>

JS:

var pdf = new PDFObject({
  url: "https://nett.umich.edu/sites/default/files/docs/pdf_files_scan_create_reducefilesize.pdf",
  id: "pdfRendered",
  pdfOpenParams: {
    view: "FitH"
  }
}).embed("pdfRenderer");

This should work. Let me now if i doesnt

Upvotes: 4

Related Questions