Tips & Tricks: SharePoint 2010 Modal Dialogs

UPDATE: Check out my follow up post for SharePoint 2013 Modal Dialogs.

In this post I’ll be presenting some tips and tricks with regards to SharePoint 2010 modal dialogs. I hope these examples will save you some time by not having to reinvent the wheel and help keep your custom components’ user experience consistent with the OOTB SharePoint 2010 experience.

DISCLAIMER: Some of the code below uses private functions/methods of the SP2010 API. They have been stable throughout the Service Packs and Cumulative Updates, but nothing is guaranteed. If you’re working on stuff for SP2013, you’ll also want to read this post as well.

Opening and Closing Modal Dialogs

Opening and closing SharePoint modal dialogs has been blogged to death already so here are a few resources for that:

The first thing that I wanted to point out is the SP.UI.ModalDialog.RefreshPage method. If dialog requires updating information on the parent page, which you may not have access to, you can use this method to force a page refresh if the dialog returns a success value. An example of this is when your dialog results in column values being updated on a SP list view.

function myShowDialog() {
  var options = {
    url: '[YOUR URL HERE]',
    dialogReturnValueCallback: myDialogCallback
  };
  SP.UI.ModalDialog.showModalDialog(options);
}

function myDialogCallback(dialogResult, data)
{
  if (dialogResult = SP.UI.DialogResult.OK) {
    //DO YOUR DIALOG SUCCESS STUFF HERE
  }
  // this will refresh your page if dialogResult is successful
  SP.UI.ModalDialog.RefreshPage(dialogResult);
}

The second tip around opening a modal is that if you pass in a null value for the title property for any of the open methods, the modal dialog will use the title of the page that is loaded inside of it.

Loading Message & Wait Screen

I see a lot of custom solutions on SharePoint implement their own loading message and interface blockers even though SP2010 already provides this functionality through the SP.UI.ModalDialog client-side API.

SP.UI.ModalDialog.showWaitScreenWithNoClose is a method that allows you to show a loading message of your choice. You can specify the loading message’s title, content, height and width. For example:

SP.UI.ModalDialog.showWaitScreenWithNoClose('Loading...', 'Please wait while the content loads.', 60, 270);

Displays:
Loading modal using SP.UI.ModalDialog.showWaitScreenNoClose()

But if you look carefully, you’ll notice SharePoint’s loading message has a different look!
SharePoint 2010's internal loading message

Spot the differences? Why I need a maximize button on the former is beyond me.

You can display the latter message by calling the private SP.UI.ModalDialog.$2O() method. This gets you the above message and as an added bonus, the text displayed is localized to the user’s settings.

You can also replicate the look with your own messsaging by calling another private method with a specific set of parameters. You can create your own wrapper function as such:

function myShowWaitScreenWithNoClose (title, message) {
  return SP.UI.ModalDialog.$1I_1(title, message, false, false, null, null, 270, '12px 12px 4px 6px', 0);
}

myShowWaitScreenWithNoClose('Your Title Here...', 'Your custom loading message.');

Displays:
Loading message using private SP.UI.ModalDialog.$1I_1() method.

Resizing Modal Dialogs

The modal dialog will automatically resize to its content’s dimensions if you do not specify width and/or height parameters when opening the modal. However, the SP.UI.ModalDialog API does not provide a method to resize the modal. This is problematic when you have dynamic content or elements within your modal that cause the modal’s page dimensions to change. The modal does not resize, and users are either forced to use the scroll bars to view the new content, or they are left with a bunch of white space where content has been removed.

Perhaps my Googling skills are not up to snuff, but I have yet to find a complete example for dynamically resizing a SharePoint 2010 modal. There are a few posts that correctly point to using the dialog object’s autoSize() method, but then they fail to reposition the dialog or account for situations such as the resized dialog being larger then the browser view port.

Below is a version of the resize code we use in Collabware CLM. We traced the code found in SP.UI.Dialog.js, and this leverages all of the OOTB code that SharePoint uses for resizing the dialog on page load. I’ve changed some of the internal variable names from the OOTB names for readability purposes.

// wrapper which ensures SP.UI.Dialog.js is loaded before re-size fires.
// (if you need to trigger a re-size in your init scripts as the JS library is loaded asyncronously)
function resizeModalDialog() {
  SP.SOD.executeOrDelayUntilScriptLoaded(_resizeModalDialog, 'sp.ui.dialog.js');
}

function _resizeModalDialog () {
  // get the top-most dialog
  var dlg = SP.UI.ModalDialog.get_childDialog();

  if (dlg != null) {
    // dlg.$S_0 - is dialog maximized
    // dlg.get_$Z_0() - is dialog a modal
    if (!dlg.$S_0 && dlg.get_$Z_0()) {
      // resize the dialog
      dlg.autoSize();

      var xPos, yPos, //x & y co-ordinates to move modal to...
      win = SP.UI.Dialog.get_$1(), // the very bottom browser window object
      xScroll = SP.UI.Dialog.$24(win), // browser x-scroll pos
      yScroll = SP.UI.Dialog.$26(win); // browser y-scroll pos

      //SP.UI.Dialog.$1d(win) - get browser viewport width
      //SP.UI.Dialog.$1c(win) - get browser viewport height
      //dlg.$2_0 - modal's DOM element

      // caculate x-pos based on viewport and dialog width
      xPos = ((SP.UI.Dialog.$1d(win) - dlg.$2_0.offsetWidth) / 2) + xScroll;

      // if x-pos is out of view (content too wide), re-position to left edge + 10px
      if (xPos < xScroll + 10) {
        xPos = xScroll + 10;
      }

      // caculate y-pos based on viewport and dialog height
      yPos = ((SP.UI.Dialog.$1c(win) - dlg.$2_0.offsetHeight) / 2) + yScroll;

      // if x-pos is out of view (content too high), re-position to top edge + 10px
      if (yPos < yScroll + 10) {
        yPos = yScroll + 10;
      }

      // store dialog's new x-y co-ordinates
      dlg.$T_0 = xPos;
      dlg.$U_0 = yPos;

      // move dialog to x-y pos
      dlg.$m_0(dlg.$T_0, dlg.$U_0);

      // set dialog title bar text width
      //dlg.$H_0 - dialog title text SPAN
      //dlg.$6_0 - dialog title bar
      dlg.$H_0.style.width = Math.max(dlg.$6_0.offsetWidth - 64, 0) + 'px';

      // size down the dialog width/height if it's larger than browser viewport
      dlg.$2B_0();
    }
  }
}

About Sing Chan
SharePoint Interface Architect at Collabware Systems

9 Responses to Tips & Tricks: SharePoint 2010 Modal Dialogs

  1. Pingback: Buta no Ie » SharePoint 2010 Modal Dialog Tips & Tricks

  2. Pingback: Tips & Tricks: SharePoint 2010 Modal Dialogs | UXWeb.info

  3. Lew Cain says:

    I am new to SharePoint 2010 so forgive my ignorance. I am using a custom template that does not autoSize, your blog describes my issues perfectly. Where would I place the code snippet above?

    • Sing Chan says:

      Hi Lew,

      I would say you want to have the autosizing code in some sort of commonly used Javascript file. You can register the script file using the ScriptLink control declaratively or ScriptLink.Register programmatically (or even use Script on Demand if you’re adventurous).

      If you’re creating a custom application page (layouts page), make sure you’re inheriting from either LayoutsPageBase or UnsecuredLayoutsPageBase as they’ll register the required OOTB scripts.

      Call the resizeModalDialog whenever you need to resize the page.

  4. Pingback: Tips & Tricks: SharePoint 2013 Modal Dialogs | Collabware Blog

  5. Pingback: Buta no Ie » SharePoint 2013 Modal Dialog Tips & Tricks

  6. Pingback: Dynamic Forms for SharePoint: Now with side-by-side « SharePoint JavaScripts

  7. Ofer Gal says:

    I am getting error: Microsoft JScript runtime error: Object doesn’t support property or method ‘$2O’

    What is missing?

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

Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: