wkhtmltopdf dynamic margins - php

Is it possible, using wkhtmltopdf, to define dynamic margins ?
I'm generating a pdf for an invoice, on the first page I have the BVR in the footer so the user can cut it out and pay with it. On pages besides the first one, I have no footer.
The problem is that, when having enough content to fill the second page fully, the page breaks occurs at the given footer margin, leaving me with a page empty for 1/3.
Is it possible to define (javascript or other ways) a dynamic margin size for the first page, and then remove the bottom margin for any other ?

Nope. You can create a feature request at https://github.com/wkhtmltopdf/wkhtmltopdf/issues, but I don't think this is coming any time soon because the underlying technology (webkit) has stabilised (doesn't change often) and doesn't really need this feature.
How about for a workaround you examine the content and if it's the specific length you split the HTML to two files and convert them individually. Then you can join them with pdftk for example.

Related

MPDF - Full page background based on page orientation

I am using MPDF to generate a PDF from some data.
The general flow is as follows: I collect data from a database, I start output buffering, include a template, and clear the buffer and append the HTML to the PDF (calling $mpdf->AddPage when necessary). So far so good.
In my css, I have defined the body to have background-image: url('portrait-bg.png');, which works great.
Now, I want to add some pages that are in landscape format ($mpdf->AddPage(..., 'L');). That works too - but I cannot figure out how to set a different background for those pages (so that the image isn't stretched).
What I've tried:
Setting an image directly on the pdf using $mpdf->Image (doesn't work, it counts as an actual image that content flows around, not as a background).
Putting a tag on the relevant page template, and then specifying a different background in my CSS (doesn't work, shows the original background - in fact, I don't seem to be able to select the body element at all in this manner!)
So after struggling with this for a long time, I was unable to find a good, clean way to do this - presumably due to shortcomings in MPDF.
In any case, the workaround I went with was using a style attribute on each body element that needed a special landscape background. It's not clean, it's not nice - but it seems to be the only way that works, unfortunately. Giving the body a class attribute and defining that in the linked CSS seems not to work (although I can't tell why - the MPDF docs claim to support this functionality, and it is how I set the standard background in the rest of the document).

Multipage invoice/document in PHP

TL;DR: I have problems with PHP generating PDF's longer than 1 page total.
Hello again. My goal is to create a script that will basically get all the important data and create a A4 format PDF invoice/document for printing/mailing/archiving. Generating PDF document is fine as long as the document does not overflow.
I want the invoice pages to be outlined with a border, it should contain:
the needed stuff required for the invoice to be valid
billed products/other information
place for supplier/customer signature and stamp or other data
All the pages HAVE to contain header and footer (company logo) and footer (page # of # - Invoice/Document ID - Date and Time - office ID - Printer ID, assigned personnel, whatever someone can ask), as well as border around the document body (under header, above footer).
Everything is fine as long as the document size is not bigger than
$pageSize-$pageMargins-$header-$footer-$invoiceDataBlock-$signaturesBlock
which is basically just like 10 cm for the actual invoiced items. If the document is bigger, I actually create attachment for the invoice manually using spreadsheet editor.
The question is: What can I do to create a multipage PDF document that has no problems like invoiced items overlaying the header/footer? I need to know when to continue on the next page. How do I know this? What is the best way to accomplish this task?
Thank you in advance!
I've used both FPDF and TCPDF to generate multi-page invoice files. They are roughly the same in terms of how they work. (I started with FPDF, then switched to TCPDF when I needed to include Unicode characters, which FPDF didn't support at the time.)
As Eugen suggested, you can hand-roll your own headers and footers more easily than using the functions built in to either FPDF or TCPDF.
My strategy for making sure I don't overwrite footers is simply to be careful with the data included on the invoice. When adding new SKUs, I test long names to make sure they will fit in their field in the invoice PDF. For items that must be variable-length, I put unknown content onto its own line to reduce possible impact:
Domain registration (2 years)
↳ example.com
As I generate each page of the invoice, I keep track of how many lines I've used. I know I can safely put 20 lines of items, and I know my maximum single item is 2 lines, then when I get to 20 lines, I start a new page. 15 items means 1 page. 25 items means two pages. The item counter goes up, and every time I hit the 20 line limit, it generates the next page and resets the page item counter.
Note that I'm not including any code in this answer because you didn't include any code in your question. If you'd like help with implementation, I suspect that will be grounds for an additional question. :-)
Use TCPDF. It has a very handy SetY() / GetY() pair of functions, that allows you to know, where on the page you are. You can use this to know when to do a page break.
Hint: Do not use the Header/Footer capabilities - they are clunky. Draw your own headers/footers.
Edit
As from discussion below, here are some details: To avoid overlaying you have 2 possibilities
Use getStringHeight() and calculate
Use Transactions
The first version draws its rationale from the fact, that of all objects you typically use in generating a PDF a text-flow is the only one, of which you cannot tell beforehand the height it will use. getStringHeight() provides you with a good enough estimate, so you know before adding the element, if it will fit on the page (leaving enough room on the bottom for the footer). So basically you extend your drawing loop to calculate the height of each element and test, if you need to start a new page first. This allows also for some sort of keeptogether, e.g. if the remaining space after a section title is too low, start a new page before, to keep section title and section body together.
The second version is even easier: In TCPDF you can use transactions simialr to a Database: Start a transaction, draw, if the result is not to your liking roll back, else commit. We found this to be quite a performance hog, ultimately deciding against it for long textual reports, but a 2-page invoice is a very different beast.

Will user custom styling work with document.ready + localStorage?

I run and actively develop a forum (which in itself runs on heavily modified SMF 1.1.16) - one feature I would like to add is the ability for the user to pick custom colours (say 2-4) from a widget in the corner of the page to customize the colours of the forum.
The HTML output of the forum is structured such that modifying the colours can be done with pure CSS, and I'm wondering what the right way to insert this CSS is.
The idea I had was that once the user saves their colour information, a piece of javascript would generate the necessary CSS and save it using HTML5 localStorage (probably using a polyfill library). Then, on $(document).ready(), we check for this CSS being present and if it is, we inject it into the page head.
Is this approach sensible? It's easy to develop, but will it result in a flicker of the usual styling (given that pages are rather heavyweight) before custom styling is applied?
If so, is there a better way to do this completely client-side? I would rather not involve the server if at all possible, but if I must I can just have the server generate CSS files for every user who saves custom styling.
What's the best approach?
I suggest you have a base style for the page first so that there won't be FOUC. Then, have your JS load the custom styles, parse it, and apply it to the page afterwards. You could do a "fade-in change" (like fade in the background etc) so the styles won't load like a snap.
You could also blank the page first, like set the body to display:none, before you load the styles, then after the styles are applied, remove the display:none
You also have to note that local storage has it's size limit. Don't load too much. Consider looking for the LZW compression in JS. It might help.

Can we measure height of a div using php?

Can we measure height of a div using php?
This is not possible at all: PHP serves HTML code. The browser renders it. Only after it is rendered, can height be determined reliably. Different browsers may end up with different heights. Different user settings (like font size) may end up with different heights.
The only way to find out an element's height is using JavaScript which runs in the browser. You can theoretically send the results back to a separate PHP script using Ajax, but I doubt that'll make much sense.
You could use jQuery's .height() like so:
var height = $("#elementID").height();
(there are native JavaScript approaches to this as well, but they tend to be a bit long and complicated.)
As others have said here, you cannot use PHP to read the height/width of a div already rendered. However, aside from the javascript options already presented keep in mind that you can use PHP to set the height/width of a div before it is sent to the browser. This would be in the form of an inline style of course. This is not the most elegant solution and to be honest I would avoid it, but you did not state what specifically it is that you want to do, and why.
Not sure if that info will help you in your implementation but it wasn't mentioned so far and thought I would contribute it.
No, we cannot. div is rendered by a browser based on CSS/JS. in a different browsers it can be different (IE, Firefox). It does not depends of PHP.
In case you are using text inside the div you could use strlen() to have some kind of measurement of height. I am saying some kind ofcourse because you are just counting the number of characters which then can be equated to some height depending on the font-size of the text, the line-height, the width of the div.
Lets say one screenheight can output 2000 characters on your website
If you count 4000 characters you have 2 screenheigths.
954 characters = almost half of a screenheight ...
i have used this method once to calculate the amount of ads i could implement in the sidebanners on a blog styled website with mainly textcontent on it ...
The height of a vertical ad was about one screenheight. If the text that needed to be outputted was 7000 characters i knew i had room for 3 ads ...

Pagination of text from xml file onto html page

O.K. so I'm developing a website to feature my fiction writings. I'm putting all of my documents into XML files, pulling and parsing them from the server with PHP and displaying them on the page. You can visit the page here for an example.
As implied from the background image, What I would like to do is take the text and split it into two columns, (with the text from the first spilling into the second), then allow for the overflow to be paginated so that there is no scrolling necessary. In other words, I'd like for the text to read like a book with the paging based on how long the body of the XML document is.
I would like for this to be done on the server side using PHP or something similar. Is there a way I can do this with an xsl stylesheet or a server-side script? I've been looking everywhere and can't seem to find anything.
Any help is appreciated.
Mr. Mutant
This is a surprisingly hard problem in general, and it's one you'll have no end of trouble with if you try to do it on the server. The problem with paginating HTML text is that where the page breaks go are entirely contingent on the client. The server doesn't know the client's screen resolution, font selection, or window size, and apart from the text itself those are the dependent variables for the problem.
I'd be surprised if at this point there weren't some jQuery library that just does this, but when I had to implement it myself about 7 years ago, here's the approach I took:
Create a div for each column. Each one contains the entirety of the document text. Style the divs with fixed line height. Put the column divs bottom in the document's z-order. Now you can lay out the rest of the page, leaving holes of known size in the layout that the divs can show through, and by manipulating the vertical position of each div you can control which line is the first to appear inside a given hole.
You can then let the client manipulate the font size, and as long as you recalculate the height of the holes and then reposition the divs properly, it will all magically work.
There may be ways of doing this in HTML5 that are easier; I would definitely look into that.

Categories