By Daniel Wood and Stephen Baker, 29 April 2011
In this article I demonstrate how you can use image maps with web viewers in FileMaker. In doing so, you can display images that, when clicked, can report the coordinate chosen back to FileMaker to handle in whichever manner you wish.
Wikipedia says that an image map is a list of coordinates relating to a specific image, created in order to hyperlink areas of the image to various destinations. The intention of an image map is to provide an easy way of linking various parts of an image without dividing the image into separate image files.
Wouldn't it be great if we could use an image map in FileMaker. This would allow us to display an image, and have FileMaker know the exact location on that image the user clicked. In knowing this information, you could then program a response, perhaps via a script.
Below is a photograph of a farm, with the paddocks on that farm outlined. We have a database that is used to manage the farm and the paddocks on it. Each Paddock is a record in the database.
Well, we could (but c'mon where is the fun in that!). A common method of making a clickable image in FileMaker would be to place the image direct on the layout, or in a container, and underly buttons beneath the image that when clicked, run a script.
Here's the problem - paddocks are not necessarily rectangular, circular, or oval shaped. As such, to underly buttons beneath a paddock, you must use a combination of many buttons or shapes to replicate the paddocks shape, then group those objects and turn them into one large button.
Furthermore to this issue, what happens if in future the paddock fence-line changes? What happens if two paddocks become one? What happens if more paddocks are added? Basically it all boils down to the fact that the layout is going to have to be changed - not a very nice soft-coded solution.
If the image of the farm were presented as an image map, then there would be some feedback as to the location on the image that was clicked. We could then leave it up to FileMaker to determine what to do with that coordinate such as find out the paddock chosen, and run an appropriate script. In doing so, there would be no need for hard-coding of buttons required.
Okay enough talk, lets get into the nitty gritty.
Here is some very basic html code to establish an image map. We have specified an image called "Map.png". It is given width and height dimensions in pixels. The image is established as an image map via the use of the "ismap" attribute. the html file is called Map.html.
Pretty simple, around 6 lines of code. Image maps are widely varied and can include more fanciful features, but for this example we are sticking to the basics. In the example file we offer a slight variation on the above but basically its the same code.
Web Viewers are the tool in FileMaker that allow you to display web content on a layout. Given image maps are used on the web, it only makes sense that we will be using the web viewer. Basically we require to display the above html file in the web viewer, this can be achieved in a few ways.
The first is via a web server. If we host Map.html and Map.png on a web server then we simply need to point the web viewer to that URL and the image map will be displayed. Of course, this method requires the database have access to the web server location, either via local network or over the internet. In the demo file, we give an example of this method.
The second option for those not averse to using a plugin, is to use Reactor plugin, or any other plugin capable of hosting up web content. The reactor plugin is perfect for this because it is exactly what it was designed to do.
For those not familiar with the Reactor plugin, what it does is emulate a web server within a plugin. You can pass any file to the plugin using ReactorFeed function, and it will in return give you a URL which you can then place in the web viewer to display that content.
We normally use ReactorFeed for things such as displaying PDF documents or images within a web viewer, and it does a great job. In this situation we are going to pass it Map.html and Map.png, and it in turn gives us a URL to use in our web viewer.
We have included a reactor example in the demo file for those readers who have Reactor installed. If you do not have Reactor, you can download a demo copy Here.
The above methods outlined require either a plugin or access to a web server hosting the content. Both methods work great, but in developing this technique we aimed to provide an all-encompassing self contained solution. Unfortunately we failed (someone take up the challenge!) but I thought I would mention that method here.
We attempted to base-64 encode both Map.html and Map.png and serve it up in the web viewer by using a data url. While we were able to display the map in the web viewer, we were unable to obtain the selected clicked coordinate via this method, more on what I'm talking about later...
We are using the isMap attribute to setup an image map on the image. How this works is when the user clicks on a location on the image, the chosen coordinate in pixels is appended to the end of the URL of the page.
When we defined the image map code, you'll notice we gave it a width and height in pixels. This defines the area of the image. The top-left corner of the image is given the x,y coordinate of 0,0, and from there the coordinates extend out to all four corners of the image.
When the user clicks on a point on the image, the x,y coordinate is placed on the end of the link.
For example if the URL to the image map page is:
and the user clicks at coordinate 100,200 then the resulting URL of the page becomes
It all boils down to the GetLayoutObjectAttribute function. This FileMaker function allows you to obtain the source url of a web viewer. Thus if we are able to obtain the source URL of the web viewer after the user has clicked in it, then it will tell us the URL with the coordinate appended! Brilliant!
GetLayoutObjectAttribute ( "WebViewer" ; "Source" )
Web viewers generally offer up content that the user interacts with independently of FileMaker. What we need is a way for FileMaker to know the user has just clicked on a position in the image map.
We can achieve this now using script triggers that were introduced in FileMaker 10. Specifically, the onObjectEnter script trigger can fire off a script to run when the user enters an object - including a web viewer. This is how we are going to go about obtaining the source URL of the web viewer after the user enters the web viewer.
Now, if we were to run a script triggered by onObjectEnter as soon as the user clicks into the web viewer, the problem is that the script runs before the users interaction with the web viewer occurs. So if we run a script that tries to evaluate the source of the web viewer, it's just going to tell us the original URL because the users click on the image map has not yet been registered. What we need to do instead is delay our script from evaluating the source URL of the web viewer - finally a great use for the onTimer script step!
As you can see in the image above, we set an onTimer to run .25 seconds after the triggered script is run. The delay you specify depends upon various factors, mostly related to the speed of the web server hosting the image map, or your internet connection (Rector being local tends to be faster). We find that a quarter of a second is ample time for the URL to update, and short enough to not be noticeable by the user.
The process of events that occurs from the moment the user clicks into the web viewer is:
So that's basically it. You have an image with a width and height in pixels, and by using script triggers, onTimers, and various FM functions you can obtain the x,y coordinate clicked. From there, you can parse out the coordinates from the end of the web viewers URL, and do with them whatever you want, great.... but is that the end?
Well not really. Once you have the coordinates the question now becomes what do you do with them? Being able to obtain the coordinates is nice, but unless you can do something meaningful with them, whats the point.
So lets now return to the example originally established, and see if we can figure out a nice way to select paddocks using this technique.
Recall that each paddock is a record in the database, and we know the x,y coordinate clicked, but we don't yet know which paddock the user clicked in. What we now need to do is establish a method of defining paddocks in terms of their coordinates on the image map, and then evaluating the chosen coordinate to determine if it falls within one of the paddock boundaries.
Paddocks are shapes, and shapes are called polygons. A polygon is simply a shape with many sides (according to the weetbicks big book of mathematics).
Where two edges meet, you get a corner, and a corner is defined by an x,y coordinate. We can define a polygon by a series of x,y coordinates, obtained by traversing the polygon in a clockwise (or anti-clockwise) fashion, and grabbing the coordinates of the corners.
Lets assume for example we have a paddock defined by:
This defines the paddock as a perfect square, 20x20 in size on the image map. The paddock begins in the upper left corner at 0,0. From there, the upper right edge of the paddock is at 20,0. the lower right corner at 20,20, and the lower left corner at 20,0.
We can define paddocks in this fashion regardless of their shape or location simply by plotting the corners of that paddock in order. In the example file, these are recorded on the paddock records in return-delimited lists of both the X and Y coordinates respectively.
So now we have a paddock defined as a series of x,y coordinates. What we now need to determine is whether a given x,y coordinate lies within the boundaries of that polygon.
For more information about this technique, you can check out this great site that explains how the process works, and gives a C function of how to achieve it. Also please check out the acknowledgements at the bottom of this article for those who helped me take this C function and turn it into a FileMaker custom function.
In the example file you will find this function which can tell you if a given coordinate is inside or outside of a polygon. the pointinPolygon function treats coordinates that fall on the edge of a polygon as outside. There is also an alternative function provided that treats boundary coordinates as inside the polygon. The functions have been provided by Nick Orr and Jason DeLooze respectively.
With the function now in place, we can let each paddock determine if they were selected by adding a calculation field to each record, that calls the custom function, testing its own coordinates against that of the selected coordinate.
Each paddock now has basically a flag set that determines if it was chosen or not. What you do with that information is up to you. In the example file, I am grabbing the ID of the chosen paddock, and using it in a relationship to that record for editing purposes, but the possibilities for this application are huge.
Hopefully this article has proved enlightening and helpful for people. This is very much a work in progress and one of the goals of this article is to get peoples minds thinking about how this technique can be used and applied to FileMaker solutions, and also how it can be refined and improved upon, I would love to see peoples examples of how they can take this technique and run with it. Possible applications or improvements might include:
Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.
Note: Example file updated on 4/5/11 to fix an issue in alternate ptInPoly function.
Douglas Adler from HomeBase Software has taken some ideas and techniques from this article and run with them. He has revitalized an earlier image map technique he had worked on and put a new spin on it.
I encourage you to check out his great article outlining what he has done over at his blog site here.
David Wikstram from CamelCase Data has produced this awesome demo file showcasing his extension of the image map idea. In this example, David has taken it to the next level, using SVG technology to not only produce a clickable image in a web viewer, but he also demonstrates how you can very easily setup your polygons on the image - with live visual feedback! In addition to this, using SVG has allowed David to do other cool things like have the selected polygon highlight itself upon selection. Check it out, you won't be disappointed!
In preparing for this article, I sought the help of a number of people and would like to thank them here:
Stephen Baker - Digital Fusion Ltd
Stephen is the one who deserves the most credit for this article as this was a technique he developed when working on a client solution. Steve has been the main source of reference in writing this article and also helped in writing the pointInPolygon function, cheers!
Sam Sehnert - Digital Fusion Ltd
Nick Orr - Goya Pty Ltd
After struggling to write a FileMaker version of the pointInPolygon function (I was working off a C code example), I put the word out on the FmExperts mailing list for help in writing a FileMaker equivalent. Nick was quick to jump in and help out and spent a great deal of his own time in helping to write the final pointInPolygon function, which is the one you see in the example file. I can't thank Nick enough for his willingness to help out - he is a real class act!
Jason responded to the call for help on the FmExperts mailing list and came up with another cracking version of pointInPolygon which has been included in the example file. Jason's version is slight different to Nicks in that it treats points that fall on the edge of a polygon as inside, rather than outside, so thanks to Jason you have two choices in which function you wish to use, thanks Jason!
Mikhail Edoshin, Mike Duncan and Leland Long
These 3 top blokes all answered the call on FmExperts and offered advice, suggestions, and even had a crack at the pointInPolygon function too, huge thanks for taking the time to help out, cheers!