Script Triggers: Using Layout Triggers for a Dynamic Tab Orders

Leave a comment

1-7-2009 by Jesse Antunes

If you’re a male, do you really need to be asked you if you’re pregnant when you are at a clinic? If your female, do you need a prostate exam? Probably not. There are little nuances to data entry that occur with just about every solution that make it just slightly more tedious to collect information with just a standard tab order. We’re going to remedy that with using a simple layout keystroke trigger.

Dynamic Tab Order for FileMaker 10

In FileMaker there is only one way to navigate the tab order. This can be annoying to an end user who has to tab through a bunch of useless fields to get to the good stuff. The gender question above is a perfect problem to solve using a dynamic tab order in FileMaker 10.

Note: As Mikhail Edoshin points out, this process could be accomplished by attaching a script trigger directly to the field in question. The reason I chose to attach the trigger to the layout is so all tab order changes are centralized in one script. For instance if you had 4 or 5 different modifications to the tab order, you would still only have one script when using the layout trigger. If you were to place a trigger on each individual field you would need 4 or 5 scripts. That was really the main idea of this whole post but I left it out for some stupid reason.

Thanks for the heads up Mikhail.

A better way for our tab order to progress in our example is to just skip fields depending on which gender is choosen. Here is the psuedocode for what I think the tab order should look like:

IF the active field is Gender THEN
  IF Gender = Male THEN go to the prostate question END
  IF Gender = Female THEN go to the pregnancy question END
END

Finding our Key

The TAB, ENTER and RETURN as they are the three keys that filemaker uses to move to the next field.

Note:  You can specify one, two, three of these keys to progress to the 
next field in the Format >> Field/Control >> Behavior...

So using our knowledge from the previous article about keystroke triggers and consulting our ascii tables we know the following will return true if any one of those keys is pressed:

Let(
  keyCode = Code( Get ( TriggerKeystroke ) );

  keyCode = 9 or //Tab Key
  keyCode = 10 or // Enter
  keyCode = 13 // Retun
)

Overriding the tab order

Assuming that my table name is TEST and my field names are GENDER, PROSTATE_EXAM? and PREGNANT, we can write our script.

If[ Let( keyCode = Code( Get ( TriggerKeystroke ) ); keyCode = 9 or keyCode = 10 or keyCode = 13) ]
  If[Get( ActiveFieldTableName ) & "::" & Get( ActiveFieldName ) = getFieldName( TEST::GENDER )]
    If[ TEST::GENDER = "F"]
      Go to Field [ TEST::PREGNANT? ]
      Exit Script [Result: False]
    Else If [ TEST::GENDER = "M" ]
      Go to Field [ TEST::PROSTATE_EXAM? ]
      Exit Script [Result: False]
    End
  End
End

Notice on the second line of the script we combined two get functions to determine the table and name of the field and then compared that to the result of getFieldName( TEST::GENDER ):

Get( ActiveFieldTableName ) & "::" & Get( ActiveFieldName ) = 
getFieldName( TEST::GENDER )

The reason we do this is to make sure that if for some reason you ever decide to change the name of either the table or field the script won’t break.

You’ll also noticed that I use the step Exit Script [Result: False] after I navigate to each field. The purpose of this step is to reject the TAB, ENTER or RETURN key press. If we were to leave the Exit Script step out, FileMaker would process the keystroke and therefore go the the next field in the tab order after the field I just told it to go to. This would drive everyone crazy!

Once I’ve played with this technique a little more I’m sure it will prove quite useful. It definitely makes data entry a little more user friendly.

7 Comments

  1. Mikhail Edoshin

    Why not to attach this event to the Gender field in the first place? Then you won’t have to check the field name.

  2. David Graham

    Following up on Mikhail’s comment, you wouldn’t need 4 or 5 scripts to accomplish this if attach the event to the field’s OnObjectKeystroke event. Your script just needs a single parameter and two steps.

    Script: GoToObjectOnKeystroke [objectName]

    Script Steps:
    Go to Object [Object name: #P ( “objectName” )
    Exit Script [Result: False]

    I hate long branching If, Else If branching scripts. I much prefer to put the logic right into the field’s script parameter so I can see all of my layout logic without having to go back to ScriptMaker. In addition, you now have a single script which can be used for your entire solution.

    You should probably create two custom functions (e.g., IsKeystrokeForward, IsKeystrokeBackward), which trap for the shift modifier key for a backwards tab.

    The Script Parameter wold look like:

    Case(
    Self = “F” and IsKeystrokeForward ;
    PassParameter( “objectName” ; “field_Pregnant” ) ;
    Self = “F” and IsKeystrokeBackward ;
    PassParameter( “objectName” ; “field_PriorFieldName” )
    Self = “M” and IsKeystrokeForward ;
    PassParameter( “objectName” ; “field_ProstateExam” ) ;
    )

    Of course you’ll have to assign object names to the fields in question, but I think it’s worth it.

  3. Jesse Antunes

    @David – I like where you’re going with that. I think you can even approve it by passing the field names like so:

    PassParameter( "objectName" ; GetFieldName( TEST::field_Pregnant )

    That way you don’t have to worry about the names of the fields changing.

    I still believe it’s a little cleaner to do it in one centralized script because you don’t have to go to each individual field to figure out where it goes. I think at this point it’s more of personal preference though. Thanks for the comment.

    We are actually going to be writing a post about using a script much like the one you just wrote for copying entire records into hashes and passing them around.

  4. David Graham

    @Jesse: The only problem with passing a field name is you can’t go to a field by it’s name, which is why I used object names. Once I set an object name I never change it so I don’t have to worry about it breaking. Of course, it’s much easier if you have a concrete naming convention.

    You’re right though … there’s definitely more than one way to skin a cat, eh?

  5. Jesse Antunes

    @David… ummmm yea I knew that. :) Thanks for the correction again.

  6. David

    have you tried this. I can see the cursor skip to the desired field and then back the the field following gender.

  7. Brent Durland

    One thing to keep in mind when playing with tab order is the behavior of the date picker. Selecting a date automatically advances the focus to the next field in the tab order, so to make that happen programatically, either trigger a script when leaving the date field, or when entering the next field in the order.

Tell Us What You Think

*
* (will not be published)