By Daniel Wood, 11 March 2022
Allowing a user to easily select a color in your FileMaker solution is hugely beneficial. Often times we need a user to pick a color for something such as a status, a way to identify a record, or a color for a chart.
We want to provide a simple approach for the user in which they can visually select a color instead of entering it as hexadecimal or RGB values.
Currently in the FileMaker world there are 2 approaches, both of which utilise a web viewer. One is to use HTML5 to use the native OS color picker and the other is to use a javascript based color picker library.
The native OS picker is visually very nice. Its major benefit is that it is not limited to the confines of the web viewer, and so the web viewer object itself merely acts as a color swatch displaying the selected color. You can find examples of an OS color picker approach in my elemental_ux solution.
However one of the big drawbacks I see with the OS picker is its cross-platform differences. You will get a different experience on a Mac versus on Windows. The picker also doesn't work at all on FileMaker Go, and is flaky on WebDirect.
For these reasons we went with a javascript based approach.
Example files sit at the core of all our articles and much time and love goes into them, not only to present a particular technique but also as a way for us to help refine the technique. We always encourage you to download and try out the example file for yourself as the best way to read and understand the article is by having the example file open at the same time and exploring both.
Click here to download the Color Picker example file
By using a javascript based color picker we achieve the following benefits:
In looking for a suitable javascript library for a color picker our main requirement was that the picker be large enough in size to be presentable in a card window as well as a popover. We also wanted it to be simple to implement and customisable for developers.
We went with the Pickr library which you can find here.
We mentioned before the requirement to have the picker work in both a card window and a popover. The reason for this is that web viewers do not work when placed inside a portal and so if you wanted to select a color from within one you would need to find an approach where the color was selected outside of the portal.
We found building a simple card window layout containing the web viewer for the color picker was ideal. When a color needs to be selected, the picker is invoked, a color is chosen, and the card closes. Upon closing the requested field is populated with the chosen color (more on how this works later).
We still wanted to offer an approach where the color picker is able to placed within an existing layout for times when a color is chosen outside of a portal. For this approach we utilise a popover. This allows you to have multiple pickers on the same layout.
The card window picker can be utilised anywhere by any button, to set any field. The basic workflow is as follows:
We pass the parameters through to the open script in JSON format, and they look like this:
There really is nothing overly complicated here, it's about as basic a Javascript/FM integration as you can get!
In addition to the open and set scripts, there is a third script ColorPicker_Close which is responsible for the tidy-up of the picker after a selection is made. More on this later for the geeks who like to know the technicalities!
The popover approach is almost identical to the card approach however instead of explicitly calling the ColorPicker_Open script, we instead set it as the OnObjectEnter trigger for the popover. Similarly the onObjectExit trigger for the popover is set to the ColorPicker_Close script.
These two scripts will initialise the picker in the popover, and tidy-up and close the picker when done.
The parameters passed to the open script are the same with one exception. For popovers we also pass through the name of the web viewer object that is in this particular popover. Because you can have more than one popover picker on a layout, we need to differentiate between them.
We are potentially dealing with multiple color pickers here, and each picker needs to be aware of the field that it needs to set when a selection is made.
We saw 2 ways to achieve this - one would be to pass it through to the javascript code and store it there. The other is to store the field to set within FileMaker in global variables. We went with the latter approach because while not as elegant, it allowed us to illustrate some cool techniques for this article! (We will likely change it to store it within each web viewer as this is much nicer.)
Anyways, let's delve into what's going on here. This is for the FM geeks who like the nitty gritty.
We can have multiple pickers in a few ways:
When a picker opens, we need to know the field that needs to be set with a color, and we need to store this field name so that when the time comes we can retrieve it for setting. We also need to tidy up after ourselves and clear this variable when complete.
The open script kicks things off by gathering the passed parameters, and loading the html javascript and css code into the web viewer - all stock standard stuff.
When it comes to storing the field name to be set, we want to associate that field name to this specific card picker instance. We do this by assigning the card a unique window name, using Get ( UUID ). We then define a variable called $ident to store this value.
In the case of a popover, because only one popover can be active on any given layout at any given time, our $identifier value just needs to represent the current window name. For this, we assign a value to $ident of
"colorpicker_" & Get ( WindowName )
Right, so we now have a variable that is a unique identifier of the specific card picker, or popover picker being instantiated. This will be different for situations where multiple windows are open - each with their own active picker.
Next, we take this value, and hash it into an MD5 hash. This returns us a large numerical string. We do this as follows:
GetAsNumber ( GetContainerAttribute ( $ident ; "MD5") )
We are utilising a container function on a text string which can give us an MD5 hash of that text.
The final step is to take this number, and treat it as a repetition value for a global variable. Into this repetition we set our field name for the color field to be set:
Set Variable [ $$COLORPICKER.FIELD[$hash] ; Value: Home::Color ]
The beauty of this technique is you can effectively take a string, and turn it into a repetition into which you can place a value. You can then easily regenerate that same hash number later to retrieve and clear this repetition.
Now that we know how this part works, setting the field to the chosen color, and clearing the global variable value when done is easy. We simply regenerate our hash by evaluating the window name, and retrieve or clear the variable as needed. The Set Field by Name step is used to set the color into the chosen field.
So we have a color chosen - in this case hexadecimal. So what? What good is a hexadecimal color as a text string, if we can't actually turn it into a physical color? Fortunately we can and it's really easy!
There is a neat little trick you can use to generate a 1x1 pixel gif image of a chosen hexadecimal color. This is done by producing it as base64 encoded text, which is then decoded back into a gif file for rendering in a container. The code is as follows and we have wrapped it up into a custom function called @COLOR_swatch in the example file:
If ( IsEmpty ( _hex ) ; "" ; HexDecode ( "47494638376101000100910000000000" & Substitute ( _hex ; "#" ; "" ) & "FFFFFF00000021F90409000003002C00000000010001000002024C01003B" ; "red.gif" ) )
By calculating/inserting this result into a container, you can create a color swatch of any size. Just set your container properties to "Reduce or Enlarge Image to Fit" and remove the option to Maintain Original proportions.
We decided on a simple implementation of Pickr for our Color Picker, but the reality is Pickr is quite powerful and you can produce some cool pickers simply by altering the configuration parameters in the javascript setup.
If you wish to investigate this further, the documentation will provide you with all necessary configuration options.
You can find this code in the example file in the ColorPicker_Open script. Here are just a few examples of what you can do:
and more.
Pickr is by far the simplest and best javascript based pickr we have come across, and implementing it was really easy. We hope that we have done a good enough job that you can take the example file and easily incorporate the picker into your own solutions and improve upon what we have done.
We'd love to see folks take this and improve upon it by optimising how the picker manages the storage of the field it is required to set the color into - perhaps storing it in the Javascript? If anyone would like to take up the challenge we'd love to see what you come up with.
Even if you don't use the picker, consider the technique for generating color swatches, this is a really powerful and awesome function. You'll also find on briandunning.com a number of custom functions that can convert an RGB value into a hexadecimal value which would allow you to utilise this swatch technique with the standard FileMaker RGB function.
Example files sit at the core of all our articles and much time and love goes into them, not only to present a particular technique but also as a way for us to help refine the technique. We always encourage you to download and try out the example file for yourself as the best way to read and understand the article is by having the example file open at the same time and exploring both.
Click here to download the Color Picker example file
Something to say? Post a comment...
Comments
Jason 21/12/2023 10:01am (1 year ago)
This is fantastic, thank you!
Matthew Carrigam 03/06/2023 9:27am (2 years ago)
Awesome article and demo file.
I've been interested in learning more about Javascript and how to extend FileMaker using it, finally needed a color picker today, and boom!
Many thanks!!
Jesus Sanchez 29/07/2022 7:43pm (2 years ago)
Great job Daniel, very useful and cool. Thanks.
Alex Zueiv 12/03/2022 6:47am (3 years ago)
Great work, Daniel!
FYI, you can put a Web Viewer in a Popover within a Portal and it will work just as well as Interactive Containers. See the notes in the 'Using data in container fields' section of the FM Help:
"You cannot work interactively with container fields that are in portals. However, you can if the container field is in a popover within a portal."
I simply moved the Popover Pickers to the portal in your example file and they work great.
Tip: Use the GetLayoutObjectAttribute ( objectName ;"content"; 1 ; Get ( ActivePortalRowNumber ) ) function in the Web Address calculation to get data from the fields located in the Popover.
Josh Willing 11/03/2022 8:01am (3 years ago)
Awesome file, thanks!
Daniel Wood 11/03/2022 7:22am (3 years ago)
hi Tony,
Thanks for your comment, I appreciate it. Your custom function looks to be hard coded to a specific subset of hexadecimal values am I correct? Otherwise I may not be understanding it. the CF in the example file is generalised and can work with any hexadecimal value.
Tony White 11/03/2022 7:14am (3 years ago)
Very interesting article.
I like the custom function that produces .gif files.
The png1x1 ( hex_string ) custom function that produces .png files could probably be upgraded to be more calculated/generalized and less brute force?
https://www.briandunning.com/cf/2456
I wonder if .gif or .png is better or they are equally useful.
Thanks!
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments