Saturday, August 11, 2007

FieldListener class for NotesUI - search on enter, etc.

To redeem myself from my previous SNTT post, I did a little brainstorming, to find something worthy for SNTT. I hope this one is..

A while back Chris Blatnick posted a method to listen for 'Enter', and search based on JavaScript in the Notes client.

Lotus did a bad implementation of setInterval in the Notes client (several actions by the user can cause the interval to run "forever" -> high CPU usage). Because of that, the method is probably not an option for most people.

The FieldListener class I made for this demo, uses the NotesTimer, and On Event Alarm to do the same. Since you're working with LS, you can add whatever functionality you want in response to something the user writes.

The downside with NotesTimer is that you can only specify whole seconds (Integer) as the intervals. Worst-case scenario, there is a delay of one second between a phrase being typed and the action execution.

Demo (the button calls the same method as the fieldListener, onEnter):






To implement the FieldListener-object on a form:
Globals in the form:

Option Public
Use "FieldListener"


Declarations:

Dim fieldListenerObject As FieldListener


In the QueryOpen event:

Sub Queryopen(Source As Notesuidocument, Mode As Integer,_
Isnewdoc As Variant, Continue As Variant)
Dim interval As Integer
interval = 1
Set fieldListenerObject = New FieldListener( Source, "fieldName",_
"substring(Chr(10) without quotes=enter)", interval, "actionToExecute" )
End Sub


I'm running two paralell "listeners" on one field in the demo, one for "johnny", and one for Chr(10) (Enter).

Download the application to see the implementation of the demo. Johnny can speak, but my screen capture software (free) cannot listen (there is a setting for it, but it doesn't work on my machine).

2 comments:

Tim Tripcony said...

Looks good, Tommy. Couple suggestions:

You could add a FieldListenerManager class, with a global instance for the form. It would hold a List of arrays; the Listtag would be the field name, and the array members would be instances of FieldListener. FieldListenerManager.addFieldListener would take the same parameters as the FieldListener constructor; it would instantiate a new FieldListener and add it to the array of listeners for that field.

In the FieldListener constructor, prior to binding the Alarm event handler, it would set .Enabled to false. Then in the Entering event of each monitored field you could call FieldListenerManager.enableListeners(currentFieldName). This method would check IsElement to see if the field has any listeners, and if so, call FieldListener.enable on each, which would enable its NotesTimer. Finally, the field's Exiting event would call .disableListeners, which would disable the NotesTimer for any listeners, but then force one last execution to ensure that any pending action is taken.

On complex forms that might have three different listeners for each of dozens of fields, this would ensure that the only NotesTimers running at any given time are the ones associated with the focused field. What do you think? Worthwhile modification?

Unknown said...

All suggestions look good.

I'm not fond of too much code in the different field events. This probably comes from working mostly with web applications. From experience, the more events coded in the form, the harder it is to maintain (I don't know if the same is correct for working with Notes Client apps).

I try to do most of the event-binding in JavaScript libraries.

I don't know why Lotus/IBM haven't made available dynamic event-binding on fields.

e.g.
On Event Entering From_
Source.GetField( "fieldName" )_
Call fieldEntered

...

Sub fieldEntered( field As NotesUIField )

Select Case( field.name )
Case "fieldName"
FieldListManager.enableListeners(_
field.name )
End Select

End Sub

I'm not going to use the class (I only work with Domino web apps) in work-related projects. I'll probably be messing about and try out new stuff in the client. Maybe if the client-guys at work want this in their apps, I'll try to implement your suggestions.

I'm more of a proof-of-concept (less time consuming) guy, than a perfectionist when it comes to my non-work time.