wicked_pdf
wicked_pdf copied to clipboard
Best way to exclude header and footer from first page
Hello,
I'm having a very hard time removing the header and footer on the cover page of a document that's being generated with wicked_pdf within a Rails app.The controller's action renders the pdf document, using:
*snipped*
render pdf: @document.document_type,
page_size: 'A4',
layout: false,
orientation: @document.landscape ? 'Landscape' : 'Portrait',
encoding: 'UTF8',
header: {html: {template: 'documents/_header'}, spacing: 35 },
footer: {html: {template: 'documents/_footer'}, spacing: 0 },
margin: {top: 30, bottom: 20, left: 0, right: 0},
show_as_html: params[:html].present?
*snipped*
I'm aware that wicked relies on wkhtmltopdf to convert html to pdf. I checked their discussions and the the only one that I found suggest usage of JS. This is my version of the JS I found there.
function hideHeader() {
var vars={};
var x=document.location.search.substring(1).split('&');
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
if(vars['page'] == 1){
var elt = document.getElementById("document-header");
elt.parentNode.removeChild(elt);
}
}
When the header and footer is removed, the content of the PDF moves upwards which results to breaking the layout of the rest of the pages.
For example, there are couple of pages where the main content of the page "slips under" the header:
I used to sort this out with a top margin in the render action, but if I use it, the margin will be applied to the first page too, which will result with a blank white block in the top of the document. Other possible solution is removing that margin on the first page using JavaScript. Is that possible?
Thanks in advance for any help or advice on this.
Because headers and footers are repeated on every page, my first thought is that you should ditch setting up the header and footers in the controller for wicked_pdf
, and instead in your body:
<div id="pdf-header" style="display:none;">
<%= render template: 'documents/_header' %>
</div>
Then use JavaScript to unhide it only on the first page, or alternately, hide it on every page but the first. Same deal with the footer.
Please let me know if this helps (or not)!
Hi, in order to do what you suggested I need to know where every page begins/ends. But, there will be couple of pages in the document that I'm not sure where they will begin/end because I'm generating some tables using Underscore.js/Handlebars. So, this isn't an option for me.
Is there another way to achieve this, or maybe, a way to target the top margin using JS?
Thanks!
If the problem with your first approach is that the content "slips up" after removal, then instead of:
elt.parentNode.removeChild(elt);
You do something a little less drastic than removing the element entirely.
Perhaps just remove the content with elt.innerHTML = '';
, and/or set the css to visibility: hidden;
, and use CSS to give it the height, width and padding desired.
I thought about not removing the element and hiding it instead. Using visibility: hidden
means that there will be blank areas on the cover page where the cover/header should be placed.
I guess that adding proper margins to the elements on the cover page could "push" the document downwards so the pages don't break.
Any other ideas? Thanks!
Have you tried the :cover option? If the gem and binary version are compatible it works.
@danimataonrails the :cover option seems to be using a separate source:
:cover => 'URL, Pathname, or raw HTML string',
In my project, we don't use a separate cover page. But still want the first page to be without header and footer.
any success?
In the end, we went with generating the cover and the body as separate documents and merging them into one before sending it to the user.
Achieved the result quickly by using "cover" option.
You can use some javascript to detect the current page and then add display none
to your header only in first page.
Following the Page Numbering instructions from WickedPDF documentation.
This is working in my PDF.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function headerCheck() {
var x=document.location.search.substring(1).split('&');
for (var i in x) {
if(x[i] == "page=1") {
document.getElementsByClassName("header")[0].style.display = "none";
}
}
}
</script>
</head>
<body onload="headerCheck()">
<div class='header'>
<h1><%= cellar.name %></h1>
</div>
</body>
</html>