By Daniel Wood, 25 September 2019
Back in 2008 when Digital Fusion released Reactor, we used web viewers a lot and we printed them a lot too. Display of javascript based gantt charts, calendars and other rich UI widgets would inevitably require printing by clients and so we'd come up with correctly sized print layouts to do the job.
That was the pre FileMaker 16 days, dating back to the introduction of web viewers in version 8.5. Printing web viewers back then worked pretty darn good.
Then in FileMaker 16 things changed. All of a sudden web viewers that render content fine in browse mode, would fail to render when in Preview mode, printed, or saved as PDF. The exact reasons for this change are murky and unclear.
These days, javascript is everywhere and more popular in FileMaker than ever. It therefore makes sense that people are going to want to be able to print the content they build for the web viewer.
In this article we cover a really simple and easy technique you can quickly add to your own solution to start printing web viewer content. No plugins are needed and no external OS level scripting or screen capturing required.
Is anything these days not solvable with an API? I like to think not. When looking for a solution to a problem such as this, my first option is to look for an API that can do the job. So when looking for an API to solve this issue I looked for one capable of rendering html content.
The results took me to phantomjscloud.com.
PhantomJsCloud is actually a spinoff of an earlier project named PhantomJS. This was a headless browser API allowing testers to carry out user interactions on a website through javascript. Developers would write code to simulate user actions on a site. This project has since been discontinued.
PhantomJsCloud is a cloud based variant based on the same principle. It has a restful API where you can request the API to render a website and return the rendered site as an image, pdf, text or json.
Where PhantomJsCloud is really useful for us as FileMaker developers is its ability to render specific html code you specify, and it is this feature we use to print the web viewer.
Setup of the API is really easy. The API is free for up to 500 calls per day - more than enough for most people. With it you get an API key that you use in each request. There is no additional authentication required.
Let's say you wanted to print a web viewer that contained a javascript based chart such as the one below:
The steps involved to print are:
That's it in a nutshell. We'll go into a little more detail as to how the setup and post request is constructed, but that is really all there is to it.
I encourage you to download and try out the example file for this article. You can use it to follow along with the rest of the article.
Simply go to phantomjscloud.com and sign up for an account. Verify your email address, and when you sign in on the dashboard screen you'll find your API key, that's really all there is to this part.
If you require more than 500 requests per day, there are pre-pay options or pricing plans available, but we think most developers won't need more than 500 a day.
There are so many different ways to render code in a web viewer. Some like to use a Data URL to render html content stored in a field or variable. Others might like to export their files to disk and reference them via the web viewer URL. Others might use a plugin to render content.
Whichever method you use, you're going to need your html code to be available to you in a script so that you can pass it to the API. If you simply display a standard URL in your web viewer than you are all set.
The API can accept either html code, or a URL to render.
using code in a field, rendered using a data URL.
The API request is a POST, and for this we'll use the "Insert from URL" script step, and some CURL parameters.
The URL for the request is pretty simple, it's the PhantomJsCloud site URL with the API key included:
The request is formulated as JSON, and sent as data in the CURL part of the request as a POST.
In our example file we have done the heavy lifting for you and written a standalone script you can use in your own solution. In it we've included the basic request parameters used, these include:
When it comes specifying what to render, the two key json key parameters are "content" and "url". If you are simply rendering a URL, you specify the URL, and content can be empty.
If however you specify content, then the content parameter will include your html code. The URL parameter must be set to "http://localhost/blank" for it to work.
We send the request as a POST using CURL options as shown below. The $body variable contains our JSON request.
The response from the API is typically an image (unless you specify the text or json options). So you simply set the result from the Insert from URL step into a container field. When done, now you have an image in a container that you are able to print however you wish, and that's all there is to it!
Rendering code as an image using an API is a really novel way to render the web viewer. But there are other interesting applications to this API. One of which solves an issue I had recently when developing the Elemental solution. In this solution some of the APIs I integrated with would return the result as an SVG image. This meant that the SVG was unable to be rendered in a container field, and so for those examples, the image had to be rendered in a web viewer only.
This meant the image - in this case an avatar - could not be easily used by a developer. It couldn't be rendered in a portal (web viewers don't render in portals), and so the only option is to convert. In Elemental, my solution was a clunky web based method that was unreliable. It involved rendering there SVG in a canvas object in a web viewer, then converting the canvas to base64 encoded PNG. In order to extract the PNG out of the web viewer, a callback URL to a FileMaker script was used and the base64 encoded image passed to the script as a parameter. However there were 2 major issues:
The technique was abandoned. However in using this technique, I realised this actually solves the SVG conversion issue really nicely, here's how:
In the example file for this article you'll find this exact technique as a working example. It can be used to convert any SVG of any size or complexity to png or JPG quickly and reliably.
We've used the API purely for rendering a site as an image to suit our needs. However the API is pretty cool and does some other potentially useful things, such as:
You must take caution when using any API, especially if you are sending it sensitive or private confidential information in your site or code. Any information you send to the API could be stored on the servers at their end, and so make sure you only use this for generic purposes where you are not using information you wish to keep private.
If security is a concern, then consider purchasing phantomJsCloud enterprise plans. These are private cloud instances dedicated to your solution.
We've found this to be a really easy to implement and reliable way to render web viewer content generated directly from FileMaker. The API takes around 1-2 seconds on average to return the rendered image (usually 30-40kb in size). Other methods we tried involved plugins that screen capture the web viewer part of your screen. The issue here is around resolution and size of the capture, it is quite limiting. The API gives fuller flexibility around this. Not to mention no plugin is needed. This one is definitely worth checking out.
We always strive to provide the best example file to help you understand the article and get a head start on implementing techniques found therein. Please download and try it out for yourself below:
Click to download the example file here.
Something to say? Post a comment...
Comments
Joan Subirós 28/05/2024 4:39am (6 months ago)
i have tried to use your technique to print add-on calendar of filemaker pro 19, but cannot. I think because of the code html.
If you have a solution to print add-on calendar, please let me know.
Thanks.
Tim Anderson 13/09/2023 8:59pm (1 year ago)
This is great and I am sure I will be able to use it, but doesn't work for my first use case.
I am trying to create images from a PivotTable installed using Carafe. The api always renders the default table that is returned, it ignores any modifications of included/excluded data or table type.
I suspect this is down to the changes being managed in javascript not in the web viewer itself. I have tried using the code and the web viewer name - both behave the same.
Do you know of any way I could capture modified reports and charts?
Thanks
Daniel Wood 10/06/2021 11:19am (3 years ago)
hi Jeff, thank you for the comment and apologies for the late reply.
The only real advice I can offer here is to probably turn on script debugger and work through the script step by step, investigating the JSON built up and sent to the "capture web viewer" script, and after that whether that script itself is performing as expected. It may be something you are missing is there.
Web viewers are expected to be named with an object name for reference so I'd make sure that is also done.
Finally, you say an 'incomplete png' is returned, does this mean it's half rendered but not fully ?
Jeff Drake 28/05/2021 4:25am (3 years ago)
Awesome stuff! However, I’ve got an insanely weird situation: your sample file works beautifully, but when I send the exact same code—to the character!—from my own file, it returns an incomplete png.
By any chance, do you have any suggestions? (I’ve checked everything a colleague and I can think of, to no avail.)
Andreas Thyholdt 16/11/2019 10:34pm (5 years ago)
Thanks, Daniel.
This is going to be extremely useful to avoid all kinds of issues with printing Web Viewers. Much appreciated.
Daniel Wood 26/09/2019 2:25pm (5 years ago)
hi Steve,
Yeah you're quite right, I'm not sure what version that became implemented, but the data:text/html is not required, I think I'm just so used to always adding it in for backwards compatibility I tend to forget about that change. Thank you for pointing that one out :)
Steve 26/09/2019 10:47am (5 years ago)
Thanks for the article. I seem to recall reading somewhere that the:
"data:text/html,"
is no longer required for Web Viewers, maybe since v16. Do you know anything about this change?
cheers,
Steve
Daniel Wood 25/09/2019 7:46pm (5 years ago)
You're most welcome Jeff :)
Jeff 25/09/2019 4:47pm (5 years ago)
thanks
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments