How to close SharePoint modal wait screen after postBack when page is in dialog mode

————–
UPDATE: The code originally posted doesn’t work with IE. You get a “Can’t execute code from a freed script” error and the wait screen is not removed after postBack. The code works fine in Chrome and Firefox.

I now have updated this post with new code to work with both IE and Chrome. I haven’t tested with Firefox, but it should also work.
————–

You can use SharePoint 2010’s JavaScript method SP.UI.ModalDialog.showWaitScreenWithNoClose() to show a modal wait screen that looks like below:

This can be a nice alternative to SPLongOperation when you need to perform time consuming operations. You can attach the call to this method on the client click event of a button as below:

<asp:Button ID="btnDoWork" Text="Do Some Work" runat="server" OnClientClick="javascript:SP.UI.ModalDialog.showWaitScreenWithNoClose('Please Wait', 'Please wait as this may take a few minutes...', 76, 330);" OnClick="btnDoWork_Click"/>

If this was on a normal application page this would work fine. The wait screen would be displayed, the server-side code of the button will be fired, and when the page comes back from postBack, the wait screen would be removed.

If the same page was being displayed in dialog mode however, the wait screen would not be removed after the postBack is completed. This is because the postBack only updated the IFRAME that displays our application page and the wait screen does not belong to that IFRAME.

The showWaitScreenWithNoClose() actually returns a reference to the wait screen, and we can call the close() method on this variable to close the wait screen. The problem is we need to store this variable in the right place for it to survive the postBack – and that place is the window.frameElement object.

Change the button to as below:

<asp:Button ID="btnDoWork" Text="Do Some Work" runat="server" OnClientClick="javascript:showWaitScreen();" OnClick="btnDoWork_Click"/>

Next add the following JavaScript to the page, e.g. in the PlaceHolderAdditionalPageHead section:

————–
UPDATE: The code below has been updated to work with IE. Review the in-code comment below.
————–

<script language="javascript">
	function showWaitScreen() {
		/*When our page is in dialog mode, then window.parent is the parent page of the dialog. When it is NOT
	in dialog mode, then window.parent is just the current page. window.parent is never null.

	When our page is in dialog mode, we need to execute showWaitScreenWithNoClose in the context of the parent page. This
	is because when the postBack completes on our dialog, the context of our dialog will be destroyed, and calling close
	on the wait screen object will result in a "Can't execute code from a freed script" error in IE (works OK in Chrome though).

	When our page is NOT in dialog mode, the wait screen will be removed when the postBack completes and the page is reloaded
	anyway, i.e. we don't have to worry about it.

	We also need to store the waitDialog variable in a place that will survive the postBack. This is the parent page
	when our page is in dialog mode. When our page is NOT in dialog mode, then we don't really care - so just put it anywhere.

	Because we are calling eval under the parent page's context, the waitDialog below is stored in the correct place.
	*/
	window.parent.eval("window.waitDialog = SP.UI.ModalDialog.showWaitScreenWithNoClose('Please Wait', 'Please wait as this may take a few minutes...', 76, 330);");
	}

In the server-side code of the button, emit JavaScript to retrieve the waitDialog variable and call the close() method as below:

————–
UPDATEThe code below has been updated to work with IE. Review the in-code comment below.
————–

protected void btnDoWork_Click(object sender, EventArgs e)
{
	//Simulate a time consuming operation
	System.Threading.Thread.Sleep(3000);

	//Emit the script that will close the wait screen. We only need to do this when
	//the app page is in dialog mode, in which case window.frameElement will NOT be null
	this.ClientScript.RegisterStartupScript(this.GetType(), "CloseWaitDialog", @"
<script language='javascript'>
	if (window.frameElement != null) {
		if (window.parent.waitDialog != null) {
			window.parent.waitDialog.close();
		}
	}
</script>");
}
Advertisements

About Bernado

Based in Australia, I am a freelance SharePoint and Dynamics CRM developer. I love developing innovative solutions that address business and everyday problems. Feel free to contact me if you think I can help you with your SharePoint or CRM implementation.
This entry was posted in ModalDialog, SharePoint 2010, SharePoint JavaScript API and tagged . Bookmark the permalink.

10 Responses to How to close SharePoint modal wait screen after postBack when page is in dialog mode

  1. Tomas says:

    Hello Bernardo!
    I have tried your code but after postback im getting exception in JavaScript: ‘Can’t execute code from a freed script.’ on waitDialog.close(); Any ideas what can cause this?

  2. Works perfectly in a modaldialog. Thnx!!

  3. Alfonso T says:

    Thanks a lot! Works like a charm.

  4. Joel H says:

    Thanks so much. I was really struggling with this, but this worked perfectly.

  5. Mallikarjun says:

    Hi Bernado,
    I am trying to show wait modal wait screen during long running operation, and modal dialog is not appearing. In my case long operation is happening at client side and i want to show SharePoint no close model dialog. I have posted a question in stack overflow http://stackoverflow.com/questions/27274772/sharepoint2013-modal-dialog-box-is-not-loading
    Let me know if you have any input on this.

  6. Yathiraj says:

    Thank you so much Bernado. you saved my day 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s