How to display the wait or hourglass cursor

244 views
Skip to first unread message

Randy Stewart

unread,
Dec 19, 2007, 1:32:52 PM12/19/07
to InterSys...@googlegroups.com

This would seem to be simple but it is not.  

 

The customer wants to be able to display a wait cursor when a user clicks a button. The wait cursor will display but not at the correct time. For example, if the process that is started by clicking the button takes 10 seconds then instead of displaying the wait cursor instantly and for a 10 second duration when the button is clicked, the wait cursor displays 10 seconds AFTER the button is clicked and then only briefly. I hope there is an easier and more universal way to accomplish this than what I am about to describe below.

 

I have worked out one way of displaying a wait cursor on a page after a user clicks a button. The problem is that it works on my setup but NOT on the customer’s setup. To get this to work I had to wrap the document.body.style.cursor statements in Zen Methods and then invoke the ZenMethods from the javascript. You would think that you can just put the document.body.style.cursor statements directly in the javascript method but doing that is what causes the wait cursor to display 10 seconds AFTER the button is clicked.

 

Here is the way I have worked out to do this:

 

First, create two ZenMethods

 

/// Set the cursor style to hourglass.
ClassMethod
WaitCursor() [ ZenMethod ]
{
           &js<document.body.style.cursor = "wait";>
}

/// Restore the cursor style to default.
ClassMethod
DefaultCursor() [ ZenMethod ]
{
           &js<
document.body.style.cursor = "default"; >
}

 

Second, call the ZenMethods at the appropriate place in the javascript

 

/// Event handler for when a user clicks on the 'Order Reports' button.
Method
btnOrderReports(form) [ Language = javascript ]
{

      this.WaitCursor();

 

      try
      {

            // user code here

      }
      catch(ex)
      {
              alert("Error: " + ex.name + "\n" + "Error Message: " + ex.message);
      }

 

      this.DefaultCursor();
}

 

If it makes a difference I am running Windows with IIS local on my pc and the browser (FF or IE) also local on my pc. The customer is running Linux with Apache on a server and the browser is running on a windows pc on the same network as the server but not the same pc as the server.

 

To restate what I am looking for, I hope there is an easier and more universal way to accomplish this than what I have described.  I have even gone as far as to make a custom button class that sets the wait cursor when a custom attribute, wait, is set to true. This has not worked out so well either.

 

This is a very small thing but it is also very annoying to the customer’s users. When they get no feed back to indicate the button was clicked, they click it again and again with very undesirable results. You know how that goes. This has been an issue for a long time now and I would like to remove this negative from the customer’s experience.

 

Thanks.

 

Randy L Stewart

Sales Engineer

InterSystems Corporation

 

Randy....@intersystems.com

214-551-5781

 

 

Joe DeSantis

unread,
Dec 19, 2007, 1:58:03 PM12/19/07
to InterSys...@googlegroups.com
The customer wants to be able to display a wait cursor when a user clicks a button. The wait cursor will display but not at the correct time. For example, if the process that is started by clicking the button takes 10 seconds then instead of displaying the wait cursor instantly and for a 10 second duration when the button is clicked, the wait cursor displays 10 seconds AFTER the button is clicked and then only briefly. I hope there is an easier and more universal way to accomplish this than what I am about to describe below.

I am not sure that this is something that browsers were designed to do, though maybe there is a CSS hack that can accomplish it.

Rule one for this type of thing is: find another web page that does what you want and see how they do it.
Rule  two is: web applications are not client/server applications; somethings you have to do thing differently....

Thanks


Ernesto Fischer

unread,
Dec 19, 2007, 3:43:19 PM12/19/07
to InterSys...@googlegroups.com
Hi Randy,

To have immediate effect the cursor style change must be done in a javascript method so it is executed directly by the browser. Setting the style in a ZenMethod it will be run as a hyperevent to Cache server and it will only take effect after quitting the method when all data in tcp buffer is flushed to the browser that will execute the style change.

-Ernesto

Dale du Preez

unread,
Dec 21, 2007, 10:05:28 AM12/21/07
to InterSys...@googlegroups.com
Randy,

The one thing you've got to be really careful of are synchronous methods to the server, i.e. calls to ZenMethods with return values. If you have some Javascript something like
    var someVar = zenPage.ZenMethod()
you won't get ANY other interaction with the page to be processed until the ZenMethod returns (including a previous WaitCursor call). (I tried this with Hang 5 on the server, so I saw how much the client freezes up.) So subsequent alerts etc only occur after the ZenMethod returns. Even the button stays in a clicked/"down" state in the meantime. Unfortunately, you CAN click on other buttons without any immediate effect, but those clicks all get processed on your return from the server, which can cause all sorts of problems if you have a lengthy server-side call.

If at all possible, I would suggest you try to move away from a synchronous approach and use &js<> or Objectscript equivalents in your ZenMethod to update the page whenever you've done your processing. That way you can set your cursor to wait, and avoid client-side behaviour that semi-locks the page in a way that doesn't make sense to the user.

Dale

P.S. I have been working on this issue with your customer, but I think that this is something other people using Zen should know about.
-- 
Dale du Preez
Support Advisor
Dale.d...@intersystems.com
+1 (617) 621 0700
Please CC sup...@intersystems.com with regard to any active problems so that you can receive assistance should I be unavailable.

Randy Stewart

unread,
Dec 21, 2007, 12:35:14 PM12/21/07
to InterSys...@googlegroups.com

Thanks for the additional clarification, Dale. This definitely squares with what I have seen. I would love to see a swim lane diagram of the client-server communications for the various combinations of calls (js->ZenM asynch, js->ZenM synch, js->js, ZenM->js, callback->js, etc). That would make it much easier to see how things work under the covers. There are many excellent diagrams in the Zen documentation (like the one that shows the initial sequence that displays a Zen page in a browser window) but I have not seen one that shows the underlying operations that occur for an event on the page such as:

button.onclick()

myJSMethod()

myZenASynch()

myJSMethod()

myZenSynch()

myJSMethod()

myOtherJSMethod()

Return

 

A visual trace of several different patterns of calls like this would be a treat.

 

As you said, if you set the cursor to wait in a js method and set it back to default in an asynch ZenMethod then that works fine. Other combinations are not so good. One thing I like to do in ALL cases is to disable the button that was clicked. That seems to ALWAYS work and at least the user cannot click multiple times (some users just double-click everything). The only problem with this is that the user can mistake a ‘busy’ button with a ‘hung’ button. They don’t really know which it is until the button is re-enabled. The key is feedback. The users of our applications are typically not techies and they have become used to feedback so they know their pc has not locked up (if pc’s never locked up, then the feedback would not be necessary but I will stay away from that rant).

 

I understand that Web programming is not the same as our old true client-server programs of the past (as Joe pointed out in an earlier post). However, the promise of Zen, AJAX, etc. is that developers and users can get the look and feel of the old true client-server programs in a Web based application. Getting that promise fulfilled may involve some clever tricks (yes, hacks).  If the wait cursor just does not do it then other approaches might work.

 

I saw a post called ‘Building a Better Busy Box’ (http://blogs.crsw.com/mark/articles/642.aspx) as I was looking for hacks. I have been able to get this approach to work on plain old html pages but have not been able to make it into a working Zen component yet so it will work on a Zen Page (I have successfully modified other Zen components but am not advanced enough to create one from scratch yet). The thing I like about this animated approach is that it not only tells the user to wait but since it is ‘busy’ it gives comfort that something is indeed occurring in the background. I also hope that if it (or something like it) is a Zen component that it can be universal solution and not subject the issues seen with the ‘wait’ cursor.

 

It may be a while before I figure out if I can build the component and see if it fills the gap. Of course, there might be some clever people reading this who beat me to the punch or even find a better approach. You will not hurt my feelings if you do.

 

Randy L Stewart

Sales Engineer

InterSystems Corporation

 

Randy....@intersystems.com

214-551-5781

 

Andreas

unread,
Jan 10, 2008, 7:16:50 AM1/10/08
to InterSystems: Zen Community
The origin problem has something to do with the sequence JavaScript
handles the commands.
The cursor does not getting set to "wait" even this command is before
the server call. JavaScript obviously tries to execute the server call
before modifying the client/browser. This makes it neccessary to
modify the browser first, than call the server method.

Try this:
Method callServerMethod(...) [ Language = javascript ]
{
zenPage.showWait();
window.setTimeout("zenPage.ServerMethod(...)",1);
window.setTimeout("zenPage.clearWait()",1);
}

Method showWait() [ Language = javascript ]
{
//set corsor style, display loading picture, or whatever
}

Method clearWait() [ Language = javascript ]
{
//set corsor style, hide loading picture, or whatever
}

Unfortunetelly it does not work with animated loading gifs because the
browser still freezes (synchronous call).
But with simple "please wait" information it should work fine (so does
for me).

Of cource changing it to an asynchrounous call might be the better
solution, but sometimes not wanted ;-)

Andreas

Reply all
Reply to author
Forward
0 new messages