PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, April 14, 2022

[FIXED] How to make height of receipt invoice print from iframe to the maximum height of content in the receipt invoice?

 April 14, 2022     css, html, iframe, javascript     No comments   

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: Actual Output

Expected Output - To have exact height of the content: Expected Output

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.

Expected Receipt Output



Answered By - fingers10
Answer Checked By - Mary Flores (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing