XPages Tip: A modal waiting dialog for background processes.
Overdemanding?
I found a very simple solution to this problem. Sure there is more elegant solutions without dojo, but let me share it...
This is the main screen:
When user clicks the pointed button, there is a background process which would take 20-25 seconds. It is a long time for a web application. So we will somehow alert user that s/he has to wait a moment...
This is the initial code of the button:
<xp:button value="Puanla..." id="button1" styleClass="lotusBtn">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="termsPanel">
<xp:this.action><![CDATA[#{javascript:scoreTerm(termEntry.getDocument())}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
First we activate dojo and add needed modules in our XPage/custom control:
Now we will create our dialog div. You can create it anywhere in the page:
<div id="progressDialog" dojoType="dijit.Dialog" title="Please wait...">
<div>
<xp:image url="/inProgress.gif" id="image3"></xp:image>
</div>
</div>
We could use "xp:panel" tag here and set dojo attributes. It's a matter of preference. "inProgress.gif" is an animated image just to create an illusion of progress :)
Now we create a couple of client side javascript functions to show and hide this dialog. Here is a little trick. We don't want the dialog closable. Since I could not find a solution for 'non-closable' dialog, just googled and used this approach.
function scoringCompleted() {
dlg=dijit.byId("progressDialog");
dlg.hide();
}
function scoringStarted() {
dlg=dijit.byId("progressDialog");
dlg._onKey = function(){return false;};
dlg.show();
}
Here (in the bold part), we set a widget event to prevent "ESC" key. Escape keystroke stop loading of the page but does not close the dialog. If you are using a background agent for processing, escape will not stop the processing. Meanwhile, a little close icon is automatically placed on the title bar of the dialog. We should hide it as well. Put the following code to the CSS file.
#progressDialog .dijitDialogCloseIcon {display:none;}
Now, it comes to the crucial part. We want to show our dialog when background process started and hide it finally. We simply change the button code as follows:
<xp:button value="Puanla..." id="button1" styleClass="lotusBtn">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="termsPanel"
onStart="scoringStarted()"
onComplete="scoringCompleted()">
<xp:this.action><![CDATA[#{javascript:scoreTerm(termEntry.getDocument())}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
Result is something like that:
Remember, onStart and onComplete parameters will only work with partial refresh... You may also use onError for handling errors (like time out).
UPDATE!!!
Tim suggested far better solution to use dojox.widget.Standby. I updated start and complete functions and now there is no need to create divs or css on my page. It may be parameterized laterfor different purposes. Here are my functions:
function scoringStarted() {
if(this.fullStandby==null) {
this.fullStandby = new dojox.widget.Standby({
target: document.forms[0] // it was dojo.body() which creates a problem in some dojo versions.
});
document.body.appendChild(fullStandby.domNode);
fullStandby.startup();
}
fullStandby.show();
}
function scoringCompleted() {
if(this.fullStandby!=null) fullStandby.hide();
}
Target object can be customized for a region in screen...
Comments (10)
I don't think there is a solution for this. Because the page is not being loaded partially in XPages (not like a CGI app).
Maybe you may use a intermediate page for this ?
But it's a good idea, worth looking for...
@Serdar, I have an XPage that takes a few seconds to load and I want to display a loading prompt onload and oncomplete of the page.
@Tim, I imagine I can put something like this directly on the XPage to hide the dialog with XSP:addOnLoad:
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA
XSP.addOnLoad
(
function scoringCompleted()
{
dlg=dijit.byId("progressDialog");
dlg.hide();
}
scoringCompleted();
)
]></xp:this.value>
</xp:scriptBlock>
I'm having issues getting the dialog to show on page load. What event in XPages would be the best to use for this? Another scriptBlock?
Tim,
It's fantastic and elegant :)
I will use it and update the post. Thank you!
@Ryan, you can schedule any code to run when the page has finished loading by using the following pattern:
XSP.addOnLoad(function(){
// insert your code here
});
@Serdar, another dijit you may find interesting for this purpose is dojox.widget.Standby: it allows you to mask a specific portion of the page instead of modally blocking the entire page. For example, if you know a certain partial refresh event tends to be slow, you can mask just the partial refresh target for the duration of the event, while still allowing the user to interact with the remainder of the page.
Ryan,
Can you specify an example?
Another thing you can do is put a div above the image, and pass text to the function so you could do something like
scoringStarted('Loading')
scoringStarted('Saving Document')
scoringStarted('Updating Records...')
scoringStarted('Searching Records...')
and set the div content to the text to customize the message
Great Post, thank you for sharing!!