dominoGuru.com
Your Development & Design Resource
Context-Sensitive Tabbed Navigation in the Lotus Notes Client
02/16/2006 09:21 AM by Chris Toohey
It's something that gave our CRM product (Revolution CRM) an amazingly fresh and simple-to-navigate Notes-client user interface, and despite it's seemingly simple function... implementing a context-sensitive navigation system for a table-based form layout in the Lotus Notes client required quite a bit of hackery. In this article, I'll showcase exactly what we did to facilitate such functionality and ultimately provide our users with a simple, intuitive interface (at least in my and several of our users' opinions)
We start
off by creating a Programmed Table, turning off the table tabs to the UI (fig.
1), then naming the table row
and assigning each row tag a unique
name (fig. 2).
Now that we
have our Programmed Table, we need to create the dynamic display
functionality. To do this, we simply create a field called
$row
:
Field Type: Text - Computed for Display (CFD)
Field Formula:
@If($row="" ; "1"; $row)
And now that we have our Programmed Table and programatic control field, we'll work on the tabbed interface.
You can make this navigation system look however you would like, but the ultimate goal is to have an active and inactive state for each of your navigation tabs, and set the active table row's correlating navigation tab to it's "active" state. To do this, we'll first build out the navigator. And for this navigator, we'll use a table, and more specifically, a table cell.
We are going to put a hotspot in a table cell, and when said hotspot is clicked, I want to 1) set the current navigation tab to it's "active" state and 2) activate the correlating Programatic Table row. For 1, we'll need to place the following formula in the cell properties of the navigation tab (fig. 3):
@If($row="1";"activetab.gif";"tab.gif")
The above code, checks to see if the first tab is active, and if so, sets the cell background-image to "activetab.gif". Otherwise, it remains "tab.gif", which is the application's inactive tab background-image. Pretty simple approach, so far. The problem that we ran into is that we could not successfully "reload" the page to display the now-active navigation tab nor the now-active Programmed Table row.
Bring on the hackery!
We start by using Lotuscript on the form at various form events, and then an on-click function loaded from a script libary. We'll start by displaying a list of form events and their script counterparts:
QueryOpenSub Queryopen(Source As Notesuidocument, Mode As Integer,
Isnewdoc As Variant, Continue As Variant)
Set w = New
NotesUIWorkspace
Set s = New NotesSession
Set db = s.CurrentDatabase
Set uidoc = source
Call InitializeRow ( s, uidoc )
End
Sub
QueryCloseSub
Queryclose(Source As Notesuidocument, Continue As Variant)
Call FinalizeRow ( s, source )
End
Sub
PostOpenSub
Postopen(Source As Notesuidocument)
Set doc =
source.Document
End
Sub
DeclarationsDim s As NotesSession
Dim w As NotesUIWorkspace
Dim db
As NotesDatabase
Dim doc As NotesDocument
Dim uidoc As
notesuidocument
And now, for our on-click function. On each "tab", you'll want to create a hotspot with the following Lotuscript (replacing the "1" with the intended Programmed Table's Row name:
Sub
Click(Source As Button)
Call OnClickTab ( w, s, uidoc,
doc, "1" )
End Sub
And now, for our
OnClickTab
, InitializeRow
, and
FinalizeRow
functions:
Sub OnClickTab (
w As NotesUIWorkspace, s As NotesSession, uidoc As NotesUIDocument, doc As
NotesDocument, row As String )
' FUNCTION: OnClickTab ( w, s, uidoc, doc,
row )
' PURPOSE: Change the row the the programmable table
'
ARGUMENTS:
' w ( NotesUIWorkspace ) - global ui
workspace
' s ( NotesSession ) - global session
' uidoc ( NotesUIDocument ) - notes ui document
' doc ( NotesDocument ) - notes backend document
' row ( row ) - row to set
If
uidoc.editmode Then
Call doc.ReplaceItemValue("$row",
row)
Call uidoc.refresh
Else
Call s.setEnvironmentVar("RevolutionRow", row)
Call
uidoc.close
Call w.EditDocument(False , uidoc.Document)
End If
End Sub
Sub InitializeRow ( s As Notessession, uidoc
As notesuidocument )
' FUNCTION: InitializeRow ( uidoc )
' PURPOSE:
Initialize the row to one pressed by user
' ARGUMENTS:
'
s ( NotesSession ) - global session
' uidoc (
NotesUIDocument ) - current ui document
Dim doc As
NotesDocument
Dim row As String
Set doc =
uidoc.Document
If doc Is Nothing Then Exit Sub
If uidoc.editmode Then
Call
doc.ReplaceItemValue("$row" , "1")
Else
row = s.getEnvironmentString("RevolutionRow")
If row = "" Then row = "1"
Call
doc.ReplaceItemValue("$row", row)
End If
End
Sub
Sub FinalizeRow ( s As NotesSession, uidoc As
notesuidocument )
' FUNCTION: FinalizeRow ( s, uidoc )
'
PURPOSE: Reset the rows to first row
' ARGUMENTS:
'
s ( NotesSession ) - global session
' uidoc (
NotesUIDocument ) - current ui document
Call
s.setEnvironmentVar("RevolutionRow", "1")
End Sub
Now this is a
simple example of how you can manually refresh the current UI to not only
display the currently active Programmed Table row, but also the currently
active Navigation tab. You could just as well conditionally set font colors,
weight, and even the text itself by simply computing the values based on the
$row
field - thus completely allowing your applications to provide
a more controlled and more intuitive UI for your users.
Technorati tags: Show-n-Tell Thursday