Fun with Numbers – Part 2

by Geoff Gerhard - Technical Lead

Combine a strong sense of curiosity with a compulsion to solve puzzles and you can easily find yourself “down the rabbit hole” when working in Claris FileMaker. This article, and the demo file for the technique it describes, emerged from a deep dive into FileMaker’s number fields. It started with noticing the dissonance, when clicking into a number field that has display formatting applied to it, of finding the cursor blinking in an unexpected location within the number. Following an “are there alternatives to that behavior?” path led to an article [link] describing a method of eliminating most of that dissonance. Continuing down the path, we emerge with a method that goes further, applying and updating the formatting/masking of a number field’s value as the user interacts with it.

Improve Number Field Interaction

Why is that useful? It further reduces the dissonance that comes from clicking into a number field that has display formatting applied to it. The previous article’s demo file put the cursor in the expected location relative to the number field’s digits but dropped the additional “waypoints” (currency symbol, thousand’s separators) that are the reason developers so often choose to apply display formatting to a field in the first place. This article’s demo file expands on that technique, preserving those landmarks within the field’s value and accurately placing the cursor in the expected location when entering the field. It also updates the field value and its formatting as the user keys/deletes/cuts/pastes values into it. And it updates the field value on exit to include only digits, decimal, and—when relevant—the negative sign.

That’s a plus from the UI/UX perspective, but the demo file also allows the developer to prohibit non-numeric and inappropriate characters that can be entered even when validation requiring a strict data type of “Numeric Only” is applied to the field. Two examples: entering “12,,34.01” and “   1.23  ” do not trigger the “This field is defined to contain numeric values only….” validation message. While there may be limited value in that level of granularity, it’s important that the technique excises or ignores invalid characters the user enters because “Numeric Only” validation must be disabled when display formatting includes a currency symbol.

The validation mechanism in the demo file is applied using the scripts initiated by script triggers, and they disallow the entry of invalid or otherwise inappropriate characters. They excise all but the aforementioned “number relevant” characters (digits, decimal, and negative sign) when pasting, and update the field’s value only in response to those keystrokes, plus the Backspace and Delete keys. They update the value to exclude subsequent decimal characters if the user types more than one. (Number fields allow the entry of multiple decimal characters, recognizing only the left-most as the end of the integer/start of the decimal.) Note that the OnObjectKeystroke is not triggered by the Cut/Paste key combos, so we capture the impact those events have on the number value by filtering then formatting it using an OnObjectModify trigger.

Unconventional Number Formatting Options

A hosted file may be used in regions that have different characters marking the decimal and thousands separation points, and I’m guessing that’s one reason FileMaker allows the developer to apply data formatting options to a number field. While traversing the rabbit hole, I noticed that it’s possible to select nonsensical options, including the use of:

– the same character for both decimal and 1000s separator

– a letter as a decimal and/or 1000s separator

– a digit as a 1000s separator ( but not a decimal separator )

The ability to apply data formatting options means appearances can be deceptive: using the decimal character applied via Data Formatting within the number field value while typing can easily result in bad data when it doesn’t match up with the value imposed by the Text Data Entry selection in the File Options in a file created in a locale with different defaults. To overcome this limitation, the technique in the demo file’s OnObjectEnter script identifies the decimal character dictated by those settings and instantiates the $$actualDecimal value used by it and all the other script trigger scripts tied to the number field.

The OnObjectEnter script also instantiates other global variables that it and the other scripts use to format the number so its formatted value—while focus is within that field—matches the format (dictated by the Data Formatting options applied to it) when focus is outside of the field. Those variables include the $$displayNumberCurrency, $$displayNumberSeparator, $$displayNumberDecimal, and $$displayNumberPrecision values. These values are needed for more than identifying the expected cursor location: they are parameters used by a custom function I wrote in 2008 to apply consistent formatting to numbers that will be used in text blocks. Here, it reformats the number in response to all relevant user actions while focus remains within the number field.


The result is akin to the Masking technique I described in an article on interactively formatting phone, SS, and Federal ID numbers. It shares most of the same caveats described as “A Couple Things to Keep in Mind” in the follow up article that detailed that technique, which boil down to this: taking over a field’s behaviors is an all or nothing endeavor, and likely a heavier lift than it seems at first glance. The latter article has a section titled “UI/UX and The Weight of The World” that’s relevant for those interested in a deeper dive.

Cursor Behavior for Backspace and Delete Keys

There’s one important difference in the way a “script triggerless” field and the number field in this file responds to keystrokes, and that’s with respect to the behavior when a user types the backspace or delete key. While either would normally delete the character immediately preceding or following the cursor location, the OnObjectKeystroke script alters that response when the affected character is a 1000s separator or a currency symbol. When either of those keystrokes would delete the 1000s separator, the demo file uses a model that seems consistent with what a touch typist might expect: it moves the insertion point to the other side of it instead of deleting it.

When the currency symbol is to the left side of a positive number and the cursor is next to it on the right, the backspace is ignored unless the number is less than zero and the display formatting options place the negative symbol to the left of the currency symbol. In the latter case only, backspace steps over the currency symbol so the user can delete the negative sign. Entering a negative sign is only allowed when number is greater than zero and the cursor is in front of the first numeric digit, without regard to whether the data formatting applied displays the currency symbol.

An Alternative Method for Identifying Click Positions

For those who read the previous “Fun with Numbers – Part 1” article and saw the technique for identifying the point at which the user clicked into the field: This demo file uses an alternative method (overlayed instances of a repeating field that trigger the OnObjectEnter script) to identify the point in the string where the user clicked when entering the number field. My colleague, Cristos Lianides-Chin, suggested that using a repeating field could be substantially less cumbersome than setting up an array of tooltips to instantiate the cursor position but noted that it afforded less precision when trying to accurately capture the spot where the user clicked. A bit of testing showed that the gap in precision becomes more pronounced as the number of digits in the integer and decimal segments increase.

Overlaying the number field with two instances of the repeatingOverlay field, one for the integer digits placed with its right edge centered on the decimal position and the other with its left edge centered on the decimal position, resolves the issue with precision and is far quicker to implement. Number fields are monospaced regardless of their assigned font, so aligning the repeatingOverlay fields with each repetition centered on the space between a digit/formatting element makes capturing the user’s “click position” perfect. This technique works with numbers of any length, so long as they’re fully enclosed within the field boundaries. We set the length to 25 characters in the demo file. The repeatingOverlay field covering the integer digits shows repetition 1 through n, where n is the count of integer digits the developer intends to support. The repeatingOverlay field covering the digits in the decimal section starts with the n+1, which is the position of the decimal as dictated by the display formatting options applied, and ends with the repetition equal to its starting repetition (n+1) plus the precision value.

Considerations for Replicating the Technique

There are a couple other things happening in our demo file worth noting, especially if you plan to replicate the technique from scratch. First, the number field needs an object name—the demo file identifies “currency” and “international” number field objects. When adding the first repeatingOverlay field to the layout, append “ overlay” to the object name of the field it will target. (In our demo file the first repeatingOverlay fields for the currency object are “currency overlay” “currency overlay Copy”.) Use “Set Script Triggers…” to enable the OnObjectEnter event for the newly added field, assigning the “OnObjectEnter” script to it.

The second thing worth noting is that the script parameter uses “Let notation” to instantiate $$cfr (for “Click From Right”) and assigns to it the value of to the numeric position of the user’s click. The parameter calculation’s result passes a parameter that identifies the underlying number field’s object name. And that brings us to the third thing worth noting: the underlying field uses the same script trigger event to call the same script, but without passing a parameter. That’s intentional, in case the number field is included in the tab order. Because the OnObjectEnter event triggered by the Go to Object script step fires even before the running script has completed its work, we need to determine whether the script is currently running because the user clicked into a repeatingOverlay field, clicked directly into the number field at its extreme right edge—possible because of the padding assigned to the number field—or tabbed into it.

The lack of a script parameter in the last two cases means the script will finish its work without calling itself as a subscript. The presence of a parameter means we will use the Go to Object script step and the script will be rerun as a subscript. In that case, it’s work is finished when the subscript completes so we call a Halt Script step to ensure that the cursor stays where it belongs.

Final Step: Adjusting Repeating Overlay Fields

For those replicating the technique, the last step in the process is the duplication of the first repeatingOverlay field, adjusting its starting and ending repetition values, and aligning it as described on the decimal position as described above. There’s no need to update its object name, as our parameter calc is looking only at the position of “ overlay” in the object name to determine the target object’s name. And for those who recall the footnote in the previous article about numbers formatted with a trailing currency symbol, this technique does not require an adjustment to make it compatible.

Please enter your contact information to download the Demo file.

This field is for validation purposes and should be left unchanged.

Leave a comment

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

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

Built with you in mind

Speak to one of our expert consultants about making sense of your data today. During
this free consultation, we'll address your questions, learn more about your business, and
make some immediate recommendations.


Stay in touch!

This field is for validation purposes and should be left unchanged.