Tuesday, February 11, 2014, 1:49:33 PM
Here’s a question that comes up quite frequently: I’m running a backend request that takes a few seconds to run – how do I show a simple ‘wait’ message while this request runs?
There are a number of ways to approach this problem including some more complex async processing concepts that offload processing to a separate process to avoid tieing up Web Connection instances that are running. But, if your process is a one off process that rarely runs and doesn’t take a huge amount of time (my cutoff is usually in the 10-20 second range before I’d consider async operations), there’s a simple UI solution that might make waiting a little easier to deal with.
It’s the UI Stupid
The problem with long running submit requests is that when the user clicks a button to submit a form, they likely expect something to happen right away. If your app however, just sits around waiting for a response to come back, the user is very likely to think that something is wrong. The most likely response will be that they either wander off without waiting for completion, or in a typical UI will try to click the Submit button again. For the latter, where you had one small problem before, you now have multiple small problems that can very easily tie up your server because those requests are slow.
So a UI solution to this should address two things:
- Providing some sort of UI that lets the user know that something’s happening
- Prevents the user from clicking the submit button again
It turns out doing this is pretty simple. Let’s look at an example. The following is a simple form that has a submit button.
I’m using a Web Connection Web Control Framework button here, but the same rules apply if you’re using Web Connection templates or script and plain HTML controls – the WCF just makes the code more self-contained.
<form id="form1" runat="server">
<ww:wwWebErrorDisplay runat="server" id="ErrorDisplay" />
<h2>Slow Submit Operation</h2>
The following button click will take a few seconds to run.
If your code doesn't do anything, the application will appear
to simply be unresponsive but the existing form is still active
daring the user to click the submit button again... and again...
<ww:wwWebButton runat="server" id="btnSubmit" Text="Submit to Server"
On the server side the FoxPro code in the button simply waits for a few seconds and dumps a message to the ErrorDisplay control on the page.
WAIT WINDOW "Hold on - processing..." TIMEOUT 10
this.ErrorDisplay.ShowMessage("Waited for 10 seconds.")
This forces the server to essentially ‘hang’ for 10 seconds to simulate some long running task.
If you run this now by hitting the Submit button, you’ll see that the UI doesn’t change after the submit button is hit. The HTML DOM pointer changes to a spinning pointer, but otherwise the UI stays the same. The Submit button is still active so you can actually press it again, and if you do you generate another hit against the server.
Ok, so this UI works for quick requests that process in under 1 second, but for anything over a few seconds this becomes problematic.
The HTML DOM has a form submission event that fires when an HTML form is submitted. When you click the Submit button the form.submit() event is fired and we can capture this event to modify the browser UI by showing a progress dialog.
I’m going to be using the Web Connection client modal dialog control that makes this super easy. Modal dialogs show a black overlay on the page and overlay whatever content you apply it to ontop of this black overlay. The overlay basically prevents access to the underlying document – so you can’t click the submit button again – and provides nice visual feedback that the content is not accessible. You can then overlay some content of your choice.
Here I use a rotating image gif and some text. Here’s what it looks like:
The markup for this simple HTML looks like this and I simply add this to the bottom of the HTML page.
<div id="WaitDialog" class="hidden" style="text-align: center">
<img src="css/images/loading_black.gif" />
<div style="margin-top: 10px; color: white">
Note this uses the westwind.css stylesheet for the hidden CSS class and the loading_black.gif from the CSS folder.
I’m loading jQUery and ww.jquery.js from the scripts folder. jQuery provides the base functionality for document parsing and ww.jquery.js provides the modal dialog feature (and a lot more modular functionality built-ontop of jQuery).
The .modalDialog() jQuery plug-in is attached to the element you want to display centered on the screen on top of the darkened background. Here I’m using the default modal dialog behavior without any options parameters, but there are a host of options available to customize the modal popup and you can see some more examples on the Web Connection sample site.
Using a modal overlay like this is a simple solution to longish but not overly long server side requests where you want to prevent users from just walking off or double clicking buttons. Capturing the form submission can also be even simpler – for example you could simply disable the submit button, or change the submit button text into something like “Processing…” and disabled rather than displaying the overlay which is a good idea for shorter requests where it might be jarring to have a modal dialog pop up and then disappear immediately.