How to handle PDF pagination in PhantomJS - node.js

I am using PhantomJS to create PDFs from html.
It works fine, but I can't find out how to work with pagination; I want to create a page for each div in my document, but I can't find anything in the doc. about pagination.
If my document is short, it makes only one page, and if it is bigger, it creates one second empty page and my contents are in the first page which becomes very long.
Any idea ? (I am using phantomJS-node module for nodeJS)

PhantomJS takes care of webkit’s css implementation. To implement manual page breaks you can use these properties :
page-break-before : auto/always/avoid/...
page-break-inside : auto/always/avoid/...
page-break-after : auto/always/avoid/...
For example, a div can be :
<div style="page-break-before:always;"><!-- content --></div>
or
<div style="page-break-after:always;"> <!-- content --></div>
Controlling page breaks when printing in Webkit is sometimes not easy, in particular with long html tables.

Very late, but I had issues with "break-inside:avoid" using JsReport that were fixed by changing the element's display type to inline-block. More info here:
https://github.com/ariya/phantomjs/issues/10638

You should see this issue with different tips.
Try to use display:inline-block in the element that you don't want to breaks because the page break. The reasoning behind is that webkit already tries to preserve images from breaking. And images are inline-blocks.

Pagination works fine with :
var page = webPage.create();
page.paperSize = {
format: 'A4',
orientation: 'portrait',
margin: '1cm'
}
Check documentation here http://phantomjs.org/api/webpage/property/paper-size.html

Related

JSDom's querySelectorAll function not retrieving elements inside of <div>

jsdom version 15.1.1 jest version 24.9.0 node.js version 10.16.0
I am trying to get information from an offline html page by using
var summaryInfo = document.querySelectorAll(".className");
Array.prototype.slice.call(summaryInfo).forEach(n => ... }
In this case there should return 6 arrays of info, but I only get 2
The same exact code works fine in a normal browser, but when I use jsdom with jest it has this problem
I put in a log to see what was being passed through and found with the 2 that work the outermost tag is an <li> and everything inside is just as it should be, but with the other elements the outermost tag is a <div> interestingly nothing shows up inside.
I also checked the html document I am drawing from to make sure that those <div> elements are indeed not empty and they aren't.
Any help that you can provide would be much appreciated!
Thank you in advance.
It turns out that the HTML page had a structure where some <li> tags did not have surrounding <ul> containers. While this worked in browsers like Chrome and Firefox, that was more because the browsers were designed to correct problems like that. Intrinsically my problem is with the HTML page I am trying to use and I can't correct that.

How to use Growl with 'position: sticky' in Primefaces?

I am trying to change the p:growl position of primefaces through the .ui-growl class to use position: sticky. However, since the component is rendered at the end in body, the relative behavior of the position does not work as I would like.
Is there any way to use the sticky position for this component?
Or some way to get the component to render where it is declared?
PrimeFaces 5.1;
Mojarra 2.1;
Disclamer: I tried this with the PF 7.0 showcase, but I think the basics also work with the 5.1 version.
You effectively have 4 options. The latter three all need you to inspect the javascript source of the component (which is open, so you can ALWAYS inspect it before asking questions, the java source is irrelevant here) and for the first solution it helps to see how the component works, but inspecting with a browser developer tool is sufficient (that is how I did it).
Basic analysis with or without looking at the source
This is a variant on your "Or some way to get the component to render where it is declared?". Since on the client side, it is all plain html, css and javascript, you can manipulate with al tools available on the client-side.
You can see that the main part of the grow is html technically rendered where it is declared. Check the PrimeFaces showcase and you'll see
<span id="j_idt700:growl" class="ui-growl-pl" data-widget="widget_j_idt700_growl" data-summary="data-summary" data-detail="data-detail" data-severity="all,error" data-redisplay="true"></span>
right inside the form where it also is in the xhtml. The javascript of the component creates the client side dom things, amongst which is the container that you see right before the end of the body (from the showcase)
<div id="j_idt700:growl_container" class="ui-growl ui-widget" style="z-index: 1002;"></div>
This last piece is html is where the individual growls are added to when they need to be rendered and hence the part that makes the component in most normal cases behave correctly but needs to be done differently in your case.
Solution 1, pure client-side component agnostic solution
Effectively this is as simple as moving this piece of html in the dom, see How to move an element into another element?.
In the online showcase I put the following jquery code in the browser developer tool console
$("#j_idt700\\:growl_container").prependTo(".layout-content");
And added the following css
position: sticky;
top: 10px;
float: right; // this is needed in the showcase, might not always be needed
And it worked.
The jquery should be put somewhere in your page where it runs after the component javascript is executed, so best is to do it right before the end of the body.
Keep in mind that the j_idt700 prefix is the dynamic id of the form in the showcase (it does not have a fixed id here), but you can also use different selectors based on the classes or whatever)
Solution 2, changing the source 'locally'
In the javascript source, you can see where the container is technically rendered
render: function() {
//create container
this.jq = $('<div id="' + this.id + '_container" class="ui-growl ui-widget"></div>');
this.jq.appendTo($(document.body));
//render messages
this.show(this.cfg.msgs);
},
Changing the this.jq.appendTo($(document.body)); in some way to have it appended to the current html node ('this'?) will make it work too. Regarding the overriding, you have two options
How do I find and/or override JavaScript in Primefaces component based on widgetVar?
Override a method from a Primefaces specific widget
Solution 3 Changing the source server side
Effectively you do the first part of #2 but patch the source and create a new custom PrimeFaces version
Solution 4 Make this feature avaiable for others too
What can be done here is to create a new attribute on the component and patch the source in some places so it is configurable to have the component behave as it is now or as sticky (they changed the existing 'sticky' attribute to 'keepAlive' in 7.0.x so sticky is avalable again ;-)). Of course this should be submitted as a patch then...

How to create a general-purpose VisualForce page that can appear on any layout?

VisualForce pages can have the format:
<apex:page standardController="Case" >
<div id="content"></div>
<script>
... javascript to render a UI into #content ...
</script>
</apex>
which means it can appear on the "Case" layout. If you want a generic VisaulForce page (appearing all alone on a tab, let's say) you can remove the standardController parameter:
<apex:page>
...
</apex>
Is there a way to specify that a single VisualForce page can appear anywhere? (In our case, it's a javascript utility which is not layout-dependent).
I'm new to SalesForce, and the closest I could come up with would be to dynamically populate the standardController field (if that is supported) but I feel there must be a better way. Any help is greatly appreciated!
Do you mean it's a piece of javascript you can include in other pages? If so you should be doing it as a component, or you could put the JS in a static resource and include that in your pages.
If it's actually a page, you can include it in a page layout as well, though it's a little clunky and goes in an iFrame so that would probably cause problems for you.

Layout based on Page - OrchardCMS

I have encountered an issue when using Orchard that I am sure there should be a fairly simple fix / solution for, but I have yet to find it.
I am trying to establish a specific width content area for my home page (580px), and a larger width for content pages (800px).
Layout.cshtml Snippet:
<div id='content'>
#Zone(Model.Content)
</div>
Style:
#Content
{
[...]
width: 580px;
}
Currently - the Content div wraps all of my content regardless of the page (either Home Page or Content). I am wondering if it is possible to use a different div to wrap the content based on the Page, as shown:
Layout.cshtml Idea:
#if(Model.Page != "Home")
{
<div id='fullcontent'>
#Zone(Model.Content)
</div>
}
else
{
<div id='content'>
#Zone(Model.Content)
</div>
}
I'm unsure if the above suggested method is possible (or I am unsure how to check for the current Page) - but any other suggestions would be appreciated.
You can use the Designer Tools module (built-in all recent Orchard versions) and enable the URL alternates feature. You'll then be able to create a layout-url-homepage.cshtml alternate for your layout.
You can use the Layout Selector Module to assign a custom layout to any content item.
http://gallery.orchardproject.net/List/Modules/Orchard.Module.Orchard.DesignerTools
You could use the Vandelay.Classy module to add custom tags to the page that represents your homepage, although it does add a lot of fields to the Page content editor.

How do I get at image title attributes in Watir?

Given the following HTML code (which, I realise, sucks, but that's not something I can currently solve):
<img height="64" width="64" class='list_item' src="/img/icon/first.jpg"
title="This is the first item::Completed the item "I did this first"" alt="First" />
gives me a result of (this is an image.to_s)
name:
type:
id:
value:
disabled:
src: /img/icon/first.jpg
width: 64
height: 64
alt: First
Note lack of "title" element. This does not actually change (the lack of the title element)
If I get the contents of the parent div of one of those icons, I get something like:
<img class="list_item" I="" did="" this="" first="" src="/img/icon/first.jpg" alt="First">
The broken HTML of the original has been turned into separate attributes somewhere down the line, but the title tag appears to have been stripped completely, and since it's the contents of the title tag I need, I'm a little stuck.
This has been tried with lastest Watir on Ruby 1.9.2 using Firefox.
Perfect world solution: I'd like to get the original transmitted HTML for the image tag, so I can "special case" (ie, hack) around the stupid double-quote problem.
Good Enough Solution: the contents of the title tag.
There is actually a #title method on Watir::Image. With the above incorrect HTML the output would be like this (where 'i' is the Image object):
i.title
=> "This is the first item::Completed the item "
This shows only part of the title.
But you could use #html and then parse all the necessary information out of it with some magic:
i.html
=> "<IMG class=list_item title=\"This is the first item::Completed the item \" alt=First src=\"/img/icon/first.jpg\" width=64 height=64 first?? this did I>"
But as other answers above have mentioned - you cannot get it out correctly due to the bad HTML. Maybe there's some other way to accomplish your bigger goal you're having?
getting the title probably isn't working because the way the title attribute is set on that element isn't valid. entities " and < and > need to be escaped inside html attributes, with " and < and > respectively. Escape the quotes and try again.
Not sure, but I don't think Watir supports image titles. I looked over the Supported Elements page, title was x'ed out. I don't see it in the RDoc for Watir::Image type either.

Resources