Navigating Portals Like a Spreadsheet

Navigating Portals Like a Spreadsheet

We had an interesting request on a recent project where the client wanted to navigate two portals on a layout using the keyboard. The portals needed to be setup in a way that makes them appear to be one large portal with a static header row in the middle. The client also wanted the interface design to allow for very fast data entry. We concluded that using the navigational keys to navigate the portal would be the best choice, since it performed similar to navigating a spreadsheet.

In a typical single-portal setup, a user can navigate through the fields using Tab/Enter keys, as long as the tab order is setup correctly, but for a multi-portal setup, we chose to add object names into the mix, as well as tab orders, in order to get the final result.

In the demo file, the script “PortalNav” grabs the keyboard code using the Get ( TriggerKeystroke ), then navigates appropriately based on which keystroke was entered: Left = 28, Right = 30, Up = 29, and Down = 31. For the Left and Right keystrokes, the script simply goes to the previous field (Left) or goes to the next field (Right).

For the Up and Down keystrokes, there’s a bit more complexity.

  • If the user presses the Up keystroke and is in the first portal, row 1, FileMaker throws an error, it has no other rows above it to navigate to, so it beeps to let the user know.

  • If the user presses the Up keystroke and is in the second portal, row 1, it navigates to the last portal row in the first portal.

  • Similarly, if the user presses the Down keystroke and is in the second portal, last row, it beeps to let the user know it has no other rows below it to navigate to.

  • If the user presses the Down keystroke and is in the first portal, last row, it navigates to the first portal row in the second portal.

# Navigates a portal using arrow keystrokes
# relies on correct tab order of fields in portal object
#
Set Variable [ $keystroke ; Value: Code ( Get ( TriggerKeystroke ) ) ]
Set Variable [ $row_current ; Value: Get ( ActivePortalRowNumber ) ]
Set Variable [ $object ; Value: Get ( ActiveLayoutObjectName ) ]
#
# Left
If [ $keystroke = 28 ]
       Go to Previous Field
       #
       # Right
Else If [ $keystroke = 30 ]
       Go to Next Field
       #
       # Up
Else If [ $keystroke = 29 ]
       If [ $row_current ≤ 1 and Left ( $object ; 2 ) = "p1" ]
                Beep
       Else
                Go to Portal Row [ Select: On ; With dialog: Off ; $row_current - 1 ]
                If [ Get ( LastError ) = 0 ]
                             Go to Object [ Object Name: $object ]
                Else
                             # If navigating up, but it's the first row in portal2, go to the last row in portal1
                             Set Variable [ $object ; Value: Substitute ( $object ; "p2" ; "p1" ) ]
                             Go to Object [ Object Name: $object ]
                             Go to Portal Row [ Select: Off ; Last ]
                End If
       End If
       #
       # Down
Else If [ $keystroke = 31 ]
       Go to Portal Row [ Select: On ; With dialog: Off ; $row_current + 1 ]
       If [ Get ( LastError ) = 0 ]
                Go to Object [ Object Name: $object ]
       Else
                # If navigating down, but it's the last row in portal 1, go to the first row in the next portal object (portal2)
                Set Variable [ $object ; Value: Substitute ( $object ; "p1" ; "p2" ) ]
                Go to Object [ Object Name: $object ]
                If [ Get ( LastError ) ≠ 0 ]
                             Beep
                End If
       End If
End If

The final result turned out to be a simple solution that can be easily expanded upon and implemented into any other database. Feel free to download the demo file to use as a reference. As always, if you have any thoughts on portal navigation or need assistance implementing a similar solution into your database, please feel free to contact us or leave a comment below.

Leave a Reply

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