Marquees are a familiar sight on the Web -- for displaying headlines, important messages, advertisements, and more. They enliven the page and catch the user's eye. When combined with hotspots, marquees can even act as a navigation tool for sending users to other parts of the site. What you may not know is that you can use marquees to do these things in both your Web and Notes applications.
Note: We designed the code in this article to work with Domino and Notes R4.6, Netscape Communicator 4.x and Microsoft Internet Explorer 4.x. Results with other releases may vary.
You can try out the techniques described in this article by downloading the sample database from the Sandbox.
To get started, copy the database to a Domino server and open the application using both clients to see the marquee in operation. This article is a guided tour through the key aspects of the design, so be sure to have the sample database open in design mode as you read along.
When we first decided to create a marquee on our newsletter application, we instantly thought of three techniques for displaying the headlines. These techniques involved using:
- A Java applet or JavaBean
- The <MARQUEE> HTML tag
We quickly ruled out these techniques because none of them offer a cross-platform solution. They also lack the integration with Domino we needed to offer a robust feature for our customers. Java applets don't run on the Notes client (unless you embed the applet into the rich-text field of a document), the <MARQUEE> tag is limited to Internet Explorer, and frames are limited to Web browsers. Further, we needed our solution to:
- Load quickly over dial-up connections (this further ruled out Java)
- Appear and operate virtually the same for both Notes and Web clients
- Provide a way for new headlines to automatically appear on the marquee without having to recode the home page every time
- Allow the database administrator to easily schedule the headlines, and to set the time interval between headlines
We found a solution to fit all these requirements. Let's take a look at the sample database to see how our marquees look and work.
Before getting down to the code level, let's take a look at how the marquee operates for both Notes and Web browser clients. The application home page for the Notes client displays the headlines marquee like this:
Figure 1. The application home page Headlines marquee in Notes
The marquee displays each of the headlines one-at-a-time, continuously cycling through the current list of headlines. To read the story related to the headline, you can click the Hand icon to open the document of interest.
Of course, the marquee is only a part of the overall home page design, which may be the starting point for your entire site or just for a single application.
The application home page for the Web browser client displays the headlines marquee like this, and works the same way as for the Notes client:
Figure 2. The application home page headlines marquee for the Web browser
Now that you have seen the marquee in action, let's start with an overview of its architecture. If you are accustomed to thinking of reading a Notes document only as the merging of a form with a document, this technique will stretch your understanding of Notes forms. In fact, Notes can emulate other database front-end tools that open a form and then bring the data into the form (with the exception of rich text fields) using some sort of control to navigate to the first/last and next/previous records. This technique uses both constructs: it displays some data from the underlying document and automatically rotates the value of a single field using back-end data access methods to display the marquee.
This diagram shows the key elements of the application architecture:
Figure 3. The elements of the application architecture
The headlines displayed by the marquee come from Notes documents created using the Headline form and selected by the Headlines view.
When launched by the Notes client, the HomePage form uses the LotusScript NotesTimer object to loop through the Headlines view. It then changes the value of the marquee field each time the NotesTimer object raises its Alarm event.
For both clients, the marquee field is updated every N seconds with another headline, with N being set by the database administrator via the HeadlineAdmin view.
Both clients rely on the pre-existence of an application HomePage document that is created at design time. Though set to launch the "About database" document, the Notes client runs a Database Postopen event to switch the user to the home page. The Web browser client, on the other hand, is set to launch the first document in the HomePage view (in which there is only one document, the home page).
While it is entirely possible to use the same forms for both Notes and Web browser clients, we find it easier to keep the code separate so we do not have to wrestle with hide-when formulas or computed subforms. In this case, we developed separate HomePage and Headline forms for each of the two clients. In addition, we use different forms for creating documents than for displaying them -- that is, we create Headline documents on Notes clients, but then use a different form for displaying the documents on Web browser clients. You will see how to do this as we go along.
With the architecture in mind, let's step through the application design.
The first step is to create the Headline form, which we use to create documents that feed the marquee. As I mentioned, we use the Notes version of the Headline form to create Headline documents, and we also use it to display the document to Notes clients. I will show you the Web version of the form in Step 4. This screen shows the Notes version of the Headline form in design mode:
Figure 4. The Headline form in design mode
The two fields StartDate (Time calendar widget) and CutoffDate (Time calendar widget) are in a layout region and are unique to this form. They control whether or not the document appears in the Headlines view, which feeds the marquee. With these fields you can, for example, schedule a Headline to appear starting on Monday next week, and have it display for only two days. Once set, you can be assured that users will see fresh content in the marquee without further intervention on your part.
The Subject (Text) and Body (Rich text) fields are editable fields, and the Owner (Authors) and PostedOn (Time) are computed-when-composed fields. The Subject field is the source for the headlines displayed by the marquee. The Body field (rich text) contains the story contents.
Once you have created the form to create the headlines, the second step is to create a view to display Headline documents. Each time a user opens the home page of the application, the marquee displays the current headlines from the Headlines view. This is highly useful, in that as soon as a content author creates a new Headline document, the marquee automatically displays them along with the other current headlines. This screen shows the Headlines view:
Figure 5. The Headlines view
The Headlines view selects Headline documents based on this selection formula:
SELECT @Today >= StartDate & ( @Today <= CutoffDate | CutoffDate = "")
As you saw in the Headlines form, the StartDate and CutoffDate fields allow you to schedule headlines to appear and disappear from the Headlines view (and consequently, from the marquee). This view selection formula ensures that only headlines scheduled to appear today actually are included in the view. If the CutoffDate field is empty, the headline never expires.
The third step is to develop a form naming scheme to use in conjunction with the "hide from Web/Notes" design property to ensure that the correct form is shown to each of the two clients. As stated earlier, we use separate forms for displaying the Headline documents to Notes and Web browser clients.
We named the form "Headline | Headline." Notice that both the Headline and WebHeadline forms use the same form alias (the name to the right of the pipe), "Headline." Then, in the Design Document properties, you can identify which form is displayed to which client. This screen shows the Design Document properties for the Headline form, which we selected to hide from Web browsers:
Figure 6. The Design Document Properties box
Though you could accomplish the form swapping using a view form formula that uses @ClientType to display the appropriate form, this method is easier, more direct, and also performs much better (that is, the form opens faster).
The fourth step is to create the form for displaying Headline documents to Web browser clients. The Web version of the Headline form is presented to Web browser clients for display purposes only. This screen shows the WebHeadline form:
Figure 7. The WebHeadline form
Notice that the schedule control fields are omitted, as they are not needed for display purposes.
We named this form "WebHeadline | Headline," and used the same form alias "Headline" as the Notes version of the form. The difference is that this form is hidden from Notes clients in the Design Document properties. So, when a Notes client opens a document from the Headlines view, the Headlines form is used to read the Headlines document; when a Web browser client opens the same document from the same view, the WebHeadline form is used.
This step creates a view for the database administrator to use for creating and scheduling Headline documents. This screen shows the HeadlineAdmin view:
Figure 8. The HeadlineAdmin view
The difference between this view and the Headlines view is that this one shows all Headline documents, even if they are not currently scheduled to be displayed by the marquee.
The StartDate and CutoffDate fields are used to determine if the document is included in the Headlines view and, therefore, in the marquee. The sun icon tells you if today's date falls within the two dates -- that is, the date currently on display by the marquee.
The Configure action button in the HeadlineAdmin view opens a dialog box that calls the AdminProfile form. The only setting is the time delay interval between headlines displayed by the marquee:
Figure 9. The Configuration dialog box
The value of the DisplayInterval in the dialog box is read by the Postopen event from the Delay field in the HomePage document and set back to the HomePage document by the Queryclose event. Note that this use of a dialog box (called without an underlying document open in edit mode to accept the values) is unconventional, but works because the AdminProfile form events take care of writing field values via back-end methods.
Since users do not modify or save the HomePage document, there is no chance of save conflicts if the interval is changed on the fly. We also include the ability for the database administrator to shut off the marquee feature altogether. Then, using a formula in the hide-when text property, the headline is hidden from all users.
This step makes the marquee idea possible for Notes clients, because without a field on a form, the marquee could not exist. While a form is necessary to display the marquee (because it requires a field), in practice, the HomePage form can also contain other information and navigation relevant to the entire application. The advantage of using a form over a full-screen navigator or the About document is that you can include fields and computed text that dynamically alter the content of the home page for various users. For Web browsers, you gain the ability to include embedded Web elements (view list, view, and navigator), all right within in the application home page.
But using a form for an application home page is not easy, and requires a degree of programming to make it happen. Most of the work centers around security issues, such as how to prevent users from modifying or deleting the home page. You'll learn about the required security settings in Step 10.
The HomePage and WebHomePage forms follow a similar architecture to the Headline forms. We use the Notes version of the form to create the Home Page document and to display the home page to Notes clients; we use the Web version only to display the home page to Web browser clients. The most significant difference between the two versions of the form, of course, is the code behind the marquee display. This screen shows the HomePage form:
Figure 10. The HomePage form
This is the step you have been waiting for, where you create the code for displaying the marquee to Notes clients. The Notes version of the HomePage form creates a NotesTimer object and then starts the timer running in the form Postopen event. Let's step through each piece of the code in the HomePage form used to display the marquee:
- The Options Public statement in the Globals Option event and the declarations in the Global Declarations event scopes public variables across all of the events in the form, making them available to any LotusScript code in form, field, button, or action events (if you declare the variables at the Form level, they are global only to the form events). These variables need to be global, since you want to keep a running count of which Headline document you are displaying (DocCounter) and want to keep the NotesTimer object "alive" when the form Postopen code ends (HeadlineTimer).
- The Postopen event is responsible for initializing the public variables and instantiating the NotesTimer object. The NotesTimer object is set to run every N seconds (as stored in the Delay field). You can use this annotated code for the HomePage form Postopen event:
Sub Postopen(Source As Notesuidocument) Dim Session As New NotesSession Dim WS As New NotesUIWorkSpace Set ThisDB = Session.CurrentDatabase Set UIDoc=WS.CurrentDocument Set Doc = UIDoc.Document '1) Get Delay field value from the document GetDelay = Cint(Doc.Delay(0)) '2) Instantiate the NotesTimer object using the DisplayInterval setting Set HeadlineTimer = New NotesTimer( GetDelay ) '3) loop through Headlines view to get the document COUNT Set HeadlineView = ThisDB.GetView( "Headlines" ) Set CounterDoc = HeadlineView.GetFirstDocument If CounterDoc Is Nothing Then Exit Sub Do Until CounterDoc Is Nothing NumDocs = NumDocs+1 Set CounterDoc = HeadlineView.GetNextDocument (CounterDoc) Loop '4) select the first document in the view (NthDocument starts at 1) DocCounter=1 Set HeadlineDoc = HeadlineView.GetNthDocument( DocCounter ) Doc.Headline = HeadlineDoc.Subject(0) '5) set the NotesTimer event to hit the other documents If NumDocs=1 Then ' there is only one doc Set HeadlineDoc = HeadlineView.GetFirstDocument Else '6) run the HeadlineTimerHandler function when the Alarm event fires On Event Alarm From HeadlineTimer Call HeadlineTimerHandler End If End Sub
Notice that the form Postopen code runs only once when the document is opened, but that the NotesTimer event runs until the document is closed. What does the NotesTimer object do? Its Alarm event runs the HeadlineTimerHandler function once every N seconds (with N being the value stored in the Delay field). So let's look at the HeadlineTimerHandler function that does all of the work.
- The tasks performed by the NotesTimer object are performed by the HeadlineTimerHandler function. Keep in mind that we have set the global variable DocCounter to keep track of which document is being accessed by the NotesView object GetNthDocument method. You can use this annotated code for the HeadlineTimerHandler function:
Sub HeadlineTimerHandler(Source As NotesTimer) '1) increment the counter DocCounter = DocCounter + 1 '2) get the corresponding document from the Headlines view Set HeadlineDoc = HeadlineView.GetNthDocument( DocCounter ) '3) read the Subject field and set the current document Headline field (the marquee) Doc.Headline = HeadlineDoc.Subject(0) '4) reset the counter when we run out of documents so we start over at the top of the view If DocCounter = NumDocs Then DocCounter = 0 End Sub
Remember that the NotesTimer object continues to run as long as the document is open (even if it is not the current window), and will continually loop through the view to reset the value of the Doc.Headline field using the documents found in the Headlines view until the HomePage document is closed.
This step exposes the code behind the home page's hand icon, which users can click to open the Headline document for the corresponding headline on display.
The hotspot code on the Notes version of the HomePage form is a small bit of LotusScript that opens the document of interest using the headline as the key value to find the matching Headlines document in the Headlines view. You can use this annotated code for the hotspot code:
Sub Click(Source As Button) On Error Goto ErrorHandler '1) Get a handle on the current document for both the front-end and back-end Dim WS As New NotesUIWorkSpace Dim UIDoc As NotesUIDocument Set UIDoc = WS.CurrentDocument Dim Doc As NotesDocument Set Doc = UIDoc.Document '2) declare and instantiate the Headlines view Dim DisplayView As NotesView Set DisplayView = ThisDB.GetView("Headlines") Dim HeadlineDoc As NotesDocument '3) using the currently displayed headline, get a handle on the Headline document Set HeadlineDoc = DisplayView.GetDocumentByKey (Doc.Headline(0), True) '4) declare a new front-end UI document and load it with the Headline document Dim NextUIDoc As NotesUIDocument Set NextUIDoc = WS.EditDocument( False, HeadlineDoc, True ) '5) close the Home Page to save window resources Call UIDoc.Close Exit Sub ErrorHandler: Messagebox "Error " & Err( ) & ": " & Error(), 0, "Error" Exit Sub End Sub
While you could write this using the @Command language, the advantage of using LotusScript is that you can also close the HomePage document using the NotesUIDocument Close method, thereby conserving the number of open windows. We also found that if the HomePage document is still open in a background window, the NotesTimer object will diminish the performance of whatever is running in the foreground window.
At some point, you need to create a HomePage document, which you may have already done. If you haven't, from the HomePage form, choose Design - Preview in Notes. Then, save the document.
Now, the tricky part. As mentioned earlier, using a form for our home page presents some security concerns. An essential point to remember is that Notes doesn't let you dynamically change field values unless the form is open in edit mode. And, of course, this is the crux of changing the marquee display.
This is no minor detail, as it may impact the entire security architecture of your application. Even if your application is largely a publishing application where most users only read documents, they must be given Author access to the database and the rights to edit the HomePage document! But before you panic, Notes provides a number of security mechanisms that, if used properly, will keep your application as secure as if these users were given only Reader access to the database.
Use the following steps to give users edit access the HomePage document, while keeping the rest of the database secure:
- Add a group to the ACL that includes the users who will only be considered readers. Since you don't want these users to add new documents, give them Author access in the ACL but do NOT give them the rights to create new documents. Also, be sure to disable their right to delete documents.
- Use the security tab on the Form properties for all forms (including the HomePage form) to disable the group from creating any new documents with the forms.
- Add the group name to the DocAuthors field (Authors data type) on the HomePage form. Authors fields allow any users listed as Author in the ACL the right to open the document in edit mode, even if they cannot create a new document using the same form.
- Use the Field properties to set all editable fields on the HomePage as requiring Editor access to use. This keeps the users from entering any editable fields you may have on the form.
- After you have created the first (and only) HomePage document, set the SaveOptions field on the form to "0". With this set, users cannot save the document and are not prompted to save the document when it is closed.
Because the HomePage document pre-exists and the users are listed in the Authors field in the document, they can, in effect, "edit" the document, but cannot change any of the fields (all are marked "Must have at least Editor access to use") or save the document (SaveOptions="0"). So, you can allow the document to open in edit mode without giving users any real "Author" capabilities with respect to the HomePage form.
Figure 11. The HomePage form for Web browsers
All of the displayed text on this form is defined using the "Pass-Thru HTML" text property. We could also have used the "[" and "]" characters to define the pass-thru HTML, but the "Pass-Thru HTML" text property makes for easier coding. The third option for passing HTML to the browser, the "Treat document contents as HTML" form property, cannot be used in this case because clients open the form in edit mode, which is not allowed by this property.
Let's save explaining the $$HTMLHead field for last. Most of what you see on the form is the HTML anchor tag for the link to open the Headlines view wrapped around the code to display the Hand image (which is ACTN017.GIF read from the \DOMINO\ICONS directory on the Domino server).
The key to the marquee display for browsers is found in the $$HTMLHead field (hidden, computed-for-display) containing this formula:
- The first five lines are a straight Notes function language assignment of temporary variables:
- ThisFile returns the name of the current database (replacing backslashes with forward slashes and spaces in filenames with "+" symbols), which will be used later to build a URL to open the Headlines document chosen by the user.
- GetValues is the complete multi-value list of headlines from the Headlines view. Remember that all of the values must be present on the page when it is sent to the browser.
- GetInterval is the number of seconds between the display of headlines by the marquee, taken from the HomePage document that was set via the HeadlineAdmin view. If, for some reason, the value is NULL, we will use three seconds.
- NumDocs counts the number of headlines in the GetValues list, which is used later to determine if the marquee has hit the end of the array and should start over.
- The line
- docCounter is a counter that is incremented each time the cycle function runs and is used to select one element in the headlineArray array.
- The cycle function performs four tasks:
- Increment the docCounter variable by 1 each time it runs using the ++ operator.
- Reset the docCounter when it equals the number of Headline documents (stored in NumDocs, a Notes variable).
- Set the value of the getHeadline field to the value of the element selected by docCounter from the headlineArray.
- The openDoc function performs three tasks:
- Replaces any spaces in the headline with "+" symbols, which is necessary to create a valid URL to open the document (spaces are invalid characters in URLs).
- Changes the browser's Location object href property to the new URL.
Nothing in the $$HTMLHead actually kicks off the first execution of the cycle function or takes the user to the Headline document. The first task, starting the cycle function, is performed by the browser's onload form event, which runs when the page is loaded. The onload event is triggered from the <BODY> tag, which on the design side, is entered in the HTML Attributes event in the Notes form:
When the form opens in the browser, the cycle function is executed for the first time by the browser's onload event. The cycle function, in turn, calls itself recursively after waiting the specified number of milliseconds. Each time the function runs, it increments docCounter, which in turn is used to select another headline to display from the array until it reaches the last element, after which it starts over from the top. This will occur indefinitely until the window changes location to another URL or is closed.
The second task, changing the location to the selected Headline document via the openDoc function, isn't performed until the user clicks the icon. The openDoc function is called by the anchor tag using this syntax:
Because both the Notes and Web versions of the HomePage form use the same alias name and each is hidden from the other client, Domino selects the appropriate form to display the HomePage document (created in Step 10) from the HomePage view to each client. This final step shows what happens after the user opens the application, and how it differs between the two clients.
Use the Database properties to specify a different launch option for each of the two clients. This screen shows the Database properties:
Figure 14. The Database Properties box
First, let's look at the "On Web Open" launch option, which is actually a more direct way of launching the home page than the Notes launch option. The HomePage view contains a single HomePage document, which in turn is opened using the Web version of the HomePage form.
Now, let's look at the Notes launch option. Because the Notes launch setting does not include the "Launch first document in view" option, the best we can do is open the "About database" document and then wait for the Database Postopen event code to run. The Database Postopen event code finds the HomePage document in the HomePage view and opens it in the workspace in edit mode. You can use this annotated code for the Database Postopen event:
Sub Postopen(Source As Notesuidatabase) Dim WS As New NotesUIWorkSpace Dim UIDoc As NotesUIDocument Dim Session As New NotesSession Dim ThisDB As NotesDatabase Set ThisDB = Session.CurrentDatabase '1) find the HomePage document in the HomePage view via back-end methods Dim HomePageView As NotesView Set HomePageView = ThisDB.GetView("HomePage") Dim OneDoc As NotesDocument Set OneDoc=HomePageView.GetFirstDocument '2) using the EditDocument method, open a front-end document window using ' the contents of the back-end document object Set UIDoc = WS.EditDocument( True, OneDoc, False) End Sub
The user sees the "About database" document open, but then the Notes version of the HomePage opens. Since there are no editable fields, the user is unaware that the document is open in edit mode. The parameters for the EditDocument method force the document into edit mode and further prevent the user from switching the document into read mode.
Now that you have seen one way to launch the HomePage, let me tell you another way. This time, assume that users have the right to create new documents in the database. Rather than rely on a pre-existing HomePage document, you can, instead, allow users to compose a new HomePage document. To do this for the Notes client, change the Database Postopen event code to use the NotesUIWorkspace ComposeDocument method. For the Web browser client, simply create a link to the database using the
/marquee.nsf/WebHeadlines?openform URL syntax. The only catch is that because the HomePage document no longer pre-exists, it cannot store the delay value. So you will have to split off the configuration information from the HomePage form and place it on another document hidden somewhere in the database (or use an unkeyed Profile document).
No technique is ever perfect or complete. Here is a list of additions and caveats you may want to consider as you implement this technique in your applications:
- Although we first developed a scrolling marquee (one character at a time), it involved too much screen flashing on the Notes clients, and consequently, we decided that the headline is really more comprehensible to users if it appears all at once. Compose a Scrolling Headlines document in the sample database to see an example of a scrolling marquee. If you use this technique, I would recommend adding a second NotesTimer event to control the character parsing. We cheated and used a loop to eat up time between character placement, but this consumes processor time and results in different scrolling speeds depending on the speed of the computer running the code.
- As stressed in the article, the application home page must be a form opened in Edit mode for the marquee to update. This means that users must have Author access to the database and that you must be ever more vigilant in protecting access to every other form. I see this attention to security not as a caveat, but as an overall good design practice. This is especially true in the Web world, where users can hack a URL to do things you never intended them to do but didn't prevent them from doing with sound security design.
- As the number of headlines increases, the time to load the page also increases (this is more of an issue for the Web browser client). Plus, with each added headline, the overall attention-getting potential of each headline decreases. Keep the list short for maximum impact, and use the marquee technique judiciously.
- We originally coded the application using a Notes Profile document to save the delay interval information, but found this technique to be unreliable between platforms. If set by a Notes client, the delay interval was seemingly unavailable to browser clients (which is saying that the HTTP server task may be caching the delay interval value, and therefore, not allowing the new value to work for browser clients). There was also an issue on the Notes side, where the NotesTimer Interval property would report an absurdly large interval, even though the delay variable from the Profile was used to create the object. So we changed strategies and saved the delay interval to the HomePage document instead.
- Because LotusScript is missing a "Window" object, there is no way to know how many windows are open and no graceful way to programmatically close the "About database" document or view windows. So we are left with extra windows open, which must eventually be closed by the user. This is not an issue for Web browser clients because they have an unlimited number of windows that never have to be closed.
We also wanted Notes documents to be the source of the headlines displayed by the marquee. To do this, we pull headlines from documents in the Headlines view. As stories are published, their headlines are automatically added to the queue of headlines displayed by the marquee.
Finally, we wanted a way to schedule the headlines to appear and disappear, and for easily adjusting the delay interval between headlines. To do this, we created a selection formula for the Headlines view that selects Headline documents with starting and cutoff dates before and after today's date. We set the delay interval on the HomePage document by using a dialog box opened from the HeadlineAdmin view.
- Marquee Sample Download
- The ABC's of using the ACL
Kent Kurchak is the president of Courseware Source, a Lotus Business Partner that specializes in creating in-depth training materials for Lotus Notes and Domino developers, administrators, and users. Courseware Source is also the developer of Network Delivered Knowledge (a knowledge management application suite used to create on-line courses, books, job aids, knowledgebases, newsletters, and expertise directories) and TeamApps (teamware applications designed to help make groups more productive).