Open a Link in SharePoint 2010’s Modal Dialog

Applies To: SharePoint 2010

Recently I’ve been customizing the XSLT of some of my XsltListViewWebParts. Getting all of that to work is worth another post in itself, but I wanted to talk briefly about a small frustration I had. I was customizing an announcement’s list part and I stripped out most of the nearly 1700 lines of XSLT used by default. However, one of the things I liked was being able to open the announcement in the modal dialog (sometimes called the Lightbox or the popup window):

Some searching through the autogenerated XSL for my view, I came across this section in the LinkTitleNoMenu.LinkTitle template:

<a onfocus="OnLink(this)" href="{$FORM_DISPLAY}&amp;ID={$ID}&amp;ContentTypeID={$thisNode/@ContentTypeId}" onclick="EditLink2(this,{$ViewCounter});return false;" target="_self">
	<xsl:call-template name="LinkTitleValue.LinkTitle">
		<xsl:with-param name="thisNode" select="$thisNode"/>
		<xsl:with-param name="ShowAccessibleIcon" select="$ShowAccessibleIcon"/>
	</xsl:call-template>
</a>

I’m going to dissect what’s happening in terms of XSL for the next couple of paragraphs. If you’re just looking for the format needed, skip to the Link Format section.

Basically this is the link that gets generated inside the view’s table. The call-template element is used to fill the contents (link text), but I already had that covered and am mostly just interested in the formatting of the link to do the modal dialog magic.

Some quick experimentation shows that the onfocus call was not needed for the popup (This is what causes the menu to display and the box around the row in a standard view). Also not needed is the target=”_self” since this is equivalent to leaving the target attribute out entirely. There are really just 2 key items:

HREF

This is the URL to display in the modal dialog. In this case, it’s generated using a number of variables defined automatically. The $FORM_DISPLAY is the absolute path to the item display page. The $ID is generated using a simple Template call (we’ll come back to this). and the $thisNode/@ContentTypeId is pulling the ContentTypeId attribute from the current Row element in the $AllRows variable populated by the dsQueryResponse XML. For now, all you need to know is that it is automatically finding the display form URL and populating the necessary ID and ContentTypeId query strings for the specific item URL.

OnClick

This calls the EditLink2 javascript method defined in Core.js. This extracts the link with the webpart’s ID ($ViewCounter) and shows it in the modal dialog. Then it returns false to prevent the browser from following the link like normal.

Trying to implement this exactly in my code wasn’t too hard. Unfortunately, it wouldn’t load in the popup and always just opened the page directly. Doing some searching, I came across a quick explanation and solution on technet. The EditLink2 function attempts to use a window object referenced by my webpart’s id ($ViewCounter). Whatever code sets this all up wasn’t firing in my XSL causing the window reference to be NULL and making the function default to just opening the link. Instead of tracking it down somewhere in the default generation, I did something similar to the proposed solution on technet.

Link Format

Ultimately my goal was to have a link generated using this format:

<a href="http://mysharepoint.com/sites/thesite/_layouts/listform.aspx?PageType=4&amp;ListId={SomeGUID}&amp;ID=SomeID&amp;ContentTypeID=SomeContentTypeID" onclick="ShowPopupDialog(GetGotoLinkUrl(this));return false;">Click Me</a>

So, I’m using the same link generation (but this could be any link). The real difference is that instead of calling EditLink2 I’m calling ShowPopupDialog. For the URL, I’m using a technique found in the EditLink2 method of calling GetGotoLinkUrl which extracts the URL from the link element.

XSL Implementation

To get this to work in XSL, you can do something similar to this:

<xsl:for-each select="$AllRows">
	<xsl:variable name="thisNode" select="."/>
	<xsl:variable name="link">
		<xsl:value-of select="$FORM_DISPLAY" />
		<xsl:text>&amp;ID=</xsl:text>
		<xsl:call-template name="ResolveId">
			<xsl:with-param name="thisNode" select ="$thisNode"/>
		</xsl:call-template>
		<xsl:text>&amp;ContentTypeID=</xsl:text>
		<xsl:value-of select="$thisNode/@ContentTypeId"/>
	</xsl:variable>

	<a onclick="ShowPopupDialog(GetGotoLinkUrl(this));return false;">
		<xsl:attribute name="href">
			<xsl:value-of select="$link"/>
		</xsl:attribute>
		<xsl:text>View Announcement</xsl:text>
	</a>
</xsl:for-each>

In the above XSL, we’re looping through each row returned by your view’s CAML query. We setup a link variable that builds the full HREF attribute in lines 3-11. The thing to note is the call to the ResolveId template to pull the item’s ID from the row. This is a standard template that will automatically be referenced as long as you keep the standard includes (main.xsl and internal.xsl).

Then we generate the actual html link in lines 13-17 using the $link variable we created above. This could be consolidated some, but hopefully it’s relatively easy to follow in this format.

That’s it! Now you can generate those links using XSL or follow the link format to make them on your own (like in a content editor web part).

Using Feed Parameters in the RSS Viewer Web Part

Applies To: SharePoint 2010, RSS Viewer Web Part

The RSS Viewer web part is an Out of the Box SharePoint web part that can really add to your site by allowing you to integrate dynamic content directly on your pages from other sites in your environment (requires either anonymous or kerberos authentication) or from sites all over the web. You can add it like any other web part (Located under Content Rollup) and get it going quickly by setting the Feed URL property.

There are feeds all over the web and getting the URL for these is generally straight forward (click the RSS icon/button and then copy the URL) and I’ll let you figure that part out. If you’re simply grabbing a news feed from Yahoo! or someplace, then you’re probably done. There’s a lot that can be done with the formatting of the feed’s content using XSLT, but that’s out of scope for this particular article.

However, what if you would like something a little bit more dynamic? Some feeds are very customizable using query string parameters to automatically filter what you want. A good example might be pulling the SEC Filings from the Securities and Exchange Commission website. You can get a feed of Google’s Filings using the following URL:

http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001288776&type=&dateb=&owner=exclude&start=0&count=40&output=atom

There are several parts to this URL beyond the base of http://www.sec.gov/cgi-bin/browse=edgar (They begin after the ? mark and are separated by the & and take the format of name=value). The one I’m most interested in is the CIK (Central Index Key). This is what tells the feed to return Google’s filings. (As a bonus, for publicly traded companies you can replace that 10 digit number with their Ticker Symbol: GOOG for Google).

Great! Now you can generate a feed for multiple companies’ SEC filings using multiple RSS Viewer web parts. But what if you only want one web part that can switch which company is being displayed? That’s exactly where Feed Parameters come in.

Configure the Filter

Like many web parts, the RSS Viewer web part allows connections to other parts including the filter web parts. Most any of the Filter parts will work depending on what you’re trying to accomplish. An obvious example would be to use the SharePoint List Filter web part to pull company ticker symbols in from another SharePoint list and use a drop down to select which filings to view. My preference, however, is to use a Query String (URL) Filter part so that I can hook it to multiple parts to create a dynamic page that can be linked as if it were many pages. I’ll show you how to hook that up, but the basic concept is the same for any of the parts – Filter some value and send it to the RSS Viewer.

Add a Query String (URL) Fitler part to your page (Located under Filters):

From the tool pane for the Query String (URL) Filter part the key values can be found in the Filter section. The Filter Name property should match the query string property name in your RSS Feed’s URL. So in this case our Filter Name is CIK. The Query String Parameter Name is the name of your own query string to the page. In this case I’ve set it to Symbol. The Default Value is optional, but is generally a good idea so that if the page is accessed without a query string, the feed still shows something. I’ve set ours to GOOG (Although I could easily have set it to Google’s CIK value since the SEC feed is pretty flexible):

It’s also a good idea to also give your filter web part a better name than the default since this is the name you’ll see when setting up the connection. This is just the Title property in the Appearance section. I’ve set mine to Symbol Filter. Press OK to save your changes.

Setup the Connection

Using the drop down menu for the RSS Viewer Web Part choose Connections > Get Feed URL From > Symbol Filter (If you don’t have a Connections menu, select Edit Web Part and look again):

If everything has been successfully connected the Query String (URL) Filter should look similar to this when editing the page (it isn’t visible normally):

If you add ?Symbol=MSFT to the end of your page’s URL (If your page is http://app/site/SitePages/Home.aspx then the filtered url would be http://app/site/SitePages/Home.aspx?Symbol=MSFT) then the RSS Viewer should now be showing Microsoft’s latest SEC Filings. Just kidding! There’s one little gotcha that’s very easy to fix.

If a feed parameter is already set in the RSS Viewer’s URL, then any feed parameters from connected web parts are ignored. In this case, this is because we pasted the sec.gov feed’s URL in directly including the CIK=0001288776 section of the URL. To fix this, just delete this part of the URL. So our new feed URL will look like:

http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&type=&dateb=&owner=exclude&start=0&count=40&output=atom

Now try that filtered URL (Your page + ?Symbol=MSFT) again and you should see Microsoft’s SEC Filings:

This quickly gives us a lot of flexibility. This works great for all sorts of feeds allowing you to filter or customize your feeds before they ever get to you; and all on the fly.

Conclusion

So here’s the summary of what you need to do to get this working:

  • Add an RSS Viewer web part and set the Feed URL to the address of the feed you want to pull. Remove the dynamic parameter you want to set.
  • Add a Filter web part and configure it to pass the filter name as the name of the dynamic filter in the feed URL
  • Connect the RSS Viewer web part to the Filter web part using the Feed Parameter connection
  • Shout Abracadabra every time anyone uses a dynamic view of the page

The RSS Viewer part can be a very powerful part of your page allowing dynamic content without any custom code.

Hiding the Recently Modified Section in SharePoint 2010

Applies To: SharePoint 2010, CSS

I recently added a Wiki Pages Library to a site for some end users and they really like it. However, they had a seemingly straight forward request to hide the Recently Modified section that was showing up above the Quick Launch:

This may come up as a requirement when using some of the default templates that automatically include a Site Pages library or if a user adds a new page and is prompted to create the Site Pages library automatically.

I assumed there was a setting somewhere either for the library or the site in order to turn off this “feature”. Nope. Somebody decided that this was not only a feature everyone would want, but it was so great they put it in the left actions content place holder (PlaceHolderLeftActions) of the master page – which puts it on top of the quick launch.

Some quick searching turned up “solutions” that suggested setting the contentplaceholder’s visible property to false within the master page. This works; however, it also hides anything that uses that contentplaceholder such as some of the Blog tools. This makes it a very poor candidate for a farm wide branding solution.

The other option is to use some CSS (cascading style sheets). If you’re pushing this as part of a branding solution, just add this to one of your style sheets:

.s4-recentchanges{
	display:none;
}

That’s it. Microsoft provided a very handy class just for this section and some quick use of the CSS Display property takes care of it.

So what if this is just a one off thing – You aren’t currently using any custom branding or just want it to affect one site? For a single site you can use SharePoint Designer 2010 to open the master page (v4.master – choose edit in advanced mode). Then somewhere on the page add the following:

<style>
.s4-recentchanges{
	display:none;
}
</style>

If you just want to apply it page by page, you can put the style directly in the HTML of the page. Since this is a Wiki page, choose to edit the page (Under the Page Ribbon assuming you have the rights). Click anywhere on the page and choose the HTML drop down and pick Edit HTML Source:

Somewhere on the page add the following:

<style>
.s4-recentchanges{
	display:none;
}
</style>
You can also do this in a content editor web part using the same Edit HTML Source option.

If you don’t hide this thing, I would suggest editing the master page to at least move that contentplaceholder below the quicklaunch so your navigation doesn’t get all wonky or at least displaced by a relatively unused feature.