A few people who’ve been using BaseElements have commented to me on the usefulness of the back and forward buttons. It’s something I quite often implement in solutions I’ve developed, and I think it’s particularly suited to something like BaseElements where you’re often working your way down a “path” of dependencies and then wanting to trace your way back.

There are also plenty of places where this idea doesn’t really suit, so it’s not something for everyone, but there are times when it’s very handy. A lot of people also decry the internet/web nature of the idea and say it doesn’t belong in a database. That may be so, but it’s now a very familiar concept thanks to the web, and reducing your learning curve for new users is always a good idea, regardless of where you “steal” your concepts from. 🙂

How does it work

The basic concept is fairly simple, you keep a list of every file/record/layout that your user visits, and when they want to go back you just return them to an existing location.

It uses an existing programming concept of a stack, and as the user works their way through the path you push the current location onto the top of the stack, and then to go back, pop the last location off the top, and push it onto the forward stack. Stacks, and push and pop have been around for ages, so they’re not new. What this technique does is use a few new and neat functions in the latest versions of filemaker to make this much easier and to work around limitations in how much history we can store and retrieve.


Found Sets and Sort Orders

The largest limitation in this particular implementation is that it doesn’t store a found set or sort order when going back to a record.

The found set issue could be worked around by storing a list of all of the unique IDs for a found set with each location. You would set the list of ID’s in a global field and then do a GTRR script step to get the correct found set. Then you would go to the specific record via another GTRR script step, and you’d be on the right record.

However it’s obvious that this would grow the data you’d need to store exponentially, and the time taken to get and store the found set would also be large, so you’d slow the system down considerably.

Plus that wouldn’t avoid the issue of sort orders. You would have to be able to grab the sort order criteria in a script, and then re-apply the sort order once you’d got to the found set. That again would be time consuming and involve extra scripting to achieve.

In reality, the way this is used you don’t often need to go back to an old found set. The back and forward could easily store a limited set of back locations. It’s unlikely that you’ll be going back more than half a dozen steps. For one you can’t remember where you were that far back, but more importantly, it’s not often that the place you’re going to, and then going back from is more than 2 or 3 steps away. If it is, then it’s likely to be a new location and the start of a new “set” of back history.

Also with the found set issue, you’re often working in a subset of records, so your back and forward stays within the found set, even if it changes record and your found set and sort order is maintained.

So I made the decision that it isn’t worth the extra overhead in trying to maintain the found set / sort order. For the small number of times it would be helpful, the slowdowns and extra data storage issues aren’t worth the benefits.

Unscripted Location Changes

There is one other limitation worth mentioning. You can only track the process via a script, so you can only track a scripted “location” change, not a user managed change. What that means is that if the user switches record by using the status bar, or changes layout from the layout menu, or changes file via the window menu, this method won’t include those changes in it’s back history.

Again, there are possibly other ways to track this, by locking down those built in functions in the interface, or using plugins to override the defaults with your own interface options, or even event management plugins like SecureFM to capture these sorts of changes and call scripts as appropriate.

But as with the found set issue we decided it wasn’t worth the extra effort to capture this. In BaseElements for example, I wanted the interface to be as open as possible, so locking down functions was contrary to our other design goals. In essence, it’s just another limitation of the process that’s known in advance.