Estimated Time To Read This: 15 – 24 minutes
The third and – promise – final part on script parameters exploits the option of triggering the script using a parameter stored within the solution.
For those not having the pleasure to read the first two parts, but want to have some clue on what might have been discussed, here is a short summary:
One of the exciting new features in FileMaker Pro 7 is the option to use a script parameter. A parameter can be associated with the button that triggers the script or with the Perform Script step when called by another script. The script parameter, technically a single text string, can be used to transfer a complex set of information that can be used to either get processed by the script (data parameter) or that can be used to control the behaviour of the script (control parameter). The parameter string can even be formed in a way to actually contain more than one data or control parameters, or a mix of data and control parameters. FileMaker Pro 7 provides the opportunity to use a calculation to determine the actual script parameter string, so, for example, the script parameter might depend on the context of where the script has been called.
The first part of this article introduced the concept, provided examples on how to pass multiple parameters to the script in a single string, on how to use the parameter to control a script and on how to use a calculation to determine the parameter on the go. The article argued for a thorough planning to fully release the powers the script parameter provides the developer with. The article also warned against getting lost in trying to put too much into the parameter, thus creating a script that is too complex to develop, to troubleshoot or to adjust to changing needs.
The second part introduced the term “umbrella script” (a script that is designed to provide multiple functionality at a single access point) and discussed different ways to pass more than a single parameter in a –technically– single parameter string. It encouraged developers to use the new Let and Evaluate functions in FileMaker Pro 7 to make the parameter easily readable and carry more information over to the script.
Stored Parameter
The very essence of a script parameter –and the major source of the speed gain associated with its use– is the fact that it does not get stored in the solution but still can be accessed throughout the execution of the script. A stored parameter violates the very principle the concept of the script parameter is built upon. It sounds useless too: why store a parameter for a script when it can be used in any step during the execution of the script and can be easily passed to any subscript called from the main script without being stored? (See the first part of this series on how to pass a parameter to a subscript.) Indeed, we would not encourage anybody to create a field in order to save the parameter into it and refer to that field during the execution of the script.
The term “stored parameter” refers to the option to store data to determine the parameter when the time comes for the script to get executed. The data stored can then be accessed in the context from which the script is triggered, thus providing an option to tailor the behaviour of the script based on factors that are specific to the environment the script is initiated from.
A. The Case of the Chameleon Button
Buttons on a layout can consist of three layers: the background graphics, the text that tells the user what the button is for and an invisible layer that marks the borders of the button and to which the actual functionality is attached. This construction has provided the developer with an easy way to standardise buttons, provide a uniform user experience with the graphic background, separate the text part so it is easier to edit and mark the territory and attach the functionality the button was created for in the first place. This construction also has the advantage of streamlining the creation of layouts as needed: the same general structure was easy to repeat throughout all the user accessible layouts while adjusting the text and functionality of the button to the layout context by assigning different scripts to different buttons.
Chameleon buttons take this concept one step further. In pre-FileMaker 7 solutions, while it was possible to store the text part of the button(s) in one or more fields, it was not possible to directly manipulate the functionality provided by the button itself without some extra scripting and consequently considerable time lag in the execution of the functionality of the button. In FileMaker Pro 7, however, the use of the button text itself as a stored parameter can make the button’s behaviour adjust itself to the button automatically, so that the button, once created, can be reused without modification on as many layouts as needed, serving different purposes.
Example:
(1) Create a script, BTN: findButton that might be used for both changing to Find mode and to Show all records, like the one below
If [Get(ScriptParameter) = “Find”] /* enter find mode */
Enter Find Mode
Else If [Get(ScriptParameter) = “Find All”] /* show all records */
Show All records
End If
Construct a button as described above but instead of using static button text, create a field named zi_btnFind_gt and assign the button to the script above using the contents of the field as the parameter. It is almost magical to see the button react to what you order it to do by simply modifying the text content of the field.
In the example file:
1. Go to Preferences
2. Switch contents of the zi_btnFooterSW and zi_btnFooterSE (use the Switch button to save time)
3. See how the Find and Find All buttons switch positions – correctly reassigning their functionality on all corresponding layouts
If you first see in it nothing more than child’s play, think about how this simple concept can speed up development if you have to put the same type of button with different functionalities on several different layouts in your solution, or if you have to adjust your solution fast to the changing needs of your client.
The elementary example above can be altered in very different ways to improve your solution, simplify its construction and make development easier. The content of the global text field can be changed in a scripted way as part of the layout or record navigation, thus having a way for the button to “self-adjust” to the task it is to perform depending on the environment it is used in. The best part is: you do not have to change anything on the layout itself.
(2) Using a calculation field to set the text on the button(s) takes the concept one step further.
Example:
You want to provide the “Delete” option in Form view only to reduce accidental deletion of records. In your design it is replaced by “Omit” in all other views. (Note: from a usability perspective it is questionable to mix destructive and non-destructive functionality on a button in the same layout position. It is done here for the sake of the example only.)
The core of the script looks like this:
If [Get(ScriptParameter) = “Omit”] /* omit */
Omit Record
Else If [Get(ScriptParameter) = “Delete”] /* delete */
Delete Record/Request []
End If
The zi_btnFooterNE is to be defined as an unstored calculation (text) field like this:
If (Get (LayoutViewState) ; “Delete” ; “Omit” )
The script parameter assigned to the corresponding button is [the content of] the field.
In the example file:
Select Contacts and switch View in the View menu or use the List option in the footer – one showcases how the changes affect the button’s look and functionality on the very same layout, the other proves how that very same Chameleon button can adjust to its environment when layouts are changed.
(3) “Personalised” buttons
There are lots of solutions with a single developer/user but even in those solutions some sort of separation between “developer mode” and “user mode” can be fruitful. (It is at least not a good or advisable developer practice to jump into the middle of initiating far-reaching changes on the live solution every time a user issue hits the developer’s eye.) So even in those situations it might be good to separate the user-specific approach from that of the developer, and the security model of FileMaker Pro 7 provides a nice way to achieve this by assigning different privileges to the person – depending on the account she/he is using. No question about the need of personalization in complex solutions with groups of users accessing data based on different privilege sets. Creating separate layouts for each privilege set to separate options or write scripts in which an army of sophisticated error trapping and corresponding error messages warn the user what she/he is not allowed to do, however, is a very labour-intensive procedure, not to mention how frustrating the resulting user experience might get. It is much easier not to offer options that are not available, or customize the button to offer just what is allowed for the given privilege set.
Example 1
Users without “administrator” privileges do not have the right to delete records. They are still allowed to omit them, however. With a slight modification of the previous example, it is easy to achieve this. The zi_btnFooterNE is to be defined as an unstored calculation (text) field still, this time like this:
If (Get (LayoutViewState) or Get ( PrivilegeSetName ) ? “administrator” ; “Omit” ; “Delete” )
The button – and the script assigned to it – will still prevent even the “administrator” user to delete a record when not in Form view.
Example 2
Hiding an option altogether: no user but the developer makes use of the options offered on the Developer Preferences Layout, so a button taking the user to it better not be visible for anybody else but for those with [Full Access] privileges.
The main change to be made in this case is in the parameter that gets passed to the script. If the field that was set up to store the parameter and be used as the text on the button is empty, it is advised to use the “doNothing” text string as the parameter. (For further details, see Part 2 of this series in the previous issue.)
Instructions for the example file
1. Go to the Preferences layout and set the zc_mode field to “testing”. This will tell the application to show the Re-login button.
2. Go to the company layout and Re-login as user ‘sales’ using the password ‘sales’ (without the quotation marks in both cases). The option to go to the preferences simply disappeared from the company layout: you can still click into that empty space, but nothing happens. Should you not set the zc_mode field to “testing”, the Re-login button would also disappear, so in a non-testing situation the missing Preferences link does not leave such an obvious void on the layout – and you would not have the option to simply Re-login back to the solution as “admin” either. (You can re-login as admin using the password ‘admin’.)
B. Stored Script Options
The text on the button provides an obvious reason to look for a way to use it in guiding the script assigned to the button. The coordination between the functionality triggered by the button and the text label on the button is arguably the easiest and most obvious exploitation of the concept of the stored script parameter. This case, however, is also an atypical use of the concept: there is a dual use of the field the parameter is stored in, so the storage is not for the scripting part only. It might even remind us of cases when the contents of a field in a “regular” data record are used to guide the response from a script, like the case of a discount option guided by the type of commodity processed.
On the other hand, Chameleon buttons are typical in the sense that they show how a field (or fields) designed with the intent to store control strings for scripts in order to improve flexibility is a viable, legitimate use of the concept of the script parameter. The next logical step on this road is to set up fields without any other purpose but to store strings to control what a script does or does not do.
One example we already had: that of the zc_mode field in the Preferences of the example solution. Although it is not used directly as the parameter to control the Re-login script, it has the decisive influence on its behaviour, and it was set up with only this purpose in mind. Unless the stored parameter field is used in a separation-like approach, that is, being part of an interface or business rules table with several different records describing different scenarios, the stored parameter field is rarely used without some ‘mediation’. The actual script parameter is set by either a calculation that uses the contents of this field, a calculation that selects the field itself or a calculation that grabs one repetition of this field when it is defined as a repeating field. The ‘mediator’ can even be a script in its own right, the “trigger script”, that provides the selection / calculation procedure to decide the script parameter for the script that does the real job.
Stored parameters are more of a phenomenon for larger, more complex solutions, where the flexibility resulting from their use significantly exceeds the extra time required to carefully design them and set them up. They might be very helpful if the solution uses the separation model, during certain phases of development, testing and implementation of the solution, or when certain changes in several scripts’ behaviour has to kick in on short notice. They should be considered also if a group of developers is working on the solution and the immediate visibility of the parameter can help coordination and greatly simplify the work of those developing separate but interconnected parts.
Example
Contacts shown in a list can be sorted by – among others – First Name or Last Name. The client wants the sort to affect how the result is shown:
- if sorted by first name, the name is to be shown in the order of (First Name) (Last Name);
- if sorted by Last Name, the client wants to see it on the layout in the format of (Last Name) comma (First Name).
These are two separate tasks: sorting is one, presenting the result is another. In this simple example they might be easily squeezed into a single script guided by parameters like sortFirst and sortLast, the result being shown, for example, in two separate layouts the selection of which is based on the very same parameter. But if we think about it in a wider context, considering, for example, that the presentation options are not necessarily bound to the sort applied in the solution as a whole, the correct procedure is to separate the sort from the presentation, create two scripts, one for the sort and another for the presentation. The presentation script thus becomes a subscript called from the sort script (the “trigger script”) using the parameter calculated on the basis of the sort option selected. The more complex the sort and presentation requirements get the more complicated these scripts become, and any time the user wants to make changes in the presentation, a corresponding change has to be made in the script that is supposed to do the sorting. (The outcome is the same if we build the solution around the presentation script, using the sort script as a subscript, and the user asks for more sophisticated sort options. Complexity is not reduced if the whole process is guided by an umbrella script that triggers both the sort and the presentation scripts as subroutines either.)
Instead of getting into this jungle of scripts, our suggestion is to create zc_sortParameters_gtr as a global repetition field with as many repetitions as sort options, and store the parameter that guides the presentation in the repetition corresponding to the location of the column records are to be sorted by. We have then nothing else to do but to adjust the sorting script to this change, pair the presentation option / script parameter with the column number, set up the presentation script with as many parameters as presentation options, and set the parameter using the repetition of the zc_sortParameters_gtr field corresponding to the column number. (Easier to do than to describe.)
This way we:
- preserve the connection between the sort requested and the presentation of the result without using any complex calculation in either the sort or the presentation scripts;
- there is no need to compromise in the presentation script for sorting;
- there is no need to touch the sort script if the presentation requirements change and vica versa.
The additional advantage is a solution that is easy to understand and extremely flexible as to sorting and presentation options, whatever our client comes up with next.
See this working in the example file on the contact list layout. The presentation behaviour can be changed in the Preferences.
C. Storing Expressions / Calculation Formulae as Parameters
The only twist remaining for stored parameters is when a calculation formula is entered into the field set up to store a parameter. This provides the highest level of flexibility but also has the highest chance to go wrong, since:
- the formula is not checked by FileMaker for its syntax;
- the formula as a text string does not automatically adjust to changes in names of layouts, table occurrences or fields;
- the formula gets evaluated in the context where the script is triggered from, thus the parameter resulting from its evaluation is not necessarily the one the developer dreams about. It might, on the other hand, dramatically simplify the solution’s complexity in general and the scripting in particular.
This option, challenging as it is, exceeds the limits of this article, and we brought it up only to have all options covered with regards to stored parameters. The easiest approach to experiment with stored formulae (provided that the developer is experienced in the use of the Evaluate function in general) is to start with assigning the script parameter using the Evaluate function. A constant evaluates to itself, a field’s content (a static text string) evaluates to itself too, so this should cause no change in the outcome. Create a script to test the formula, try it in all contexts the evaluation might be triggered from, checking if the resulting parameter meets your expectations, than copy the formula in the parameter field and try not to change factors that influence the outcome of the evaluation, like the names of layouts, table occurrences or fields, also try not to change the table occurrence the layouts the script is triggered from are based upon, and if you do make changes, make sure you follow up with changing the formulae too.
The main reason for using a stored formula to determine the parameter can be seen in Cases where a complex set of criteria determines the script behaviour but the evaluation of those criteria has little or nothing to do with the functionality of the script.
Stored parameters are not script parameters stored after the script has been triggered. The term we introduced here refers to the option to use one or more fields set up with the definite purpose to store a string to be used as a script parameter. As with all development options, this one can be misused, unnecessarily adding to the complexity of the solution. As with all development options, this might change the way we approach the use of script parameters, relieve the burden of scripting too many unrelated options directly into our scripts, making both the design easier to set up and read and the script easier to use and reuse.
All the warnings we made in the previous parts of this series still apply. Use of stored parameters does not replace documentation. Careful consideration should be given and the use of a stored parameter is justified only if it saves development time and does not increase solution complexity. Rather, it makes the solution more transparent, easier to adjust to changing user requirements, more flexible to satisfy varying needs. Stored parameters is a way to design and create scripts using script parameters in the way we argued for in the first part: to focus the script on different aspects of the same functionality and clean it from elements that has nothing to do with the very purpose the script is set up to serve.
This concludes our tour of the script parameter.
László Vajda





