Monday, December 22, 2008

Holy Cow, This Is Cool!

A blog post entitled "Holy Cow, This Is Cool Or In Which I Introduce A New UI Technique But Give It A Vague And Flavorful Title to Game People Into Coming Here From Planet Lotus Since No One Really Reads This Interface Stuff"

Hi All...I always seem to come up with these posts at times that no one is around, but what the heck. Lotusphere is almost here and I'm lucky enough to be presenting once again (more on that later). As I was driving to a customer's site the other day, I thought of this technique and after playing around for a few minutes, I found that it works great. If you like it, consider it an early Christmas (Festivus, Hanukkah, insert holiday of choice here) gift.

I really love many of the UI patterns that have become popular in "Web 2.0" applications. Among these, one of the techniques that you see quite often is that of the "Fade In/Fade Out" element. Let's say you want to display a status or error message to a user after they enter an incorrect value. Sure you can just use a hide-when and make the text appear or pop up a message in a dialog box. But that just isn't sexy. You can add a little spice to your app by applying this modern looking UI device. First, let's see it in action, then I'll explain what's going on.

Now...that's the Lotus Notes client you are looking at, not a browser. While it's a very basic effect, it enhances the user experience in a nice and subtle way. It helps draw attention to the fact that there is a new element on the page and does so in a way that is less jarring than a pop-up box or instantly having the message appear on the screen. The beauty of this technique is that it is very simple to implement in your application. Here's how.

The key to this technique is the versatile programmable tabbed table (I continue to find new uses for this design element....I love it!). What I did is create a tabbed table and set the text and background colors to get progressively darker for a fade in effect. Then, using script, I simply switched from one row to the next on a timed interval using Sleep to pause the necessary amount of time.

For purposes of this example, I hard-coded everything, but after going through the steps, you should see how easy it would be to modify this so it is dynamic. The picture below shows the six rows that I used for the table. I selected a base color for the final display box background and then used lighter shades of that color for the previous rows. I did the same thing for the text in each row. I haven't really thought of any hard and fast rules here...just play with it until it looks good to you.

Formatting before setting it as a programmable tabbed table
Hint: I find it easier to do the formatting for a tabbed table as just a standard table at first, then switch it via the Table Rows property tab.

As you may recall, you can programmatically switch rows in a tabbed table by writing a single formula line such as FIELD $DisplayTable1:= "4", where DisplayTable1 is the name of the table as defined in the Table HTML Tags properties and 4 is the name of the row.

Setting the table and row names via the properties box

You can also change the row via script, which is what I did in this case. I resorted to using LotusScript since it provided me with a facility to directly control how much time I wanted between each row change. If you are going to use LotusScript to do the row switching, make sure you add a field to your form that is the same name as that of the table (e.g. $DisplayTable1), otherwise you'll get an error when you try to set this field in your code.

Once you have the programmable tabbed table setup and formatted as you like, you just need to write the script to display the table rows to simulate the fade in effect. If I was doing this in a production app, I would probably hide the table until I needed it, fade in to the message and then fade out when the user dismisses it. Thus, the code would look something like this:
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument

uidoc = workspace.CurrentDocument

Call uidoc.FieldSetText("ShowMessage", "1")
uidoc.FieldSetText("$MessageTable1", "1")
uidoc.FieldSetText("$MessageTable1", "2")
Call uidoc.FieldSetText("$MessageTable1", "3")
Call uidoc.FieldSetText("$MessageTable1", "4")
uidoc.FieldSetText("$MessageTable1", "5")
uidoc.FieldSetText("$MessageTable1", "6")
Call uidoc.Refresh
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at

Notice here that the first thing I am doing is setting a field called ShowMessage to "1", which is just a field I use to control the hide-when properties on the table. Then, I set the table to row 1, refresh the document and sleep for .15 seconds, switch to the next row, sleep again and so on until the final row is revealed. To fade out, just repeat the steps above in reverse. That's all there is to it. I told you it was easy.

In case any of that was unclear, I've created a sample database that you can download to deconstruct the technique. It is simple and elegant, which you know by now is my favorite kind. I hope you can find a use for this in your applications.

Now...I mentioned before about Lotusphere. Did you like that technique? Do you want to learn even more "Web 2.0" UI goodies? Well, it just so happens that I'll be teaming up once again with my friend Nathan Freeman to present AD212 - 10 Web 2.0 User Interface Patterns for IBM Lotus Notes and XPages. In this session, we'll be taking a look at 10 popular modern UI patterns and showing you how to bring them to the client and to XPages. I'm excited about how it's coming out and I hope you'll drop by to check it out.

In addition to my session with Nathan, I'm very pleased to report that I'm teaming up for the first time with Tom Duff, aka Mr. "Now I'm published in a popular article" (go read's awesome!). We're going to be presenting BP108 - Getting To WOW...Interface First Design for IBM Lotus Notes Developers (it's also being repeated in case you can't make the first session). This is an updated version of some of my past presentations and I'm excited about it because Tom will bring his unique insight into the process of moving from a code-focused orientation to a more holistic one. Please come by if you can (and we'll have some goodies to give away as well! :-)

That's all for now. Signing off so I can work on more Lotusphere stuff. I hope you all have a fantastic holiday and very happy New Year!


Rob McDonagh said...

Holy Cow, That is Cool! *grin*

Phil said...

You truly rock my friend! Great technique, and something I wouldn't have thought of in a million years. Will be looking to implement this forthwith!

Tim Tripcony said...

Aha, so that's why you were trying to simulate Sleep in Formula last week...

Great work, Chris. That looks sharp.

Keil said...

Chris, I would think that refreshing the page so often might be a bad thing. Maybe it's just me. So many of my forms use embedded views and field formulas, not to mention having way too many fields on them period. You had me so stoked because I have a perfect application for a fade-in technique (a duplicate name pop-up on a contact form), but I think the notes client would just explode in a smoking heap if I did that many refreshes close together on that form.
Thanks for the post though. I love seeing new content on the blog.

Chris Blatnick said...

Thanks, guys!

@Keil...I agree about the refreshes and there must be a way around it that I just haven't had a chance to figure out yet. When you use formula, you only have to use @Command([RefreshHideFormulas]) to trigger the row change, but that didn't work in Script. I'm hoping one of you smart people out there can tell me what I did wrong.

Charles Robinson said...

Tommy Valand has some Javascript options, too: They work in both the Notes client and the Web.

Tommy Valand said...

@Charles: Thanks for the link :)

The yellow fade technique only works with a frameset. As far as I remember, the only part of a page you can control the background color of with JS is the body of a page/form. The fading part of the (yellow fade) demo is a separate form.

Regarding Javascript. You can use Javascript to click a hidden formula-button. This button can do @Command([RefreshHideFormulas]).

I did a simple test, and it seems to work. I put this code on the button that triggers the fade-in.
var remainingRefreshes = 6;
var visibleTab = 0;
window.setFadeAndRefresh = function(){
if( remainingRefreshes === 0 ){ return; }
var f = document.forms[0];
if( f.ShowMessage.value != '1') { f.ShowMessage.value = '1'; }

visibleTab += 1;
remainingRefreshes -= 1;
f.$MessageTable1.value = visibleTab;;
setTimeout( "setFadeAndRefresh()", 50 );

I also added a hidden button named "refreshHideFormulas" that does the @Command([RefreshHideFormulas]).

Chris Blatnick said...

@Tommy...nice job! :-)

So I started doing this with formula language (and did get it to work, although you can't control the timing too accurately), and then switched over to LotusScript, but not before thinking about trying it with JavaScript. However, several people, including myself, have been burned with JS memory leaks in the client. Do you think this would suffer from similar issues?

belgort said...

Very nice technique Chris!

Tommy Valand said...

@Chris: I banged my head a lot against setInterval in the Client during my NotesFX-days. But I haven't used setTimeout enough in the Client to say either way.

It shouldn't be hard to rewrite my example code to do 100/1000/1000 iterations. Shorter intervals may (or may not) increase the probability of leaks.

quintessens said...

Nice work, but on the other hand it makes me sad that it is hard coded on the form. Something that we seems not to be able to get away from in LN.

Think how wonderfull this would be if we could achieve the same thing by going through the DOM structure of a page/form/document??

Hurry IBM for allowing us to really create dynamic interfaces for the LN client!

Nate said...

I hate you for thinking of this before me. :-P

Curt said...

Thanks and Merry Christmas!

quintessens said...

(I continue to find new uses for this design element....I love it!).

I use the versatile programmable tabbed table for showing/hiding rich text fields (or sections of a form). it looks nicer than sections. The disadvantage is however when using for richt text fields, the rich text fields is in an additional table. Notes only allows 8 levels of tables in tables...

Corey Davis said...

This is one of those moments where I hit myself on the head and say "Doh! I should have figured this out before!" Very very nice one! I will most certainly be stealing, err leveraging this technique for my own code! ;)

Hans Fokine said...

Brilliant as always, Cris! Great work.