Beezwax has always been active in the community regarding advanced use of web viewers in FileMaker. Check out the previous postings if you’d like to learn more.
- Native Web 2.0 Controls in FileMaker 12 Layouts
- Enable WebKit debugger in FileMaker Web Viewer
When the Web Viewer was introduced in FileMaker v8.5, it was designed to display websites such as a Google Maps which included the address of the current record. It accomplished this by inserting record data into the url as an HTTP GET request. However, it didn’t take long for developers to take advantage of html’s data URI syntax to insert html directly into the Web Address box. This seems to be the most popular method currently to display a local web page inside of a web viewer. The main advantage here is that you can include field references directly in the code as a way to pass data into a Web Viewer.
You can think this of this method as analogous to a php server inserting data from a database before rendering the html to be delivered to the browser. Similarly, when new data needs to be injected, the entire page is re-rendered. However, we are moving towards a more asynchronous world were only the data is transferred and the state of the web page is not reset. This is generally done with ajax calls to a server, but in our web viewer, there is no server.
Treat the Web Address box as the url
If you use the web address box as intended, then you’ll gain the advantage of some html features such as GET parameters and hash values. However, the Web Viewer will need to locate a resource, so where should we point it?
Export web files to the temporary directory
Using local files instead of inline html has some advantages such as faster load times, use of browser caching, and easier editing of the files. It is also necessary in order to use the url features mentioned above. Now that we’re loading static pages which don’t have inline field references, we’ll have to figure out a better way to get data into the Web Viewer.
Talking to the web viewer
As mentioned above, we can pass data to the Web Viewer by adding values to the url as get parameters at the time of page load.
This is perfect for passing smaller amounts of data to a Web Viewer, but it has a couple of problems. First, the data must be encoded to be url safe, which can cause a bit of a slowdown on large data. Secondly is that Internet Explorer has a url character limit of 2,083 characters. Hopefully, one day this will be expanded, but until then, we’ll have to work around the limit. A file would have no length limit, and wouldn’t need to be url safe, so let’s use hashchange to alert the Web Viewer that it should go get a file of data that FileMaker just exported to the temp directory. I’ll use jQuery in the example below for brevity.
As the web has matured, we’ve grown more accustomed to asynchronous requests for data which return only the needed data while not reloading the entire page and losing the user’s state. This is commonly known as ajax and has become a staple of modern web development. However, ajax relies on a server to return the data, and in our humble web viewer environment, there is no server. You can kinda make ajax requests to local files, but this is problematic.
Cross-Origin Resource Sharing
For security reasons, ajax calls can only be made to the same domain as the page that requested it (i.e. the “origin” server). This means that a page hosted on beezwax.net could not load data from filemaker.com through ajax unless filemaker.com explicitly allows it by configuring their server to set the response headers to allow it. You may be wondering what this has to do with a Web Viewer because there’s no server, per se, and therefore no origin are involved. Different browsers treat local files differently. For example, Firefox allows ajax calls to local files, Chrome allows with with an option setting, Safari allows it with a developer preference change, and Internet Explorer doesn’t allow it at all. Interestingly, a Web Viewer on OS X still allows it, but I suspect that this could change at any moment.
<script> and JSONP
First, a script tag is added to the dom:
The contents of data.js could be:
When the script tag is added to the dom, the data.js file is loaded and executed, meaning the function “receiveData” is called with the data as an argument. “receiveData” would be a function that you would write to handle the data. The idea of wrapping data in a function call or variable assignment in order to get around CORS restrictions is called JSONP. The P in this instance stands for “padding,” meaning that the data is padded with a function call.
Talking to Filemaker
For fmp:// url,
- the use is to call a particular script in a particular database
- format is fmp://account:password@netaddress/databasename?script=scriptname¶m=scriptparameter&$var1=value&$var2=value
- account, password, param, & variables are optional
- “$” works as the netaddress for local files
- support for local files was added in FileMaker 13.0v2
- Export web contents as files to the temporary directory.
- Load the location of the index file into your Web Viewer’s web address box.
- When you have data you want to send to the Web Viewer, first export a jsonp data file to the temporary directory. The data should be wrapped in a callback function.
- Alert the Web Viewer that there is new data available by changing the hash of the url in the Web Viewer (I use a utc timestamp with a prefix so the hash is always something different).
- Add an event listener for the “hashchange” window event with a handler function.
- The handler function will then inject a script tag into the dom with the source set to the data file.
- The callback function in the data file is called with the data sent as an argument.
- If a Web Viewer calls an fmp:// url while a script is busy, the call is ignored
- localStorage and web sql not available in the Web Viewer
- hash cannot begin with a number
- data is exported as a file to temp directory, which could be a security concern for some