Issue
I'm trying to print a receipt invoice from browser using iframe
. I was able to invoke the print and I'm able to get the receipt dispalyed in browser print window. However the height of the receipt is more than the maximum content in the receipt which leads to waste of paper.
Here is what I have done so far.
HTML
:
<!DOCTYPE html>
<html lang="en">
<body>
<button id="print">Print</button>
<section id="section-to-print">
<header>
<h1>Brand Name</h1>
<hr />
<address>Address: #1234,<br /> Street,<br /> Area,<br />
District - PinCode</address>
<p>Phone: 22334455</p>
<p>Mobile: 9876543210</p>
<p>GSTIN: GSTIN123456789</p>
</header>
<hr />
<main>
<section id="customerdetails">
<h3>Abdul Rahman</h3>
</section>
<hr />
<section id="invoicedetails">
<p>Invoice No: 1234</p>
<p>Invoice Date: 24 MAR 2022)</p>
<p>Payment Mode: Cash</p>
<p>Total Amount: 1234</p>
<p>Serviced By: Undertaker</p>
</section>
<hr />
<section id="invoiceitems">
<div class="header justify-self-start">Description</div>
<div class="header">Qty</div>
<div class="header justify-self-end">Price</div>
<div class="item justify-self-start">Category <br /> - Item</div>
<div class="unit">1</div>
<div class="price justify-self-end">100</div>
<div class="footer justify-self-start font-bold">Total QTY</div>
<div class="footer justify-self-start font-bold">1</div>
<div></div>
<div class="footer justify-self-start span-2 font-bold">Sub Total</div>
<div class="footer justify-self-end font-bold">90</div>
<div class="footer justify-self-start span-2 font-bold">DISCOUNT</div>
<div class="footer justify-self-end align-self-center font-bold">-10</div>
<div class="footer justify-self-start span-2 font-bold">CGST (1%)</div>
<div class="footer justify-self-end align-self-center font-bold">1</div>
<div class="footer justify-self-start span-2 font-bold">SGST (1%)</div>
<div class="footer justify-self-end align-self-center font-bold">1</div>
<div class="footer justify-self-start span-2 font-bold">ROUNDOFF</div>
<div class="footer justify-self-end align-self-center font-bold">-0.01</div>
<div class="footer justify-self-start span-2 font-bold">TOTAL</div>
<div class="footer justify-self-end align-self-center font-bold">100</div>
</section>
<hr />
<section id="invoicesummary">
<p>Total Amount in Words ($)</p>
<p>ONE HUNDRED ONLY</p>
</section>
</main>
<hr />
<footer>
<p><small>Thank you for the business</small></p>
<p><small>This is a computer generated invoice</small></p>
</footer>
</section>
<script>
window.addEventListener("DOMContentLoaded", function () {
document.getElementById("print").addEventListener("click", function () {
var iframe = document.querySelector('#invoice-print') || document.createElement('iframe');
iframe.setAttribute("id", "invoice-print");
document.body.appendChild(iframe);
iframe.contentWindow.document.body.innerHTML = document.querySelector('#section-to-print').innerHTML;
var printScript = document.createElement("script");
printScript.innerHTML = `function setPrintStyles(pagesize) {
var documentHeight = document.getElementsByTagName('html')[0].offsetHeight;
var css = \`@media print { @page { size: $\{pagesize} $\{documentHeight}px; } }\`,
head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
head.appendChild(style);
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
}`;
iframe.contentWindow.document.head.appendChild(printScript);
var bodyScript = document.createElement("script");
bodyScript.innerHTML = `fetch('${window.location.origin}/receipt.css')
.then(response => response.text())
.then(data => {
var head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
head.appendChild(style);
style.type = 'text/css';
style.appendChild(document.createTextNode(data));
setPrintStyles('2.7in');
window.print();
});`;
iframe.contentWindow.document.body.appendChild(bodyScript);
});
});
</script>
</body>
</html>
Receipt CSS:
@media print {
#section-to-print {
position: absolute;
left: 0;
top: 0;
}
html, body {
margin: 0 2px;
height: max-content;
}
body {
font-family: Calibri;
text-align: center;
font-size: 0.8rem;
}
p, h1, h3 {
margin: 0.25rem 0;
}
#customerdetails {
text-transform: uppercase;
}
main #invoiceitems {
display: grid;
grid-template-columns: auto min-content max-content;
grid-column-gap: 1px;
}
main #invoiceitems .header {
text-transform: uppercase;
font-weight: bold;
}
main #invoiceitems .item {
text-align: left;
}
main #invoiceitems .price {
text-align: right;
}
main .justify-self-start {
justify-self: start;
}
main .justify-self-end {
justify-self: end;
}
main .align-self-center {
align-self: center;
}
main .span-2 {
grid-column-start: 1;
grid-column-end: 3;
}
footer {
margin-top: 0.75rem;
text-transform: uppercase;
}
#invoicesummary {
text-transform: uppercase;
font-weight: bold;
}
.font-bold {
font-weight: bold;
}
}
Actual Output - Having extra height which leads to wastage of paper:
Expected Output - To have exact height of the content:
When I click on print button I want to make the receipt to have height of it's maximum content. I tried to the set page height inside iframe using the following code var documentHeight = document.getElementsByTagName('html')[0].offsetHeight;
. But still the height is almost double the content height. Please assist on what I'm doing wrong.
Solution
Finally, I resolved this by reducing the documentHeight
to half
and added a breathing space of 50px
inside my iframe
script
TLDR:
from
var documentHeight = document.getElementsByTagName('html')[0].offsetHeight;
to
var documentHeight = `${(iframe.contentWindow.document.body.offsetHeight / 2) + 50}`;
This gives the expected output as shown below.
Answered By - fingers10 Answer Checked By - Mary Flores (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.