Overriding the SharePoint Modal Dialog Close Button

July 16, 2014

The close button in a SharePoint modal dialog is built into SP.UI.ModalDialog and simply closes the dialog. However, we would like to run some backend code before the dialog closes.  Attempts to use the $clearHandlers and $removeHandler SharePoint functions to remove the original click handler have failed.

Workaround:

1. Create an ASP.NET Button control and hide it with css:

<asp:Button
    ID="btnClose"
    runat="server"
    text="Close"
    CssClass="hidden" />
.hidden {
    display: none;
}

2. Add a backend click event handler containing the code we want to run before the dialog closes, as well as code to close the dialog afterwards:

btnClose.Click += this.BeforeClose;

protected void BeforeClose(object sender, EventArgse )
{
    // stuff to do before close
    [...]

    // close the dialog
    var script = string.Format("window.frameElement.commonModalDialogClose({0}, '{1}');", 0, "Cancelled the dialog");

    this.Page.Response.Clear();
    this.Page.Response.Write("<script type=\"text/javascript\">" + script + "</script>");
    this.Page.Response.End();
}

3. Using JavaScript, remove the original SharePoint close button, create a new one using the same HTML, then add a click event listener which triggers a click on the ASP.NET Button control:

jQuery(document).ready(function() {
    // find the newly created ASP.NET Button
    var aspCloseButton = jQuery('input[id*="btnClose"]');

    // find the SharePoint dialog button container
    var spButtons = jQuery('.ms-dlgTitleBtns', window.parent.document);

    // find the SharePoint dialog close button and remove it
    spButtons.find('a.ms-dlgCloseBtn').remove();

    // append a new close button
    spButtons.append('<a accesskey="C" class="ms-dlgCloseBtn" title="Close dialog">' +
                     '<span style="padding: 8px; height: 16px; width: 16px; display: inline-block;">' +
                     '<span class="s4-clust" style="height: 16px; width: 16px; position: relative; display: inline-block; overflow: hidden;">' +
                     '<img class="ms-dlgCloseBtnImg" style="left: -0px !important; top: -645px !important; position: absolute;" alt="Close dialog" src="/_layouts/15/images/fgimg.png" />' +
                     '</span></span></a>');

    // add a click event handler to the new close button
    spButtons.find('a.ms-dlgCloseBtn').on('click', function() {
        if (aspCloseButton.length)
            // trigger a click on the ASP.NET button
            aspCloseButton.click();
        else
            // failsafe if the ASP.NET button is not found
            window.frameElement.commonModalDialogClose(0, 'Cancelled the dialog');
    });