Geeks With Blogs

Tangible Thoughts SharePoint, MOSS? and all the other questions

OK; I have been holding out on you guys.

A couple of months back I was talking to Sig, and we were discussion how the entire navigation story in SharePoint can be improved. This was the discussion that started this off for me. But he happened to show me a couple of alternatives that he was working on. And this one really caught my eye. I'm talking about the 'Go To' menu on the top left. Now Sig's version there is a DVWP with some super JavaScript to crawl the DOM and build the contents of the Quick Launch in the form of an IE Menu. The beauty of the Go To menu for me is that, you can hierarchically group items, and jump to them without having to endure many post-backs or page loads.

Now here's my spin on it. Remember the Tab Navigation through a DVWP I showed you guys sometime back. Well along those lines, wont be neat to build that Go To menu based on a list or document library.

Here's what I got.

OK so how do you do it? First off the SharePoint menu above (or ie:menu as I call it) is already built in to SharePoint. you only need to call the proper js function, and have the menu contents (in xml) loaded on the page. More information on the ie:menu can be found on this post by Dustin Miller.

So building that on a DVWP is almost the same as the Tab Strips; just using a different JavaScripts.

So whats the run down? Well basically my implementation uses each column in the list as level in the menu, so for instance the first level of the menu is actually a column called Category that is used to group a bunch of links. Here's a what the list looks like (yes I am using a list, you can do a document library if you want ;) )

Now the DVWP; Its a simple DVWP, I have grouping set on the Category Column with Show Groupheader and Groupfooter both set (You will see the reason for this later). That actually gives us 4 call templates in the Xsl corresponding to the 3 main sections of the menu (i.e. the link to launch the menu, the first level of the menu, and the second level of the menu). 4 because grouping header has a call template, and grouping footer has another call template.

the xsl templates are

<xsl:template name="dvt_1"> <- The main section responsible for calling the other templates.

<xsl:template name="dvt_1.body"> <- The template responsible for most of the body rendering.

<xsl:template name="dvt_1.groupheader0"> <- The template responsible for displaying the groupheader

<xsl:template name="dvt_1.groupfooter0"> <- The template responsible for displaying the groupfooter

So in the dvt_1 template you would initialize most of you JavaScript variables, place a link to the pull down menu, and create a layer that would host the menu contents (i.e. in xml format)

<xsl:template name="dvt_1">
<xsl:variable name="StyleName">Table</xsl:variable>
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
<xsl:variable name="RowCount" select="count($Rows)"/>
<xsl:variable name="IsEmpty" select="$RowCount = 0"/>
<xsl:choose>
<xsl:when test="$IsEmpty">
<xsl:call-template name="dvt_1.empty"/>
</xsl:when>
<xsl:otherwise>

<!-- Create the link to the pull down menu -->

<div class="ms-HoverCellInActive" onmouseover="this.className='ms-HoverCellActive'" onmouseout="this.className='ms-HoverCellInActive'">

<table>

<tr>

<td class="ms-vb" align="right">

<a id="MSO_GoMenuLink" title="Go Menu" style="CURSOR: hand" onclick="MSOWebPartPage_OpenMenu(MSO_GoMenu, this);"

tabindex="0">

Go to: <img alt="Go to" src="/_layouts/images/menudark.gif" align="absBottom" />

</a>

</td>

</tr>

</table>

</div>

<script type="text/javascript">

// Initialize the JavaScript variable that will

// store the menu contents

var strMenu = "";

strMenu = "&lt;menu id='MSO_GoMenu' class='ms-SrvMenuUI'&gt;";

</script>

<!-- Call the template to render the body -->

<xsl:call-template name="dvt_1.body">

<xsl:with-param name="Rows" select="$Rows" />

<xsl:with-param name="FirstRow" select="1" />

<xsl:with-param name="LastRow" select="$RowCount" />

</xsl:call-template>

<!-- Create a layer to host the menu conents on the page -->

<Div id="goMenuLayer"></Div>

<script type="text/javascript">

// Close the Menu Xml tag

strMenu += "&lt;/menu&gt;";

// Replace all escaped angle braces

var lt = "<a></a>";

var gt = "<a></a>";

lt = lt.substr(0,1);

gt = gt.substr(2,1);

strMenu = strMenu.replace('&lt;',lt);

strMenu = strMenu.replace('&gt;',gt);

// Write the menu contents onto the layer

var x = document.getElementById("goMenuLayer");

x.outerHTML = strMenu;

</script>


</xsl:otherwise>
</xsl:choose>
</xsl:template>


In the dvt_1.body where normally the list item contents of rendered in to table cells, create a ie:menuitem node and append it to strMenu

<xsl:template name="dvt_1.body">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:for-each select="$Rows">
<xsl:variable name="NewGroup_0">
<xsl:choose>
<xsl:when test="not ($dvt_groupfield)">
<xsl:value-of select="ddwrt:NameChanged(string(@Category), 0)" />
</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="0" />
<xsl:when test="not($dvt_groupfield) and (not($NewGroup_0='') and position() &gt;= $FirstRow and position() &lt;= $LastRow or ($FirstRow = position()))">
<xsl:if test="not ((position()=1) or (position()=$FirstRow))">
<xsl:call-template name="dvt_1.groupfooter0">
<xsl:with-param name="fieldtitle">Category</xsl:with-param>
<xsl:with-param name="fieldname">Category</xsl:with-param>
<xsl:with-param name="fieldvalue">
<xsl:choose>
<xsl:when test="$NewGroup_0=''">
<xsl:value-of select="@Category" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$NewGroup_0" />
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="fieldtype" select="'text'" />
<xsl:with-param name="nodeset" select="$Rows" />
<xsl:with-param name="groupid" select="'0'" />
<xsl:with-param name="displaystyle" select="'auto'" />
</xsl:call-template>
</xsl:if>
<xsl:call-template name="dvt_1.groupheader0">
<xsl:with-param name="fieldtitle">Category</xsl:with-param>
<xsl:with-param name="fieldname">Category</xsl:with-param>
<xsl:with-param name="fieldvalue">
<xsl:choose>
<xsl:when test="not (@Category)">
<xsl:value-of select="' '" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@Category" />
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="fieldtype" select="'text'" />
<xsl:with-param name="nodeset" select="$Rows" />
<xsl:with-param name="groupid" select="'0'" />
<xsl:with-param name="displaystyle" select="'auto'" />
<xsl:with-param name="imagesrc" select="'/_layouts/images/minus.gif'" />
<xsl:with-param name="alttext" select="'collapse'" />
<xsl:with-param name="altname" select="'expand'" />
<xsl:with-param name="hidedetail" select="false()" />
</xsl:call-template>
</xsl:when>
</xsl:choose>
<xsl:variable name="BreakOut">

<xsl:choose>
<xsl:when test="not($dvt_groupfield) and position()=$LastRow+1">
<xsl:value-of select="ddwrt:NameChanged('', -1)" />
</xsl:when>
<xsl:otherwise>BreakOut</xsl:otherwise>
</xsl:choose>

</xsl:variable>
<xsl:variable name="KeepItemsTogether" select="false()" />
<xsl:variable name="HideGroupDetail" select="false()" />
<xsl:variable name="GroupStyle" select="'auto'" />
<xsl:if test="(position() &gt;= $FirstRow and position() &lt;= $LastRow) or $KeepItemsTogether">
<xsl:if test="not($HideGroupDetail)" ddwrt:cf_ignore="1">

<script type="text/javascript">

// Append the Menu item tag to the menuContents String

var title = '<xsl:value-of select="@Title" />';

var url = '<xsl:value-of select="@Url" />';

var icon = '<xsl:value-of select="@Icon"></xsl:value-of>';

strMenu += '&lt;ie:menuitem title="'+ title +'" onMenuClick="window.location.href=\''+ url +'\'" iconSrc="' + icon + '" &gt;' + title + '&lt;/ie:menuitem&gt;';

</script>

</xsl:if>
</xsl:if>

<xsl:choose>
<xsl:when test="0" />
<xsl:when test="($NewGroup_0 or true()) and not($dvt_groupfield)">
<xsl:if test="(position() = count($Rows) and ($LastRow=position() or $KeepItemsTogether)) or (not($KeepItemsTogether) and position() &gt; $LastRow and not($BreakOut='BreakOut')) or (not($KeepItemsTogether) and position() = $LastRow+1) or (position()=last() and $LastRow &gt; last())">
<xsl:call-template name="dvt_1.groupfooter0">
<xsl:with-param name="fieldtitle">Category</xsl:with-param>
<xsl:with-param name="fieldname">Category</xsl:with-param>
<xsl:with-param name="fieldvalue">
<xsl:choose>
<xsl:when test="position() = count($Rows) and ($LastRow &gt;= position() or $KeepItemsTogether) or not($NewGroup_0)">
<xsl:value-of select="@Category" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$NewGroup_0" />
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="fieldtype" select="'text'" />
<xsl:with-param name="nodeset" select="$Rows" />
<xsl:with-param name="groupid" select="'0'" />
<xsl:with-param name="displaystyle" select="'auto'" />
</xsl:call-template>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="dvt_1.empty">
<xsl:variable name="ViewEmptyText">There are no items to show in this view.</xsl:variable>
<table border="0" width="100%">
<tr>
<td class="ms-vb">
<xsl:value-of select="$ViewEmptyText" />
</td>
</tr>
</table>
</xsl:template>


Then to create each submenu you require an xml structure as follows

<ie:menuitem type="submenu">

<ie:menuitem type="label">Sub Menu Name</ie:menuitem>

<ie:menuitem ..............................

Each submenu item node comes here

................./ie:menuitem>

</ie:menuitem>

So how you go about creating that is, in the dvt_1.groupheader template you append the purple bit to the JavaScript menu string. in dvt_1.groupfooter you append the blue bit to the JavaScript Menu string.

<xsl:template name="dvt_1.groupheader0">
<xsl:param name="fieldtitle"/>
<xsl:param name="fieldname"/>
<xsl:param name="fieldvalue"/>
<xsl:param name="fieldtype"/>
<xsl:param name="nodeset"/>
<xsl:param name="groupid"/>
<xsl:param name="displaystyle"/>
<xsl:param name="imagesrc"/>
<xsl:param name="alttext"/>
<xsl:param name="altname"/>
<xsl:param name="hidedetail"/>

<script type="text/javascript">

// Write the tag to form a submenu in the menu contents

var title = '<xsl:value-of select="$fieldvalue" />';

var icon = '<xsl:value-of select="@Icon" />';

strMenu += '&lt;ie:menuitem title="Test" type="submenu" &gt;&lt;ie:menuitem type="label" &gt;'+ title +'&lt;/ie:menuitem&gt;'

</script>

</xsl:template>

<xsl:template name="dvt_1.groupfooter0">
<xsl:param name="fieldtitle" />
<xsl:param name="fieldname" />
<xsl:param name="fieldvalue" />
<xsl:param name="fieldtype" />
<xsl:param name="nodeset" />
<xsl:param name="groupid" />
<xsl:param name="displaystyle" />


<script type="text/javascript">

strMenu += '&lt;/ie:menuitem&gt;';

</script>

</xsl:template>

Here is the DVWP code for your reference.

Another variation of this is to create the first level of the menu horizontally as links to call new submenus, that way you can create a menu system.

Posted on Tuesday, February 15, 2005 5:41 AM SharePoint | Back to top


Comments on this post: 'Go To' Menu - Sig's Style

# re: 'Go To' Menu - Sig's Style
Requesting Gravatar...
Hi...
How I Can without dvwp create 'Go To' Menu?
Left by IZASoufi on Apr 20, 2005 6:39 AM

# re: 'Go To' Menu - Sig's Style
Requesting Gravatar...
Great Post! It definitely got me thinking...

Try this...
In a Content Editor web part with a script like this would launch the menu from a SharePoint Portal main menu.

<script>

if (document.all && document.getElementById){
if (document.getElementById("NavCatH0_C_0")){
var navRoot = document.getElementById("NavCatH0_C_0");
navRoot.onmouseover = function() {
MSOWebPartPage_OpenMenu(MSO_MyMenuSedgwick_CMS_Home, this);
}
}
}

</script>

Change "NavCatH0_C_0" to "hrefPortal" and you could launch the menu from the "Up to <Portal name>" link on the My Site.

Of course you need another Data View web part like the in this post to create the menu. I created a SQL view in the Portal SITEDB to populate it but it's not my first choice.
Left by EGoforth on Jan 06, 2006 1:20 PM

# re: 'Go To' Menu - Sig's Style
Requesting Gravatar...
I reused some of your ideas for my own WSS Navigation...
Left by - B@rney on Jan 12, 2006 12:14 PM

# Sharepoint designer 2007 for wss 2.0
Requesting Gravatar...
Hi - This dropdown worked (when I updated my .aspx in notepad and imported it), but when I open it in SP designer 2007, then hit 'save' the " 's (only in the javascritpt) are converted to '&quot' and I get an error/ the dropdown doesn't work anymore (and it says there's a missing ; after the "s are automatically changed to '&quot's).

I tried shutting all the auto-stuff off in SP designer, but it hasn't helped.

Thanks
Left by srs on Jul 14, 2009 4:34 AM

# re: 'Go To' Menu - Sig's Style
Requesting Gravatar...
I tried this on Sharepoint 2003, but it doesn't work. After putting the code exactly as mentioned, when I open the page in browser, I get the Go To with an down arrow but when I click on it, I get "Error on page" and nothing happens..
Will this work with Sharepoint 2003 ?

Left by Rajat on Feb 09, 2010 7:22 PM

Your comment:
 (will show your gravatar)


Copyright © Tariq | Powered by: GeeksWithBlogs.net | Join free