Web Viewer Tips For FileMaker 19 – Hosting Your Web Viewer Add-On

What are the benefits of building a hosted app for the web viewer in FileMaker? And how can we make this approach work in WebDirect where it looks like FileMaker only supports data URLs?

In a previous article, we looked at writing JavaScript for FileMaker 19 that matches a typical  JS pattern of making asynchronous calls to a data source and handling the results. One of the important takeaways of writing JavaScript this way is that we can now maintain a single code base for our DayBack Calendar app across all platforms. In this article, we’re going to look at taking this idea a step further. In addition to being able to maintain a single codebase, we can host that codebase on a single server and have the FileMaker web viewer simply reference the server’s URL.

Hosting Web Viewer Apps in FileMaker 19
DayBack as a hosted app in FileMaker Pro client

This is a pattern that we’ve become very familiar with: it’s how DayBack works in Salesforce using Salesforce’s Canvas toolkit.

FileMaker 19 Best Practices
DayBack as a hosted app in Salesforce Lightning

Why Host your FileMaker Web Viewer Add-On?

For DayBack Calendar, which works with different platforms both embedded, like the FileMaker web viewer, and in the browser, hosting offers us a single code base and a single host for us to maintain. If we had to maintain different repositories and servers for the different platforms, that would exponentially more complex with each new calendar source we added–both in terms of architecture and in terms of making decisions on which version gets which features deployed. However, there are other benefits beyond working with multiple platforms that FileMaker developers should consider.

All Users are on the Same Version

Having multiple versions of the same product out in production can make things extra difficult for your support team. Even though there are some scripts and schema to maintain on the FileMaker side, by moving most of the logic into the single JavaScript build we can cut down chasing if an issue a customer is facing is based on a versioning issue or not. New features and bug fixes get deployed simultaneously and while not all features can be used on every platform, the default becomes that all users get the new features.

We worked very hard to develop scripted, in-app updates for the previous version of DayBack, which was not hosted. And even though most updates were installed with a single click, users still didn’t always know to update. This meant that we’d occasionally hear from folks using a version of DayBack that was over a year old, having missed out on a ton of new features and bug fixes. And while our in-app update scripts (alongside tools like Otto) work to minimize the amount of work it takes to get a file back up to date, all these users wished DayBack had just been updated for them. That’s what hosting the file accomplishes.

Connecting to Other Apps

DayBack Calendar can use events from multiple platforms within a FileMaker web viewer, including Google Calendars, Office 365 Calendars, BaseCamp, and Google Sheets. This is difficult to do if the web viewer is based on a data URL since most APIs need to work with a hosted domain for authentication. It would be technically possible to handle this on the FileMaker side with its native cURL functionality, but this would be a lot of FileMaker specific code vs. being able to take advantage of our hosted app’s existing ability to authenticate and work with these APIs. By referencing our hosted app, all these other non-FileMaker sources just work inside FileMaker.

How It Works: Setting Up the Web Viewer

Hosted apps work in FileMaker Pro client’s web viewer without issue. All we need to do to get them to work is to set up our web viewer to reference our server with a few parameters to tell the app in which context it’s being accessed.

https://app.dayback.com/?type=FileMakerJS&fmFileName=DayBack%20Calendar

However, if we try this in WebDirect, the app will load, but the FileMaker.PerformScript function is not injected into the web viewer code so we have no way of pulling or pushing info between the FileMaker file and the web viewer. In WebDirect the web viewer reference must have the data:text/html prefix in order for the FileMaker.PerformScript function to be injected. In order to get this to work in WebDirect, a data URL is used for the actual page, so the FileMaker.PerformScript function is injected properly, and then include an iFrame that references the hosted app within the data URL. Here’s an example:

data:text/html,
<!doctype html>
<html>
 
<body style="padding:0px;overflow:hidden">
  <iframe id="dbk_iframe" style="margin:0;position:fixed;top:0;bottom:0,right:0;left:0;width:100%;height:100%;overflow:hidden;" frameborder="0" src="https://app.dayback.com"></iframe>
</body>
 
</html>

Using the iFrame in FileMaker 19’s Web Viewer: Sending Data In and Out

At this point, the iFrame is loading DayBack from the server, but the FileMaker.PerformScript function isn’t injected into the iFrame and can only be referenced in the scope of the data URL. iFrames are designed this way intentionally as the parent window and iFrame are typically from other domains and can introduce cross-site attacks. However, modern browsers do provide a way to safely communicate with iFrames via JavaScript if the proper protocols are set up on both pages.

To send a message from an outer page to an iFrame, the JavaScript function the postMessage window method is used. From the parent page, the iFrame element can be identified by its ID and a message sent.

var target = document.getElementById('dbk_iframe');
target.contentWindow.postMessage(  'hello iFrame', 'https://app.dayback.com');

In the hosted app in the iFrame, an event listener can be added when the page loads to listen for the message and then run the appropriate function, in this case, postToDayBack.

window.addEventListener( 'message',
  function(e){
  var data = e.data;
  postToDayBack(data);
}, false);

To send a message from the hosted code in the iFrame to the parent window a similar process is set-up in reverse. Here the domain will be set as a wildcard so we can post the message to a data URL.

window.parent.postMessage( JSON.stringify( payload ), ‘*');

Then a listener is added to the data URL which can then receive the message from the iFrame and use the FileMaker.PerformScript function to relay that to the file.

window.addEventListener('message',function(e){
var data = e.data;
var objectData = JSON.parse(data);
if(objectData.dbk) {
  FileMaker.PerformScript(e.data);
}
},false);

The reason we test for the dbk property in the message is that the FileMaker script step Perform JavaScript in Web Viewer also uses the postMessage method and this will trigger the listener that’s been we’ve added to the data URL ensuring that we only messages coming from the DayBack iFrame will actually be processed and execute the FileMaker.PerformScript function.

Essentially, the data URL serves as a relay between FileMaker and DayBack since they can’t communicate with each other directly in WebDirect. The idea to do this in FileMaker was mostly inspired by our experience with bringing DayBack to the Salesforce platform as the Canvas toolkit we used there actually provides developers with ready-made tools for doing this kind of communication. So, again we have similar patterns being used across different platforms which helps simplify DayBack’s code significantly. And we have a familiar pattern for getting DayBack working as a hosted app in WebDirect.

Web viewer add-on FileMaker 19 Web Direct
DayBack as a hosted app in FileMaker WebDirect

Conclusions

A hosted app can dramatically reduce the amount of effort required to deploy and maintain code being used by a FileMaker web viewer app. It also provides a centralized way of allowing your app to communicate with other APIs without having to reinvent the wheel with FileMaker scripts.  Although there are a few extra steps to making things work in WebDirect, there’s actually not that much additional code needed. Using postMessage and message listeners is also an established JavaScript pattern with tons of examples and best practices available to get you started. In addition to these benefits, if you build your app this way, you’re probably much closer to taking your app beyond the FileMaker platform than you may realize.

Happy hosting!

Featured Posts

Follow Along

Stay up to date with the latest news & examples from SeedCode

4 Comments

  • Greg Lane

    Hi Jason. Thanks so much for sharing this article! It solved my problem today as I was trying to update a FileMaker variable with the currently visible page number as a user scrolls a PDF viewer (rendered by JavaScript coming from another server) in a Web Viewer in WebDirect.

    • Jason Young

      Hi Greg,
      Great to hear from you and so glad this helped. Even though it’s been more than a year, I still think getting this kind of 2-way action with a web viewer on WebDirect is a game-changer for FileMaker. Looking forward to seeing you in person again…someday =)
      -Jason

  • Michelle

    Hi Jason, I’m curious if you have any advice when using custom html (stored in a FileMaker field) in a web viewer to perform the ‘FileMaker.PerformScript’ function? When I try to view this in WebDirect I always get the error ‘FileMaker is not defined’. We are running FM Server 19.0.1 and I am encoding the html in the web viewer using the prefix “data:text/html;base64,”.

Leave a Reply

Your email address will not be published. Required fields are marked *

Check out some of our other posts ...

Comments in FileMaker Calendar

Highlight Notes and Comments in Your Calendar

Inline Notes in DayBack Calendar The latest DayBack extension adds an icon to your events when there is a comment present that matches your criteria. You can

Closed Through the New Year

SeedCode is closed for our holiday break from December 19th through the end of the year. We’ll have folks available in case of emergencies and

COMPANY

FOLLOW ALONG

Stay up to date with the latest news & examples from SeedCode

© 2023 SeedCode, Inc.