By Daniel Wood, 6 June 2011
In part one, we built a basic navigation bar made from repeating fields. In this followup article we take the formatting of the navigation bar further by introducing highlights. We also adjust the construction of the navigation, and introduce a custom menu implementation that can be used in conjunction with, or in place of the navigation bar.
In order to make some of the new features of this upgraded navigation bar easier to manage, we are going to make a few minor tweaks to how the navigation bar is constructed. These changes may slightly affect how the navigation bar looks from earlier versions, but these can easily be overcome with field formatting options.
On first glance it may look very similar to the navigation bar in part one, but there are a couple of changes that are shown better in layout mode.
Here, the icon repeating fields have been increased in height so that their bottom border touches the top border of the label repeating fields, creating a single block with no gaps in between the icon & the labels.
Another change less noticeable, is that each icon/label combination has been created as a separate series of objects to the other repetitions, better illustrated in the following picture:
Recall in part one that we specified the icons and labels as single fields that were set to show all repetitions. There are a few reasons for this change which will become clear later.
One final change is that each repetition combination of icon & label are grouped into a single object.
The navigation bar in part one gave no visual indication of which screen the user was currently viewing. It would be nice to highlight the screen being viewed so the user is not left guessing where they ended up, it also provides some solid feedback that the users click on the navigation bar was successful.
What we are going to do then is to implement some highlight formatting as shown below:
In the picture above you can see two things happening:
Both of these formatting changes have been done by using conditional formatting.
The decision to use conditional formatting over calculation fields that make use of text formatting functions is a conscious decision. The downside to the conditional formatting is that if you ever want to change the fill color or label changes, then the change has to be applied to all navigation bars (or a single navigation bar that is then replaced on all layouts). This could become a nuisance but we are going on the assumption that once set it won't change. The fact the entire navigation system is based on globals means changes aren't that difficult to make as it is a case of copy/pasting a new navigation bar on all layouts that use it.
The reason why calculation fields that use text formatting functions were not used for the formatting, is because the goal here is to keep the navigation system entirely global. By having it all global based, there is only the need for a single Navigation table occurrence on the graph, and navigation bars can easily be applied to new layouts without additional setup. Global calculation fields are not suitable in this situation as they do not refresh as desired.
NOTE: This section is somewhat irrelevant now after a discovery by Peter Bouma after the article was written. Please see the extra section at the bottom of this article before reading this section as it may save you some time, cheers :-)
In order to highlight any particular screen in the navigation bar, we require a calculation that can be evaluated that is generic, but at the same time evaluated differently for each repetition. How can a specific repetition evaluate differently from another repetition you ask? Well the answer lies in using a FileMaker function that will give a different result depending on which repetition evaluated from, and there are two prime candidates:
Both of these are concerning repeating fields so have potential. Get ( ActiveRepetitionNumber ) however is of no real use because that only evaluates when the user has placed the mouse cursor inside of a repeating field. Because we have disabled browse mode access into our navigation bar, this function will never evaluate.
The other possibility is Get ( CalculationRepetitionNumber ). This function will return a repetitions number when evaluated from a calculation context of that repetition. There is just one problem here, our navigation bar is composed of non-calculation repeating fields. The solution then is to make it based on calculation repeating fields :)
In the picture above you can see two new fields added to the Navigation table - Labels Display and Icons Display. Both are global calculation fields set to their equivalent non-calculation field.
Now, we mentioned earlier that we chose not to use global calculations to do the formatting, yet here we are using global calculations, what gives? Well in this situation they are fine because they will be used only for the navigation bar, and not formatting. Global calculation fields will re-evaluate when fields they reference are changed, but they will not change however when non-field references in them change, such as the current layout name.
Here is the new navigation bar above, based on the global calculation fields. Note the label definition is not visible because the label text is white by default.
Now that the navigation bar is based upon global calculations, the Get ( CalculationRepetitionNumber ) field can be used in the conditional formatting. Here is the conditional formatting calculation we can apply across all repetitions:
Get ( LayoutName ) = Navigation::Layout Names[Get ( CalculationRepetitionNumber ) ]
It is simply comparing the current layout name, to the layout name contained in the Layout Names field repetition that corresponds to the current repetition being evaluated. For example, the 5th repetition in the nav bar will compare the current layout name, to that in the 5th repetition of the Layout Names field. If it is a match, the conditional formatting will evaluate to true.
Recall earlier the changes made to the navigation bar construction. These were done for various reasons, but one is to make the conditional formatting of the nav bar simpler.
The grouping of the label and icon repetition means that we can apply a single conditional formatting property across the single object that takes care of both the highlight and the text formatting, no need for a separate condition for the label and the highlight.
This single conditional formatting condition can be applied across the entire navigation bar in a single hit, because it is generic across all repetitions. The text formatting of bold & text color will have no affect on the icon, and the fill color will be applied to both icon and label which is what we want.
Note that in order for the highlight fill to work correctly, your icons should be transparent png's or gifs.
While not strictly necessary, we have used a custom function in the example file to contain the conditional formatting calculation. This is a nice illustration of how custom functions can actually reference fields - so long as those fields are able to be evaluated from the context of where the custom function is evaluated from.
Now that the text label and icon are touching borders, and they are grouped, we can just make the clickable button the grouped object. This removes the need for a separate button overlay which was used in part one. The reason it was used there was because our icon and label were not aligned and the same size as the clickable area. Because of this change, we can remove the button overlays, reducing the complexity of the navigation bar.
With the navigation system completely global and already built, building it as a custom menu is a piece of cake.
To do this, we use a technique demonstrated in a previous article called Hide Custom Menu Elements Dynamically.
The technique consists of creating menu items in a new menu. The name of each item is set using a calculation to a specific repetition of the labels repeating field. Because this is global based, it should work across all layouts where the menu item is used.
When building a custom menu, there is no ability to soft-code item names making use of the menu items position in the menu. For this reason, each menu item's name is set from an explicit repetition of the Labels field. Because we may not know exactly how many repetitions of the navigation bar a solution may use, we accommodate for this by adding as many menu items as possible. Menu items will not display if their name evaluates to blank. This is the technique outlined in the article above, and for this reason we can be sure that the menu will only display items for just those that are in the navigation bar.
The picture above illustrates how the custom menu is built, and the fact that unused repetitions contain no name, and so will not be displayed in FileMaker 11 (in FileMaker 10 they display as blank, but have no action).
The menu item name is set via the Labels repetition, and the action attached is a script that is passed a corresponding repetition number.
We have gone from using a single script step for the navigation, to putting that inside a script. The reason for this is one of future-proofing. If we ever wish to do post-navigation stuff, this lets us add that in later without having to redo the navigation bar or custom menu.
The above shows the custom menu in action.
If you had a solution with lots of screens, you could choose to do away with the visual navigation bar entirely, and simply use the custom menu aspect for navigation.
With a few tweaks and additions, we have made the navigation bar more responsive visually, by having it give feedback on which screen is selected. We also extended it's use by building a custom menu to supplement it. All the while the navigation system has been kept global and generic so that it can easily be applied to layouts with zero modifications required.
As always the readers of these articles come up with some great suggestions and contributions after the article is written and this case, Peter Bouma from Amsterdam, has discovered that in fact the need for global calculations that contain the icons and the labels is not necessary for using the Get ( CalculationRepetitionNumber ) function as I had assumed.
He has found that this function still evaluates correctly even from the context of a layout-based calculation such as the conditional formatting calculation. Even though the original labels and icons repeating fields were not calculations, the function still is able to obtain the relevant repetition via the conditional formatting calculation set on each repetition.
End result is the solution can be made simpler than I originally presented, you can do away with the Icons Display and Labels display calc fields entirely and just keep the Icons and Labels global fields for your nav bar, awesome!
Please find attached an example file. This file was used for all the screenshots in this article, and is provided to help you fully understand what is going on in this article, and to let you experiment in FileMaker with this solution.
Stephen Dolenski of Ocean West Consulting, Inc. has provided an awesome adaptation of the original example file for this article. In Stephen's adaptation, he has added functionality to allow the navigation bar to toggle between each screens various list & form views, as well as a dashboard view, very cool, and I encourage you to check it out also.