Archive

Archive for September, 2012

SharePoint: How to close a Modal Dialog Window

September 18th, 2012 Admin 6 comments

    How to create/open a Modal Dialog Window (along with the passing parameters into it) is shown in the post SharePoint: How to pass parameters into a Modal Dialog Window and then access them. This post, in turn, will be devoted to closing the Modal Dialog Window.


Modal Dialog Window is based on IFrame element

As you probably know, Modal Dialog Windows are implemented through IFrame elements. So, when saying “open a web page in a Modal Dialog Window” we mean to load another Html document into an IFrame element of the current Html document. Let’s call the page, which hosts the IFrame element, a Parent-page and the page loaded into the IFrame – a Child-page. From the Child-page the IFrame element containing it can be reached by means of the window.frameElement DOM-object.


Methods to close Modal Dialog Window

To close a Modal Dialog Window we can employ the methods shown below. Note that the methods become accessible through the window.frameElement after the dialog has been opened/created, in other words, SP Dialog framework extends the window.frameElement object by adding these custom methods.


SP.UI.ModalDialog.commonModalDialogClose

This method allows to close the current (the most recently opened) Modal Dialog Window, passing a desirable DialogResult and a return value into the dialogReturnValueCallback method. This method is mostly intended to be called from the Parent-page. Below is a sample of possible use. Let’s assume that within the Parent-page we have two JavaScript functions, OpenChildDialog and CloseChildDialog, and a Html link, which opens the dialog and sets up the delayed closing of it. The functions:

function OpenChildDialog() {
  var opt = {
    url : 'childPage.aspx',

    dialogReturnValueCallback:
      function (res, retVal) {
        alert(retVal);
      }
  };
  SP.UI.ModalDialog.showModalDialog(opt);
}
function CloseChildDialog() {
  //SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Closed with OK result');
  SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel,'Cancelled');
}

The link:

<a href="#" onclick="OpenChildDialog(); setTimeout(function(){ CloseChildDialog(); }, 10000); return false;">
Open dialog
</a>

So, clicking on the link you open the dialog, which will be closed automatically in 10 seconds unless you close it manually before.


window.frameElement.commonModalDialogClose

Technically, it’s the same commonModalDialogClose function, but accessible through the window.frameElement object. Unlike the previous one the given function is intended to be called from within the Child-page (opened in the dialog). The main advantage of the window.frameElement.commonModalDialogClose is that it can be invoked from within a SharePoint-independent page, which knows nothing about SP Dialog framework and its js-files. Before showing an example, let’s take a look at the SP.UI.DialogResult enumeration, which is situated in the SP.UI.Dialog.js file:

SP.UI.DialogResult.prototype = {
    invalid: -1,
    cancel : 0,
    OK     : 1
}

Use of SP.UI.DialogResult inside the SharePoint-independent page will cause getting of ‘SP’ is undefined error message. So, we have to use the real values of SP.UI.DialogResult as the enumeration apparently will be undefined. So, below is an example of use. Let’s assume that to open the dialog we use the same OpenChildDialog method listed above and, somewhere within the Child-page, we have two Html links to close the dialog with OK or cancel as the result. The links:

<a href="#" onclick="window.frameElement.commonModalDialogClose(1 /*OK*/, 'Closed with OK result'); return false;">
Commit
</a>
<a href="#" onclick="window.frameElement.commonModalDialogClose(0 /*cancel*/, 'Cancelled'); return false;">
Cancel
</a>


window.frameElement.commitPopup

The given function closes the dialog and passes SP.UI.DialogResult.OK as the result. It also allows to pass a return value into the dialogReturnValueCallback method. Like the previous one, window.frameElement.commitPopup is intended to be called from within the Child-page, which may be SharePoint-independent. Traditionally, an example implies that the dialog is opened by the OpenChildDialog method and contains a Html link:

<a href="#" onclick="window.frameElement.commitPopup('Closed with OK result'); return false;">
Commit
</a>

Another good example of use of window.frameElement.commitPopup is demonstrated in the article – SharePoint: SPLongOperation inside a Modal Dialog Window.


window.frameElement.cancelPopUp

The window.frameElement.cancelPopUp closes the dialog as well. However, as opposite to commitPopup, it returns the SP.UI.DialogResult.cancel as the dialog result and doesn’t allow to pass a return value. It should be called from within the Child-page, which may be SharePoint-independent. The opened dialog can be closed, for example, by the Html link, which is placed within the Child-page and defined as the following:

<a href="#" onclick="window.frameElement.cancelPopUp(); return false;">
Cancel
</a>


Summary

Let’s take a look at a summary table below. The SharePointless column indicates whether the appropriate function can be used from within a SharePoint-independent page. The Intended to be placed within column shows where the appropriate function should be put in, in either Parent- or Child-pages. Note that there are no strict rules where the functions must be used, all of them, in some conditions, can be used on any pages.

Function & Description SharePointless Intended to be placed within
SP.UI.ModalDialog.commonModalDialogClose

Closes the most recently opened Modal Dialog Window, passes a DialogResult and a return value into the dialogReturnValueCallback.

NO Parent-page
window.frameElement.commonModalDialogClose

Closes the most recently opened Modal Dialog Window, passes a DialogResult and a return value into the dialogReturnValueCallback.

YES Child-page
window.frameElement.commitPopup

Closes the dialog, passes SP.UI.DialogResult.OK as the result and a return value into the dialogReturnValueCallback.

YES Child-page
window.frameElement.cancelPopUp

Closes the dialog and passes SP.UI.DialogResult.cancel as the result.

YES Child-page

SharePoint: SPLongOperation inside a Modal Dialog Window

September 10th, 2012 Admin 3 comments

    In one of my posts I wrote about using SPLongOperation. When a lengthy operation has been accomplished the usual behavior of the SPLongOperation is to redirect user to another web page. In SharePoint 2010, however, the web page containing long operation could be opened in a Modal Dialog Window. In this case, instead of redirection, we often need to close the dialog right after the long operation is completed.


SPLongOperation.EndScript method

Fortunately, the SPLongOperation class provides us with a new useful method, EndScript, which notifies server that the operation has been completed and sends a specified JavaScript into the user browser. A typical use is presented below:

using (SPLongOperation operation = new SPLongOperation(this.Page))
{
    operation.LeadingHTML  = "Long operation";
    operation.TrailingHTML = "Please wait while the long operation is in progress";

    operation.Begin();

    // the code of the lengthy operation
    ...

    // check if the current page is opened in dialog
    if(SPContext.Current.IsPopUI)
        // signal that the lengthy operation is completed and
        // send a script to close the current dialog
        operation.EndScript("window.frameElement.commitPopup();");
    else
        // signal that the lengthy operation is completed and
        // redirect to another page
        operation.End("anotherPage.aspx");
}

The window.frameElement.commitPopup() script allows to close the dialog and pass SP.UI.DialogResult.OK as the result. The SPContext.Current.IsPopUI flag indicates if the current page is going to be opened in dialog and should be rendered in an appropriate way.


Wrapper around SPLongOperation

In the same old post I demonstrated a handy wrapper around SPLongOperation. Taking into account the dealing with dialogs, the updated version of the wrapper looks as follows:

public class SPLongOperationExecutionParams
{
    public string LeadingHtml  { get; set; }
    public string TrailingHtml { get; set; }
    public string RedirectUrl  { get; set; }
    public bool   CloseDialog  { get; set; }
}

public static void DoInSPLongOperationContext(SPLongOperationExecutionParams executionParams, Action action)
{
    if (HttpContext.Current.CurrentHandler is Page)
    {
        using (SPLongOperation operation = new SPLongOperation(HttpContext.Current.CurrentHandler as Page))
        {
            operation.LeadingHTML  = !string.IsNullOrEmpty(executionParams.LeadingHtml)  ? executionParams.LeadingHtml  : "Long operation";
            operation.TrailingHTML = !string.IsNullOrEmpty(executionParams.TrailingHtml) ? executionParams.TrailingHtml : "Please wait while the long operation is in progress";

            operation.Begin();

            if (action != null)
                action();

            try
            {
                if (executionParams.CloseDialog)
                    operation.EndScript("try { window.frameElement.commitPopup(); } catch (e) {}");
                else
                    operation.End(executionParams.RedirectUrl, SPRedirectFlags.DoNotEndResponse | SPRedirectFlags.Trusted, HttpContext.Current, "");
            }
            catch (ThreadAbortException)
            {
                // This exception is thrown because the SPLongOperation.End
                // calls a Response.End internally
            }
        }
    }
    else
        throw new ApplicationException("Couldn't find a host page!");
}

Below is an example of how to use it:

void startLongOperationButton_Click(object sender, EventArgs e)
{
    SPLongOperationExecutionParams executionParams = new SPLongOperationExecutionParams()
    {
        LeadingHtml  = "Creation of a new list item",
        TrailingHtml = "Please wait while the item is being created",
        CloseDialog  = SPContext.Current.IsPopUI, // if the page is in a dialog, the latter will be closed
        RedirectUrl  = "anotherPage.aspx" // if it's not a dialog, user will be redirected to that page
    };

    DoInSPLongOperationContext(executionParams, delegate()
    {
        // the code of the lengthy operation
        Thread.Sleep(5000);
    });
}