Creating Mega Drop Down Navigation in SharePoint with jQuery – Part 1 » To The Point

Creating Mega Drop Down Navigation in SharePoint with jQuery – Part 1

August 10th, 2009 by tdietz Leave a reply »

This is part one in a three part series for implementing Mega Drop Down navigation in SharePoint 2007.  The topics covered are:

Part 1 – Tables, Unordered Lists, and SharePoint
Part 2 – Custom Control Rendering
Part 3 – Hooking it all up with jQuery

Although the styling and navigation had to be scrubbed, a screen cast of the final solution can be found here:

 

Providing users with rich navigation is the latest trend in web design and the hottest technique today is the Mega Drop Down.  Rather than providing single column navigation, Mega Drop Downs present menu information in a rich, two-dimensional format:

image

As you can see in the above example, the drop down menu provides navigation links in multiple columns (and even has a slick transparency effect).  Sites with Mega Drop Downs are popping up all over the web and usability guru Jakob Nielsen has written a great article describing the benefits.

For most sites, implementing a Mega Drop Down is fairly straightforward and most of the effort focuses around CSS.  If you have ever customized navigation in SharePoint, you are well aware that things are easy enough—but only to a point.

Out-of-the-box, SharePoint uses the SharePoint:AspMenu class that inherits from the standard ASP.NET asp:Menu control.  This control provides the ability to be skinned and can be customized through the use of CSS and ItemTemplate support, but at its core, it still is a <TABLE> based control and isn’t flexible enough to radically change its appearance.

Rather than relying on <TABLE> based navigation, CSS unordered lists <UL> can easily be used to implement navigation.  I want to keep this post focused on SharePoint and not CSS, so if you want to read up on how to create the shell for the Mega Drop Down, I recommend starting with this article,   To summarize the concepts, we essentially create a nested set of unordered lists:

&lt;ul id=’topNav’>
  <li>Employee Services</li>
    <div id='mdd'>
      <h3>Benefits</h3>
       <ul id='subNav'>
        <li>401(k) Information</li>
      </ul>
     </div>
   </li>
</ul>

 

The ‘topNav’ <ul> represents the top navigation that is displayed horizontally.  The <div> is the actual Mega Drop Down itself and contains one or more ‘subNav’ <ul> elements that represent the sub-menu items.  The <h3> tag is used as a category heading so we can group menu items together (more on that in part 2).

CSS is used to style the outer ‘topNav’ so elements are displayed inline.  We also hide the <div> as it should only appear when you hover over an <li> within ‘topNav’.  I applied some extra styling, but so far, navigation should look something like this:

 

image

 

We’ve defined the structure of the menu and navigation, but up until now, it has all been static.  To make this work in SharePoint, we have to provide a method of displaying navigation dynamically.  There are several different methods of replacing the default navigation, and for this solution, I opted to create a custom navigation control.   A great overview of the various options can be found here.  Earlier I mentioned that out of the box, SharePoint uses the asp:Menu control to render menu items.  This is a standard data-bound control that references a DataSource for rendering navigation.  If you look inside default.master with SharePoint Designer, you’ll see how all this works:

 

<SharePoint:AspMenu
  ID="TopNavigationMenu"
   DataSourceID="topSiteMap"
   runat="server"
   ...
/>
<asp:SiteMapDataSource
  ShowStartingNode="False"
   SiteMapProvider="SPNavigationProvider"
   id="topSiteMap"
   runat="server"
  StartingNodeUrl="sid:1002" />

 

The SiteMapDataSource is a standard ASP.NET data source control and is widely used in ASP.NET web development.  If you are not familiar with how navigation works in ASP.NET, MSDN has a great overview.  The important concept to note here is the SiteMapProvider property and the SPNavigationProvider value.  SPNavigationProvider is a class that follows the standard provider model and essentially is the code that retrieves the navigation hierarchy from SharePoint.  SPNavigationProvider handles all the mundane tasks of retrieving the data and security trimming results so users don’t see links to sites that they may not have access to.

As mentioned, we are scrapping the SharePoint:AspMenu control because it renders <TABLE> based navigation and are replacing it with a shiny, new <UL> based navigation control.  Other than being difficult to pronounce (and type), HierarchicalDataBoundControl is the underlying class that asp:Menu uses to retrieve its data.  We are simply bypassing asp:Menu and its bias for <TABLE> layouts and going directly at the data.   Our custom control’s declaration looks something like this

:

public class MegaDropDown : HierarchicalDataBoundControl
{
   protected override void PerformDataBinding()
   protected override void Render(HtmlTextWriter writer)
}

 

The two methods that we need to override are PerformDataBinding() and Render().

The PerformDataBinding method is where we will retrieve our data from the data source (indirectly through SPNavigationProvider) and then (ultimately) parse the hierarchical data that is returned.  Initially, the GetData() method is called to…wait for it…get the data.  In general, these controls can represent many different flavors of data.  Since we are working with hierarchical data, GetData() happily returns a reference to a HierarchicalDataSourceView object that represents a view into the navigation.  A data source view is similar to a database view and has the ability to provide a subset of data based on a query.  Coincidentally, HierarchicalDataSourceView points to a nested list of the navigation data.  For our purpose, there isn’t a need a need to filter results and a simple call to the Select() method will suffice.

Having a reference to the view is great, but what we really want is an enumerable reference to the actual data (remember, the view is just an abstraction of the data).  Having the IHierarchyData interface gives us so many options (well, not really) but since everyone likes enumerable objects, getting to the data is only a two-step process.  Once we call GetHierarchyData(), we only need to invoke IHierarchyData.GetChildren() to access the enumerable data

Surprisingly it is very straightforward and only involves a dozen or so lines of code::

protected override void PerformDataBinding()
{
   base.PerformDataBinding();

   // Do not attempt to bind data if there is no data source set.
   if (!IsBoundUsingDataSourceID && (DataSource == null))
      return;

   HierarchicalDataSourceView view = GetData("");

   if (view == null)
      throw new InvalidOperationException("Cannot get any data.");

   IHierarchicalEnumerable enumerable = view.Select();

   if (enumerable != null)
   {
      IHierarchyData data = enumerable.GetHierarchyData(rootItem);
      IHierarchicalEnumerable newEnum = data.GetChildren();
   }
}


Next up is the HTML rendering and actual control implementation…Part 2 – Custom Control Rendering

Advertisement

11 comments

  1. cactork says:

    Hi there tom,
    When d you think that this tutorial series will be ended?

    Very promising by the way!
    Regards,

  2. tdietz says:

    Hopefully very soon. I have been with a few clients but I plan to have the second article ready in a few days.

    Thanks!

  3. cactork says:

    Great news tom!!

    Thank’s again 4sharing,
    cya!

  4. marc says:

    Any chance on parts 2 and 3 being posted soon, I am looking to make something like this for a site I am working on.

  5. Rishi says:

    HI tom, Good work. Can you pls complete the remaining, i am eagerly waiting for this…

  6. tdietz says:

    Sorry for the delay, part 2 is finally posted.

  7. BobC says:

    Looking foward to part 3… the wrap-up.

  8. lex says:

    Great Post! Where is rootItem initialized?

  9. tdietz says:

    rootitem is the top level node returned from
    HierarchicalDataSourceView

  10. marina says:

    hi,
    Great post, thank you.
    I was wondering if this will work for SP2010 also?

Trackbacks /
Pingbacks

  1. ÁghyBlog » links for 2009-10-27

Leave a Reply