CSS friendly menus with ASP.NET Menu control, jQuery and Superfish
March 2009
I recently updated the design of this site (ie. conceptdevelopment.net.
The site already used the ASP.NET Sitemap control but the build-in table layout looked ugly and wasn't very cross-browser compatible.
Googling for references to people using the CSS Friendly Control Adapters didn't seem to turn up
much, other than questions on stackoverflow like this one
jQuery Menu and ASP.Net Sitemap
that didn't have a complete answer. In the end I've found a "hack" solution which is explained below - it is not 100% correct as
the arrows for submenus aren't appearing (for example).
You can see the menus 'working' on this page - I have attached a sample project (60Kb) that contains JUST the stuff you need to get them working.
 |
- CSSFriendly.DLL and .browser file come from Codeplex
- Superfish.css and .js must be downloaded from Joel Birch.
hoverIntent.js is optional and is also linked from Joel
- jQuery 1.2.6 is linked from Joel or get the latest (1.3.2)
from jQuery.com
In addition to those external items, I created
- Default.aspx (which is really just content)
- Test.master
- Test.sitemap with some links to make the menu
- and added to web.config
The contents of these files are shown below:
|
Test.sitemap
This is a regular ASP.NET siteMap XML file. Normally most of these links would (presumably) be to internal pages
on your website, but for this example I have made them all external links.
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="~/Default.aspx" title="Home" description="Home Page">
<siteMapNode url="http://jquery.com/" title="jQuery" description="" />
<siteMapNode url="http://users.tpg.com.au/jbirch/plugins/superfish" title="Superfish" description="">
<siteMapNode url="http://users.tpg.com.au/jbirch/plugins/superfish/" title="About" description="" />
<siteMapNode url="http://alistapart.com/articles/dropdowns" title="What is Suckerfish" description="" />
<siteMapNode url="http://users.tpg.com.au/jbirch/plugins/superfish/#download" title="Download" description="">
<siteMapNode url="http://docs.jquery.com/Downloading_jQuery" title="Download jQuery" description=""/>
<siteMapNode url="http://users.tpg.com.au/jbirch/plugins/superfish/?#download" title="Download Superfish" description=""/>
</siteMapNode>
</siteMapNode>
<siteMapNode url="http://cssfriendly.codeplex.com/" title="CSSFriendly.dll" description="">
<siteMapNode url="http://cssfriendly.codeplex.com/?" title="About CSS Adapters" description="" />
<siteMapNode url="http://msdn.microsoft.com/en-us/library/yy2ykkab.aspx" title="ASP.NET Sitemap" />
<siteMapNode url="http://cssfriendly.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=2159" title="Download" description="" />
</siteMapNode>
</siteMapNode>
</siteMap>
Test.master
In addition to including all the relevant javascript files (lines 6 and 7) and CSS files (line 8), Superfish requires a 'setup' function
which is in the script block (lines 10-14). I changed the parameter inside from 'ul.sf-menu' to ul.AspNet-Menu because
by default the control uses that CSS class name.
Unfortunately that didn't make the menus work, so I also had to open superfish.css and search-and-replace sf-menu
with AspNet-Menu. This is the "hack" because other superfish styles (such as the one that makes the arrows appear for submenus) don't work any more.
1: <%@ Master Language="C#" AutoEventWireup="true" CodeFile="Test.master.cs" Inherits="Test" %>
2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3: <html xmlns="http://www.w3.org/1999/xhtml">
4: <head runat="server">
5: <title></title>
6: <script type="text/javascript" src="/script/jquery-1.3.2.min.js"></script>
7: <script type="text/javascript" src="/script/superfish.js"></script>
8: <link type="text/css" href="~/css/superfish.css" rel="stylesheet" media="screen" runat="server" />
9: <asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder>
10: <script type="text/javascript">
11: $(document).ready(function() {
12: $('ul.AspNet-Menu').superfish();
13: });
14: </script>
15: <style type="text/css">
16: body,h1,p,.AspNet-Menu{font-family:Tahoma}
17: </style>
18: <asp:ContentPlaceHolder id="head" runat="server">
19: </asp:ContentPlaceHolder>
20: </head>
21: <body>
22: <form id="form1" runat="server">
23: <h1>Css menus with asp:Menu and jQuery</h1>
24: <asp:SiteMapDataSource ID="SiteMapDataSource" runat="server" ShowStartingNode="false" />
25: <asp:Menu ID="Menu1" runat="server"
26: DataSourceID="SiteMapDataSource"
27: Orientation="Horizontal">
28: </asp:Menu>
29: <div id="body" style="float:left;">
30: <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
31: <!-- actual page content goes here -->
32: </asp:ContentPlaceHolder>
33: </div>
34: </form>
35: </body>
36: </html>
Web.config
The siteMapFile is configured to point at the Test.sitemap shown above. Ensure you place this in the correct location
(inside system.web in your web.config file).
<system.web>
<siteMap defaultProvider="TestSiteMapProvider" enabled="true">
<providers>
<add name="TestSiteMapProvider"
type="System.Web.XmlSiteMapProvider"
siteMapFile="~/Test.SiteMap"
securityTrimmingEnabled="false"/>
</providers>
</siteMap>
Output
The menu looks like this when rendered:

and the HTML source is a nice neat set of <ul><li> tags.

//TODO:
Ideally we would be able to have the asp:Menu output the correct classnames for Superfish, rather than
search-and-replace in the superfish.css file. The author of this codeproject article
has done exactly that by writing his own control to parse the sitemap XML directly.
It seems to me that the built-in functionality of the asp:Menu (shown below) should work - but perhaps the CSSFriendly Adapter is munging that behaviour?
<asp:Menu ID="Menu1" runat="server"
DataSourceID="SiteMapDataSource"
Orientation="Horizontal">
<DynamicMenuStyle CssClass="sf-menu" />
</asp:Menu>
Anyway, that still needs to be fixed so that the submenu arrows and drop-shadow appear -- if you have any ideas, drop me an email!
|