Wednesday, May 5, 2010

LaunchPickerTreeDialog in SharePoint 2010, and the Importance of ScopeToWeb

You know what I hate – when people start a blog, and then go months or years without publishing a topic. And then they come back and say “sorry I was gone, I’ve been busy, blah blah blah it won’t happen again – this time I’m really committed to updating this blog regularly” – whatever. I may take another 15 months off after this post, but here’s something interesting I just discovered about the behavior of the LaunchPickerTreeDialog javascript function included in SharePoint that I think is worth sharing here since it definitely falls under the “voodoo magic” category.

LaunchPickerTreeDialog – what it does

If you’re unfamiliar with LaunchPickerTreeDialog, others have written about it extensively so I won’t go into the details of how it works here. Google is your friend. I will tell you that it prompts the user to select a website, list, or document library using a graphic interface rather than forcing them to type in a URL. It’s well worth your effort to figure it out and use it in your solutions.

What’s New in SharePoint 2010?

So I’m testing some of my custom code on a site collection that was upgraded from SharePoint 2007 to SharePoint 2010, and I discover that when I call LaunchPickerTreeDialog on my site in SharePoint 2010, it is only showing lists and libraries from the current site. In SharePoint 2007, the same code would display all sub-sites as well in the tree view that the dialog box displays. What’s up with that?

image (click to enlarge)

Where’d my sites go? I know I have sub-sites, and I know they showed up in SharePoint 2007:

image (click to enlarge)

My first step towards figuring out what was going on was to load up IE8’s debugger and look at the script tab. The script I'm looking for is in PickerTreeDialog.js – that hasn’t changed from 2007. I put a breakpoint on the first line of code in the LaunchPickerTreeDialog function:

image (click to enlarge)

I was wondering if this was different from the 2007 version, so I did the same thing in my SharePoint 2007 environment. Here’s what that looked like:

image (click to enlarge)

Notice the difference? Aside from the obvious code difference inside the function, the signature changed in the 2010 version: has two new parameters:

  • ScopeToWeb
  • RequireCT

And now, in a blatant attempt to trick the search engines help people find this post, ScopeToWeb, ScopeToWeb, ScopeToWeb. That’s the key. What does this parameter do? What is the purpose? Where is it documented? No clue. But what I do know is that if you pass in an empty string to this parameter, you get your sub-sites. Pass in anything else, you don’t get your sub-sites. Hopefully someone will add in the comments exactly what this parameter is supposed to do, but for now, that’s all you need to know to fix your code.

Of course, if you’re still supporting SharePoint 2007, you can’t just go adding parameters to the LaunchPickerTreeDialog call because you’ll code won’t work in 2007. So you need to do a version check (blah) to make sure you’re only adding this parameter when you’re running on SharePoint 2010. There are several ways to do that – here’s what I chose to do:

   1: if (Microsoft.SharePoint.Administration.SPFarm.Local.BuildVersion.Major >= 14)
   2: {
   3:     // SharePoint 2010 has two new parameters - 
   4:     // ScopeToWeb and RequireCT. ScopeToWeb needs
   5:     // to be empty string to show sub-sites in the tree
   6:     sb.AppendLine("LaunchPickerTreeDialog('CbqPickerSelectListTitle','CbqPickerSelectListText','listsOnly','',serverUrl, '','','','/_layouts/images/smt_icon.gif','',callbackList,'','');");
   7: }
   8: else
   9: {
  10:     sb.AppendLine("LaunchPickerTreeDialog('CbqPickerSelectListTitle','CbqPickerSelectListText',");'listsOnly','',serverUrl, '','','','/_layouts/images/smt_icon.gif','',callbackList);");
  11: }

Wow, do I hate that. Someone rescue me and tell me there’s a better way in the comments. But in the meantime, if you’re running your LaunchPickerTreeDialog in SharePoint 2010 and trying to figure out why you can no longer see your sub-sites in the tree view, now you know – pass in an empty string for the ScopeToWeb parameter.


  1. Thx Andrew,

    It really helped me a lot.
    It seems like you don't have many blogposts - keep them coming ;)

  2. Here's my solution (heavily modified version of Jan's SmartPart v1.3, works great in 2010). This is part of RenderToolPart override...

    // the customized link lookup invoker (uses native SharePoint client-side objects)
    link_func_name = "mso_launchListSmtPicker_" + Guid.NewGuid().ToString().Replace('-', '_');
    string last_picker_id = "lastSelectedListSmtPickerId_" + Guid.NewGuid().ToString().Replace('-', '_');
    output.WriteLine("[blog won't accept script tag w/CDATA]");
    output.WriteLine("var " + last_picker_id + " = '';");
    output.WriteLine("function " + link_func_name + "(listTextBoxID) {");
    output.WriteLine(" if (!document.getElementById) return;");
    output.WriteLine(" var listTextBox = document.getElementById(listTextBoxID);");
    output.WriteLine(" if (listTextBox == null) return;");
    output.WriteLine(" var serverUrl = '\u002f';");
    output.WriteLine(" var callback = function(results) {");
    output.WriteLine(" if (results == null || results[1] == null || results[2] == null) return;");
    output.WriteLine(" " + last_picker_id + " = results[0];");
    output.WriteLine(" var listUrl = '';");
    output.WriteLine(" if (listUrl.substring(listUrl.length-1) != '/') listUrl = listUrl + '/';");
    output.WriteLine(" if (results[1].charAt(0) == '/') results[1] = results[1].substring(1);");
    output.WriteLine(" listUrl = listUrl + results[1];");
    output.WriteLine(" if (listUrl.substring(listUrl.length-1) != '/') listUrl = listUrl + '/';");
    output.WriteLine(" if (results[2].charAt(0) == '/') results[2] = results[2].substring(1);");
    output.WriteLine(" listUrl = listUrl + results[2];");
    output.WriteLine(" listTextBox.value = listUrl;");
    output.WriteLine(" };");
    output.WriteLine(" LaunchPickerTreeDialog(");
    output.WriteLine(" 'CbqPickerSelectListTitle',");
    output.WriteLine(" 'CbqPickerSelectListText',");
    output.WriteLine(" 'websLists',");
    output.WriteLine(" '',");
    output.WriteLine(" serverUrl,");
    output.WriteLine(" " + last_picker_id + ",");
    output.WriteLine(" '', '', '/_layouts/images/smt_icon.gif', '', callback");
    #if SP2010
    // 2010 has two more undocumented magic parms -- woohoo
    // thanks to Andrew Moore -- that slacker! he needs to write more blogs...
    output.WriteLine(" /* SP2010 undocumented parms */");
    output.WriteLine(" , '', ''");
    output.WriteLine(" );");
    output.WriteLine("[close script tag]");

  3. Thanks to David Dolan, who sent an email describing the purpose of the ScopeToWeb parameter. He traced the code and discovered this parameter does just what it says - scopes the list to the current sub-web instead of the root of the site. I didn't get a chance to test this out, but I'll take his word for it. Hopefully this will save someone some time.